Skip to main content

Hold The Line

Now that I have an animation system, why don't I use it to try and implement a new enemy type with minimal code? I'm going to implement an XY Zapper enemy. This is an enemy that periodically spams out a horizontal or vertical laser beam that instantly fries everything in it's path. The Zapper tracks the player's position and homes in on it, which makes it hard for the player to sit still in one place on the screen. This is good as it helps to stop the player from being lazy, sitting still and exploiting holes in the bullet patterns.


Looks

The Zapper has two states: moving and firing. Moving is just a repeated animation of four steps:
The length of this animation (it's 230 frame, or just under four seconds long) determines the length of the move state for the zapper - I'll talk about what that means in a minute...

The firing animation is a little more interesting. It includes a short "charge up" phase to telegraph to the player that the Zapper is about to fire and a "charge down" phase afterwards. The beam is only actually fatal when it is bright red:

The collision for the firing phase is also animated, like this:
The nice thing here is that only one step of the animation actually has any collision map attached to it. This means that I can rely on the animation system to turn the collision on and off at the right time, without having to do anything extra in code.

Brains

Remember that the Zapper has two states: moving and firing.

In the moving state the algorithm for the Zapper's movement is pretty simple. The Zapper has a heading (the direction of travel) and a velocity. On each update, I change the heading and the velocity and then move the Zapper's position at velocity speed in heading direction. To get the new heading, I take the current heading and I move it slightly towards the direction to the player. This means that the Zapper is always turning to face the player. The velocity at which the Zapper moves is based on its the distance from the player - when the Zapper is very close to the player it moves slowly, and when it is farther away it moves faster. As with heading, the target velocity is calculated each update, and the current velocity is nudged slightly towards it.

In the firing state, the logic is even simpler - the Zapper just continues moving in the same direction (ie: it doesn't turn) and it slows to a halt.

The lengths of the states are controlled by the lengths of animations. When the moving animation ends, it automatically goes into the firing animation, and when that ends it goes back to the moving animation. The Zapper's update() function figures out which animation is currently active and does the appropriate type of update logic

The code for all of this behaviour is in the update() function for the Zapper object. Here's a version that's slightly simplified for readability:

Note that I only talked about the X Zapper here - the Y Zapper has exactly the same logic but the graphics are in a vertical orientation.

Wrapping Up

I added a new enemy type to the game. I used the animation system that I added in the last update to drive the states of the enemy, which made it easy to implement the control logic.

I also added and changed a few other small part of the code, and you can check out the whole code online. The playable version is also available online.

Next Time

The game currently feels a little aimless - sure, you can try to get a high score but when you have unlimited time it's no big challenge. One thing that I want to implement to make high score chasing more of a challenge is to put a time limit on the levels, so that's what I'll work on next.

I also want to be heading towards adding a level editor so that you can design your own levels. Soon I will start heading towards making that happen.

Comments

Popular posts from this blog

Set The Controls For The Heart Of The Sun

When we last met, I had just started work on a level editor. I'd got as far as adding the ability to select an object and move it around, and then I added an undo/redo system using the command pattern. That was a good start, but dragging items around the level is only fun for so long. What I really want to be doing is.. ..editing the properties of the bullet spawners! And I want to be doing this in realtime as the game plays so that I can immediately see what effect my changes have made to the gameplay of the level.

World In Motion

In the last post I touched on how easy it is to score in this game - you can just camp out on the score bullet spawner and watch the points rack up. I'm going to add a little delay to the score bullets so that they start out in a deactivated and uncollectable state, and then change to active and collectable after a short time - say, half a second. To make it clear what state they are in I'm going to add code to let me change the look of Objects and allow them to be animated.

Give Me Just A Little More Time

In this post I want to make the game time limited. By doing this, I make it more of a challenge to beat the high score. I'm going to set the time limit for a level to 30 seconds - I think that's a good amount. Also, I don't want to just dump the player straight into the action unprepared, so and I'm going to add a couple of bits of  "ceremony" before and after the gameplay to make it a nicer experience. There are a few main things that need to be added to make this happen: Add "sub" states to the Game state: intro, game and outro Intro state needs to show a countdown Game state will run the game as normal, but with a visible "timer bar" to show how long is left Outro state will show a summary of the game - score, high score, etc. Let's start with defining these states: