package edu.gatech.cs2340.trydent.sample.breakout; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import javafx.scene.input.KeyCode; import javafx.scene.paint.Color; import edu.gatech.cs2340.trydent.Behavior; import edu.gatech.cs2340.trydent.ContinuousEvent; import edu.gatech.cs2340.trydent.GameObject; import edu.gatech.cs2340.trydent.Keyboard; import edu.gatech.cs2340.trydent.Time; import edu.gatech.cs2340.trydent.TrydentEngine; import edu.gatech.cs2340.trydent.math.Position; import edu.gatech.cs2340.trydent.math.Vector; import edu.gatech.cs2340.trydent.math.geom.Rectangle; /** * Main driver class for the Breakout example. */ public class BreakoutExample extends ContinuousEvent { private static final int RESOLUTION = 2; private static final int WIDTH = 240 * RESOLUTION; private static final int HEIGHT = 160 * RESOLUTION; public static void main(String[] args) { TrydentEngine.setWindowSize(WIDTH, HEIGHT); TrydentEngine.start(); new BreakoutExample(); } private int level = 1; private int blockWidth = 16; private int blockHeight = 8; private List<Brick> bricks; private GameObject paddle; private GameObject ball; public BreakoutExample() { } @Override public void onStart() { TrydentEngine.setBackgroundColor(Color.BLACK); bricks = new ArrayList<>(); initBall(); initPaddle(); initBricks(); } private void reset() { for (Brick b : bricks) { b.getGameObject().destroy(); } paddle.destroy(); ball.destroy(); initBall(); initPaddle(); initBricks(); } @Override public void onUpdate() { if (Keyboard.isKeyDownOnce(KeyCode.ESCAPE)) { reset(); return; } double speed = WIDTH / 2; double delta = speed * Time.getTimePassed(); if (Keyboard.isKeyDown(KeyCode.LEFT) || Keyboard.isKeyDown(KeyCode.A)) { paddle.translate(-delta, 0); } else if (Keyboard.isKeyDown(KeyCode.RIGHT) || Keyboard.isKeyDown(KeyCode.D)) { paddle.translate(+delta, 0); } double pwidth = blockWidth * RESOLUTION * 2; Position p = paddle.getPosition(); p.setX(Math.min(Math.max(p.getX(), pwidth / 2), WIDTH - pwidth / 2)); paddle.setPosition(p); } private void initBall() { Rectangle rect = new Rectangle(0, 0, blockHeight * 0.75 * RESOLUTION, blockHeight * 0.75 * RESOLUTION); rect.setCenter(new Position(0, 0)); ball = new GameObject(rect); ball.setFill(Color.WHITE); ball.setPosition(new Position(WIDTH / 2, HEIGHT * 0.8)); ball.addFeature(rect); new Behavior(ball) { private Vector velocity = new Vector(0, 100); private Position lastPaddle = null; @Override public void onUpdate() { GameObject g = this.getGameObject(); if (g == null || g.isDestroyed()) { this.stop(); return; } Position paddlePos = paddle.getPosition().copy(); Vector paddleVelocity = new Vector(0, 0); if (lastPaddle != null) { double dt = Time.getTimePassed(); if (dt < 0 || dt > 0.1) dt = 0.1; paddleVelocity = paddlePos.copy().subtract(lastPaddle).scale(10).toVector(); paddleVelocity.setY(0); } lastPaddle = paddlePos; Vector delta = velocity.copy().scale(Time.getTimePassed()); g.translate(delta); Rectangle bounds = g.getFeature(Rectangle.class); bounds.setCenter(ball.getPosition()); Rectangle paddleBounds = paddle.getFeature(Rectangle.class); paddleBounds.setCenter(paddle.getPosition()); if (bounds.intersects(paddleBounds)) { velocity.setY(-Math.abs(velocity.getY())); velocity.add(paddleVelocity); velocity.add(bounds.getCenter().subtract(paddleBounds.getCenter()).projectOffAxis(Vector.AXIS_Y)); return; } if (bounds.getLeft() < 0) { velocity.setX(Math.abs(velocity.getX())); } if (bounds.getRight() > WIDTH) { velocity.setX(-Math.abs(velocity.getX())); } if (bounds.getTop() < 0) { velocity.setY(Math.abs(velocity.getY())); } Set<Brick> deadbricks = new HashSet<>(); for (Brick brick : bricks) { if (brick.getGameObject().isDestroyed()) { deadbricks.add(brick); continue; } if (bounds.intersects(brick.getBounds())) { brick.hit(); velocity.scale(-1); } } bricks.removeAll(deadbricks); } }; } private void initPaddle() { Rectangle rect = new Rectangle(0, 0, blockWidth * RESOLUTION * 2, blockHeight * RESOLUTION / 2); rect.setCenter(new Position(0, 0)); paddle = new GameObject(rect); paddle.setFill(Color.WHITE); paddle.setPosition(new Position(WIDTH / 2, HEIGHT * 0.9)); paddle.addFeature(rect); } private void initBricks() { bricks.clear(); int pad = 2; int rows = 4; int cols = (WIDTH / RESOLUTION / (blockWidth + pad)); for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { double x = pad * 2 + (blockWidth + pad) * col; double y = pad * 2 + (blockHeight + pad) * row; double w = blockWidth; double h = blockHeight; x *= RESOLUTION; y *= RESOLUTION; w *= RESOLUTION; h *= RESOLUTION; Rectangle rect = new Rectangle(0, 0, w, h); GameObject g = new GameObject(rect); g.setPosition(new Position(x, y)); g.addFeature(rect); bricks.add(new Brick(g, level)); } } } }