Unity/Futile Pong Example (Part 8) – Adding powerups and introducing animated sprites

By the end of this tutorial, you should have something that looks like this. You can download the Assets folder for this tutorial here.

UPDATE: I went back and updated the ball-and-wall collision code in Part 6 of the tutorial series, which is reflected in this webplayer demo and assets file. There was an issue where rapid collisions could occur when the ball struck the wall, because I’m an idiot.

By the end of the last tutorial, we had essentially completed a remake of the game Pong. I would like to wrap things up by adding something that the original Pong did not have, which is powerups.

To keep it as simple as possible, it will be an object placed on the screen that will activate when the ball collides with it. In this case, it will increase the velocity of the ball. I would also like to use this as an opportunity to introduce a method of sprite animation. Futile is a rendering framework first above all else, and author MattRix has made it a point to stress that the application of the rendering is pretty much on the shoulders of developers. For this purpose, there is no animated sprite class. Instead, we’ll create our own. You can download a zip archive of my assets folder so that you do not have to recreate your own.

Actually, we’re going to work with the animated sprite example that MattRix provides in his Banana Game demo. First, create a new C# source file and name it PDPowerup.cs. Replace the contents of that file with the following code.

using UnityEngine;
using System.Collections;

public class PDPowerup : FSprite
{
	static int numFrames = 11; // Number of frames in our animation
	
	private int _frameCount = 0;
	private int _frameIndex = 0;
	private FAtlasElement[] _frameElements;
	
	public PDPowerup () : base("powerup_v_0")
	{
		_frameElements = new FAtlasElement[numFrames];
		
		// Add all of the sprites to our array
		FAtlasManager am = Futile.atlasManager;
		_frameElements[0] = am.GetElementWithName("powerup_v_0");
		_frameElements[1] = am.GetElementWithName("powerup_v_1");
		_frameElements[2] = am.GetElementWithName("powerup_v_2");
		_frameElements[3] = am.GetElementWithName("powerup_v_3");
		_frameElements[4] = am.GetElementWithName("powerup_v_4");	
		_frameElements[5] = am.GetElementWithName("powerup_v_5");	
		_frameElements[6] = am.GetElementWithName("powerup_v_6");	
		_frameElements[7] = am.GetElementWithName("powerup_v_7");	
		_frameElements[8] = am.GetElementWithName("powerup_v_8");	
		_frameElements[9] = am.GetElementWithName("powerup_v_9");	
		_frameElements[10] = am.GetElementWithName("powerup_v_10");	
	}
	
	override public void Redraw(bool shouldForceDirty, bool shouldUpdateDepth)
	{
		if(_frameCount % 5 == 0) //update every 5 frames
		{
			_frameIndex = (_frameIndex+1)%numFrames; //increment the frame but keep it wrapping
			this.element = _frameElements[_frameIndex];
		}
		
		_frameCount++;
		base.Redraw(shouldForceDirty, shouldUpdateDepth);
	}
}

Just like we did with PDPaddle and PDBall, we extend the FSprite class and use the base keyword to pass the sprite’s file name without the extension as a parameter to the superconstructor. In this case, since the rendered sprite will change depending on the spot in the animation loop, the only reason to use the base keyword here is to satisfy the parameter requirements of FSprite.

We create an array of FAtlasElements, which will store each frame of the animated sprite. An FAtlasElement is a Futile class which is used to store information about each sprite in the atlas. Every FSprite has a .element property, which references an FAtlasElement.

In order to actually animate the sprite, we override the Redraw method of FSprite. This method is called every frame, so it is a perfectly reasonable place to hook into. I chose to advance the animation once every 5 frames, which seems okay on the computer I am using. You can also utilize Time.deltaTime here if you do not want your animation to advance based upon the current framerate. Finally, we call the Redraw method so that our FSprite can continue to render properly.

At this point, you could create a new PDPowerup instance and add it to the stage, but since we need to do more than just display the animation, we have to do a bit more work.

I haven’t said anything about this yet, but please be aware that I’m being overzealous with my use of the public access modifier when making declarations, but proper form would be to utilize private declarations in almost all of these cases.

Let’s create a reference to our PDPowerup object by adding the following code to our PDGame class.

	public PDPowerup powerup;

At the bottom of the PDGame constructor, add the following code to instantiate, position, and render the powerup.

		// Position and render the powerup
		powerup = new PDPowerup();
		ResetPowerup();
		Futile.stage.AddChild(powerup);
    }

Now create the ResetPowerup() function we just referenced above.

	public void ResetPowerup() {
		powerup.x = Futile.screen.halfWidth/2 - (Futile.screen.halfWidth * RXRandom.Float());
		powerup.y = (Futile.screen.halfHeight - powerup.height/2) - ((Futile.screen.height - powerup.height) * RXRandom.Float());
	}

Next, let’s add collision detection by adding the following conditional statement under our paddle-and-ball collision check in the Update loop of PDGame.

			// Check for ball-and-powerup collisions
			Rect powerupRect = powerup.localRect.CloneAndOffset(powerup.x, powerup.y);
			if (ballRect.CheckIntersect(powerupRect)) {
				ResetPowerup();
				ball.currentVelocity+= 50.0f;
			}

The powerup will respawn in a new location and the ball’s velocity will increase by 50 points per second whenever a collision is made. Execute the code and you should now see the powerup in action.

In retrospect, I should have made the powerup larger to make it easier to hit. You can easily do this without recreating the textures by playing around with the scale of the powerup.

I’ll be completely wrapping up the Pong tutorial series in Futile with my next post. It won’t introduce any new Futile classes/functions, but it will add a bit more polish to the game. I will add a ball trail, as well as a delay every time the ball spawns.

Take me to the next tutorial!

By the end of the tutorial you just read, you should have something that looks like this. You can download the Assets folder for this tutorial here.

About these ads

3 thoughts on “Unity/Futile Pong Example (Part 8) – Adding powerups and introducing animated sprites

  1. Pingback: Unity/Futile Pong Example (Part 7) – Scoring conditions and the user interface | Game Development

  2. I peeked ahead and noticed you had a bunch more frames in the power up animation from tutorial 9. I grabbed those assets and found that initializing the frame elements was quite a bit cleaner with a little for loop.

    for (int i = 0; i < numFrames; i++){
    str = string.Format("powerup_v_{0}", i);
    _frameElements[i] = am.GetElementWithName(str);
    }

    • Yep, much cleaner to to do it with a for loop. It was laziness on my part. I was getting to the end of the series and was itching to get back to working on my game.

      Thanks for taking the time to go through the entire series. Hopefully you got at least something out of it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s