DAME and Spawn() (Flixel)
From Flash Game Dojo
So you've created your first demo, made your first DAME level, and are raring to go. What next? We put the two together of course!
Contents
|
Setup
For the purposes of this snippet I'll be using Andreas Zecher's excellent alien shooter tutorial. But that doesn't get us a map, does it? How about Gradius?
Go ahead and make a map, then add a player sprite to it. If you haven't tried DAME yet, feel free to check over Matthew Casperson's DAME/Flixel tutorial. There's only one real trick you need to know when making your map: we only want some of the objects to be solid, in this case the rocky ones.
You can see the DAME layer configuration above. The tileset is 256 pixels wide, or 16 tiles/row using 16x16 tile size. Counting from 0 at the top-left, we see that 48 is the start of the 4th row, and 52 is the start of the upside-down mountain. This lets us fly right through the tip of the first mountain, but since collision is per-tile that's the best we'll get unless you go to 8x8 tiles. That's actually how it's done on the NES, but it takes forever to draw in the current version of DAME.
A Word on Art
You'll notice a few things about the Gradius tileset. First, the mountains and trees on the cavern ceiling are just mirror images of those on the floor. Memory was at a premium on the NES, with 32KB of memory total on the early ROMs, so designers really had to get the most out of their pixels. All Nintendo consoles with hardware tiling have also supported tile mirroring in hardware to help alleviate the memory limit.
But the more impressive thing you'll notice is that there are only 8 tiles for the space background, one blank and the others with 1 star apiece. Yet the Gradius map designers spread these around in such a way that it really looks like a convincing starfield given the early 8-bit limitations of the cartridge. This technique is also used effectively in Mode, where the platforms and background are semi-randomly generated from a very small number of 8x8 base tiles. This can really save you (or your artist) a lot of work drawing tiles, and it's definitely worth studying the classics. If you're interested in learning more I highly recommend taking a look at the NES greats, including Castlevania, Megaman, and Batman, as discussed in this Parodius NESDev discussion.
Terrain Collision
The first law of space shooters is that pretty much everything can kill you, including the terrain. The way we do this with a DAME-generated tilemap is to check for collision with the map when we call update().
Add these lines to the end of PlayState.update():
More Snippets | |
Flixel | |
FlashPunk |
if (level1.mainLayer.collide(_ship)) overlapAlienShip(null, _ship);
And change the collision in PlayState.overlapAlienShip() to handle the null value we're passing above:
More Snippets | |
Flixel | |
FlashPunk |
if(! null == alien) // this line is added alien.kill();
Of course the function name isn't really accurate anymore, so we should probably call it killPlayer() =).
At this point you're ready to run your Gradius clone, so let's fire it up! Notice anything? Everything except you is invisible! The explosions should convince you that something's going on,
Using the Tilemap
Now that we can die properly, we just need to adjust the game so that everything else appears properly on the map, starting with the bullets we fire. You may remember that we used to make a sprite visible by adding it to the game area. With a tilemap, which DAME so kindly creates for us, we need to tweak that a bit.
Behind the scenes, Flixel is adding the tilemap above the main play area, and so when we add a bullet or alien it's actually beneath the tilemap. The solution is to add all the actors to the tilemap, then use a callback to add them to their group in PlayState.
More Snippets | |
Flixel | |
FlashPunk |
PlayState.as Spawning Code:
private function spawnAlien():void { var x: Number = FlxG.width; var y: Number = Math.random() * (FlxG.height - 100) + 50; level1.addSpriteToLayer(Alien, level1.Group1Layer2Group, x, y, 0, false, onSpriteAddedCallback) } private function spawnBullet(pos: FlxPoint, velocity: FlxPoint = null):void { level1.addSpriteToLayer(Bullet, level1.Group1Layer2Group, pos.x, pos.y, 0, false, onSpriteAddedCallback) FlxG.play(SoundBullet); } // ADDED FOR DAME INTEGRATION protected function onSpriteAddedCallback(sprite:FlxSprite, group:FlxGroup):void { if (sprite is Player) _ship = sprite as player; if (sprite is Alien) _aliens.add(sprite); if (sprite is Bullet) _bullets.add(sprite); }
onSpriteAddedCallback is a function we pass to BaseLevel.addSpriteToLayer. When we make the call to add a sprite, the Level class actually creates a new instance of the class we specify, adds it to the map display layer, and then
Extra Credit: Return Fire!
You may have noticed that spawnBullet has an optional second parameter, velocity. It's not used in this tutorial, but if you're feeling creative you could use it to allow certain bullets to fire in different directions, like the Missile powerup in Gradius. Just edit the addSpriteToLayer function to take velocity as a parameter, calculate rotation from the vector specified, and then set the velocity of the newly created bullet and you'll be in business!