I've begun several roguelike projects in the past. Some have been traditional roguelikes and some have been more roguelike-likes; similar in appearance and functionality but not really capable of falling neatly into the roguelike category. All have been ditched for more interesting projects.
Today I dug out some old code after playing Angband on my phone. I already had the basics of a C# roguelike engine and was able to neaten this up a great deal, removing a broken timeslot system and gutting the random world generation completely. I began working from the top, adding features as they were necessary.
Development
So far I have much better support for monsters than I have ever had. Before, I decided to go with one "monster" class and have the details of the individual denizens of my virtual dungeons loaded from text files. This isn't necessarily a bad way to approach things but I ended up with a massive class filled with variables and procedures that only one or two beasts used. I've now gone for a bare-bones monster class designed to be inherited by child classes. This way, I can still keep the traditional roguelike convention of the player being a "special" monster for example without having to stare at player-centric code while dealing with goblins. After breaking this down into several basic classes (such as player, flying monster, walking monster, magic using monster, etc) I then load the individuals from text files, allowing for easy content addition.
I approached world generation from a completely different angle this time and it's paid off. Before I had dived into the guts of generating a world before I'd even decided how to store it in memory. Now I have a system that allows for "chunks" of the world to be loaded in realtime, therefore allowing for an infinitely sized world. These are generated on the fly the first time you visit one and this is saved for future reference. I'll go into the reason why I chose this method, but for now although it only generates a few trees at the moment, the under-the-bonnet workings of the game allow me to do a great deal more. I can also load pre-generated chunks, allowing for pre-built villages for example. Plus, the way that they link means that caves and dungeons can also be generated this way.
Finally, I have a system that allows the world to be transformed, allowing for the player to transform one object into another. For example, on a world basis you might cast a fireball that crashes into the ground leaving a scorched patch. It would be a cinch to create a special reaction to fireballs that transforms a grass tile to a scorch tile. Similarly, you could cut a tree down, converting into inventory items of wood and leaving a stump where you cut it.
It's not a roguelike yet. I haven't coded monster AI or even support for anything but the player when it comes to monsters being drawn onscreen. This is deliberate as the player display is only a quick hack for testing purposes and I have plans for how the rendering process is going to map out. However, actions are already supported and the other monsters should be able to interact with the environment like the player as soon as I put them in.
I'll tell you more about the game shortly, but I want to introduce you to two concepts first:
The Pokemon Effect
Many roguelikes have started to involve what I like to refer to as the Pokemon effect. It's an old staple of game design and it's everywhere in popular games these days.
When I was a kid I was never into football. However, that didn't stop me from collecting football stickers, swapping duplicates with my friends and begging my mom for a new set every time I saw them on sale. In later life I was glued to GameBoy for many months trying to collect virtual fighting monsters, and nowadays I often find myself reading the Achievement list for a game on my XBox trying to find some simple ones to complete and add to my GamerScore.
The Pokemon effect comes from a natural human desire to collect a set of something. It becomes an addiction. It manifests itself in many ways and I've noticed that TOME now includes unlockable classes to keep people playing, so it's now begun to invade the world of roguelikes.
Progression
Traditional roguelikes suffer from a lack of permanent progression, bar one very small detail. When you play an RPG such as Diablo or World of Warcraft, you can enter into a fight knowing that you will probably benefit from the outcome no matter what that outcome is. In Diablo 2 you may bite off more than you can chew and lose some gold, or even lose your corpse behind something that you can't get past without gear, but most of the time it's a win-win situation. You'll gain some experience, probably an item or two to sell for gold if not a nice new upgrade and stand to lose very little. In World of Warcraft the worst you can lose is time and a small amount of gold spent on repairs.
Roguelikes aren't so friendly as they usually include permanent death as an untoggleable feature and the genre loses out somewhat because of this. If you play a roguelike chances are that you're playing it because of the permanent death amongst other things as it adds excitement, but when the time comes to lose a character I often just let it happen. Fighting against the almost inevitable death of my character seems like a lot of effort and I'd rather just let it play out and watch with morbid interest. Dice the Knight, level 14, your time has come.
So, a character has died and where does it leave the player? Well, progression rears it's head with TOME again as there's the possibility that I've unlocked a new class to play as. It's very apparent in Dwarf Fortress too, as it's permanent world allows me to venture back into my old fort and either reclaim it or just admire it's architecture. In the majority of roguelikes though, the only permanent progression is the slim chance of meeting your old ghost in a distant dungeon somewhere.
Unearthed
Unearthed builds on these concepts somewhat to try to provide an addictive yet still brutal gameplay experience. I wanted permanent death to be in and I wanted it to become a regular occurrence, but I also wanted something to show for each character's life.
You play as a sort of Indiana Jones style tomb-raider. Your task is to populate a museum with captured beasts, forgotten relics and the like and you do so by risking your life in caves, jungles, dungeons and other inhospitable places. This builds on the Pokemon effect, as the entire idea behind the game is to collect complete sets of various things.
The world in which the game is based is randomly generated and linked together by a series of "waypoints", ala Diablo 2, allowing you to warp between any two that you have discovered before. Again, another collection to complete and one that will help you immensely. After death, your new character will continue where your old one left off with any items in the museum left as they were. Therefore, you can complete the game over several characters. This is where progression comes in despite permanent death and it also allows for the interesting possibility of re-visiting an old nemesis with a tougher character, taking revenge by banishing his soul to the netherworld and then prising that one final relic for the museum from the fingers of the skeletal remains of Dice the Knight, level 14...
Monday, 17 January 2011
Friday, 29 October 2010
2D Platform Physics
So much for the new year's resolution. I haven't coded anything worth playing for a long time, so I thought it was about time that I actually finished another game.
I've recently been inspired by Super Crate Box. There was once a time when video games were just fun and nothing else, often a creatively awful excuse to mash buttons. We didn't mind back then either, happily pumping pound coins into an arcade machine or hammering the start button after countless virtual deaths on our home consoles. Occasionally a software house (often an independent one) will throw together something that reminds us of those times. Popcap's intensely addictive offerings are nearly always a good example.
Super Crate Box is another. It's simple, addictive and completely devoid of realism and storyline - in a good way.
2D platformers like Donkey Kong and Ice Climbers were relatively simple to make back in the days when 8-bit seemed like all you'd ever need to create an entertaining experience and therefore there were loads of them. It's for this reason entirely that I don't mind making my next game another non-scrolling single-screen 2D platformer. It's the gameplay mechanics that will make my game different to Super Crate Box, emulating only it's simplicity and genre.
In making a start I wanted something playable up and running quickly. Many platform game authors at this point would decide to grab a prepackaged physics engine, plug in some values to simulate gravity and let their middleware deal with all of the collisions. However, I've played many a platform game that uses the likes of Box2D, Havok and Farseer that quite honestly sucked. The problem is that it takes almost as much time to tweak one of these engines to make an enjoyable platform experience as it does to write your own, taking into account the fact that unless if your game relies heavily on realistic physics (such as Trine for example), it doesn't really need all of the bells and whistles.
Remember that our friend Jumpman (who later became Mario) didn't have a 3rd party physics solution to aid him in his fight against giant gorillas. If it can be done back in the old 8-bit days using about as much processing power as a modern-day wristwatch it can be done by your average coder on a modern day system.
I decided to use a velocity based system where x and y velocities are increased and decreased by the movement code, which is then applied to the player's position. The level format is a very basic tile-based format without slopes or complicated shapes. Either a square is passable or impassable.
Firstly, collision checking is still somewhat awkward. If, for example, we have a level made of 32x32 size blocks and our character is 32x64 in size, we have to make six different checks for collisions. I'll use Mario to demonstrate.
The most important points are 5 and 6. These are where you should be checking for collisions with the floor, obviously. By using two points and not just one in the middle between his feet, you can allow the player to stand on an edge. If you're after a SNES or Mega-Drive feel you can also use these to start a "balancing" animation as if he's standing on the edge of a cliff.
1 and 2 are very important if you don't want to give your player the ability to jump up through platforms. Most games will use these for collision checks with the ceilings or even just the roof of your map.
Finally, as the blocks are half the height of the player it's possible for him to jump in such a way that points 1 and 2 are above a block and 5 and 6 are below. Without these, depending on how you code your physics, you can end up with the player getting stuck, sliding along a platform half stuck in it or just interacting strangely before clipping back out again.
Anyone trying for the more complicated options of using slopes, abstract polygon geometry or smaller tile sizes will find that they will probably have to check more points on their character or opt for a different collision detection approach altogether.
After getting these checks done, modifications can be made to a player's velocity to allow him to walk right up to a wall, rebound of a ceiling and walk fluidly across a floor without bouncing about. Poor reaction to a collision can end up with either the player managing to force their way through solid objects, the player getting stuck or not being able to walk those last few pixels up to where a wall begins. I resolved the latter by calculating the distance between the player and the wall after a collision and then making his x velocity this value, so in the next frame he makes that last tiny step.
Finally, jumping can be problematic. Firstly you need to check that the player is on a floor tile. If he is, you subtract an amount from his y velocity so that he launches skywards. I used an approach I saw in Quake and kept a boolean flag that was set every time the player's foot collision check detected a wall. That meant that my floor collisions had to be in a little bit from the edge of the sprite, so just to the left of number 6 in the image above, just to stop wall collisions from allowing a jump. Obviously if you want N the Ninja style walljumping you're not going to need to worry too much about this.
I read in an interview with the developer of Braid a point that is worth making about jumping. It is customary in platform game design to allow the player to jump despite having left a platform and thus being in mid-air for a short time. The delay should only be a few milliseconds so that it's undetectable to the player, but still allowing for that little bit of lag between your eyes noticing a platform edge and your PC noticing your panicked button press to become less of a problem. Adding this little touch instantly made the platform physics seem more robust.
I've recently been inspired by Super Crate Box. There was once a time when video games were just fun and nothing else, often a creatively awful excuse to mash buttons. We didn't mind back then either, happily pumping pound coins into an arcade machine or hammering the start button after countless virtual deaths on our home consoles. Occasionally a software house (often an independent one) will throw together something that reminds us of those times. Popcap's intensely addictive offerings are nearly always a good example.
Super Crate Box is another. It's simple, addictive and completely devoid of realism and storyline - in a good way.
2D platformers like Donkey Kong and Ice Climbers were relatively simple to make back in the days when 8-bit seemed like all you'd ever need to create an entertaining experience and therefore there were loads of them. It's for this reason entirely that I don't mind making my next game another non-scrolling single-screen 2D platformer. It's the gameplay mechanics that will make my game different to Super Crate Box, emulating only it's simplicity and genre.
In making a start I wanted something playable up and running quickly. Many platform game authors at this point would decide to grab a prepackaged physics engine, plug in some values to simulate gravity and let their middleware deal with all of the collisions. However, I've played many a platform game that uses the likes of Box2D, Havok and Farseer that quite honestly sucked. The problem is that it takes almost as much time to tweak one of these engines to make an enjoyable platform experience as it does to write your own, taking into account the fact that unless if your game relies heavily on realistic physics (such as Trine for example), it doesn't really need all of the bells and whistles.
Remember that our friend Jumpman (who later became Mario) didn't have a 3rd party physics solution to aid him in his fight against giant gorillas. If it can be done back in the old 8-bit days using about as much processing power as a modern-day wristwatch it can be done by your average coder on a modern day system.
I decided to use a velocity based system where x and y velocities are increased and decreased by the movement code, which is then applied to the player's position. The level format is a very basic tile-based format without slopes or complicated shapes. Either a square is passable or impassable.
Firstly, collision checking is still somewhat awkward. If, for example, we have a level made of 32x32 size blocks and our character is 32x64 in size, we have to make six different checks for collisions. I'll use Mario to demonstrate.
The most important points are 5 and 6. These are where you should be checking for collisions with the floor, obviously. By using two points and not just one in the middle between his feet, you can allow the player to stand on an edge. If you're after a SNES or Mega-Drive feel you can also use these to start a "balancing" animation as if he's standing on the edge of a cliff.
1 and 2 are very important if you don't want to give your player the ability to jump up through platforms. Most games will use these for collision checks with the ceilings or even just the roof of your map.
Finally, as the blocks are half the height of the player it's possible for him to jump in such a way that points 1 and 2 are above a block and 5 and 6 are below. Without these, depending on how you code your physics, you can end up with the player getting stuck, sliding along a platform half stuck in it or just interacting strangely before clipping back out again.
Anyone trying for the more complicated options of using slopes, abstract polygon geometry or smaller tile sizes will find that they will probably have to check more points on their character or opt for a different collision detection approach altogether.
After getting these checks done, modifications can be made to a player's velocity to allow him to walk right up to a wall, rebound of a ceiling and walk fluidly across a floor without bouncing about. Poor reaction to a collision can end up with either the player managing to force their way through solid objects, the player getting stuck or not being able to walk those last few pixels up to where a wall begins. I resolved the latter by calculating the distance between the player and the wall after a collision and then making his x velocity this value, so in the next frame he makes that last tiny step.
Finally, jumping can be problematic. Firstly you need to check that the player is on a floor tile. If he is, you subtract an amount from his y velocity so that he launches skywards. I used an approach I saw in Quake and kept a boolean flag that was set every time the player's foot collision check detected a wall. That meant that my floor collisions had to be in a little bit from the edge of the sprite, so just to the left of number 6 in the image above, just to stop wall collisions from allowing a jump. Obviously if you want N the Ninja style walljumping you're not going to need to worry too much about this.
I read in an interview with the developer of Braid a point that is worth making about jumping. It is customary in platform game design to allow the player to jump despite having left a platform and thus being in mid-air for a short time. The delay should only be a few milliseconds so that it's undetectable to the player, but still allowing for that little bit of lag between your eyes noticing a platform edge and your PC noticing your panicked button press to become less of a problem. Adding this little touch instantly made the platform physics seem more robust.
Saturday, 9 January 2010
New Beginnings
It's January; the start of a new year and in this case a new decade. I've survived the national binge-drinking season and made a new year's resolution never to make any more new year's resolutions. That doesn't mean I can't start to do something different though.
I've been dabbling with programming in several languages and multiple flavours of each over the last twenty years or so but never actually got round to finishing anything, so this year I'm going to knock that habit on the head. In an attempt to find inspiration I've written an entry for the Experimental Gameplay Project, the theme of which is currently "100 things".
After struggling to come up with an idea I found myself thinking along the lines of a traditional twin-stick shooter. However, there's a huge problem when it comes to the theme. You need to shoot, which usually requires the creation of a sprite, which would increase the total amount of objects on-screen by one. Instead, I began to picture a world where your ammo was always visible, circling your avatar until it was time to use it.
That led to another problem however; if your aim is to kill people or objects, you'll end up reducing the amount of objects on the game-field. So, what if things weren't killed, but incapacitated? That's where the idea behind Denature came from.
It took two days to program and one day to fix some irritating deployment bugs that turned out to be down to my own stupidity, so I'm hoping to spend some of the next few days tidying things up a little before I submit it. We're allowed a time limit of seven days, but I think I'll probably have done all that I want with it by about day five.
Please keep checking the site!
I've been dabbling with programming in several languages and multiple flavours of each over the last twenty years or so but never actually got round to finishing anything, so this year I'm going to knock that habit on the head. In an attempt to find inspiration I've written an entry for the Experimental Gameplay Project, the theme of which is currently "100 things".
After struggling to come up with an idea I found myself thinking along the lines of a traditional twin-stick shooter. However, there's a huge problem when it comes to the theme. You need to shoot, which usually requires the creation of a sprite, which would increase the total amount of objects on-screen by one. Instead, I began to picture a world where your ammo was always visible, circling your avatar until it was time to use it.
That led to another problem however; if your aim is to kill people or objects, you'll end up reducing the amount of objects on the game-field. So, what if things weren't killed, but incapacitated? That's where the idea behind Denature came from.
It took two days to program and one day to fix some irritating deployment bugs that turned out to be down to my own stupidity, so I'm hoping to spend some of the next few days tidying things up a little before I submit it. We're allowed a time limit of seven days, but I think I'll probably have done all that I want with it by about day five.
Please keep checking the site!
Subscribe to:
Posts (Atom)