From 7588a0986bbf8263fe0a25c42e30c7975f55fa33 Mon Sep 17 00:00:00 2001 From: Matt Low Date: Tue, 13 Nov 2018 11:51:00 +0400 Subject: [PATCH] Refactored to use states Various other refactoring, no functional differences --- core/src/com/me/brickbuster/BrickBuster.java | 191 +----------------- core/src/com/me/brickbuster/Utils.java | 3 + core/src/com/me/brickbuster/entity/Ball.java | 47 ++--- core/src/com/me/brickbuster/entity/Brick.java | 17 +- .../src/com/me/brickbuster/entity/Entity.java | 14 +- .../src/com/me/brickbuster/entity/Paddle.java | 19 +- .../entity/powerup/GluePowerUp.java | 8 +- .../entity/powerup/LongerPaddlePowerUp.java | 12 +- .../entity/powerup/MultiBallPowerUp.java | 10 +- .../brickbuster/entity/powerup/PowerUp.java | 8 +- .../entity/powerup/ShieldPowerUp.java | 8 +- .../com/me/brickbuster/state/PlayState.java | 169 ++++++++++++++++ core/src/com/me/brickbuster/state/State.java | 27 +++ 13 files changed, 279 insertions(+), 254 deletions(-) create mode 100644 core/src/com/me/brickbuster/state/PlayState.java create mode 100644 core/src/com/me/brickbuster/state/State.java diff --git a/core/src/com/me/brickbuster/BrickBuster.java b/core/src/com/me/brickbuster/BrickBuster.java index 9fb6196..c271a62 100644 --- a/core/src/com/me/brickbuster/BrickBuster.java +++ b/core/src/com/me/brickbuster/BrickBuster.java @@ -1,207 +1,38 @@ package com.me.brickbuster; -import com.badlogic.gdx.ApplicationAdapter; +import com.badlogic.gdx.Game; import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; -import com.badlogic.gdx.math.MathUtils; -import com.badlogic.gdx.math.Vector2; -import com.me.brickbuster.entity.*; -import com.me.brickbuster.entity.powerup.*; +import com.me.brickbuster.state.PlayState; -import java.util.*; - -public class BrickBuster extends ApplicationAdapter { +public class BrickBuster extends Game { public static final int WIDTH = 800; public static final int HEIGHT = 600; public static final String TITLE = "Brick Buster"; - public static final Vector2 HORIZONTAL_EDGE = new Vector2(1, 0); - public static final Vector2 VERTICAL_EDGE = new Vector2(0, 1); - - public static final int SHIELD_HEIGHT = 5; - public static final float POWERUP_CHANCE = 0.15f; - - private static final Map, Integer> powerUpWeights; - private static final int weightSum; - - private BitmapFont font; - private SpriteBatch batch; - private ShapeRenderer sr; - - private Paddle paddle; - private ArrayList balls; - private ArrayList bricks; - private ArrayList powerUps; - - private int shieldCount = 0; + public BitmapFont font; + public SpriteBatch sb; + public ShapeRenderer sr; @Override public void create () { font = new BitmapFont(); - batch = new SpriteBatch(); + sb = new SpriteBatch(); sr = new ShapeRenderer(); - paddle = new Paddle(this); - - powerUps = new ArrayList(); - - bricks = new ArrayList(); - for (int col = 0; col < 13; col++) { - for (int row = 0; row < 7; row++) { - int x = 15 + (col * (Brick.BLOCK_WIDTH + 10)); - int y = 15 + Brick.BLOCK_HEIGHT + (row * (Brick.BLOCK_HEIGHT + 10)); - Class powerUpType = null; - if (MathUtils.randomBoolean(POWERUP_CHANCE)) { - powerUpType = getWeightedPowerUp(); - } - bricks.add(new Brick(this, powerUpType, x, HEIGHT - y)); - } - } - - balls = new ArrayList(); - balls.add(new Ball(this)); + setScreen(new PlayState(this)); } @Override public void render () { Gdx.gl.glClearColor(0.5f,1,1,1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); - - - long start_update = System.nanoTime(); - update(Gdx.graphics.getDeltaTime()); - long finish_update = System.nanoTime() - start_update; - - long start_render = System.nanoTime(); - for (Brick block : bricks) { - block.render(sr); - } - for (PowerUp powerUp : powerUps) { - powerUp.render(sr); - } - for (Ball ball : balls) { - ball.render(sr); - } - paddle.render(sr); - - if (getShieldCount() > 0) { - sr.begin(ShapeRenderer.ShapeType.Filled); - sr.setColor(Color.SALMON); - sr.rect(0, 0, WIDTH, getShieldCount() * SHIELD_HEIGHT); - sr.end(); - } - - long finish_render = System.nanoTime() - start_render; - - batch.begin(); - //batch.setColor(Color.BLACK); - font.draw(batch, String.format("FPS: %d Update: %.2f ms Render: %.2f ms", - Gdx.graphics.getFramesPerSecond(), finish_update/1000000f, finish_render/1000000f), 0, 13); - batch.end(); + // Render the current Screen (State) + super.render(); } - public void update(float dt) { - for (Iterator it = balls.iterator(); it.hasNext();) { - Ball ball = it.next(); - ball.update(dt); - if (ball.isDead()) { - it.remove(); - } - } - - if (balls.isEmpty()) { - reset(); - } - - paddle.update(dt); - - for (Iterator it = powerUps.iterator(); it.hasNext();) { - PowerUp powerUp = it.next(); - powerUp.update(dt); - if(powerUp.isCaught()) { - it.remove(); - } - } - - if (getBricks().isEmpty()) { - create(); - } - } - - public void reset() { - Paddle paddle = getPaddle(); - Ball ball = new Ball(this); - ball.setX(paddle.getX()); - ball.setY(Paddle.PADDLE_Y + Paddle.PADDLE_HEIGHT + Ball.RADIUS); - balls.add(ball); - paddle.setSticky(false); - paddle.setWidth(Paddle.DEFAULT_WIDTH); - } - - @Override - public void dispose () { - } - - private static final Class getWeightedPowerUp() { - int remaining = MathUtils.random(weightSum); - for (Map.Entry, Integer> entry : powerUpWeights.entrySet()) { - remaining -= entry.getValue(); - if (remaining < 0) { - return entry.getKey(); - } - } - return null; - } - - public int getShieldCount() { - return shieldCount; - } - - public void addShield() { - shieldCount++; - paddle.setY(paddle.getY() + SHIELD_HEIGHT); - } - - public void removeShield() { - shieldCount--; - paddle.setY(paddle.getY() - SHIELD_HEIGHT); - } - - public ArrayList getBalls() { - return balls; - } - - public Paddle getPaddle() { - return paddle; - } - - public ArrayList getBricks() { - return bricks; - } - - public void addPowerUp(PowerUp powerUp) { - this.powerUps.add(powerUp); - } - - static { - Map, Integer> tmp = new HashMap, Integer>(); - - // Assign PowerUp weights here - tmp.put(GluePowerUp.class, 30); - tmp.put(LongerPaddlePowerUp.class, 40); - tmp.put(MultiBallPowerUp.class, 20); - tmp.put(ShieldPowerUp.class, 40); - powerUpWeights = Collections.unmodifiableMap(tmp); - - int sum = 0; - for (int x : powerUpWeights.values()) { - sum += x; - } - weightSum = sum; - } -} \ No newline at end of file +} diff --git a/core/src/com/me/brickbuster/Utils.java b/core/src/com/me/brickbuster/Utils.java index 1eab09a..671a9a6 100644 --- a/core/src/com/me/brickbuster/Utils.java +++ b/core/src/com/me/brickbuster/Utils.java @@ -5,6 +5,9 @@ import com.badlogic.gdx.math.Vector2; public class Utils { + public static final Vector2 HORIZONTAL_EDGE = new Vector2(1, 0); + public static final Vector2 VERTICAL_EDGE = new Vector2(0, 1); + public static Vector2 reflect(Vector2 incoming, Vector2 surface) { Vector2 normal = new Vector2(-surface.y, surface.x); return incoming.sub(normal.scl(normal.dot(incoming) * 2)); diff --git a/core/src/com/me/brickbuster/entity/Ball.java b/core/src/com/me/brickbuster/entity/Ball.java index 2f0449f..74ce2a6 100644 --- a/core/src/com/me/brickbuster/entity/Ball.java +++ b/core/src/com/me/brickbuster/entity/Ball.java @@ -8,6 +8,7 @@ import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import com.me.brickbuster.BrickBuster; import com.me.brickbuster.Utils; +import com.me.brickbuster.state.PlayState; import net.dermetfan.utils.Pair; import java.util.Iterator; @@ -25,16 +26,16 @@ public class Ball extends Entity { private boolean isStuck = true; private boolean isDead = false; - public Ball(BrickBuster brickBuster) { - super(brickBuster,BrickBuster.WIDTH/2, brickBuster.getPaddle().getY() + Paddle.PADDLE_HEIGHT + RADIUS); - this.speed = getBrickBuster().getBricks().size() > BLOCKS_FOR_BOOST? DEFAULT_SPEED : BOOST_SPEED; + public Ball(PlayState state) { + super(state,BrickBuster.WIDTH/2, state.paddle.getY() + Paddle.PADDLE_HEIGHT + RADIUS); + this.speed = state.bricks.size() > BLOCKS_FOR_BOOST? DEFAULT_SPEED : BOOST_SPEED; } @Override public void render(ShapeRenderer sr) { sr.begin(ShapeType.Filled); sr.setColor(BALL_COLOR); - sr.circle(getPos().x, getPos().y, RADIUS); + sr.circle(pos.x, pos.y, RADIUS); sr.end(); } @@ -48,12 +49,10 @@ public class Ball extends Entity { } } - BrickBuster game = getBrickBuster(); - - Vector2 new_pos = getPos().cpy().add(direction.cpy().scl(speed * dt)); + Vector2 new_pos = pos.cpy().add(direction.cpy().scl(speed * dt)); boolean brickCollision = false; - Iterator brickIterator = game.getBricks().iterator(); + Iterator brickIterator = state.bricks.iterator(); while (!brickCollision && brickIterator.hasNext()) { Brick brick = brickIterator.next(); Vector2[] vertices = brick.getVertices(); @@ -75,41 +74,40 @@ public class Ball extends Entity { } if (new_pos.x + RADIUS > BrickBuster.WIDTH || new_pos.x - RADIUS < 0) { - Utils.reflect(direction, BrickBuster.VERTICAL_EDGE); + Utils.reflect(direction, Utils.VERTICAL_EDGE); } else if (new_pos.y + RADIUS > BrickBuster.HEIGHT) { - Utils.reflect(direction, BrickBuster.HORIZONTAL_EDGE); - } else if (game.getShieldCount() > 0 - && new_pos.y - RADIUS < BrickBuster.SHIELD_HEIGHT * game.getShieldCount()) { - Utils.reflect(direction, BrickBuster.HORIZONTAL_EDGE); - game.removeShield(); + Utils.reflect(direction, Utils.HORIZONTAL_EDGE); + } else if (state.getShieldCount() > 0 + && new_pos.y - RADIUS < PlayState.SHIELD_HEIGHT * state.getShieldCount()) { + Utils.reflect(direction, Utils.HORIZONTAL_EDGE); + state.removeShield(); } else if (new_pos.y + RADIUS < 0) { isDead = true; return; - } else if (direction.y < 0 && new_pos.y <= game.getPaddle().getY() + Paddle.PADDLE_HEIGHT + RADIUS) { - Pair paddle = game.getPaddle().getTopEdge(); + } else if (direction.y < 0 && new_pos.y <= state.paddle.getY() + Paddle.PADDLE_HEIGHT + RADIUS) { + Pair paddle = state.paddle.getTopEdge(); Vector2 lineDir = paddle.getValue().sub(paddle.getKey()); Vector2 nearest = Utils.nearestPoint(paddle.getKey().cpy(), lineDir, new_pos.cpy()); if (nearest.dst(new_pos.x, new_pos.y) <= RADIUS) { paddleCollision(); - if (game.getPaddle().isSticky()) { + if (state.paddle.isSticky()) { return; } } } - getPos().add(direction.cpy().scl(speed * dt)); + pos.add(direction.cpy().scl(speed * dt)); } public Vector2 paddleReflectAngle() { - Paddle paddle = getBrickBuster().getPaddle(); - float rel = MathUtils.clamp((getX() - paddle.getX()) + (paddle.getWidth()/2), 5, paddle.getWidth()-5); - float newAngle = MathUtils.PI - (MathUtils.PI * (rel / paddle.getWidth())); + float rel = MathUtils.clamp((pos.x - state.paddle.getX()) + (state.paddle.getWidth()/2), 5, state.paddle.getWidth()-5); + float newAngle = MathUtils.PI - (MathUtils.PI * (rel / state.paddle.getWidth())); return new Vector2(MathUtils.cos(newAngle), MathUtils.sin(newAngle)); } public void launch() { - if (getBrickBuster().getPaddle().isSticky()) { + if (state.paddle.isSticky()) { direction = paddleReflectAngle(); } else { // launch at random angle between 135 and 45 degrees @@ -120,10 +118,9 @@ public class Ball extends Entity { } public void paddleCollision() { - Paddle paddle = getBrickBuster().getPaddle(); - if (paddle.isSticky()) { + if (state.paddle.isSticky()) { isStuck = true; - setY(paddle.getY() + Paddle.PADDLE_HEIGHT + RADIUS); + pos.y = state.paddle.getY() + Paddle.PADDLE_HEIGHT + RADIUS; return; } direction = paddleReflectAngle(); diff --git a/core/src/com/me/brickbuster/entity/Brick.java b/core/src/com/me/brickbuster/entity/Brick.java index d957cd5..53ed380 100644 --- a/core/src/com/me/brickbuster/entity/Brick.java +++ b/core/src/com/me/brickbuster/entity/Brick.java @@ -4,10 +4,11 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; import com.badlogic.gdx.math.Vector2; -import com.me.brickbuster.BrickBuster; import com.me.brickbuster.entity.powerup.PowerUp; +import com.me.brickbuster.state.PlayState; public class Brick extends Entity { + public static final Color BLOCK_COLOR = Color.FOREST; public static final int BLOCK_WIDTH = 50; public static final int BLOCK_HEIGHT = 20; @@ -16,8 +17,8 @@ public class Brick extends Entity { private Vector2[] vertices; - public Brick(BrickBuster brickBuster, Class powerUpType, int x, int y) { - super(brickBuster, x, y); + public Brick(PlayState state, Class powerUpType, int x, int y) { + super(state, x, y); this.powerUpType = powerUpType; this.vertices = new Vector2[] { @@ -41,18 +42,18 @@ public class Brick extends Entity { } public boolean hit() { - if (getBrickBuster().getBricks().size()-1 <= Ball.BLOCKS_FOR_BOOST) { - for (Ball ball : getBrickBuster().getBalls()) { + if (state.bricks.size()-1 <= Ball.BLOCKS_FOR_BOOST) { + for (Ball ball : state.balls) { ball.setSpeed(Ball.BOOST_SPEED); } } if (powerUpType != null) { try { - PowerUp powerUp = powerUpType.getConstructor(BrickBuster.class, Brick.class).newInstance(getBrickBuster(), this); - getBrickBuster().addPowerUp(powerUp); + PowerUp powerUp = powerUpType.getConstructor(PlayState.class, Brick.class).newInstance(state, this); + state.powerUps.add(powerUp); } catch(Exception e) { - + System.out.println("Error spawning powerup: " + e.getMessage()); } } return true; diff --git a/core/src/com/me/brickbuster/entity/Entity.java b/core/src/com/me/brickbuster/entity/Entity.java index 208dbc0..2332e19 100644 --- a/core/src/com/me/brickbuster/entity/Entity.java +++ b/core/src/com/me/brickbuster/entity/Entity.java @@ -2,15 +2,15 @@ package com.me.brickbuster.entity; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.math.Vector2; -import com.me.brickbuster.BrickBuster; +import com.me.brickbuster.state.PlayState; public abstract class Entity { - private BrickBuster brickBuster; - private Vector2 pos; + protected PlayState state; + protected Vector2 pos; - public Entity(BrickBuster brickBuster, float x, float y) { - this.brickBuster = brickBuster; + public Entity(PlayState state, float x, float y) { + this.state = state; this.pos = new Vector2(x, y); } @@ -18,10 +18,6 @@ public abstract class Entity { public abstract void update(float dt); - public BrickBuster getBrickBuster() { - return brickBuster; - } - public Vector2 getPos() { return pos; } diff --git a/core/src/com/me/brickbuster/entity/Paddle.java b/core/src/com/me/brickbuster/entity/Paddle.java index a452df9..6a6d3c1 100644 --- a/core/src/com/me/brickbuster/entity/Paddle.java +++ b/core/src/com/me/brickbuster/entity/Paddle.java @@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; import com.badlogic.gdx.math.Vector2; import com.me.brickbuster.BrickBuster; +import com.me.brickbuster.state.PlayState; import net.dermetfan.utils.Pair; public class Paddle extends Entity { @@ -20,7 +21,7 @@ public class Paddle extends Entity { private int width = DEFAULT_WIDTH; private boolean sticky = false; - public Paddle(BrickBuster brickBuster) { + public Paddle(PlayState brickBuster) { super(brickBuster, BrickBuster.WIDTH / 2, PADDLE_Y); } @@ -35,26 +36,26 @@ public class Paddle extends Entity { @Override public void update(float dt) { if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) { - if (getX() - width/2 - PADDLE_SPEED * dt < 0) { + if (pos.x - width/2 - PADDLE_SPEED * dt < 0) { setX(width/2); return; } - setX(getX() - PADDLE_SPEED * dt); + pos.x = pos.x - PADDLE_SPEED * dt; - for (Ball ball : getBrickBuster().getBalls()) { + for (Ball ball : state.balls) { if (ball.isStuck()) { ball.setX(ball.getX() - PADDLE_SPEED * dt); } } } if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) { - if (getX() + width/2 + PADDLE_SPEED * dt > BrickBuster.WIDTH) { + if (pos.x + width/2 + PADDLE_SPEED * dt > BrickBuster.WIDTH) { setX(BrickBuster.WIDTH - width/2); return; } - setX(getX() + PADDLE_SPEED * dt); + pos.x = pos.x + PADDLE_SPEED * dt; - for (Ball ball : getBrickBuster().getBalls()) { + for (Ball ball : state.balls) { if (ball.isStuck()) { ball.setX(ball.getX() + PADDLE_SPEED * dt); } @@ -64,8 +65,8 @@ public class Paddle extends Entity { public Pair getTopEdge() { return new Pair( - new Vector2(getX() - width/2, getY() + PADDLE_HEIGHT), - new Vector2(getX() + width/2, getY() + PADDLE_HEIGHT) + new Vector2(pos.x - width/2, pos.y + PADDLE_HEIGHT), + new Vector2(pos.x + width/2, pos.y + PADDLE_HEIGHT) ); } diff --git a/core/src/com/me/brickbuster/entity/powerup/GluePowerUp.java b/core/src/com/me/brickbuster/entity/powerup/GluePowerUp.java index a61af04..1ed22b2 100644 --- a/core/src/com/me/brickbuster/entity/powerup/GluePowerUp.java +++ b/core/src/com/me/brickbuster/entity/powerup/GluePowerUp.java @@ -1,18 +1,18 @@ package com.me.brickbuster.entity.powerup; import com.badlogic.gdx.graphics.Color; -import com.me.brickbuster.BrickBuster; import com.me.brickbuster.entity.Brick; +import com.me.brickbuster.state.PlayState; public class GluePowerUp extends PowerUp { - public GluePowerUp(BrickBuster brickBuster, Brick brick) { - super(brickBuster, brick, Color.WHITE); + public GluePowerUp(PlayState state, Brick brick) { + super(state, brick, Color.WHITE); } @Override public void activate() { - getBrickBuster().getPaddle().setSticky(true); + state.paddle.setSticky(true); } } diff --git a/core/src/com/me/brickbuster/entity/powerup/LongerPaddlePowerUp.java b/core/src/com/me/brickbuster/entity/powerup/LongerPaddlePowerUp.java index 7b1825e..9463d0f 100644 --- a/core/src/com/me/brickbuster/entity/powerup/LongerPaddlePowerUp.java +++ b/core/src/com/me/brickbuster/entity/powerup/LongerPaddlePowerUp.java @@ -1,20 +1,20 @@ package com.me.brickbuster.entity.powerup; import com.badlogic.gdx.graphics.Color; -import com.me.brickbuster.BrickBuster; import com.me.brickbuster.entity.Brick; import com.me.brickbuster.entity.Paddle; +import com.me.brickbuster.state.PlayState; public class LongerPaddlePowerUp extends PowerUp { - public LongerPaddlePowerUp(BrickBuster brickBuster, Brick brick) { - super(brickBuster, brick, Color.OLIVE); + + public LongerPaddlePowerUp(PlayState state, Brick brick) { + super(state, brick, Color.OLIVE); } @Override public void activate() { - Paddle paddle = getBrickBuster().getPaddle(); - if (paddle.getWidth() < 250) { - paddle.setWidth(paddle.getWidth() + 50); + if (state.paddle.getWidth() < 250) { + state.paddle.setWidth(state.paddle.getWidth() + 50); } } } diff --git a/core/src/com/me/brickbuster/entity/powerup/MultiBallPowerUp.java b/core/src/com/me/brickbuster/entity/powerup/MultiBallPowerUp.java index 4a91caa..85891ae 100644 --- a/core/src/com/me/brickbuster/entity/powerup/MultiBallPowerUp.java +++ b/core/src/com/me/brickbuster/entity/powerup/MultiBallPowerUp.java @@ -3,28 +3,28 @@ package com.me.brickbuster.entity.powerup; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; -import com.me.brickbuster.BrickBuster; import com.me.brickbuster.entity.Ball; import com.me.brickbuster.entity.Brick; +import com.me.brickbuster.state.PlayState; public class MultiBallPowerUp extends PowerUp { private Vector2 pos; - public MultiBallPowerUp(BrickBuster brickBuster, Brick brick) { - super(brickBuster, brick, Color.ROYAL); + public MultiBallPowerUp(PlayState state, Brick brick) { + super(state, brick, Color.ROYAL); this.pos = getPos().cpy(); } @Override public void activate() { for (int x = 0; x < 2; x++) { - Ball ball = new Ball(getBrickBuster()); + Ball ball = new Ball(state); ball.setPos(pos.cpy()); float angle = MathUtils.random(MathUtils.PI*2); ball.setDirection(new Vector2(MathUtils.cos(angle), MathUtils.sin(angle))); ball.setStuck(false); - getBrickBuster().getBalls().add(ball); + state.balls.add(ball); } } } diff --git a/core/src/com/me/brickbuster/entity/powerup/PowerUp.java b/core/src/com/me/brickbuster/entity/powerup/PowerUp.java index 63d43ae..6915b43 100644 --- a/core/src/com/me/brickbuster/entity/powerup/PowerUp.java +++ b/core/src/com/me/brickbuster/entity/powerup/PowerUp.java @@ -4,10 +4,10 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; import com.badlogic.gdx.math.Vector2; -import com.me.brickbuster.BrickBuster; import com.me.brickbuster.Utils; import com.me.brickbuster.entity.Brick; import com.me.brickbuster.entity.Entity; +import com.me.brickbuster.state.PlayState; import net.dermetfan.utils.Pair; public abstract class PowerUp extends Entity { @@ -18,8 +18,8 @@ public abstract class PowerUp extends Entity { private Color color; private boolean isCaught; - public PowerUp(BrickBuster brickBuster, Brick brick, Color color) { - super(brickBuster, brick.getX() + Brick.BLOCK_WIDTH/2, brick.getY() + Brick.BLOCK_HEIGHT/2); + public PowerUp(PlayState state, Brick brick, Color color) { + super(state, brick.getX() + Brick.BLOCK_WIDTH/2, brick.getY() + Brick.BLOCK_HEIGHT/2); this.color = color; } @@ -35,7 +35,7 @@ public abstract class PowerUp extends Entity { public void update(float dt) { setY(getY() - FALL_SPEED * dt); - Pair paddle = getBrickBuster().getPaddle().getTopEdge(); + Pair paddle = state.paddle.getTopEdge(); Vector2 lineDir = paddle.getValue().sub(paddle.getKey()); Vector2 nearest = Utils.nearestPoint(paddle.getKey().cpy(), lineDir, getPos().cpy()); diff --git a/core/src/com/me/brickbuster/entity/powerup/ShieldPowerUp.java b/core/src/com/me/brickbuster/entity/powerup/ShieldPowerUp.java index cf4fc4b..6a8cade 100644 --- a/core/src/com/me/brickbuster/entity/powerup/ShieldPowerUp.java +++ b/core/src/com/me/brickbuster/entity/powerup/ShieldPowerUp.java @@ -1,18 +1,18 @@ package com.me.brickbuster.entity.powerup; import com.badlogic.gdx.graphics.Color; -import com.me.brickbuster.BrickBuster; import com.me.brickbuster.entity.Brick; +import com.me.brickbuster.state.PlayState; public class ShieldPowerUp extends PowerUp { - public ShieldPowerUp(BrickBuster brickBuster, Brick brick) { - super(brickBuster, brick, Color.SALMON); + public ShieldPowerUp(PlayState state, Brick brick) { + super(state, brick, Color.SALMON); } @Override public void activate() { - getBrickBuster().addShield(); + state.addShield(); } } diff --git a/core/src/com/me/brickbuster/state/PlayState.java b/core/src/com/me/brickbuster/state/PlayState.java new file mode 100644 index 0000000..6c77b8a --- /dev/null +++ b/core/src/com/me/brickbuster/state/PlayState.java @@ -0,0 +1,169 @@ +package com.me.brickbuster.state; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; +import com.badlogic.gdx.math.MathUtils; +import com.me.brickbuster.BrickBuster; +import com.me.brickbuster.entity.Ball; +import com.me.brickbuster.entity.Brick; +import com.me.brickbuster.entity.Paddle; +import com.me.brickbuster.entity.powerup.*; + +import java.util.*; + +public class PlayState extends State { + + public static final int SHIELD_HEIGHT = 5; + public static final float POWERUP_CHANCE = 0.15f; + + public static final Map, Integer> powerUpWeights; + private static final int weightSum; + + public List powerUps; + public Paddle paddle; + public List balls; + public List bricks; + + private int shieldCount = 0; + + private float updateTime = 0f; + + public PlayState(BrickBuster game) { + super(game); + } + + @Override + public void setup() { + powerUps = new ArrayList(); + paddle = new Paddle(this); + + bricks = new ArrayList(); + for (int col = 0; col < 13; col++) { + for (int row = 0; row < 7; row++) { + int x = 15 + (col * (Brick.BLOCK_WIDTH + 10)); + int y = 15 + Brick.BLOCK_HEIGHT + (row * (Brick.BLOCK_HEIGHT + 10)); + Class powerUpType = null; + if (MathUtils.randomBoolean(POWERUP_CHANCE)) { + powerUpType = getWeightedPowerUp(); + } + bricks.add(new Brick(this, powerUpType, x, BrickBuster.HEIGHT - y)); + } + } + + balls = new ArrayList(); + balls.add(new Ball(this)); + } + + @Override + public void render() { + long start = System.nanoTime(); + for (Brick block : bricks) { + block.render(game.sr); + } + for (PowerUp powerUp : powerUps) { + powerUp.render(game.sr); + } + for (Ball ball : balls) { + ball.render(game.sr); + } + paddle.render(game.sr); + + if (getShieldCount() > 0) { + game.sr.begin(ShapeType.Filled); + game.sr.setColor(Color.SALMON); + game.sr.rect(0, 0, BrickBuster.WIDTH, getShieldCount() * SHIELD_HEIGHT); + game.sr.end(); + } + long renderTime = System.nanoTime() - start; + + game.sb.begin(); + game.font.setColor(Color.GRAY); + game.font.draw(game.sb, String.format("FPS: %d Update: %.2f ms Render: %.2f ms", + Gdx.graphics.getFramesPerSecond(), updateTime/1000000f, renderTime/1000000f), 0, 13); + game.sb.end(); + } + + @Override + public void update(float dt) { + long start = System.nanoTime(); + paddle.update(dt); + + for (Iterator it = balls.iterator(); it.hasNext();) { + Ball ball = it.next(); + ball.update(dt); + if (ball.isDead()) { + it.remove(); + } + } + if (balls.isEmpty()) { + ballReset(); + } + + for (Iterator it = powerUps.iterator(); it.hasNext();) { + PowerUp powerUp = it.next(); + powerUp.update(dt); + if(powerUp.isCaught()) { + it.remove(); + } + } + + if (bricks.isEmpty()) { + // TODO: Fix this - go to an after-game menu + //create(); + } + updateTime = System.nanoTime() - start; + } + + public int getShieldCount() { + return shieldCount; + } + + public void addShield() { + shieldCount++; + paddle.setY(paddle.getY() + SHIELD_HEIGHT); + } + + public void removeShield() { + shieldCount--; + paddle.setY(paddle.getY() - SHIELD_HEIGHT); + } + + public void ballReset() { + Ball ball = new Ball(this); + ball.setX(paddle.getX()); + ball.setY(Paddle.PADDLE_Y + Paddle.PADDLE_HEIGHT + Ball.RADIUS); + balls.add(ball); + paddle.setSticky(false); + paddle.setWidth(Paddle.DEFAULT_WIDTH); + } + + private static final Class getWeightedPowerUp() { + int remaining = MathUtils.random(weightSum); + for (Map.Entry, Integer> entry : PlayState.powerUpWeights.entrySet()) { + remaining -= entry.getValue(); + if (remaining < 0) { + return entry.getKey(); + } + } + return null; + } + + static { + Map, Integer> tmp = new HashMap, Integer>(); + + // Assign PowerUp weights here + tmp.put(GluePowerUp.class, 30); + tmp.put(LongerPaddlePowerUp.class, 40); + tmp.put(MultiBallPowerUp.class, 20); + tmp.put(ShieldPowerUp.class, 40); + powerUpWeights = Collections.unmodifiableMap(tmp); + + int sum = 0; + for (int x : PlayState.powerUpWeights.values()) { + sum += x; + } + weightSum = sum; + } + +} diff --git a/core/src/com/me/brickbuster/state/State.java b/core/src/com/me/brickbuster/state/State.java new file mode 100644 index 0000000..22fe224 --- /dev/null +++ b/core/src/com/me/brickbuster/state/State.java @@ -0,0 +1,27 @@ +package com.me.brickbuster.state; + +import com.badlogic.gdx.ScreenAdapter; +import com.me.brickbuster.BrickBuster; + +public abstract class State extends ScreenAdapter { + + protected final BrickBuster game; + + public State(BrickBuster game) { + this.game = game; + this.setup(); + } + + @Override + public final void render(float delta) { + update(delta); + render(); + } + + public abstract void setup(); + + public abstract void render(); + + public abstract void update(float dt); + +}