- PointSprites :
- Shapes :
XNA Games - PointSprites
The game boomshine, by Danny Miller, is everything a Flash game should be.
It's easy to play, simple at the start, but maddeningly difficult in later rounds.
Plus it looks pretty sweet.
The gameplay is simple... when you click on the playfield, a bubble appears, expands to a set size, then after a pause shrinks away to nothing.
The goal is to hit the other bubbles that float randomly on the playfield with your bubble.
They in turn expand, potentially colliding with other bubbles in a chain reaction.
I spend a good hour trying to finidh level 12 where you need to hit 55 of 60 bubbles.
Pretty bubbles in XNA
Implementing something similar in XNA seemed a good way to play with collision detection algorithms in XNA.
Since we're dealing with circles, we only need to know the position of the center (a Vector2 in XNA) and a radius (a float) for each bubble.
To see if two hit, we need to know the distance between the centers and the radius of each.
If the distance is less than or equil to the length of each radius added together, we hit.
In XNA we can use a built in function, Vector2.distance() to give us the distance between any two Vector2 objects.
We then check to see if that is less or equal to the two radii added togerther.
One thing to note: using this function is pretty expensive (slow) since it uses a square root.
Fortunately, we can use Vector2.DistanceSquared() and just square the sum of our radii.
On a test machine, this took the minimum average frames per second for 750 bubbles from around 15 to just over 40.
While it would make a nice screensaver, anything over 500 bubbles pretty much guarantees hitting them all in a massive chain reaction.
retVal = true;
Design
After making the sprite textures in the Gimp, it was time to design some of the classes. For 2D games (my favorite) I tend to keep the objects that will be rendered in a 'manager' class. This way I can just call someManager.Update(GameTime g) and someManager.Draw(SpriteBatch s) to handle the updates and drawing. The other option is to have a collection of some sort in the game class for the objects. The update and draw methods would then iterate through the collection.
I made a class for the sprites called PointSprite. This holds things like color, position, velocity and state. The bubbles State is an enumeration that determines behavior. (check out Finite state machines on Wikipedia). The states are:
- normal: bubble is moving about at it's normal small size (15x15)
- hit: The bubble has been hit by another bubble. It's velocity goes to zero.
- expanding: It's starting to get bigger! Radius should start to increase until we hit a max radius.
- atMax: It's reached it max size.
- shrinking: It's starting to shrink. Radius should start to decrease until we hit 0.
- inactive: It's radius is zero, stop drawing it onscreen.
The game then applies rules to how the bubbles behave in the various states. These are in the Update method of the PointSprite class.
- All bubbles start as normal EXCEPT the one creater by the player; it starts at expanding.
- As long at a bubble isn't inactive, it needs to get drawn.
- As long as it's not inactive OR normal, it can hit other bubbles that are in the normal state.
- If the player bubble is inactive and all other bubbles are inactive or normal, the level is over.
Another class is responsible for maintaining and drawing the bubbles. This is PointSpriteManager. It keeps a list of the individual sprites, the texture used to draw them and the assorted game parameters. These are things like how many bubbles to draw, how fast do they go, how big are they, etc.
With a class to hold all our sprites, the game loop is pretty simple. When the game starts we fill a dictonary with the level information. The game then goes into a loop based on the gameState. These are:
- Loading. Display 'Loading' for a bit and call PointSpriteManager.InitLevel()
- Playing. Has the player Clicked yet?
- Yes!
Is the level still running?- Yes!
Has the player hit enough bubbles to win the level?- Yes!
Start to change the background color to indicate they rule. - No!
Keep updating the remaining bubbles.
- Yes!
- No!
Did the player win the level?- Yes!
Start loading the next level - No!
Shrink the remaining bubbles and retart the level
- Yes!
- Yes!
- No!
Keep updating all the bubbles.
- Yes!
- clearing. The player lost the level. Shrink the remaining bubbles.
- tryAgain. Reload the level.