diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5c0014e --- /dev/null +++ b/.gitignore @@ -0,0 +1,72 @@ +# ---> Java +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +# ---> Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +# Eclipse m2e generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# ---> NetBeans +**/nbproject/private/ +**/nbproject/Makefile-*.mk +**/nbproject/Package-*.bash +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +# IntelliJ IDEA +.idea +*.iml +*.ipr +*.iws + +# VS Code +.vscode/ +.attach_pid* + +# macOS +.DS_Store + +# Etc +*~ +*.log + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..66b53da --- /dev/null +++ b/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + dev.boyfailure.quajra + VectorBreakout + 1.0-SNAPSHOT + jar + + UTF-8 + 21 + dev.boyfailure.quajra.vectorbreakout.VectorBreakout + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.4.1 + + + + dev.boyfailure.quajra.vectorbreakout.VectorBreakout + + + + + + + \ No newline at end of file diff --git a/src/main/java/dev/boyfailure/quajra/vectorbreakout/Ball.java b/src/main/java/dev/boyfailure/quajra/vectorbreakout/Ball.java new file mode 100644 index 0000000..48ff7fa --- /dev/null +++ b/src/main/java/dev/boyfailure/quajra/vectorbreakout/Ball.java @@ -0,0 +1,186 @@ +package dev.boyfailure.quajra.vectorbreakout; + +public class Ball { + + short ballX = 250; + short ballY = 300; + short ballWidth = 7; + short ballHeight = 7; + boolean isActive = false; + byte ballColor = 0; + + byte speedX = 5; + byte speedY = 5; + + public Ball(int x, int y, int width, int height, int color, boolean active) { + this.ballX = (short) x; + this.ballY = (short) y; + this.ballWidth = (short) width; + this.ballHeight = (short) height; + this.ballColor = (byte) color; + this.isActive = active; + } + + public void spawnBall(boolean useChancey) { + if (useChancey) { + this.ballX += (short) (VectorBreakout.chancey * 3); + this.ballY += (short) VectorBreakout.chancey; + } + VectorBreakout.ballsOnScreen++; + this.isActive = true; + } + + public void spawnBall(int x, int y) { + this.ballX = (short) x; + this.ballY = (short) y; + VectorBreakout.ballsOnScreen++; + this.isActive = true; + } + + public void moveBall() { + this.ballX += this.speedX; + this.ballY += this.speedY; + + this.checkCollision(); + } + + public void bounce(byte bounceType) { + switch(bounceType) { + case 0: + this.speedY = (byte) -(this.speedY); + switch (VectorBreakout.chancey) { + case 0: break; + case 1: this.speedX++; break; + case 2: break; + case 3: this.speedX--; break; + case 4: break; + case 5: this.speedY++;break; + case 6: break; + case 7: this.speedY--;break; + case 8: break; + case 9: this.speedY++;speedX++;break; + case 10: break; + case 11: this.speedY--;speedX--;break; + case 12: break; + case 13: this.speedY++;speedY++;break; + case 14: break; + case 15: this.speedY--;speedY--;break; + } + break; + case 1: + this.speedX = (byte) -(this.speedX); + break; + case 2: + if (this.speedX > 0) { + this.speedX = (byte) -(this.speedX); + } + else { + this.speedX -= 4; + } + this.speedY = (byte) -(this.speedY); + break; + case 3: + if (this.speedX < 0) { + this.speedX = (byte) -(this.speedX); + } + else { + this.speedX += 4; + } + this.speedY = (byte) -(this.speedY); + break; + } + if (this.speedX < 2 && this.speedX >= 0) {this.speedX = 2;} + else if (this.speedX > -2 && this.speedX < 0) {this.speedX = -2;} + else if (this.speedX > 11) {this.speedX -= 3;} // Slow down if too fast + if (this.speedY < 4 && this.speedY >= 0) {this.speedY = 4;} + else if (this.speedY > -4 && this.speedY < 0) {this.speedY = -4;} + else if (this.speedY > 11) {this.speedY -= 3;} // Slow down if too fast + } + + public void destroyBall() { + this.isActive = false; + this.ballX = 32767; + this.ballY = 32767; + VectorBreakout.ballsOnScreen--; + if (VectorBreakout.ballsOnScreen <= 0) { + VectorBreakout.lives--; + } + if (VectorBreakout.lives <= 0) { + VectorBreakout.gameLose(); + } + } + + // Checks to see if the ball is in contact with bricks, paddles, or walls + public void checkCollision() { + + // Check floor + if (this.ballY >= VectorBreakout.gameResY) { + this.destroyBall(); + return; + } + // Check ceiling + else if (this.ballY <= 0) { + this.bounce((byte) 0); + this.ballY = 0; + return; + } + + // Check walls + if (this.ballX <= 20) { + this.bounce((byte) 1); + this.ballX = 22; + return; + } + else if ((this.ballX + this.ballWidth) >= (VectorBreakout.gameResX - 20 - this.ballWidth)) { + this.bounce((byte) 1); + this.ballX = (short) (VectorBreakout.gameResX - 25 - this.ballWidth); + return; + } + + // Check bricks + for (byte i = 0; i < VectorBreakout.currentBricks.length; i++) { + if (VectorBreakout.currentBricks[i] != null) { + if (VectorBreakout.currentBricks[i].brickY <= this.ballY && + VectorBreakout.currentBricks[i].brickY + VectorBreakout.currentBricks[i].brickHeight >= this.ballY + this.ballHeight) { + if (VectorBreakout.currentBricks[i].brickX <= this.ballX && + VectorBreakout.currentBricks[i].brickX + VectorBreakout.currentBricks[i].brickWidth >= this.ballX + this.ballWidth) { + VectorBreakout.currentBricks[i].breakBrick(); + this.bounce((byte) 0); + return; + } + } + } + } + + // Check paddles + for (byte i = 0; i < VectorBreakout.currentPaddles.length; i++) { + if (VectorBreakout.currentPaddles[i] != null) { + if (VectorBreakout.currentPaddles[i].paddleY <= this.ballY && + VectorBreakout.currentPaddles[i].paddleY + VectorBreakout.currentPaddles[i].paddleHeight >= this.ballY + this.ballHeight) { + if (VectorBreakout.currentPaddles[i].paddleX <= this.ballX && + VectorBreakout.currentPaddles[i].paddleX + VectorBreakout.currentPaddles[i].paddleWidth >= this.ballX + this.ballWidth) { + this.ballY -= 2; + // Check which section of paddle + + short paddleSectionLength = (short) (VectorBreakout.currentPaddles[i].paddleWidth / 4); + + // If on left edge + if (this.ballX + this.ballWidth < VectorBreakout.currentPaddles[i].paddleX + paddleSectionLength) { + this.bounce((byte) 2); + } + // If on right edge + else if (this.ballX > VectorBreakout.currentPaddles[i].paddleX + (paddleSectionLength * 3)) { + this.bounce((byte) 3); + } + // Center + else { + this.bounce((byte) 0); + } + return; + } + } + } + } + } + +} diff --git a/src/main/java/dev/boyfailure/quajra/vectorbreakout/Brick.java b/src/main/java/dev/boyfailure/quajra/vectorbreakout/Brick.java new file mode 100644 index 0000000..e8be25a --- /dev/null +++ b/src/main/java/dev/boyfailure/quajra/vectorbreakout/Brick.java @@ -0,0 +1,47 @@ +package dev.boyfailure.quajra.vectorbreakout; + +public class Brick { + + short brickX; + short brickY; + short brickWidth = 40; + short brickHeight = 17; + boolean isBroken = false; + byte brickColor = 0; + byte scoreOnBreak = 10; + byte specialAbility = 0; + + public Brick(int x, int y, boolean bk, int bc, int sc, int sa) { + this.brickX = (short) x; + this.brickY = (short) y; + this.isBroken = bk; + this.brickColor = (byte) bc; + this.scoreOnBreak = (byte) sc; + this.specialAbility = (byte) sa; + } + + public void breakBrick() { + isBroken = true; + VectorBreakout.score += this.scoreOnBreak + (VectorBreakout.level - 1); + VectorBreakout.bricksOnScreen--; + switch(this.specialAbility) { + case 1: + VectorBreakout.lives++; + break; + case 2: + for (byte i = 0; i < VectorBreakout.currentBalls.length; i++) { + if (VectorBreakout.currentBalls[i] == null) { + VectorBreakout.currentBalls[i] = new Ball(300, 300, 7, 7, 0, true); + VectorBreakout.currentBalls[i].spawnBall((this.brickX + (this.brickWidth / 2)), (this.brickY + (this.brickHeight / 2))); + return; + } + } + break; + default: + break; + } + this.brickX = 32767; + this.brickY = 32767; + } + +} diff --git a/src/main/java/dev/boyfailure/quajra/vectorbreakout/GameDisplay.java b/src/main/java/dev/boyfailure/quajra/vectorbreakout/GameDisplay.java new file mode 100644 index 0000000..f3a565b --- /dev/null +++ b/src/main/java/dev/boyfailure/quajra/vectorbreakout/GameDisplay.java @@ -0,0 +1,333 @@ +package dev.boyfailure.quajra.vectorbreakout; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import javax.swing.JComponent; +import java.awt.geom.Line2D; + +public class GameDisplay extends JComponent { + + float beamX = 0; // Horizontal location of "vector beam" + float beamY = 0; // Vertical location of "vector beam" + + // Change this to 1 if you build for older versions of Java. Older versions + // will render a leading zero otherwise. (tested on JDK 1.5) + byte iStart = 0; + + public static float beamScaleX = 1; // Horizontal drawing scale + public static float beamScaleY = 1; // Vertical drawing scale + + public void paint(Graphics gameGraphics) { + + super.paint(gameGraphics); + + Graphics2D g2 = (Graphics2D) gameGraphics; + + g2.setColor(Color.white); + + /** + * Note on rendering numbers: + * + * I am aware that I could be using a switch statement for these. + * However, this did not compile when testing in JDK 1.5, as it would + * refuse to accept anything other than numbers in a switch statement. + * Since I am a silly little nerd who wishes to use this on my older + * systems, I used these goofy if/else statements so I could compile + * on the older JDKs and play on my older systems... + */ + + // Score + resetBeam(); + moveBeam(20, -13); + g2.setStroke(new BasicStroke(2)); + String numToString = String.valueOf(VectorBreakout.score); + String[] numToRender = numToString.split(""); + for (byte i = iStart; i < numToRender.length; i++) { + if ("1".equals(numToRender[i])) {moveBeam(13, 0);g2.draw(drawVec(0, -24));moveBeam(5, 24);} + else if ("2".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(-14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(14, 0));moveBeam(4, 0);} + else if ("3".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(-14, 0));moveBeam(14, 0);g2.draw(drawVec(0, 12));g2.draw(drawVec(-14, 0));moveBeam(18, 0);} + else if ("4".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(0, 12));g2.draw(drawVec(14, 0));moveBeam(0, -12);g2.draw(drawVec(0, 24));moveBeam(4, 0);} + else if ("5".equals(numToRender[i])) {moveBeam(14, -24);g2.draw(drawVec(-14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(-14, 0));moveBeam(18, 0);} + else if ("6".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(0, 24));g2.draw(drawVec(14, 0));g2.draw(drawVec(0, -12));g2.draw(drawVec(-14, 0));moveBeam(18, 12);} + else if ("7".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 24));moveBeam(4, 0);} + else if ("8".equals(numToRender[i])) {g2.draw(drawVec(0, -24));g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 24));g2.draw(drawVec(-14, 0));moveBeam(0, -12);g2.draw(drawVec(14, 0));moveBeam(4, 12);} + else if ("9".equals(numToRender[i])) {moveBeam(14, 0);g2.draw(drawVec(0, -24));g2.draw(drawVec(-14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(14, 0));moveBeam(4, 12);} + else {g2.draw(drawVec(14, 0));g2.draw(drawVec(0, -24));g2.draw(drawVec(-14, 0));g2.draw(drawVec(0, 24));moveBeam(18, 0);} + } + + // Lives + resetBeam(); + moveBeam(200, -13); + numToString = String.valueOf(VectorBreakout.lives); + numToRender = numToString.split(""); + for (byte i = iStart; i < numToRender.length; i++) { + if ("1".equals(numToRender[i])) {moveBeam(13, 0);g2.draw(drawVec(0, -24));moveBeam(5, 24);} + else if ("2".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(-14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(14, 0));moveBeam(4, 0);} + else if ("3".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(-14, 0));moveBeam(14, 0);g2.draw(drawVec(0, 12));g2.draw(drawVec(-14, 0));moveBeam(18, 0);} + else if ("4".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(0, 12));g2.draw(drawVec(14, 0));moveBeam(0, -12);g2.draw(drawVec(0, 24));moveBeam(4, 0);} + else if ("5".equals(numToRender[i])) {moveBeam(14, -24);g2.draw(drawVec(-14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(-14, 0));moveBeam(18, 0);} + else if ("6".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(0, 24));g2.draw(drawVec(14, 0));g2.draw(drawVec(0, -12));g2.draw(drawVec(-14, 0));moveBeam(18, 12);} + else if ("7".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 24));moveBeam(4, 0);} + else if ("8".equals(numToRender[i])) {g2.draw(drawVec(0, -24));g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 24));g2.draw(drawVec(-14, 0));moveBeam(0, -12);g2.draw(drawVec(14, 0));moveBeam(4, 12);} + else if ("9".equals(numToRender[i])) {moveBeam(14, 0);g2.draw(drawVec(0, -24));g2.draw(drawVec(-14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(14, 0));moveBeam(4, 12);} + else {g2.draw(drawVec(14, 0));g2.draw(drawVec(0, -24));g2.draw(drawVec(-14, 0));g2.draw(drawVec(0, 24));moveBeam(18, 0);} + } + + // Level + resetBeam(); + moveBeam(380, -13); + numToString = String.valueOf(VectorBreakout.level); + numToRender = numToString.split(""); + for (byte i = iStart; i < numToRender.length; i++) { + if ("1".equals(numToRender[i])) {moveBeam(13, 0);g2.draw(drawVec(0, -24));moveBeam(5, 24);} + else if ("2".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(-14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(14, 0));moveBeam(4, 0);} + else if ("3".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(-14, 0));moveBeam(14, 0);g2.draw(drawVec(0, 12));g2.draw(drawVec(-14, 0));moveBeam(18, 0);} + else if ("4".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(0, 12));g2.draw(drawVec(14, 0));moveBeam(0, -12);g2.draw(drawVec(0, 24));moveBeam(4, 0);} + else if ("5".equals(numToRender[i])) {moveBeam(14, -24);g2.draw(drawVec(-14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(-14, 0));moveBeam(18, 0);} + else if ("6".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(0, 24));g2.draw(drawVec(14, 0));g2.draw(drawVec(0, -12));g2.draw(drawVec(-14, 0));moveBeam(18, 12);} + else if ("7".equals(numToRender[i])) {moveBeam(0, -24);g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 24));moveBeam(4, 0);} + else if ("8".equals(numToRender[i])) {g2.draw(drawVec(0, -24));g2.draw(drawVec(14, 0));g2.draw(drawVec(0, 24));g2.draw(drawVec(-14, 0));moveBeam(0, -12);g2.draw(drawVec(14, 0));moveBeam(4, 12);} + else if ("9".equals(numToRender[i])) {moveBeam(14, 0);g2.draw(drawVec(0, -24));g2.draw(drawVec(-14, 0));g2.draw(drawVec(0, 12));g2.draw(drawVec(14, 0));moveBeam(4, 12);} + else {g2.draw(drawVec(14, 0));g2.draw(drawVec(0, -24));g2.draw(drawVec(-14, 0));g2.draw(drawVec(0, 24));moveBeam(18, 0);} + } + + // Walls + g2.setColor(Color.gray); + g2.setStroke(new BasicStroke(10)); + resetBeam(); + moveBeam(15, 0); + g2.draw(drawVec(0, 600)); + moveBeam(770, 0); + g2.draw(drawVec(0, -600)); + moveBeam(15, -5); + g2.draw(drawVec(-800, 0)); + + // Bricks + for (byte i = 0; i < VectorBreakout.currentBricks.length; i++) { + if (VectorBreakout.currentBricks[i] != null) { + if (VectorBreakout.currentBricks[i].isBroken == false) { + resetBeam(); + g2.setStroke(new BasicStroke(3)); + moveBeam(VectorBreakout.currentBricks[i].brickX + 1, VectorBreakout.currentBricks[i].brickY + 1); + switch(VectorBreakout.currentBricks[i].brickColor) { + case 0: + g2.setColor(Color.red); + break; + case 1: + g2.setColor(Color.getHSBColor(25, 258, 77)); + break; + case 2: + g2.setColor(Color.cyan); + break; + case 3: + g2.setColor(Color.green); + break; + case 4: + g2.setColor(Color.magenta); + break; + default: + g2.setColor(Color.gray); + break; + } + g2.draw(drawVec(VectorBreakout.currentBricks[i].brickWidth - 2, 0)); + g2.draw(drawVec(0, -(VectorBreakout.currentBricks[i].brickHeight - 2))); + g2.draw(drawVec(-(VectorBreakout.currentBricks[i].brickWidth - 2), 0)); + g2.draw(drawVec(0, VectorBreakout.currentBricks[i].brickHeight - 2)); + } + } + } + + // Paddle + g2.setColor(Color.white); + for (byte i = 0; i < VectorBreakout.currentPaddles.length; i++) { + if (VectorBreakout.currentPaddles[i] != null) { + if (VectorBreakout.currentPaddles[i].isActive) { + resetBeam(); + /*g2.setStroke(new BasicStroke(VectorBreakout.currentPaddles[i].paddleHeight)); + moveBeam(VectorBreakout.currentPaddles[i].paddleX, VectorBreakout.currentPaddles[i].paddleY + (VectorBreakout.currentPaddles[i].paddleHeight / 2)); + g2.draw(drawVec(VectorBreakout.currentPaddles[i].paddleWidth, 0));*/ + g2.setStroke(new BasicStroke(3)); + moveBeam(VectorBreakout.currentPaddles[i].paddleX, VectorBreakout.currentPaddles[i].paddleY); + g2.draw(drawVec(VectorBreakout.currentPaddles[i].paddleWidth, 0)); + g2.draw(drawVec(0, -(VectorBreakout.currentPaddles[i].paddleHeight))); + g2.draw(drawVec(-(VectorBreakout.currentPaddles[i].paddleWidth), 0)); + g2.draw(drawVec(0, VectorBreakout.currentPaddles[i].paddleHeight)); + } + } + } + + // Balls + g2.setStroke(new BasicStroke(1)); + g2.setColor(Color.yellow); + for (byte i = 0; i < VectorBreakout.currentBalls.length; i++) { + // Check if ball is null first! + if (VectorBreakout.currentBalls[i] != null) { + if (VectorBreakout.currentBalls[i].isActive) { + resetBeam(); + moveBeam(VectorBreakout.currentBalls[i].ballX, VectorBreakout.currentBalls[i].ballY); + for (byte ii = 0; ii < VectorBreakout.currentBalls[i].ballHeight; ii++) { + g2.draw(drawVec(VectorBreakout.currentBalls[i].ballWidth, 0)); + moveBeam(-(VectorBreakout.currentBalls[i].ballWidth), -1); + } + } + } + } + + // Paused + g2.setStroke(new BasicStroke(3)); + if (VectorBreakout.isPaused) { + g2.setColor(Color.white); + resetBeam(); + moveBeam(110, 260); + // P + g2.draw(drawVec(0, -110));g2.draw(drawVec(80, 0));g2.draw(drawVec(0, 50));g2.draw(drawVec(-80, 0)); + moveBeam(100, 60); + // A + g2.draw(drawVec(0, -70));g2.draw(drawVec(40, -40));g2.draw(drawVec(40, 40));g2.draw(drawVec(0, 70));g2.draw(drawVec(0, -40));g2.draw(drawVec(-80, 0)); + moveBeam(100, 40); + // U + moveBeam(0, -110);g2.draw(drawVec(0, 110));g2.draw(drawVec(80, 0));g2.draw(drawVec(0, -110)); + moveBeam(20, 110); + // S + g2.draw(drawVec(80, 0));g2.draw(drawVec(0, -55));g2.draw(drawVec(-80, 0));g2.draw(drawVec(0, -55));g2.draw(drawVec(80, 0)); + moveBeam(20, 110); + // E + moveBeam(80, 0);g2.draw(drawVec(-80, 0));g2.draw(drawVec(0, -55));g2.draw(drawVec(80, 0));moveBeam(-80, 0);g2.draw(drawVec(0, -55));g2.draw(drawVec(80, 0)); + moveBeam(20, 110); + // D + g2.draw(drawVec(40, 0));g2.draw(drawVec(40, -40));g2.draw(drawVec(0, -30));g2.draw(drawVec(-40, -40));g2.draw(drawVec(-40, 0));g2.draw(drawVec(0, 110)); + moveBeam(100, 110); + } + + VectorBreakout.actualFrames++; // Count up actual frames rendered + + // Debug Menu + if (VectorBreakout.debugMenuEnabled) { + g2.setColor(Color.white); + g2.drawString("Quajra Debug", 1, 12); + g2.drawString("frame: " + VectorBreakout.frameCounter, 1, 24); + g2.drawString("beamScaleX: " + beamScaleX, 1, 36); + g2.drawString("beamScaleY: " + beamScaleY, 1, 48); + g2.drawString("isPaused: " + VectorBreakout.isPaused, 1, 60); + g2.drawString("targetFrameRate: " + VectorBreakout.targetFrameRate, 150, 24); + g2.drawString("actualFrameRate: " + VectorBreakout.actualFrameRate, 150, 36); + g2.drawString("actualFrames: " + VectorBreakout.actualFrames, 150, 48); + g2.drawString("chancey: " + VectorBreakout.chancey, 150, 60); + g2.drawString("ballsOnScreen: " + VectorBreakout.ballsOnScreen, 300, 24); + } + + } + + public Line2D.Float drawVec(float x, float y) { + float oldBeamX = beamX; + float oldBeamY = beamY; + beamX += (x * beamScaleX); + beamY += (y * beamScaleY); + return new Line2D.Float(oldBeamX, oldBeamY, beamX, beamY); + } + + public void moveBeam(float x, float y) { + beamX += (x * beamScaleX); + beamY += (y * beamScaleY); + } + + public void resetBeam() { + beamX = 0; + beamY = 40 * beamScaleY; + } + + public GameDisplay() { + } + + /* For later use + // A + g2.draw(drawVec(0, -70)); + g2.draw(drawVec(40, -40)); + g2.draw(drawVec(40, 40)); + g2.draw(drawVec(0, 70)); + g2.draw(drawVec(0, -40)); + g2.draw(drawVec(-80, 0)); + moveBeam(100, 40); + + // B + g2.draw(drawVec(0, -110)); + g2.draw(drawVec(60, 0)); + g2.draw(drawVec(20, (float) 18.333)); + g2.draw(drawVec(0, (float) 18.333)); + g2.draw(drawVec(-20, (float) 18.333)); + g2.draw(drawVec(-60, 0)); + g2.draw(drawVec(60, 0)); + g2.draw(drawVec(20, (float) 18.333)); + g2.draw(drawVec(0, (float) 18.333)); + g2.draw(drawVec(-20, (float) 18.333)); + g2.draw(drawVec(-60, 0)); + moveBeam(100, 0); + + // C + moveBeam(80, -110); + g2.draw(drawVec(-80, 0)); + g2.draw(drawVec(0, 110)); + g2.draw(drawVec(80, 0)); + moveBeam(20, 0); + + // D + g2.draw(drawVec(40, 0)); + g2.draw(drawVec(40, -40)); + g2.draw(drawVec(0, -30)); + g2.draw(drawVec(-40, -40)); + g2.draw(drawVec(-40, 0)); + g2.draw(drawVec(0, 110)); + moveBeam(100, 110); + + // E + moveBeam(80, -110); + g2.draw(drawVec(-80, 0)); + g2.draw(drawVec(0, -55)); + g2.draw(drawVec(80, 0)); + moveBeam(-80, 0); + g2.draw(drawVec(0, -55)); + g2.draw(drawVec(80, 0)); + moveBeam(20, 0); + + // F + g2.draw(drawVec(0, 110)); + moveBeam(0, -110); + g2.draw(drawVec(80, 0)); + moveBeam(-80, 50); + g2.draw(drawVec(80, 0)); + moveBeam(10, 60); + + + // P + g2.draw(drawVec(0, -110)); + g2.draw(drawVec(80, 0)); + g2.draw(drawVec(0, 50)); + g2.draw(drawVec(-80, 0)); + moveBeam(100, 60); + // A + g2.draw(drawVec(0, -70)); + g2.draw(drawVec(40, -40)); + g2.draw(drawVec(40, 40)); + g2.draw(drawVec(0, 70)); + g2.draw(drawVec(0, -40)); + g2.draw(drawVec(-80, 0)); + moveBeam(100, 40); + // U + moveBeam(0, -110); + g2.draw(drawVec(0, 110)); + g2.draw(drawVec(80, 0)); + g2.draw(drawVec(0, -110)); + moveBeam(20, 110); + // S + g2.draw(drawVec(80, 0)); + g2.draw(drawVec(0, -55)); + g2.draw(drawVec(-80, 0)); + g2.draw(drawVec(0, -55)); + g2.draw(drawVec(80, 0)); + moveBeam(20, -110); + + */ + +} diff --git a/src/main/java/dev/boyfailure/quajra/vectorbreakout/Paddle.java b/src/main/java/dev/boyfailure/quajra/vectorbreakout/Paddle.java new file mode 100644 index 0000000..483ec76 --- /dev/null +++ b/src/main/java/dev/boyfailure/quajra/vectorbreakout/Paddle.java @@ -0,0 +1,37 @@ +package dev.boyfailure.quajra.vectorbreakout; + +public class Paddle { + + short paddleX; + short paddleY; + short paddleWidth = 100; + short paddleHeight = 7; + byte paddleColor; + byte paddleSpeed = 0; + boolean isActive = true; + float speedMultiplier = 1; + + public Paddle(int x, int y, int w, int h, int bc, float sm) { + this.paddleX = (short) x; + this.paddleY = (short) y; + this.paddleWidth = (short) w; + this.paddleHeight = (short) h; + this.paddleColor = (byte) bc; + this.speedMultiplier = sm; + } + + public void movePaddle(boolean direction) { + if (this.paddleSpeed <= 15) {this.paddleSpeed += 3;} + if (direction) {this.paddleX += (this.paddleSpeed * this.speedMultiplier);} + else {this.paddleX -= (this.paddleSpeed * this.speedMultiplier);} + if (this.paddleX <= 20) {this.paddleX = 20;} + else if (this.paddleX >= (VectorBreakout.gameResX - this.paddleWidth - 20)) {this.paddleX = (short) (VectorBreakout.gameResX - this.paddleWidth - 20);} + } + + public void cullPaddle() { + isActive = false; + this.paddleX = 32767; + this.paddleY = 32767; + } + +} diff --git a/src/main/java/dev/boyfailure/quajra/vectorbreakout/VectorBreakout.java b/src/main/java/dev/boyfailure/quajra/vectorbreakout/VectorBreakout.java new file mode 100644 index 0000000..779088f --- /dev/null +++ b/src/main/java/dev/boyfailure/quajra/vectorbreakout/VectorBreakout.java @@ -0,0 +1,290 @@ +package dev.boyfailure.quajra.vectorbreakout; + +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import javax.swing.JFrame; +import javax.swing.Timer; + +public class VectorBreakout { + + public static String gameName = "Vector Breakout"; + public static boolean isPaused = false; + public static boolean debugMenuEnabled = false; + public static boolean isLost = false; + public static short gameResX = 800; + public static short gameResY = 600; + public static byte lives = 5; + public static byte chancey = 0; + public static short level = 1; + public static byte ballsOnScreen = 0; + public static byte bricksOnScreen = 76; + public static byte targetFrameRate = 60; + public static byte actualFrames = 0; + public static byte actualFrameRate = 0; + public static byte gameTickRate = 60; + public static int score = 0; + public static long frameCounter = 0; + public static boolean movingLeft = false; + public static boolean movingRight = false; + public static Ball[] currentBalls = {null,null,null,null,null}; + public static Paddle[] currentPaddles = {new Paddle(350, 500, 100, 15, 0, 1)}; + public static Brick[] currentBricks = { + new Brick(20, 50, false, 0, 32, 0), + new Brick(60, 50, false, 0, 32, 0), + new Brick(100, 50, false, 0, 32, 0), + new Brick(140, 50, false, 0, 32, 0), + new Brick(180, 50, false, 0, 32, 0), + new Brick(220, 50, false, 0, 32, 0), + new Brick(260, 50, false, 0, 32, 0), + new Brick(300, 50, false, 0, 32, 0), + new Brick(340, 50, false, 0, 32, 0), + new Brick(380, 50, false, 0, 32, 0), + new Brick(420, 50, false, 0, 32, 0), + new Brick(460, 50, false, 0, 32, 0), + new Brick(500, 50, false, 0, 32, 0), + new Brick(540, 50, false, 0, 32, 0), + new Brick(580, 50, false, 0, 32, 0), + new Brick(620, 50, false, 0, 32, 0), + new Brick(660, 50, false, 0, 32, 0), + new Brick(700, 50, false, 0, 32, 0), + new Brick(740, 50, false, 0, 32, 0), + new Brick(20, 70, false, 1, 16, 0), + new Brick(60, 70, false, 1, 16, 0), + new Brick(100, 70, false, 1, 16, 0), + new Brick(140, 70, false, 1, 16, 0), + new Brick(180, 70, false, 1, 16, 0), + new Brick(220, 70, false, 1, 16, 0), + new Brick(260, 70, false, 1, 16, 0), + new Brick(300, 70, false, 1, 16, 0), + new Brick(340, 70, false, 1, 16, 0), + new Brick(380, 70, false, 1, 16, 0), + new Brick(420, 70, false, 1, 16, 0), + new Brick(460, 70, false, 1, 16, 0), + new Brick(500, 70, false, 1, 16, 0), + new Brick(540, 70, false, 1, 16, 0), + new Brick(580, 70, false, 1, 16, 0), + new Brick(620, 70, false, 1, 16, 0), + new Brick(660, 70, false, 1, 16, 0), + new Brick(700, 70, false, 1, 16, 0), + new Brick(740, 70, false, 1, 16, 0), + new Brick(20, 90, false, 2, 8, 0), + new Brick(60, 90, false, 2, 8, 0), + new Brick(100, 90, false, 2, 8, 0), + new Brick(140, 90, false, 2, 8, 0), + new Brick(180, 90, false, 2, 8, 0), + new Brick(220, 90, false, 4, 8, 2), + new Brick(260, 90, false, 2, 8, 0), + new Brick(300, 90, false, 2, 8, 0), + new Brick(340, 90, false, 2, 8, 0), + new Brick(380, 90, false, 2, 8, 0), + new Brick(420, 90, false, 2, 8, 0), + new Brick(460, 90, false, 2, 8, 0), + new Brick(500, 90, false, 2, 8, 0), + new Brick(540, 90, false, 4, 8, 2), + new Brick(580, 90, false, 2, 8, 0), + new Brick(620, 90, false, 2, 8, 0), + new Brick(660, 90, false, 2, 8, 0), + new Brick(700, 90, false, 2, 8, 0), + new Brick(740, 90, false, 2, 8, 0), + new Brick(20, 110, false, 3, 4, 0), + new Brick(60, 110, false, 3, 4, 0), + new Brick(100, 110, false, 3, 4, 0), + new Brick(140, 110, false, 3, 4, 0), + new Brick(180, 110, false, 3, 4, 0), + new Brick(220, 110, false, 3, 4, 0), + new Brick(260, 110, false, 3, 4, 0), + new Brick(300, 110, false, 3, 4, 0), + new Brick(340, 110, false, 3, 4, 0), + new Brick(380, 110, false, 3, 4, 0), + new Brick(420, 110, false, 3, 4, 0), + new Brick(460, 110, false, 3, 4, 0), + new Brick(500, 110, false, 3, 4, 0), + new Brick(540, 110, false, 3, 4, 0), + new Brick(580, 110, false, 3, 4, 0), + new Brick(620, 110, false, 3, 4, 0), + new Brick(660, 110, false, 3, 4, 0), + new Brick(700, 110, false, 3, 4, 0), + new Brick(740, 110, false, 3, 4, 0) + }; + + public VectorBreakout() { + } + + public static void main(String[] args) { + final JFrame gameFrame = new JFrame(); + + gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + gameFrame.setTitle(gameName); + gameFrame.setSize(gameResX, gameResY); + gameFrame.getContentPane().setBackground(Color.black); + + final GameDisplay gameCanvas = new GameDisplay(); + gameFrame.getContentPane().add(gameCanvas); + + gameFrame.setVisible(true); + + gameFrame.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + switch(e.getKeyCode()) { + case 27: // Escape + debugMenuEnabled = !debugMenuEnabled; + break; + case 10: // Enter + isPaused = !isPaused; + break; + case 32: // Space + if (isLost) {newGame();return;} + if (!isPaused) { + if (ballsOnScreen < 1) { + for (byte i = 0; i < currentBalls.length; i++) { + if (currentBalls[i] == null) { + currentBalls[i] = new Ball(200, 300, 7, 7, 0, true); + currentBalls[i].spawnBall(true); + return; + } + } + } + } + break; + case 37: // Left + movingLeft = true; + break; + case 39: // Right + movingRight = true; + break; + } + } + public void keyReleased(KeyEvent e) { + switch(e.getKeyCode()) { + case 37: // Left + movingLeft = false; + break; + case 39: // Right + movingRight = false; + break; + } + } + public void keyTyped(KeyEvent e) {} + }); + + // Adapts vector drawing scale when the window is resized + gameFrame.addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent componentEvent) { + gameCanvas.beamScaleX = gameFrame.getBounds().width / 800f; + gameCanvas.beamScaleY = gameFrame.getBounds().height / 600f; + } + }); + + Timer gameTick = new Timer((1000 / gameTickRate), new ActionListener(){ + public void actionPerformed(ActionEvent e) { + onGameTick(); + } + }); + gameTick.start(); + + Timer frameDisplay = new Timer((1000 / targetFrameRate), new ActionListener(){ + public void actionPerformed(ActionEvent e) { + frameCounter++; + gameFrame.repaint(); + } + }); + frameDisplay.start(); + + Timer gameCuller = new Timer(1000, new ActionListener(){ + public void actionPerformed(ActionEvent e) { + actualFrameRate = actualFrames; + actualFrames = 0; + for (byte i = 0; i < VectorBreakout.currentBricks.length; i++) { + if (VectorBreakout.currentBricks[i] != null) { + if (VectorBreakout.currentBricks[i].isBroken) { + VectorBreakout.currentBricks[i] = null; + } + } + } + for (byte i = 0; i < VectorBreakout.currentBalls.length; i++) { + if (VectorBreakout.currentBalls[i] != null) { + if (VectorBreakout.currentBalls[i].isActive == false) { + VectorBreakout.currentBalls[i] = null; + } + } + } + if (bricksOnScreen <= 0) { + refreshBricks(); + if (level < 32767) {level++;} else {level = 1;} + if (lives < 127) {lives++;} else {lives = 127;} + } + } + }); + gameCuller.start(); + } + + + public static void onGameTick() { + // i will implement something better than "chancey" eventually + chancey++; + if (chancey >= 16) { + chancey = 0; + } + + if (isPaused) {return;} + + // Move player if keys are held + for (byte i = 0; i < currentPaddles.length; i++) { + if (currentPaddles[i] != null) { + if (movingLeft) { + currentPaddles[i].movePaddle(false); + } + else if (movingRight) { + currentPaddles[i].movePaddle(true); + } + else { + currentPaddles[i].paddleSpeed = 0; + } + } + } + + // Ball logic (movement, collision checks) + for (byte i = 0; i < currentBalls.length; i++) { + if (currentBalls[i] != null) { + if (currentBalls[i].isActive) { + currentBalls[i].moveBall(); + } + } + } + } + + + public static void gameLose() { + for (byte i = 0; i < currentBricks.length; i++) { + currentBricks[i] = null; + } + for (byte i = 0; i < currentBalls.length; i++) { + currentBalls[i] = null; + } + isLost = true; + ballsOnScreen = 0; + } + + public static void newGame() { + lives = 5; + isLost = false; + score = 0; + level = 1; + frameCounter = 0; + ballsOnScreen = 0; + movingLeft = false; + movingRight = false; + currentPaddles[0] = new Paddle(350, 500, 100, 15, 0, 1); + refreshBricks(); + } + + public static void refreshBricks() { + bricksOnScreen = 76; + currentBricks[0] = new Brick(20, 50, false, 0, 32, 0);currentBricks[1] = new Brick(60, 50, false, 0, 32, 0);currentBricks[2] = new Brick(100, 50, false, 0, 32, 0);currentBricks[3] = new Brick(140, 50, false, 0, 32, 0);currentBricks[4] = new Brick(180, 50, false, 0, 32, 0);currentBricks[5] = new Brick(220, 50, false, 0, 32, 0);currentBricks[6] = new Brick(260, 50, false, 0, 32, 0);currentBricks[7] = new Brick(300, 50, false, 0, 32, 0);currentBricks[8] = new Brick(340, 50, false, 0, 32, 0);currentBricks[9] = new Brick(380, 50, false, 0, 32, 0);currentBricks[10] = new Brick(420, 50, false, 0, 32, 0);currentBricks[11] = new Brick(460, 50, false, 0, 32, 0);currentBricks[12] = new Brick(500, 50, false, 0, 32, 0);currentBricks[13] = new Brick(540, 50, false, 0, 32, 0);currentBricks[14] = new Brick(580, 50, false, 0, 32, 0);currentBricks[15] = new Brick(620, 50, false, 0, 32, 0);currentBricks[16] = new Brick(660, 50, false, 0, 32, 0);currentBricks[17] = new Brick(700, 50, false, 0, 32, 0);currentBricks[18] = new Brick(740, 50, false, 0, 32, 0);currentBricks[19] = new Brick(20, 70, false, 1, 16, 0);currentBricks[20] = new Brick(60, 70, false, 1, 16, 0);currentBricks[21] = new Brick(100, 70, false, 1, 16, 0);currentBricks[22] = new Brick(140, 70, false, 1, 16, 0);currentBricks[23] = new Brick(180, 70, false, 1, 16, 0);currentBricks[24] = new Brick(220, 70, false, 1, 16, 0);currentBricks[25] = new Brick(260, 70, false, 1, 16, 0);currentBricks[26] = new Brick(300, 70, false, 1, 16, 0);currentBricks[27] = new Brick(340, 70, false, 1, 16, 0);currentBricks[28] = new Brick(380, 70, false, 1, 16, 0);currentBricks[29] = new Brick(420, 70, false, 1, 16, 0);currentBricks[30] = new Brick(460, 70, false, 1, 16, 0);currentBricks[31] = new Brick(500, 70, false, 1, 16, 0);currentBricks[32] = new Brick(540, 70, false, 1, 16, 0);currentBricks[33] = new Brick(580, 70, false, 1, 16, 0);currentBricks[34] = new Brick(620, 70, false, 1, 16, 0);currentBricks[35] = new Brick(660, 70, false, 1, 16, 0);currentBricks[36] = new Brick(700, 70, false, 1, 16, 0);currentBricks[37] = new Brick(740, 70, false, 1, 16, 0);currentBricks[38] = new Brick(20, 90, false, 2, 8, 0);currentBricks[39] = new Brick(60, 90, false, 2, 8, 0);currentBricks[40] = new Brick(100, 90, false, 2, 8, 0);currentBricks[41] = new Brick(140, 90, false, 2, 8, 0);currentBricks[42] = new Brick(180, 90, false, 2, 8, 0);currentBricks[43] = new Brick(220, 90, false, 4, 8, 2);currentBricks[44] = new Brick(260, 90, false, 2, 8, 0);currentBricks[45] = new Brick(300, 90, false, 2, 8, 0);currentBricks[46] = new Brick(340, 90, false, 2, 8, 0);currentBricks[47] = new Brick(380, 90, false, 2, 8, 0);currentBricks[48] = new Brick(420, 90, false, 2, 8, 0);currentBricks[49] = new Brick(460, 90, false, 2, 8, 0);currentBricks[50] = new Brick(500, 90, false, 2, 8, 0);currentBricks[51] = new Brick(540, 90, false, 4, 8, 2);currentBricks[52] = new Brick(580, 90, false, 2, 8, 0);currentBricks[53] = new Brick(620, 90, false, 2, 8, 0);currentBricks[54] = new Brick(660, 90, false, 2, 8, 0);currentBricks[55] = new Brick(700, 90, false, 2, 8, 0);currentBricks[56] = new Brick(740, 90, false, 2, 8, 0);currentBricks[57] = new Brick(20, 110, false, 3, 4, 0);currentBricks[58] = new Brick(60, 110, false, 3, 4, 0);currentBricks[59] = new Brick(100, 110, false, 3, 4, 0);currentBricks[60] = new Brick(140, 110, false, 3, 4, 0);currentBricks[61] = new Brick(180, 110, false, 3, 4, 0);currentBricks[62] = new Brick(220, 110, false, 3, 4, 0);currentBricks[63] = new Brick(260, 110, false, 3, 4, 0);currentBricks[64] = new Brick(300, 110, false, 3, 4, 0);currentBricks[65] = new Brick(340, 110, false, 3, 4, 0);currentBricks[66] = new Brick(380, 110, false, 3, 4, 0);currentBricks[67] = new Brick(420, 110, false, 3, 4, 0);currentBricks[68] = new Brick(460, 110, false, 3, 4, 0);currentBricks[69] = new Brick(500, 110, false, 3, 4, 0);currentBricks[70] = new Brick(540, 110, false, 3, 4, 0);currentBricks[71] = new Brick(580, 110, false, 3, 4, 0);currentBricks[72] = new Brick(620, 110, false, 3, 4, 0);currentBricks[73] = new Brick(660, 110, false, 3, 4, 0);currentBricks[74] = new Brick(700, 110, false, 3, 4, 0);currentBricks[75] = new Brick(740, 110, false, 3, 4, 0); + } +}