Haxeflixel tutorial: buidling your first 2D Shoot ‘em up. Part V

Well well, things are starting to take shape don’t you think?, our “game” is starting to feel and play like one, but before we can say the thing is finished we need to start wrapping and polishing things up. That’s what we are going to start doing on today’s post. Let’s get cracking!

HaxeFlixel logo

HaxeFlixel rocks!


Build a proper stage

Ok, we had fun with our little test level. We used it to test the tile drawing and object placing system, and for this tutorial’s shake our little test level fulfilled its purpose quite well. But now it’s time to build a real playable level, for this we are going to need a proper tileset. This means drawing a small spritesheet made up of tiles that can fit and blend together somewhat nicely and that we can use to build our map objects.

I won’t go into detail about how to draw a proper tileset for tiled maps (stay tuned for future posts 😉 ) but I recommend starting out with a single tile (32×32 pixels in size in our case) and start drawing its main features and lines. If you are going for a rocky template make sure your tile blends together well with itself. This means testing how good or bad does it look to place the same tile one after another in a continuous way. Once you are satisfied with the result you can move on and start making corner, top and bottom tiles, that will be vital if you want to build a basic but interesting level.

Anyway, our tileset for this level is the following:



Basic blue rock tileset

As you can see, it’s pretty basic, but it will allow us to build a complete level without leaving any rough edges.

With this done we can now start building our full level with Tiled. Of course you can build whatever you want (and I encourage you to do that), after all, the main advantage of the tile map system we built for our game is to be able to build lots of levels in a fast way, without having to write a single line of code.

For me, since I love the Gradius series I built a simple homage to that game’s style of levels, this is how it looks on Tiled editor:


Captura de pantalla 2015-02-07 a la(s) 10.51.48

Big objects are blocks, small ones are enemies.

Captura de pantalla 2015-02-07 a la(s) 11.29.34

And this is how it looks during gameplay

For this tutorial we only have one type of enemy with one behavior, but you can always add extra properties and attributes to every object of the enemy layer and make custom enemies that chase you or fly in a zig-zag pattern. As I said, the beauty of this approach resides on it’s customizability.

Ok, now that we have finally have a proper level to play on we are going to wrap up another important aspect of any game:

Sound FX and music

Our game has been mute for too long. It’s about time we change that.

First, we are going to define what sounds do we wan’t to have on our game and then define their local paths inside our project on the Reg.hx file, like so:

If you don’t know how to create sound effect for your game you can always use the fantastic bfxr .

For the music, I got some tunes from the original NES Gradius, ripped and remastered in beautiful stereo by Wiiguy309, thanks man!

Now, to play any sound on HaxeFlixel we just have to call the FlxG method sound.play(), like this:

And for music (even though we can also use sound.play(), we can use playMusic(), which gives us some extra control over its plaback, meaning we can set it up to loop infinitely or to just play once. In my case, since I want to recreate the Gradius experience I’m going to play the level intro at first, and when that is finished I want to start playing the stage music. To do this we need to use a new HaxeFlixel class, FlxTimer!


We add the following at the end of StageState’s create method:

(Note: remember to add import flixel.util.FlxTimer)

Here,  we start playing our music right from the start, but we only play it once, and at the same time we set up a timer that will call our callbackMethod, playMusic2 after 31 seconds.

This is how our callback method looks:

With these two you can play sounds and music everytime you want, so you can play them when the player shoots or an enemy dies. This is kind of neat, but our game is still missing another important part of user feedback that any 2D shooter must have, and that is…



We all love plowing our way through waves of enemies gracing upon our destruction. This usually means having a lot of things blowing up on screen at any given time. Our game is missing that, so we must fix it right away.

Let’s create a new class -conveniently named- Explosion.hx and fill it up with the following:

As you can see it’s pretty basic stuff. Our only difference is that new variable called ttl, which as you probably have guessed by now means time to live. This is basically a timer that will be substracted from on everyframe (check the update method) and that when it runs below 0 will destroy our explosion. Neat.

Also, we made a simple but useful spritesheet for our explosion:


Notice also how our explosion already plays its own boom sound using the code we introduced before.

Now, anytime we wan’t to destroy something we just do what we must (remove an enemy from the scene, for instance) and the we can just create an explosion at that same position, setting it up with a ttl value that will indicate how long will it last.

For example, inside the StageState’s overlapped method, when we are checking for enemy deaths:

Piece of cake.


Now, you can test run your game and enjoy your full level with lots of enemies, blocks and awesome sounding effects and explosions, isn’t it nice?, yes it is. But there is something missing don’t you think?, having one type of enemy is not that bad for a small game like this but we need something bigger to end the stage the way it is supposed to be.

Something big, dangerous and menacing…

You guessed it, we need a FINAL BOSS.

And that’s precisely what we are going to build on the next part of our tutorial, stay tuned!

Thanks for reading!

This is part 5 out of 6 of a tutorial series, you can check out the rest here:


Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.