Kornel
Kisielewicz,
14 Sep 2016
Welcome, in what I hope to become a regular series, the first Dev Talk article. In this series we will try to cover various topics related to the down and gritty development of Jupiter Hell. While this post is rather a overview talk, accessible to everyone, we might venture more deeply into some topics at a later stage: I'll make sure to mark those posts with a appropriate "Here be Dragons" warning sign.
In this first post, I'd like to delve into my work from the past two weeks, where I tackled the basics of the last missing major subsystem of Jupiter Hell's engine code - namely Physics. After much research, we decided to go with Bullet Physics, due to its stability, liberal open source license (zlib), and it's proven track record in prior game integrations. Two weeks in I'm more or less happy with our choice - my only real disappointment was the almost non-existent documentation (40 page manual for multi-megabyte source Physics library?) and outdated examples (good luck trying to find a modern Ragdoll example with skinning).
You might ask, why do we need Physics in a grid and turn based game? That's a valid question! Up till now, there was really no need to have neither a physics library, nor even collision (Bullet handles both), precisely due to the grid/turn based nature of our game. The animation system (which I'll write about in some future Dev Talk post) is based on procedural techniques and for the most part doesn't need any physics integration.
However, multiple systems in the game would benefit from visual enhancements that could be brought in thanks to a physics library. Note the "visual" in the previous sentence: no gameplay system is affected by Physics in any capacity. The way we created the game, physics calculations in the game have no tangible effect on the gameworld. We will use physics to illustrate gameplay effects, not determine them. This has several benefits - we don't need to store physics information between saves, game replays will be unaffected (no need to synchronize), and we can turn on/off the physics system without any gameplay effect. The last two allow replay storage as a simple sequence of commands.
Let's get into details, illustrated by some basic gifs from the engine integration tests (not in-game yet -- see an upcoming post for that!).
So what do we need physics for?
Explosion object physics
Let's be frank - a big part of DoomRL and consequently Jupiter Hell is blowing things up. While we can use particle effects and billboards to render nice explosions, nothing is as satisfying as game world objects making up a tile (imagine a stack of crates) flying in all directions after a careful rocket launcher shot. This effect is present in many games, Jupiter Hell however presents one bonus, and one caveat.
The bonus is our fully dynamic lighting system which not only will make sure that every object in flight will cast a dynamic shadow, but also the explosion itself will cast proper shadows.
The caveat is that due to the grid/turn based nature, a tile is either passable, or impassable, there is no middle-ground. Hence, a tile must be blown up or not touched at all, no middle-ground. Once you blow up a tile, all tile elements that scatter will be treated as not taking up space, no matter how they block a given tile. We're still thinking on how to solve that in a way that won't introduce ugly visual glitches.
Ragdolls
Even if we make a dozen death animations for each of the enemies (which would take a lot of time!), they would get very repetitive in a game that's supposed to offer tons of replayability. Ragdolls are the only solution to make death animations differ significantly, and go in the fun procedural spirit that we want to maintain in all Jupiter Hell solutions. Sure, they can produce unintentionally hilarious situations from time to time, but given the procedural nature of our game I believe this is acceptable and even encouraged.
Don't be discouraged by the poor behavior of our current ragdoll setup, it's a quickly hacked doll that doesn't fit the mesh very well yet :).
Ragdoll animation refinement
Most of the games that use ragdolls limit their use to death animations and corpse dragging. Due to the procedural nature of our animation system we came up with the idea of controlled blending of ragdoll effects with our pose blending. While this can be used for a variety of effects, the obvious use is the "being hit" animation. Similarly to the death animation, instead of using a fixed set of animations, we can try to generate ones on the fly, that fully take into account the exact pose the character is in at the current moment. This system needs a ton of tweaking to get it to look right (and a way better ragdoll), but I think that in the end it will look pretty good! Here's a quick test of the idea in action:
Procedural destruction
One of my big dreams is making the whole environment in Jupiter Hell fully destructible (like it was in DoomRL). In a 3d world however this is an extremely difficult task if we want to make it look good. Sure, we could just substitute a destroyed tile with it's "destroyed" model, but that would in our opinion look pretty bad in contrast with the visual quality of the rest of the game. We do plan on making most of the scenery elements destructible (crates, doors, etc.), however full environmental destruction that includes all walls will probably be a Kickstarter stretch goal.
The temptation to do full destruction is huge though, as we do not pre-calculate any vision data, or actually anything at all -- the light and shadow play on walls falling apart would be something to behold!
Hence, I've been researching on how to make such destruction look good, and one of the cheaper (relatively) techniques is Voronoi shattering, illustrated by a very simplified example below.
Still, this technique requires a lot of preparation and additional code, including (but not limited to) - object layers, internal textures, runtime subdividing the model into convex shapes, runtime UV coordinate recalculation. After the above test, I'm pretty sure I can pull it off, but there's a long road before I can get any of that into the game.
On this note I conclude this Dev Talk. We need feedback! Both on what we talk about here, and about the games progress. Also, at this moment most importantly, did you enjoy this article? Do you want more such technical rants? Should they delve deeper into technical aspects, or should they be more of a feature discussion and rant for everyone to enjoy?
Let us know on the forum!
Welcome, in what I hope to become a regular series, the first Dev Talk article. In this series we will try to cover various topics related to the down and gritty development of Jupiter Hell. While this post is rather a overview talk, accessible to everyone, we might venture more deeply into some topics at a later stage: I'll make sure to mark those posts with a appropriate "Here be Dragons" warning sign.
In this first post, I'd like to delve into my work from the past two weeks, where I tackled the basics of the last missing major subsystem of Jupiter Hell's engine code - namely Physics. After much research, we decided to go with Bullet Physics, due to its stability, liberal open source license (zlib), and it's proven track record in prior game integrations. Two weeks in I'm more or less happy with our choice - my only real disappointment was the almost non-existent documentation (40 page manual for multi-megabyte source Physics library?) and outdated examples (good luck trying to find a modern Ragdoll example with skinning).
You might ask, why do we need Physics in a grid and turn based game? That's a valid question! Up till now, there was really no need to have neither a physics library, nor even collision (Bullet handles both), precisely due to the grid/turn based nature of our game. The animation system (which I'll write about in some future Dev Talk post) is based on procedural techniques and for the most part doesn't need any physics integration.
However, multiple systems in the game would benefit from visual enhancements that could be brought in thanks to a physics library. Note the "visual" in the previous sentence: no gameplay system is affected by Physics in any capacity. The way we created the game, physics calculations in the game have no tangible effect on the gameworld. We will use physics to illustrate gameplay effects, not determine them. This has several benefits - we don't need to store physics information between saves, game replays will be unaffected (no need to synchronize), and we can turn on/off the physics system without any gameplay effect. The last two allow replay storage as a simple sequence of commands.
Let's get into details, illustrated by some basic gifs from the engine integration tests (not in-game yet -- see an upcoming post for that!).
So what do we need physics for?
Explosion object physics
Let's be frank - a big part of DoomRL and consequently Jupiter Hell is blowing things up. While we can use particle effects and billboards to render nice explosions, nothing is as satisfying as game world objects making up a tile (imagine a stack of crates) flying in all directions after a careful rocket launcher shot. This effect is present in many games, Jupiter Hell however presents one bonus, and one caveat.
The bonus is our fully dynamic lighting system which not only will make sure that every object in flight will cast a dynamic shadow, but also the explosion itself will cast proper shadows.
The caveat is that due to the grid/turn based nature, a tile is either passable, or impassable, there is no middle-ground. Hence, a tile must be blown up or not touched at all, no middle-ground. Once you blow up a tile, all tile elements that scatter will be treated as not taking up space, no matter how they block a given tile. We're still thinking on how to solve that in a way that won't introduce ugly visual glitches.
Ragdolls
Even if we make a dozen death animations for each of the enemies (which would take a lot of time!), they would get very repetitive in a game that's supposed to offer tons of replayability. Ragdolls are the only solution to make death animations differ significantly, and go in the fun procedural spirit that we want to maintain in all Jupiter Hell solutions. Sure, they can produce unintentionally hilarious situations from time to time, but given the procedural nature of our game I believe this is acceptable and even encouraged.
Don't be discouraged by the poor behavior of our current ragdoll setup, it's a quickly hacked doll that doesn't fit the mesh very well yet :).
Ragdoll animation refinement
Most of the games that use ragdolls limit their use to death animations and corpse dragging. Due to the procedural nature of our animation system we came up with the idea of controlled blending of ragdoll effects with our pose blending. While this can be used for a variety of effects, the obvious use is the "being hit" animation. Similarly to the death animation, instead of using a fixed set of animations, we can try to generate ones on the fly, that fully take into account the exact pose the character is in at the current moment. This system needs a ton of tweaking to get it to look right (and a way better ragdoll), but I think that in the end it will look pretty good! Here's a quick test of the idea in action:
Procedural destruction
One of my big dreams is making the whole environment in Jupiter Hell fully destructible (like it was in DoomRL). In a 3d world however this is an extremely difficult task if we want to make it look good. Sure, we could just substitute a destroyed tile with it's "destroyed" model, but that would in our opinion look pretty bad in contrast with the visual quality of the rest of the game. We do plan on making most of the scenery elements destructible (crates, doors, etc.), however full environmental destruction that includes all walls will probably be a Kickstarter stretch goal.
The temptation to do full destruction is huge though, as we do not pre-calculate any vision data, or actually anything at all -- the light and shadow play on walls falling apart would be something to behold!
Hence, I've been researching on how to make such destruction look good, and one of the cheaper (relatively) techniques is Voronoi shattering, illustrated by a very simplified example below.
Still, this technique requires a lot of preparation and additional code, including (but not limited to) - object layers, internal textures, runtime subdividing the model into convex shapes, runtime UV coordinate recalculation. After the above test, I'm pretty sure I can pull it off, but there's a long road before I can get any of that into the game.
On this note I conclude this Dev Talk. We need feedback! Both on what we talk about here, and about the games progress. Also, at this moment most importantly, did you enjoy this article? Do you want more such technical rants? Should they delve deeper into technical aspects, or should they be more of a feature discussion and rant for everyone to enjoy?
Let us know on the forum!