Today I will share some things I’ve learned over the last year about making action games. They will be both practical programming tips and some theoretical game design ideas. Most of these things I’ve learned and/or stolen from other indies and a few I’ve taken from personal experience. I hope you will learn something useful you can apply the next time you’re making a prototype or participating in Ludum Dare!
Have a tweening engine ready
There’s one library I always use in my games nowadays, and it’s TweenMax. You don’t have to use this particular one, but I highly recommend using a tweening engine. TweenMax has been working great for me: it’s easy to set up, it has an onComplete-implementation that makes it fairly easy to string different tweens together, and it has a big library of different easing options. Use this for all the beautiful squashing, stretching, tweening and fading you’ll be doing.
Make easily reusable function calls for your effects
Every time I make a new effect nowadays I just make it available as a global function that any object has access to. They look something like this:
The function manyBigHitEffects() is accessible globally by any game object, and it acts on the object being sent as the parameter. The function takes the object, calculates its center point, and spawns the effect on top of it. This is a extremely simple implementation, and at times you would rather have a function that takes x- and y-coordinates instead, but in most cases this is just as good, and simpler to read.
Example of the feedback given by an asteroid reaching zero health:
Simple to code, and simple to read.
Whenever something happens in your game, show it!
If you find yourself writing code that involves the player or player objects, show the player what’s happening! If the player presses a button and a bullet is shot, have a muzzle flare and sound effect, if she hits an enemy with a projectile have the enemy light up and play a sound effect, if the player is in mid-air and then lands on a platform squash the player sprite a bit to show the force of impact etc.
All of these interactions will be better communicated if you add some “juice” to them, and with your newly created globally available functions, adding a squash effect to the player sprite is as easy as this:
Always have a sound effect
Go download sfxr right now, and whenever you need a sound effect in the game, make a placeholder and stick it in your game. Even if it’s not a 100% right it will be a lot better than no sound at all, and you’ll have an easy time replacing it later when you have something more fitting. Sound effects are by far the feedback that makes the biggest difference compared to the time invested in implementing them, so make some sounds and throw them in there!
Have all the actions be meaningful
Sid Meier has been attributed as saying that a game is a series of meaningful choices. In short this means that no choices should be obviously better than others and you should be able to anticipate what will happen to a certain extent so that you don’t end up choosing arbitrarily. This is especially true for strategy games, but it’s true for all action games on a very micro level.
In this game I chose to penalize the player pretty harshly for holding down the shooting button. Their movement speed is much lower, and you have a pretty harsh recoil, pushing your ship back towards the bottom of the screen. This forces the player to stop shooting when repositioning himself quickly, both if he’s too far from his target to hit it with projectiles, and also if he needs to dodge incoming projectiles quickly.
This adds another level of strategy to the game, and makes it a little bit less like a mindless schmup.
Another example is the fact that when the player’s projectiles hit an asteroid, the projectile adds a little force to the asteroid in the opposite direction, slowing it down a bit. This extra layer of interaction makes the player feel like his actions matter, like he has some influence over the seemingly unstoppable objects floating towards him.
Shake the screen!
Jan Willem from Vlambeer says this better than anyone, but this bears repeating. Screenshake adds a LOT to an action game, the feeling of impact is enhanced and it just feels powerful and cool! Do it! Then when you think you’re doing it enough, do it some more. You’re not done until some people feel nauseous while playing.
White hit frames
If your game involves shooting things, just take the sprite of the object that’s being hit, color it white, and flash it for a tenth of a second whenever it’s hit by a projectile. NES games were doing this 30 years ago, and it’s just as effective today! There is nothing as satisfying as seeing your enemies light up with a white flash accompanied by a punchy sound effect, except for seeing them explode in a myriad of effects and tiny particles of course!
Particularly useful effects and functions
Squash and stretch - Having functions available that can do a cool squash or stretch animation on a sprite or object can be super handy. I usually send in a power parameter and a duration in my own functions, and I like using elastic easing for these kind of effects. They are great for buttons and other HUD elements, but can also be super handy for in-game objects. Adding some squash and stretch to the character sprite during a jumping or landing animation adds a lot of juice with very little effort.
Particle effects - Being able to send in coordinates or simply an object and say “do this particle effect here” is incredibly powerful, and should not be used sparingly!
Fade - Just pass an object and a duration to this function, and it will fade out the object’s sprite until it turns invisible. Optional: add a boolean parameter called “kill” which kills the object on completion when set to true.
In closing - It’s all about feedback
Player feedback is the single most important part of making an action game that feels good. One of the mistakes I’ve made in the past is that I put up too big of a mental barrier between what’s the theoretical core gameplay (the rules of the game), and what’s “just graphics” or “polish”. The fact of the matter is that the feedback of your game is a big part of the core experience, even if the rules of the game could just as well be represented by white hitboxes colliding with each other. Don’t neglect this essential part of creating an action-packed experience!
Made some new smoke/dirt effects for Partypillars.
Just sitting here, generating amazing bugs. Don’t code before you have your coffee, kids!
I just wanted to write down my initial experiences porting Partypillars to OUYA using CocoonJS.
Controllers with CocoonJS
My first real problem appeared here when the game was already up and running. None of the buttons on the controller worked. The only response I got was from the analogues (which I had thankfully mapped to the same as the d-pad). After trying some different configs of buttons I started to realize that it wasn’t that the buttons were mapped differently, I was not getting any button presses from any of the controllers whatsoever.
ImpactJS bitmap fonts
@KrisJet probably hw accel issue. Read the .widthMap and .indices from the font on desktop and put it in your code as array literals— Dominic Szablewski (@phoboslab) August 13, 2014
Play the game on itch.io in the browser or download the OUYA compatible .apk from there! OUYA version works well most of the time but is not optimized and I have noticed some crash bugs at times.