Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411511 Posts in 69375 Topics- by 58430 Members - Latest Member: Jesse Webb

April 26, 2024, 01:26:16 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Worlds Below - Programming discussions
Pages: [1]
Print
Author Topic: Worlds Below - Programming discussions  (Read 563 times)
Squishymonster
Level 0
**


View Profile WWW
« on: January 23, 2016, 08:23:29 AM »

I'm developing a side-project called Echoes of Worlds Below, and I thought it would be interesting to discuss some of the programming and architectural decisions that are made. For this particular forum I'm more interested in actual back and forth discussion so feel free to get involved :] I have a TIGSource devlog but it seems that people focus more on player-facing discussion in those. I want to geek out on programming & architecture with this one.

Language: C++, but I don't expect much of the discussion will revolve around language. I'm not a language geek. Language is a tool to me. Though I'm happy to provide any information that you might be curious about.

Engine: "liteSpeed", custom engine with multiplatform architecture / API, but limited implementation so far on anything other than Windows. This engine is my main side-project. I've been toying with it as long as I've been programming, and I expect I will continue as long as I am a programmer.

At this point liteSpeed supports a basic implementation of most core game tasks. It doesn't blow anything out of the park really. It is a way for me to explore concepts that I can't focus on at work.

Whenever I add something to liteSpeed my first questions revolve around maintainability. How can I do something that I need while expanding the maintenance overhead as little as possible? Hence the name. And how can I refactor things that I've already done to become easier. "Unity" is a solid answer to that question, but ignores that fact that I actually enjoy bottom-up programming.

Game: I don't want to braindump the game at this point. There are other outlets for that. But if you imagine something that started off as a chunk-based Minecraft-esque voxel / block engine, add chunked terrain, remove the voxel stuff and keep the chunks, and then layer on teleporting in to dungeons ala Skyrim, you've got a solid foundation for thinking about things Smiley

TIGSource devlog: https://forums.tigsource.com/index.php?topic=49292.0

Game website & devlog: www.worldsbelow.com
Logged
Squishymonster
Level 0
**


View Profile WWW
« Reply #1 on: January 23, 2016, 12:08:35 PM »

https://www.youtube.com/watch?v=wcGcFfD17kE&feature=youtu.be
Chunk streaming and rudimentary character, item, and prop placement:

Context:
The problem I am tackling now is related to how to properly handle a large chunked procedural streaming world, while at the same time placing story-elements such as characters, items, and props in specific locations. There are a few interesting challenges to this that weren't immediately obvious to me - but as usual, they are solvable.

In the video above you'll see a demonstration of the current implementation, made more visible with debug flying. When the player is loaded the streamer is "focused" on the player's location. Then when the player moves the world streams new chunks around the player's new location. Chunks that are not within some threshold are stomped.

The vertex shader includes a horizon bending algorithm so that if the player is traversing the world normally the streaming margin is generally not visible. This still needs to be tweaked because it is also dependent on the frequency and modulation of the terrain.

Streaming runs on a separate thread (which still causes locks from time to time, especially during focus). This keeps the framerate from hitching as you move around and chunk files are accessed, or procedural generated.

Problem:
The first problem is that when the player is created the world doesn't exist. There are no chunks streamed, because streaming focus is based on the player's position. However, when creating a new game file I want to create story objects in the immediate area. The current implementation creates those objects before the world is streamed. But what height will the ground be at the specified X & Z? Unknown. So I had to expose terrain height generation function to give Y for XZ. That solves the problem fine for now. But, what if the object is dynamic, like a character, and he needs "physical" ground to stand on? I have to disable his physics until there is ground, which is what I'm doing in a sort of cheap way.

The second problem is with far away story elements, like the tower that is approached. I want to place that on new-game as well, and there is no way the world will be streamed out there for some time.

The current solution for all of these things involves calling a function during initialization and adding the desired elements to global lists in a World structure, so they're basically always there, but still have to handle the fact that the ground might not be under them yet.

I created a system called World.PushDynamicObjects and World.PullDynamicObjects. When a chunk is unloaded, this checks if the world object lists have objects within the chunk's boundary, and then pushes the object into the chunk, boots it out of the world, and saves it with the chunk. When a new chunk is loaded I procedurally generate it, and then load dynamic objects for it if there are any. So that's kind of a nice system for pushing and pulling objects. This feature is disabled in the video above.

But there's a problem with that too. Push and Pull is based on chunk streaming distance, and tall objects like the tower should be pulled much sooner than an item that might be 2 feet tall.

So I could summarize the entire problem like this: When a new game is created I want to place world-wide story elements, but I don't want them to exist in the world until the player is close enough to care about them. So I need some way of telling the world "Here's what I want, eventually. You handle it."

Solution:
Now we get to the discussion part. My idea so far is to add a Map class to the world Class and let it keep track of all story element knowledge. The World class is then delegated to watching the player's position, observing the map, and deciding what should and should not exist in the near-area - that's actually pretty close to how a 2d tile map game works between a map and a camera. My world is much larger, but density much lower, so maybe it just works.

I haven't decided if the number of story elements is so large that keeping it all active at once is viable. It definitely is for now.

When creating a new game, I ~could~ add everything to the World.Map, and then tell the map to "bake" everything it knows about down to the chunks by creating chunks where necessary, and then pushing dynamic objects down, and saving. Then completely emptying the map. In that case the map is useless to the world after baking and the world will just have to load chunks and pull dynamic objects as usual. That still leaves the problem of tall, distant props so I think the Map knowing more than the World is still important. But maybe it's selective. Maybe I flag up each element when it is added to the map. Some are "distant" and permanently known by the map, and others are "baked" into the chunks.
« Last Edit: January 24, 2016, 06:27:21 PM by Squishymonster » Logged
Squishymonster
Level 0
**


View Profile WWW
« Reply #2 on: January 24, 2016, 06:22:21 PM »





This video demonstrates the solution that I came to. The World.Map is world-wide. I load a small scene with three objects when a new game is created. The item and character types can be flagged to "allow dormancy" and "allow push". Here, the tent and NPC allow dormancy, but do not allow push. The fire doesn't allow either. When the containing chunk streams out the tent and NPC go dormant. The fire remains because it needs to stay visible from afar for navigation purposes. I have not hooked the dungeon entrances in to this system, but they will work the same way.

This is a nice improvement overall because now I don't have to do anything special to keep the NPC from falling through the world when I create him, and when the chunk goes away. He is created dormant and his chunk streaming signals him to show up.

I had some other troubles today when I realized that my character / character collision had stopped working. It was due to these changes. It turns out I was only handling collisions in the case where the player was evaluated first Tongue Things seem pretty solid now though, I think...

I haven't decided what's next yet... the only think that I really should do is put collision around the tent and 1st story dungeon, so maybe that'll be it. Then the only known bug with the current build will be the streaming thread locking up occasionally on load.
Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic