Block Breaker is a game I’m currently developing. It’s a simple game where you have to use a paddle to bounce a ball into bricks to destroy them. The game was working and had only 1 feature which was to hit a brick with a ball and collect the brick with the paddle. I wanted to add some more features to the game so I implemented a power up system where a brick would have a chance to release a power up when it is first hit.
The first thing to do was define the power up types for Block Breaker. I went with these:
- Magnetism (allows user to pull/push bricks)
- Magnet power (increase the force applied by the magnetism)
- Laser beams ( one from each side of the paddle)
- Bombs (a bomb released from paddle)
- Extra Ball ( an extra ball )
- Magnetic ball ( can be attracted/rejected by magnetism)
- Ball Laser guides ( Current balls get a directional laser showing direction )
- Extra Score ( increase score )
Once all the power ups were defined I created a Power Up class which contained all types of power ups types and powerup data such as the box2d body.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
package com.dfour.blockbreaker.entity; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.physics.box2d.Body; public class PowerUp { public static final int MAG_POWER = 0; public static final int MAG_STRENGTH = 1; public static final int BALL = 2; public static final int LAZER = 3; public static final int MAG_BALL = 4; public static final int SCORE = 5; public static final int GUIDE_LAZER = 6; public static final int BOMB = 7; public Body body; public boolean isDead = false; public boolean wasEatenByPad = false; public Color color; public Sprite sprite; public int type = 0; public PowerUp(Body bod, TextureRegion tex, int type){ this.type = type; sprite = new Sprite(tex); body = bod; sprite.setOriginCenter(); sprite.setScale(0.5f); update(); } public void update(){ sprite.setPosition((body.getPosition().x*10) - 16f, (body.getPosition().y*10) - 16f); sprite.setRotation(body.getAngle() * 57.2958f); } } |
With the power ups defined I wanted them to have a chance at getting created when the bricks were hit so I added a method call to the game model where the bricks change from static( bricks not hit yet ) bricks to dynamic (bricks that have been hit).
The code below gives the Power Ups a 20% Chance of being created.
1 2 3 4 5 6 7 8 |
if (brick.isStatic == true && brick.wasHit) { brick.body.setType(BodyType.DynamicBody); brick.isStatic = false; int rup = (int) (Math.random() * 100); if (rup > 80) { entFactory.createNewPowerUp(brick.body.getPosition()); } } |
The code above calls this method below to create a new body for the Power up and then randomly sets which type of power up it is and assigns the matching texture.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public PowerUp createNewPowerUp(Vector2 position) { Body pupBody = bodyFactory.makeCirclePolyBody(position.x, position.y, 1f, BodyFactory.RUBBER, BodyType.DynamicBody); TextureRegion tex; int type = (int) (Math.random() * 8); if (type == PowerUp.MAG_POWER) { tex = atlas.findRegion("mag_power_pup"); } else if (type == PowerUp.MAG_STRENGTH) { tex = atlas.findRegion("mag_strength_pup"); } else if (type == PowerUp.BALL) { tex = atlas.findRegion("extra_ball_pup"); } else if (type == PowerUp.MAG_BALL) { tex = atlas.findRegion("extra_mag_ball_pup"); } else if (type == PowerUp.LAZER) { tex = atlas.findRegion("lazer_pup"); } else if (type == PowerUp.SCORE) { tex = atlas.findRegion("score_pup"); } else if (type == PowerUp.GUIDE_LAZER) { tex = atlas.findRegion("ball_lazer_pup"); } else if (type == PowerUp.BOMB) { tex = atlas.findRegion("bomb_pup"); } else { tex = null; } PowerUp pup = new PowerUp(pupBody, tex, type); pup.body.setUserData(pup); pups.add(pup); return pup; } |
Now Power Ups are given a chance to spawn and appear on the screen. The next thing I needed to do was allow the paddle to pick up the Power ups. In order to do this I added some conditions in the contact listener which then told the model to gave the player the power up. The code below is from the contact listener.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
private void padHit(Pad userData, Fixture fix) { if(fix.getBody().getUserData() instanceof Ball){ if(debug) System.out.println("TODO play sound"); }else if(fix.getBody().getUserData() instanceof Brick){ Brick brick = (Brick) fix.getBody().getUserData(); parent.explosions.add(brick.body.getPosition()); brick.wasEatenByPad = true; brick.isDead = true; }else if(fix.getBody().getUserData() instanceof PowerUp){ if(debug) System.out.println("pup hit"); PowerUp pup = (PowerUp) fix.getBody().getUserData(); switch(pup.type){ case PowerUp.MAG_POWER: parent.getMagPowerUp(); break; case PowerUp.BALL: parent.getExtraBall(false); break; case PowerUp.MAG_STRENGTH: parent.getMagStrengthPowerUP(); break; case PowerUp.LAZER: parent.getLazerPowerUp(); break; case PowerUp.MAG_BALL: parent.getExtraBall(true); break; case PowerUp.SCORE: parent.score+= 10; break; case PowerUp.GUIDE_LAZER: parent.addGuidLazer(); break; case PowerUp.BOMB: parent.addBombPowerUp(); break; } pup.isDead = true; } } |
Now everything is in place for me to add the individual power ups. For each of the power ups I added a flag to signify which power up was needed. Then each update tick I would check the flags and add the power ups and reset the flags.
Block Breaker is now able to dish out power ups to players. The next step would be to implement the individual power up abilities however that’s for another time. If you want to try Block Breaker you can download it from here.