mirror of
https://codeberg.org/boyfailure/VectorBreakout.git
synced 2025-06-08 07:34:05 +10:00
Refactor Part 2: Lots of renaming, new classes, hitbox changes
This commit is contained in:
parent
475af2c03e
commit
98883aa62a
21 changed files with 1549 additions and 790 deletions
18
nb-configuration.xml
Normal file
18
nb-configuration.xml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project-shared-configuration>
|
||||||
|
<!--
|
||||||
|
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||||
|
The configuration is intended to be shared among all the users of project and
|
||||||
|
therefore it is assumed to be part of version control checkout.
|
||||||
|
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||||
|
-->
|
||||||
|
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||||
|
<!--
|
||||||
|
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||||
|
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||||
|
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||||
|
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||||
|
-->
|
||||||
|
<netbeans.hint.license>apache20</netbeans.hint.license>
|
||||||
|
</properties>
|
||||||
|
</project-shared-configuration>
|
8
pom.xml
8
pom.xml
|
@ -4,9 +4,9 @@
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>dev.boyfailure.quajra</groupId>
|
<groupId>dev.boyfailure</groupId>
|
||||||
<artifactId>VectorBreakout</artifactId>
|
<artifactId>VectorBreakout</artifactId>
|
||||||
<version>20250411_test1</version>
|
<version>1.0</version>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
<maven.compiler.target>21</maven.compiler.target>
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
<maven.compiler.release>21</maven.compiler.release>
|
<maven.compiler.release>21</maven.compiler.release>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<exec.mainClass>dev.boyfailure.quajra.vectorbreakout.VectorBreakout</exec.mainClass>
|
<exec.mainClass>dev.boyfailure.vectorbreakout.VectorBreakout</exec.mainClass>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<archive>
|
<archive>
|
||||||
<manifest>
|
<manifest>
|
||||||
<mainClass>dev.boyfailure.quajra.vectorbreakout.VectorBreakout</mainClass>
|
<mainClass>dev.boyfailure.vectorbreakout.VectorBreakout</mainClass>
|
||||||
</manifest>
|
</manifest>
|
||||||
</archive>
|
</archive>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -1,235 +0,0 @@
|
||||||
package dev.boyfailure.quajra.vectorbreakout;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class Ball {
|
|
||||||
|
|
||||||
short ballX = 250;
|
|
||||||
short ballY = 300;
|
|
||||||
short ballWidth = 7;
|
|
||||||
short ballHeight = 7;
|
|
||||||
private boolean isActive = false;
|
|
||||||
private boolean isInvincible = false;
|
|
||||||
byte ballColor = 0;
|
|
||||||
Hitbox hitBox;
|
|
||||||
|
|
||||||
byte speedX = 5;
|
|
||||||
byte speedY = 5;
|
|
||||||
|
|
||||||
private GameState gameState;
|
|
||||||
|
|
||||||
public Ball(GameState gameState, int x, int y, int width, int height, int color, boolean active) {
|
|
||||||
this.gameState = gameState;
|
|
||||||
this.ballX = (short) x;
|
|
||||||
this.ballY = (short) y;
|
|
||||||
this.ballWidth = (short) width;
|
|
||||||
this.ballHeight = (short) height;
|
|
||||||
this.ballColor = (byte) color;
|
|
||||||
this.hitBox = new Hitbox(x, y, width, height, 1);
|
|
||||||
this.isActive = active;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void spawnBall(boolean useChancey) {
|
|
||||||
if (useChancey) {
|
|
||||||
this.ballX += (short) (gameState.getChancey() * 3);
|
|
||||||
this.ballY += (short) gameState.getChancey();
|
|
||||||
}
|
|
||||||
gameState.ballsOnScreen++;
|
|
||||||
this.isActive = true;
|
|
||||||
gameState.lives--;
|
|
||||||
gameState.textElementList.get(4).setText(String.valueOf(gameState.lives));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void spawnBall(int x, int y) {
|
|
||||||
this.ballX = (short) x;
|
|
||||||
this.ballY = (short) y;
|
|
||||||
gameState.ballsOnScreen++;
|
|
||||||
this.isActive = true;
|
|
||||||
gameState.lives--;
|
|
||||||
gameState.textElementList.get(4).setText(String.valueOf(gameState.lives));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void moveBall() {
|
|
||||||
this.ballX += this.speedX;
|
|
||||||
this.ballY += this.speedY;
|
|
||||||
|
|
||||||
this.hitBox.moveTo(this.ballX, this.ballY, this.ballWidth, this.ballHeight);
|
|
||||||
|
|
||||||
this.checkCollision();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void bounce(int bounceType) {
|
|
||||||
switch((byte) bounceType) {
|
|
||||||
case 0:
|
|
||||||
this.speedY = (byte) -(this.speedY);
|
|
||||||
switch (gameState.getChancey()) {
|
|
||||||
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;
|
|
||||||
gameState.ballsOnScreen--;
|
|
||||||
if (gameState.ballsOnScreen <= 0) {
|
|
||||||
gameState.ballsOnScreen = 0;
|
|
||||||
if (gameState.lives <= 0) {
|
|
||||||
gameState.gameLose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks to see if the ball is in contact with bricks, paddles, or walls
|
|
||||||
public void checkCollision() {
|
|
||||||
|
|
||||||
this.setInvincibilityState(true); // Delay bouncing again for a frame
|
|
||||||
|
|
||||||
// Check floor
|
|
||||||
if (this.ballY >= gameState.getInternalResY()) {
|
|
||||||
this.destroyBall();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Check ceiling
|
|
||||||
else if (this.ballY <= 0) {
|
|
||||||
this.bounce(0);
|
|
||||||
this.ballY = 0;
|
|
||||||
this.wallBounceAnimation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check walls
|
|
||||||
if (this.ballX <= 20) {
|
|
||||||
this.bounce(1);
|
|
||||||
this.ballX = 22;
|
|
||||||
this.wallBounceAnimation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if ((this.ballX + this.ballWidth) >= (gameState.getInternalResX() - 20 - this.ballWidth)) {
|
|
||||||
this.bounce((byte) 1);
|
|
||||||
this.ballX = (short) (gameState.getInternalResX() - 25 - this.ballWidth);
|
|
||||||
this.wallBounceAnimation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check bricks
|
|
||||||
if (gameState.currentLevel != null) {
|
|
||||||
if (gameState.currentLevel.brickList != null) {
|
|
||||||
for (Brick brick : gameState.currentLevel.brickList) {
|
|
||||||
if (this.hitBox.collides(brick.hitBox.getBounds())) {
|
|
||||||
brick.breakBrick();
|
|
||||||
this.bounce(0);
|
|
||||||
gameState.brickCollector.add(brick);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check paddles
|
|
||||||
for (Paddle paddle : gameState.paddleList) {
|
|
||||||
if (this.hitBox.collides(paddle.hitBox.getBounds())) {
|
|
||||||
if (this.hitBox.collides(paddle.hitBoxLeft.getBounds())) {
|
|
||||||
this.bounce(2);
|
|
||||||
}
|
|
||||||
else if (this.hitBox.collides(paddle.hitBoxRight.getBounds())) {
|
|
||||||
this.bounce(3);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.bounce(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ballY -= 2;
|
|
||||||
|
|
||||||
// Draw particles
|
|
||||||
Particle particle1, particle2, particle3;
|
|
||||||
particle1 = new Particle(gameState, 0, this.ballX, this.ballY - 10, 0, -2, 1, 2, 7, 3);
|
|
||||||
particle2 = new Particle(gameState, 0, this.ballX - 3, this.ballY - 10, -2, -4, 1, 2, 6, 3);
|
|
||||||
particle3 = new Particle(gameState, 0, this.ballX + 10, this.ballY - 10, 2, -4, 1, 2, 8, 3);
|
|
||||||
gameState.particleList.add(particle1);
|
|
||||||
gameState.particleList.add(particle2);
|
|
||||||
gameState.particleList.add(particle3);
|
|
||||||
particle1.spawn(5);
|
|
||||||
particle2.spawn(5);
|
|
||||||
particle3.spawn(5);
|
|
||||||
|
|
||||||
return; // Prevents bouncing multiple times
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void wallBounceAnimation() {
|
|
||||||
Particle particle1, particle2, particle3, particle4;
|
|
||||||
particle1 = new Particle(gameState, 0, this.ballX - 3, this.ballY - 10, -2, -2, 1, 2, 6, 3);
|
|
||||||
particle2 = new Particle(gameState, 0, this.ballX + 10, this.ballY - 10, 2, -2, 1, 2, 8, 3);
|
|
||||||
particle3 = new Particle(gameState, 0, this.ballX - 3, this.ballY + 3, 2, 2, 1, 2, 2, 3);
|
|
||||||
particle4 = new Particle(gameState, 0, this.ballX + 10, this.ballY + 3, -2, 2, 1, 2, 4, 3);
|
|
||||||
gameState.particleList.add(particle1);
|
|
||||||
gameState.particleList.add(particle2);
|
|
||||||
gameState.particleList.add(particle3);
|
|
||||||
gameState.particleList.add(particle4);
|
|
||||||
particle1.spawn(5);
|
|
||||||
particle2.spawn(5);
|
|
||||||
particle3.spawn(5);
|
|
||||||
particle4.spawn(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getActiveState() {
|
|
||||||
return this.isActive;
|
|
||||||
}
|
|
||||||
public void setActiveState(boolean activeState) {
|
|
||||||
this.isActive = activeState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getInvincibilityState() {
|
|
||||||
return this.isInvincible;
|
|
||||||
}
|
|
||||||
public void setInvincibilityState(boolean invincibilityState) {
|
|
||||||
this.isInvincible = invincibilityState;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
package dev.boyfailure.quajra.vectorbreakout;
|
|
||||||
|
|
||||||
public class Brick {
|
|
||||||
|
|
||||||
short brickX;
|
|
||||||
short brickY;
|
|
||||||
short brickWidth = 40;
|
|
||||||
short brickHeight = 17;
|
|
||||||
private boolean isBroken = false;
|
|
||||||
byte brickColor = 0;
|
|
||||||
byte scoreOnBreak = 10;
|
|
||||||
byte specialAbility = 0;
|
|
||||||
Hitbox hitBox;
|
|
||||||
|
|
||||||
private GameState gameState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bricks.
|
|
||||||
* @param gameState The GameState in which the Brick will reside.
|
|
||||||
* @param x The x coordinate of the Brick.
|
|
||||||
* @param y The y coordinate of the Brick.
|
|
||||||
* @param isBroken Determines whether the Brick is broken.
|
|
||||||
* @param brickColor The color code of the Brick.
|
|
||||||
* @param score The score the Player earns upon breaking the Brick.
|
|
||||||
* @param specialAbility A special event that occurs upon breaking the Brick.
|
|
||||||
*/
|
|
||||||
public Brick(GameState gameState, int x, int y, boolean isBroken, int brickColor, int score, int specialAbility) {
|
|
||||||
this.gameState = gameState;
|
|
||||||
this.brickX = (short) x;
|
|
||||||
this.brickY = (short) y;
|
|
||||||
this.isBroken = isBroken;
|
|
||||||
this.brickColor = (byte) brickColor;
|
|
||||||
this.scoreOnBreak = (byte) score;
|
|
||||||
this.hitBox = new Hitbox(x, y, this.brickWidth, this.brickHeight, 0);
|
|
||||||
this.specialAbility = (byte) specialAbility;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void breakBrick() {
|
|
||||||
if (!isBroken) {
|
|
||||||
isBroken = true;
|
|
||||||
gameState.score += this.scoreOnBreak + (gameState.level - 1);
|
|
||||||
gameState.textElementList.get(3).setText(String.valueOf(gameState.score));
|
|
||||||
gameState.bricksOnScreen--;
|
|
||||||
switch(this.specialAbility) {
|
|
||||||
case 1:
|
|
||||||
gameState.lives++;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
Ball ball = new Ball(gameState, 300, 300, 7, 7, 0, true);
|
|
||||||
ball.spawnBall((this.brickX + (this.brickWidth / 2)), (this.brickY + (this.brickHeight / 2)));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw particles
|
|
||||||
Particle particle1, particle2, particle3;
|
|
||||||
particle1 = new Particle(gameState, 0, this.brickX + 12, this.brickY + 3, 1, 1, this.brickColor, 2, 4, 1);
|
|
||||||
particle2 = new Particle(gameState, 0, this.brickX + 20, this.brickY + 13, 1, 1, this.brickColor, 2, 3, 1);
|
|
||||||
particle3 = new Particle(gameState, 0, this.brickX + 32, this.brickY + 7, 1, 1, this.brickColor, 2, 2, 1);
|
|
||||||
gameState.particleList.add(particle1);
|
|
||||||
gameState.particleList.add(particle2);
|
|
||||||
gameState.particleList.add(particle3);
|
|
||||||
particle1.spawn(5);
|
|
||||||
particle2.spawn(5);
|
|
||||||
particle3.spawn(5);
|
|
||||||
|
|
||||||
this.brickX = 32767;
|
|
||||||
this.brickY = 32767;
|
|
||||||
this.hitBox.moveTo(32760, 32760, 2, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getBrokenState() {
|
|
||||||
return this.isBroken;
|
|
||||||
}
|
|
||||||
public void setBrokenState(boolean brokenState) {
|
|
||||||
this.isBroken = brokenState;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
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;
|
|
||||||
Hitbox hitBox;
|
|
||||||
Hitbox hitBoxLeft;
|
|
||||||
Hitbox hitBoxRight;
|
|
||||||
|
|
||||||
private GameState gameState;
|
|
||||||
|
|
||||||
public Paddle(GameState gameState, int x, int y, int width, int height, int paddleColor) {
|
|
||||||
this.gameState = gameState;
|
|
||||||
this.paddleX = (short) x;
|
|
||||||
this.paddleY = (short) y;
|
|
||||||
this.paddleWidth = (short) width;
|
|
||||||
this.paddleHeight = (short) height;
|
|
||||||
this.paddleColor = (byte) paddleColor;
|
|
||||||
this.hitBox = new Hitbox(x, y, width, height, 4);
|
|
||||||
this.hitBoxLeft = new Hitbox(x, y, width / 5, height, 4);
|
|
||||||
this.hitBoxRight = new Hitbox(x + ((width / 5) * 4), y, width / 5, height, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 >= (gameState.getInternalResX() - this.paddleWidth - 20)) {this.paddleX = (short) (gameState.getInternalResX() - this.paddleWidth - 20);}
|
|
||||||
|
|
||||||
this.hitBox.moveTo(this.paddleX, this.paddleY, this.paddleWidth, this.paddleHeight);
|
|
||||||
this.hitBoxLeft.moveTo(this.paddleX, this.paddleY, this.paddleWidth / 5, this.paddleHeight);
|
|
||||||
this.hitBoxRight.moveTo(this.paddleX + ((this.paddleWidth / 5) * 4), this.paddleY, this.paddleWidth / 5, this.paddleHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cullPaddle() {
|
|
||||||
isActive = false;
|
|
||||||
this.paddleX = 32767;
|
|
||||||
this.paddleY = 32767;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getActiveState() {
|
|
||||||
return this.isActive;
|
|
||||||
}
|
|
||||||
public void setActiveState(boolean activeState) {
|
|
||||||
this.isActive = activeState;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,126 +0,0 @@
|
||||||
package dev.boyfailure.quajra.vectorbreakout;
|
|
||||||
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
public class TextElement {
|
|
||||||
|
|
||||||
String text;
|
|
||||||
boolean active = true;
|
|
||||||
private boolean isVisible = false;
|
|
||||||
float textScale = 1;
|
|
||||||
float vectorScale = 1;
|
|
||||||
byte textColor;
|
|
||||||
short x;
|
|
||||||
short y;
|
|
||||||
short duration = 0;
|
|
||||||
long creationTime;
|
|
||||||
|
|
||||||
private GameState gameState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Text elements.
|
|
||||||
* @param gameState The GameState in which the TextElement will reside.
|
|
||||||
* @param text The text that will be displayed.
|
|
||||||
* @param textScale The size of the text on screen.
|
|
||||||
* @param x The x coordinate of the text's origin point.
|
|
||||||
* @param y The y coordinate of the text's origin point.
|
|
||||||
* @param textColor The color of the text.
|
|
||||||
* @param vectorScale The scale of the text.
|
|
||||||
*/
|
|
||||||
public TextElement(GameState gameState, String text, float textScale, int x, int y, int textColor, float vectorScale) {
|
|
||||||
this.gameState = gameState;
|
|
||||||
this.text = text;
|
|
||||||
this.textScale = textScale;
|
|
||||||
this.x = (short) x;
|
|
||||||
this.y = (short) y;
|
|
||||||
this.textColor = (byte) textColor;
|
|
||||||
this.vectorScale = vectorScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Text elements with a fadeout timer.
|
|
||||||
* @param gameState The GameState in which the TextElement will reside.
|
|
||||||
* @param text The text that will be displayed.
|
|
||||||
* @param textScale The size of the text on screen.
|
|
||||||
* @param x The x coordinate of the text's origin point.
|
|
||||||
* @param y The y coordinate of the text's origin point.
|
|
||||||
* @param textColor The color of the text.
|
|
||||||
* @param vectorScale The scale of the text.
|
|
||||||
* @param duration How long the text will stay on screen, in milliseconds.
|
|
||||||
*/
|
|
||||||
public TextElement(GameState gameState, String text, float textScale, int x, int y, int textColor, float vectorScale, int duration) {
|
|
||||||
this.gameState = gameState;
|
|
||||||
this.text = text;
|
|
||||||
this.textScale = textScale;
|
|
||||||
this.x = (short) x;
|
|
||||||
this.y = (short) y;
|
|
||||||
this.textColor = (byte) textColor;
|
|
||||||
this.vectorScale = vectorScale;
|
|
||||||
this.duration = (short) duration;
|
|
||||||
this.creationTime = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getActiveState() {
|
|
||||||
return this.active;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Prepares the TextElement for rendering.
|
|
||||||
*/
|
|
||||||
public void activateTimer() {
|
|
||||||
this.active = true;
|
|
||||||
long testLong = this.creationTime;
|
|
||||||
if (this.duration > 0) {
|
|
||||||
Timer levelTitleGTFO = new Timer();
|
|
||||||
levelTitleGTFO.schedule(new TimerTask() {
|
|
||||||
public void run() {
|
|
||||||
TextElement.this.setVisibility(false);
|
|
||||||
}
|
|
||||||
}, this.duration);
|
|
||||||
}
|
|
||||||
this.setVisibility(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getVisibility() {
|
|
||||||
return this.isVisible;
|
|
||||||
}
|
|
||||||
public void setVisibility(boolean visibility) {
|
|
||||||
this.isVisible = visibility;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares the TextElement for culling.
|
|
||||||
*/
|
|
||||||
public void cull() {
|
|
||||||
this.active = false;
|
|
||||||
this.x = 32767;
|
|
||||||
this.y = 32767;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the text that the TextElement will display.
|
|
||||||
* @param text The text that the TextElement will display.
|
|
||||||
*/
|
|
||||||
public void setText(String text) {
|
|
||||||
this.text = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the text that the TextElement will display.
|
|
||||||
* @param x The x coordinate of the text's origin point.
|
|
||||||
* @param y The y coordinate of the text's origin point.
|
|
||||||
*/
|
|
||||||
public void moveTo(int x, int y) {
|
|
||||||
this.x = (short) x;
|
|
||||||
this.y = (short) y;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the color of the text.
|
|
||||||
* @param textColor The color code of the text.
|
|
||||||
*/
|
|
||||||
public void setColor(int textColor) {
|
|
||||||
this.textColor = (byte) textColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
package dev.boyfailure.quajra.vectorbreakout;
|
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.awt.event.ComponentAdapter;
|
|
||||||
import java.awt.event.ComponentEvent;
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.Timer;
|
|
||||||
|
|
||||||
public class VectorBreakout {
|
|
||||||
|
|
||||||
// The embeddable game
|
|
||||||
public static GameState gameState = new GameState();
|
|
||||||
|
|
||||||
// The window for the game
|
|
||||||
public static JFrame gameFrame = new JFrame();
|
|
||||||
public static GameDisplay gameCanvas = new GameDisplay(gameState);
|
|
||||||
|
|
||||||
public VectorBreakout() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
|
|
||||||
// Enable OpenGL for hardware acceleration
|
|
||||||
System.setProperty("sun.java2d.opengl", "true");
|
|
||||||
|
|
||||||
// Set the game window's properties
|
|
||||||
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
||||||
gameFrame.setTitle(gameState.gameName);
|
|
||||||
gameFrame.setSize(gameState.getInternalResX(), gameState.getInternalResY());
|
|
||||||
gameFrame.getContentPane().setBackground(Color.black);
|
|
||||||
gameFrame.getContentPane().add(gameCanvas);
|
|
||||||
gameFrame.setVisible(true);
|
|
||||||
|
|
||||||
gameFrame.addKeyListener(gameState.getKeyListener());
|
|
||||||
|
|
||||||
// Adapts vector drawing scale when the window is resized
|
|
||||||
gameFrame.addComponentListener(new ComponentAdapter() {
|
|
||||||
public void componentResized(ComponentEvent componentEvent) {
|
|
||||||
gameState.setWindowResX((short) gameFrame.getBounds().width);
|
|
||||||
gameState.setWindowResY((short) gameFrame.getBounds().height);
|
|
||||||
gameCanvas.setBeamScaleX(gameState.getWindowResX() / 800f);
|
|
||||||
gameCanvas.setBeamScaleY(gameState.getWindowResY() / 600f);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Timer gameTick = new Timer((1000 / gameState.getGameTickRate()), gameState.getGameTickActionListener());
|
|
||||||
gameTick.start();
|
|
||||||
|
|
||||||
Timer frameDisplay = new Timer((1000 / gameState.getTargetFrameRate()), new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
gameState.incrementFrameCounter();
|
|
||||||
gameFrame.repaint();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
frameDisplay.start();
|
|
||||||
|
|
||||||
Timer gameCuller = new Timer(1000, gameState.getGameStateUpdateActionListener());
|
|
||||||
gameCuller.start();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
283
src/main/java/dev/boyfailure/vectorbreakout/Ball.java
Normal file
283
src/main/java/dev/boyfailure/vectorbreakout/Ball.java
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Naomi (boyfailure.dev).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The balls that move around the playfield and hit bricks.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 20250323
|
||||||
|
*/
|
||||||
|
public class Ball extends Entity {
|
||||||
|
|
||||||
|
private boolean isActive = false;
|
||||||
|
private boolean isInvincible = false;
|
||||||
|
byte ballColor = 0;
|
||||||
|
|
||||||
|
byte speedX = 5;
|
||||||
|
byte speedY = 5;
|
||||||
|
|
||||||
|
private GameState gameState;
|
||||||
|
|
||||||
|
public Ball(GameState gameState, int x, int y, int width, int height, int color, boolean active) {
|
||||||
|
this.gameState = gameState;
|
||||||
|
this.posX = (short) x;
|
||||||
|
this.posY = (short) y;
|
||||||
|
this.width = (short) width;
|
||||||
|
this.height = (short) height;
|
||||||
|
this.ballColor = (byte) color;
|
||||||
|
this.hitBox = new Hitbox(x, y, width, height, 1);
|
||||||
|
this.isActive = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void spawnBall(boolean useLFSR) {
|
||||||
|
if (useLFSR) {this.spawnBall(((gameState.getPokey().getDecimalValue() / 2) + gameState.getPokey().getShiftedDecimalValue() + 30), (this.posY + (gameState.getPokey().getDecimalValue() / 4)) - 40);}
|
||||||
|
else {this.spawnBall(this.posX, this.posY);}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void spawnBall(int x, int y) {
|
||||||
|
this.posX = (short) x;
|
||||||
|
this.posY = (short) y;
|
||||||
|
this.isActive = true;
|
||||||
|
if (gameState.getBalls().size() <= 1) {
|
||||||
|
gameState.removeLife();
|
||||||
|
gameState.getTextElements().get(4).setText(String.valueOf(gameState.getLives()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moveBall() {
|
||||||
|
this.posX += this.speedX;
|
||||||
|
this.posY += this.speedY;
|
||||||
|
|
||||||
|
this.hitBox.moveTo(this.posX, this.posY, this.width, this.height);
|
||||||
|
|
||||||
|
this.checkCollision();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Richochets the ball.
|
||||||
|
* @param bounceType The code for which direction the ball bounces
|
||||||
|
*/
|
||||||
|
public void bounce(int bounceType) {
|
||||||
|
switch((byte) bounceType) {
|
||||||
|
case 0:
|
||||||
|
this.speedY = (byte) -(this.speedY);
|
||||||
|
byte randByte = (byte) (gameState.getPokey().getDecimalValue() / 16);
|
||||||
|
if (randByte < 0) {randByte = 0;}
|
||||||
|
else if (randByte > 15) {randByte = 15;}
|
||||||
|
switch (randByte) {
|
||||||
|
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.posX = 32767;
|
||||||
|
this.posY = 32767;
|
||||||
|
this.hitBox.setBounds(32766, 32766, 32767, 32767);
|
||||||
|
if (gameState.getBalls().size() <= 1) {
|
||||||
|
if (gameState.getLives() <= 0) {
|
||||||
|
gameState.gameLose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cull() {
|
||||||
|
this.isActive = false;
|
||||||
|
this.posX = 32767;
|
||||||
|
this.posY = 32767;
|
||||||
|
this.hitBox.setBounds(32766, 32766, 32767, 32767);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks to see if the ball is in contact with other Entities and walls.
|
||||||
|
*/
|
||||||
|
public synchronized void checkCollision() {
|
||||||
|
|
||||||
|
this.setInvincibilityState(true); // Delay bouncing again for a frame
|
||||||
|
|
||||||
|
// Check floor
|
||||||
|
if (this.posY >= gameState.getInternalResY()) {
|
||||||
|
this.destroyBall();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check ceiling
|
||||||
|
else if (this.posY <= 0) {
|
||||||
|
this.bounce(0);
|
||||||
|
this.posY = 0;
|
||||||
|
this.wallBounceAnimation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check walls
|
||||||
|
if (this.posX <= 20) {
|
||||||
|
this.bounce(1);
|
||||||
|
this.posX = 22;
|
||||||
|
this.wallBounceAnimation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ((this.posX + this.width) >= (gameState.getInternalResX() - 20 - this.width)) {
|
||||||
|
this.bounce(1);
|
||||||
|
this.posX = (short) (gameState.getInternalResX() - 25 - this.width);
|
||||||
|
this.wallBounceAnimation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check bricks
|
||||||
|
if (gameState.getCurrentLevel() != null) {
|
||||||
|
if (gameState.getCurrentLevel().brickList != null) {
|
||||||
|
for (Brick brick : gameState.getCurrentLevel().brickList) {
|
||||||
|
// Check for left bounce
|
||||||
|
if (this.hitBox.collides(brick.hitBoxLeft.getBounds())) {
|
||||||
|
if (this.hitBox.collides(brick.hitBox.getBounds())) {
|
||||||
|
this.bounce(0);
|
||||||
|
this.bounce(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.bounce(1);
|
||||||
|
}
|
||||||
|
brick.breakBrick();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check for right bounce
|
||||||
|
else if (this.hitBox.collides(brick.hitBoxRight.getBounds())) {
|
||||||
|
if (this.hitBox.collides(brick.hitBox.getBounds())) {
|
||||||
|
this.bounce(0);
|
||||||
|
this.bounce(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.bounce(1);
|
||||||
|
}
|
||||||
|
brick.breakBrick();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check for vertical bounce
|
||||||
|
else if (this.hitBox.collides(brick.hitBox.getBounds())) {
|
||||||
|
brick.breakBrick();
|
||||||
|
this.bounce(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check paddles
|
||||||
|
for (Paddle paddle : gameState.getPaddles()) {
|
||||||
|
if (this.hitBox.collides(paddle.hitBox.getBounds())) {
|
||||||
|
if (this.hitBox.collides(paddle.hitBoxLeft.getBounds())) {
|
||||||
|
this.bounce(2);
|
||||||
|
}
|
||||||
|
else if (this.hitBox.collides(paddle.hitBoxRight.getBounds())) {
|
||||||
|
this.bounce(3);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.bounce(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.posY -= 2;
|
||||||
|
|
||||||
|
// Draw particles
|
||||||
|
Particle particle1, particle2, particle3;
|
||||||
|
particle1 = new Particle(gameState, 0, this.posX, this.posY - 10, 0, -2, 1, 2, 7, 3);
|
||||||
|
particle2 = new Particle(gameState, 0, this.posX - 3, this.posY - 10, -2, -4, 1, 2, 6, 3);
|
||||||
|
particle3 = new Particle(gameState, 0, this.posX + 10, this.posY - 10, 2, -4, 1, 2, 8, 3);
|
||||||
|
gameState.getParticles().add(particle1);
|
||||||
|
gameState.getParticles().add(particle2);
|
||||||
|
gameState.getParticles().add(particle3);
|
||||||
|
particle1.spawn(5);
|
||||||
|
particle2.spawn(5);
|
||||||
|
particle3.spawn(5);
|
||||||
|
|
||||||
|
return; // Prevents bouncing multiple times
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void wallBounceAnimation() {
|
||||||
|
Particle particle1, particle2, particle3, particle4;
|
||||||
|
particle1 = new Particle(gameState, 0, this.posX - 3, this.posY - 10, -2, -2, 1, 2, 6, 3);
|
||||||
|
particle2 = new Particle(gameState, 0, this.posX + 10, this.posY - 10, 2, -2, 1, 2, 8, 3);
|
||||||
|
particle3 = new Particle(gameState, 0, this.posX - 3, this.posY + 3, 2, 2, 1, 2, 2, 3);
|
||||||
|
particle4 = new Particle(gameState, 0, this.posX + 10, this.posY + 3, -2, 2, 1, 2, 4, 3);
|
||||||
|
gameState.getParticles().add(particle1);
|
||||||
|
gameState.getParticles().add(particle2);
|
||||||
|
gameState.getParticles().add(particle3);
|
||||||
|
gameState.getParticles().add(particle4);
|
||||||
|
particle1.spawn(5);
|
||||||
|
particle2.spawn(5);
|
||||||
|
particle3.spawn(5);
|
||||||
|
particle4.spawn(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getActiveState() {
|
||||||
|
return this.isActive;
|
||||||
|
}
|
||||||
|
public void setActiveState(boolean activeState) {
|
||||||
|
this.isActive = activeState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getInvincibilityState() {
|
||||||
|
return this.isInvincible;
|
||||||
|
}
|
||||||
|
public void setInvincibilityState(boolean invincibilityState) {
|
||||||
|
this.isInvincible = invincibilityState;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
120
src/main/java/dev/boyfailure/vectorbreakout/Brick.java
Normal file
120
src/main/java/dev/boyfailure/vectorbreakout/Brick.java
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Naomi (boyfailure.dev).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bricks that appear in each level.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 20250323
|
||||||
|
*/
|
||||||
|
public class Brick extends Entity {
|
||||||
|
|
||||||
|
private boolean isBroken = false;
|
||||||
|
byte brickColor = 0;
|
||||||
|
byte scoreOnBreak = 10;
|
||||||
|
byte specialAbility = 0;
|
||||||
|
Hitbox hitBoxLeft;
|
||||||
|
Hitbox hitBoxRight;
|
||||||
|
|
||||||
|
private GameState gameState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a brick.
|
||||||
|
* @param gameState The GameState in which the Brick will reside.
|
||||||
|
* @param x The x coordinate of the Brick.
|
||||||
|
* @param y The y coordinate of the Brick.
|
||||||
|
* @param isBroken Determines whether the Brick is broken.
|
||||||
|
* @param brickColor The color code of the Brick.
|
||||||
|
* @param score The score the Player earns upon breaking the Brick.
|
||||||
|
* @param specialAbility A special event that occurs upon breaking the Brick.
|
||||||
|
*/
|
||||||
|
public Brick(GameState gameState, int x, int y, boolean isBroken, int brickColor, int score, int specialAbility) {
|
||||||
|
this.width = 40;
|
||||||
|
this.height = 17;
|
||||||
|
this.gameState = gameState;
|
||||||
|
this.posX = (short) x;
|
||||||
|
this.posY = (short) y;
|
||||||
|
this.isBroken = isBroken;
|
||||||
|
this.brickColor = (byte) brickColor;
|
||||||
|
this.scoreOnBreak = (byte) score;
|
||||||
|
this.hitBox = new Hitbox(x + 2, y, this.width - 4, this.height, 0);
|
||||||
|
this.hitBoxLeft = new Hitbox(x, y + 2, 6, this.height - 4, 0);
|
||||||
|
this.hitBoxRight = new Hitbox(x + this.width - 6, y + 2, 6, this.height - 4, 0);
|
||||||
|
this.specialAbility = (byte) specialAbility;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void breakBrick() {
|
||||||
|
if (!isBroken) {
|
||||||
|
isBroken = true;
|
||||||
|
gameState.addScore(this.scoreOnBreak + (gameState.getCurrentLevelID() - 1));
|
||||||
|
gameState.getTextElements().get(3).setText(String.valueOf(gameState.getScore()));
|
||||||
|
switch(this.specialAbility) {
|
||||||
|
case 1:
|
||||||
|
gameState.addLife();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
while (gameState.getCollectorActiveState()) {}
|
||||||
|
Ball newBall = new Ball(gameState, 300, 300, 7, 7, 0, true);
|
||||||
|
this.gameState.getBalls().add(newBall);
|
||||||
|
newBall.spawnBall((this.posX + (this.width / 2)), (this.posY + (this.height / 2)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show score on break
|
||||||
|
TextElement bruh = new TextElement(this.gameState,
|
||||||
|
String.valueOf(this.scoreOnBreak),
|
||||||
|
0.25f,
|
||||||
|
this.posX + (this.width / 3),
|
||||||
|
this.posY - 3,
|
||||||
|
this.brickColor,
|
||||||
|
1,
|
||||||
|
300);
|
||||||
|
bruh.activateTimer();
|
||||||
|
bruh.setActiveState(true);
|
||||||
|
//bruh.moveUpOnFrame();
|
||||||
|
this.gameState.getTextElements().add(bruh);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw particles
|
||||||
|
Particle particle1, particle2, particle3;
|
||||||
|
particle1 = new Particle(gameState, 0, this.posX + 12, this.posY + 3, 1, 1, this.brickColor, 2, 4, 1);
|
||||||
|
particle2 = new Particle(gameState, 0, this.posX + 20, this.posY + 13, 1, 1, this.brickColor, 2, 3, 1);
|
||||||
|
particle3 = new Particle(gameState, 0, this.posX + 32, this.posY + 7, 1, 1, this.brickColor, 2, 2, 1);
|
||||||
|
gameState.getParticles().add(particle1);
|
||||||
|
gameState.getParticles().add(particle2);
|
||||||
|
gameState.getParticles().add(particle3);
|
||||||
|
particle1.spawn(5);
|
||||||
|
particle2.spawn(5);
|
||||||
|
particle3.spawn(5);
|
||||||
|
|
||||||
|
this.posX = 32767;
|
||||||
|
this.posY = 32767;
|
||||||
|
this.hitBox.moveTo(32760, 32760, 2, 2);
|
||||||
|
this.hitBoxLeft.moveTo(32760, 32760, 2, 2);
|
||||||
|
this.hitBoxRight.moveTo(32760, 32760, 2, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getBrokenState() {
|
||||||
|
return this.isBroken;
|
||||||
|
}
|
||||||
|
public void setBrokenState(boolean brokenState) {
|
||||||
|
this.isBroken = brokenState;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
65
src/main/java/dev/boyfailure/vectorbreakout/Entity.java
Normal file
65
src/main/java/dev/boyfailure/vectorbreakout/Entity.java
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 naomi.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all entities in the game.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public class Entity {
|
||||||
|
|
||||||
|
/** The horizontal position of the entity, in pixels. */
|
||||||
|
short posX;
|
||||||
|
/** The vertical position of the entity, in pixels. */
|
||||||
|
short posY;
|
||||||
|
/** The width of the entity, in pixels. */
|
||||||
|
short width;
|
||||||
|
/** The height of the entity, in pixels. */
|
||||||
|
short height;
|
||||||
|
/** The default hitbox of the entity. */
|
||||||
|
Hitbox hitBox;
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Accessor methods (get/set) ">
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the position of the entity as a Point.
|
||||||
|
* @return the position of the entity
|
||||||
|
*/
|
||||||
|
public Point getPosition() {
|
||||||
|
return new Point(this.posX, this.posY);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the horizontal position of the entity.
|
||||||
|
* @return the horizontal position of the entity
|
||||||
|
*/
|
||||||
|
public short getPositionX() {
|
||||||
|
return this.posX;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the vertical position of the entity.
|
||||||
|
* @return the vertical position of the entity
|
||||||
|
*/
|
||||||
|
public short getPositionY() {
|
||||||
|
return this.posY;
|
||||||
|
}
|
||||||
|
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,20 @@
|
||||||
package dev.boyfailure.quajra.vectorbreakout;
|
/*
|
||||||
|
* Copyright 2025 Naomi (boyfailure.dev).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
import java.awt.BasicStroke;
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
@ -7,6 +23,11 @@ import java.awt.Graphics2D;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import java.awt.geom.Line2D;
|
import java.awt.geom.Line2D;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logic to draw the game on the screen.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 20250323
|
||||||
|
*/
|
||||||
public class GameDisplay extends JComponent {
|
public class GameDisplay extends JComponent {
|
||||||
|
|
||||||
// Change this to 1 if you build for older versions of Java. Older versions
|
// Change this to 1 if you build for older versions of Java. Older versions
|
||||||
|
@ -45,7 +66,7 @@ public class GameDisplay extends JComponent {
|
||||||
this.beamThicknessScale = beamScale;
|
this.beamThicknessScale = beamScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void paint(Graphics gameGraphics) {
|
public synchronized void paint(Graphics gameGraphics) {
|
||||||
|
|
||||||
super.paint(gameGraphics);
|
super.paint(gameGraphics);
|
||||||
|
|
||||||
|
@ -65,18 +86,18 @@ public class GameDisplay extends JComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bricks
|
// Bricks
|
||||||
if (gameState.currentLevel != null) {
|
if (gameState.getCurrentLevel() != null) {
|
||||||
if (gameState.currentLevel.brickList != null) {
|
if (gameState.getCurrentLevel().brickList != null) {
|
||||||
for (Brick brick : gameState.currentLevel.brickList) {
|
for (Brick brick : gameState.getCurrentLevel().brickList) {
|
||||||
if (!brick.getBrokenState()) {
|
if (!brick.getBrokenState()) {
|
||||||
resetBeam();
|
resetBeam();
|
||||||
g2.setStroke(bt(3));
|
g2.setStroke(bt(3));
|
||||||
moveBeam(brick.brickX + 1, brick.brickY + 1);
|
moveBeam(brick.posX + 1, brick.posY + 1);
|
||||||
g2.setColor(vc(brick.brickColor));
|
g2.setColor(vc(brick.brickColor));
|
||||||
g2.draw(drawVec(brick.brickWidth - 2, 0));
|
g2.draw(drawVec(brick.width - 2, 0));
|
||||||
g2.draw(drawVec(0, -(brick.brickHeight - 2)));
|
g2.draw(drawVec(0, -(brick.height - 2)));
|
||||||
g2.draw(drawVec(-(brick.brickWidth - 2), 0));
|
g2.draw(drawVec(-(brick.width - 2), 0));
|
||||||
g2.draw(drawVec(0, brick.brickHeight - 2));
|
g2.draw(drawVec(0, brick.height - 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,34 +105,34 @@ public class GameDisplay extends JComponent {
|
||||||
|
|
||||||
// Paddles
|
// Paddles
|
||||||
g2.setColor(Color.white);
|
g2.setColor(Color.white);
|
||||||
for (Paddle paddle : gameState.paddleList) {
|
for (Paddle paddle : gameState.getPaddles()) {
|
||||||
if (paddle.getActiveState()) {
|
if (paddle.getActiveState()) {
|
||||||
resetBeam();
|
resetBeam();
|
||||||
g2.setStroke(bt(3));
|
g2.setStroke(bt(3));
|
||||||
moveBeam(paddle.paddleX, paddle.paddleY);
|
moveBeam(paddle.posX, paddle.posY);
|
||||||
g2.draw(drawVec(paddle.paddleWidth, 0));
|
g2.draw(drawVec(paddle.width, 0));
|
||||||
g2.draw(drawVec(0, -(paddle.paddleHeight)));
|
g2.draw(drawVec(0, -(paddle.height)));
|
||||||
g2.draw(drawVec(-(paddle.paddleWidth), 0));
|
g2.draw(drawVec(-(paddle.width), 0));
|
||||||
g2.draw(drawVec(0, paddle.paddleHeight));
|
g2.draw(drawVec(0, paddle.height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Balls
|
// Balls
|
||||||
g2.setStroke(bt(3));
|
g2.setStroke(bt(3));
|
||||||
g2.setColor(Color.yellow);
|
g2.setColor(Color.yellow);
|
||||||
for (Ball ball : gameState.ballList) {
|
for (Ball ball : gameState.getBalls()) {
|
||||||
if (ball.getActiveState()) {
|
if (ball.getActiveState()) {
|
||||||
resetBeam();
|
resetBeam();
|
||||||
moveBeam(ball.ballX, ball.ballY);
|
moveBeam(ball.posX, ball.posY);
|
||||||
g2.draw(drawVec(ball.ballWidth, 0));
|
g2.draw(drawVec(ball.width, 0));
|
||||||
g2.draw(drawVec(0, -ball.ballHeight));
|
g2.draw(drawVec(0, -ball.height));
|
||||||
g2.draw(drawVec(-ball.ballWidth, 0));
|
g2.draw(drawVec(-ball.width, 0));
|
||||||
g2.draw(drawVec(0, ball.ballHeight));
|
g2.draw(drawVec(0, ball.height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Particles
|
// Particles
|
||||||
for (Particle particle : gameState.particleList) {
|
for (Particle particle : gameState.getParticles()) {
|
||||||
if (particle.getActiveState()) {
|
if (particle.getActiveState()) {
|
||||||
resetBeam();
|
resetBeam();
|
||||||
moveBeam(particle.particleX, particle.particleY);
|
moveBeam(particle.particleX, particle.particleY);
|
||||||
|
@ -121,7 +142,8 @@ public class GameDisplay extends JComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TextElements
|
/*
|
||||||
|
* TextElements
|
||||||
*
|
*
|
||||||
* Note on rendering numbers:
|
* Note on rendering numbers:
|
||||||
*
|
*
|
||||||
|
@ -132,24 +154,25 @@ public class GameDisplay extends JComponent {
|
||||||
* systems, I used these goofy if/else statements so I could compile
|
* systems, I used these goofy if/else statements so I could compile
|
||||||
* on the older JDKs and play on my older systems...
|
* on the older JDKs and play on my older systems...
|
||||||
*/
|
*/
|
||||||
for (TextElement element : gameState.textElementList) {
|
for (TextElement element : gameState.getTextElements()) {
|
||||||
if (element.getActiveState() && element.getVisibility()) {
|
if (element.getActiveState() && element.getVisibleState()) {
|
||||||
|
if (element.movesUpOnFrame()) {element.moveTo(element.getPositionX(), element.getPositionY() - 1);}
|
||||||
resetBeam();
|
resetBeam();
|
||||||
moveBeam(element.x, element.y);
|
moveBeam(element.getPositionX(), element.getPositionY());
|
||||||
|
|
||||||
// Save the current beam scale to revert once TextElement is done rendering
|
// Save the current beam scale to revert once TextElement is done rendering
|
||||||
float oldBeamScaleX = beamScaleX;
|
float oldBeamScaleX = this.beamScaleX;
|
||||||
float oldBeamScaleY = beamScaleY;
|
float oldBeamScaleY = this.beamScaleY;
|
||||||
|
|
||||||
// Adjust the beam scale to accomodate the scale of the TextElement
|
// Adjust the beam scale to accomodate the scale of the TextElement
|
||||||
beamScaleX = beamScaleX * element.textScale;
|
this.beamScaleX *= element.getTextScale();
|
||||||
beamScaleY = beamScaleY * element.textScale;
|
this.beamScaleY *= element.getTextScale();
|
||||||
|
|
||||||
// Render the TextElement
|
// Render the TextElement
|
||||||
g2.setColor(vc(element.textColor));
|
g2.setColor(vc(element.getColor()));
|
||||||
g2.setStroke(bt(element.vectorScale));
|
g2.setStroke(bt(element.getVectorThickness()));
|
||||||
String stringToSplit = String.valueOf(element.text);
|
String[] stringToRender = element.getText().split("");
|
||||||
String[] stringToRender = stringToSplit.split("");
|
|
||||||
//<editor-fold defaultstate="collapsed" desc=" Beam routines for letters/numbers ">
|
//<editor-fold defaultstate="collapsed" desc=" Beam routines for letters/numbers ">
|
||||||
for (short i = iStart; i < stringToRender.length; i++) {
|
for (short i = iStart; i < stringToRender.length; i++) {
|
||||||
if ("1".equals(stringToRender[i])) {
|
if ("1".equals(stringToRender[i])) {
|
||||||
|
@ -233,7 +256,7 @@ public class GameDisplay extends JComponent {
|
||||||
}
|
}
|
||||||
// Simulates a newline in a TextElement
|
// Simulates a newline in a TextElement
|
||||||
else if ("\\".equals(stringToRender[i])) {
|
else if ("\\".equals(stringToRender[i])) {
|
||||||
moveBeam(-(beamX - element.x), 30);
|
moveBeam(-(beamX - element.getPositionX()), 30);
|
||||||
}
|
}
|
||||||
else if ("A".equals(stringToRender[i])) {
|
else if ("A".equals(stringToRender[i])) {
|
||||||
g2.draw(drawVec(0, -17));
|
g2.draw(drawVec(0, -17));
|
||||||
|
@ -477,67 +500,81 @@ public class GameDisplay extends JComponent {
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
||||||
// Revert back to the previous beam scale
|
// Revert back to the previous beam scale
|
||||||
beamScaleX = oldBeamScaleX;
|
this.beamScaleX = oldBeamScaleX;
|
||||||
beamScaleY = oldBeamScaleY;
|
this.beamScaleY = oldBeamScaleY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gameState.actualFrames++; // Count up actual frames rendered
|
gameState.incrementActualFrames(); // Count up actual frames rendered
|
||||||
|
|
||||||
// Debug Menu
|
// Debug Menu
|
||||||
if (gameState.getDebugMenuState()) {
|
if (gameState.getDebugMenuState()) {
|
||||||
g2.setColor(Color.white);
|
g2.setColor(Color.white);
|
||||||
g2.drawString(gameState.gameName + " v" + gameState.gameVersion, 1, 12);
|
g2.drawString(gameState.getGameName() + " v" + gameState.getGameVersion(), 1, 12);
|
||||||
g2.drawString("frame: " + gameState.getFrameCounter(), 1, 24);
|
g2.drawString("Frame: " + gameState.getFrameCounter(), 1, 24);
|
||||||
g2.drawString("beamScaleX: " + beamScaleX, 1, 36);
|
g2.drawString("Horizontal beamscale: " + beamScaleX, 1, 36);
|
||||||
g2.drawString("beamScaleY: " + beamScaleY, 1, 48);
|
g2.drawString("Vertical beamscale: " + beamScaleY, 1, 48);
|
||||||
g2.drawString("isPaused: " + gameState.getPausedState(), 1, 60);
|
g2.drawString("Paused: " + gameState.getPausedState(), 1, 60);
|
||||||
g2.drawString("targetFrameRate: " + gameState.getTargetFrameRate(), 150, 24);
|
g2.drawString("Target framerate: " + gameState.getTargetFrameRate(), 150, 24);
|
||||||
g2.drawString("actualFrameRate: " + gameState.getActualFrameRate(), 150, 36);
|
g2.drawString("Actual framerate: " + gameState.getActualFrameRate(), 150, 36);
|
||||||
g2.drawString("actualFrames: " + gameState.actualFrames, 150, 48);
|
g2.drawString("actualFrames: " + gameState.getActualFrames(), 150, 48);
|
||||||
g2.drawString("chancey: " + gameState.getChancey(), 150, 60);
|
g2.drawString("LFSR: " + gameState.getPokey().getDecimalValue(), 150, 60);
|
||||||
g2.drawString("ballsOnScreen: " + gameState.ballsOnScreen, 300, 24);
|
g2.drawString("Ball count: " + gameState.getBalls().size(), 300, 24);
|
||||||
|
g2.drawString("Particle count: " + gameState.getParticles().size(), 300, 36);
|
||||||
|
g2.drawString("Paddle count: " + gameState.getPaddles().size(), 300, 48);
|
||||||
|
g2.drawString("Text count: " + gameState.getTextElements().size(), 300, 60);
|
||||||
|
g2.drawString("Brick count: " + gameState.getCurrentLevel().brickList.size(), 300, 72);
|
||||||
short padBoxX, padBoxY, padBoxX2, padBoxY2;
|
short padBoxX, padBoxY, padBoxX2, padBoxY2;
|
||||||
g2.setStroke(new BasicStroke(1));
|
g2.setStroke(new BasicStroke(1));
|
||||||
|
|
||||||
// Paddles
|
// Paddles
|
||||||
g2.setColor(vc(10, 0.5f));
|
g2.setColor(vc(10, 0.5f));
|
||||||
for (Paddle paddle : gameState.paddleList) {
|
for (Paddle paddle : gameState.getPaddles()) {
|
||||||
padBoxX = (short) paddle.hitBox.getBounds().getBounds2D().getMinX();
|
padBoxX = (short) paddle.hitBox.getBounds().getBounds2D().getMinX();
|
||||||
padBoxY = (short) paddle.hitBox.getBounds().getBounds2D().getMinY();
|
padBoxY = (short) paddle.hitBox.getBounds().getBounds2D().getMinY();
|
||||||
padBoxX2 = (short) paddle.hitBox.getBounds().getBounds2D().getWidth();
|
padBoxX2 = (short) paddle.hitBox.getBounds().getBounds2D().getWidth();
|
||||||
padBoxY2 = (short) paddle.hitBox.getBounds().getBounds2D().getHeight();
|
padBoxY2 = (short) paddle.hitBox.getBounds().getBounds2D().getHeight();
|
||||||
g2.fillRect(padBoxX, padBoxY + (40 - paddle.paddleHeight), padBoxX2, padBoxY2);
|
g2.fillRect(padBoxX, padBoxY + (40 - paddle.height), padBoxX2, padBoxY2);
|
||||||
padBoxX = (short) paddle.hitBoxLeft.getBounds().getBounds2D().getMinX();
|
padBoxX = (short) paddle.hitBoxLeft.getBounds().getBounds2D().getMinX();
|
||||||
padBoxY = (short) paddle.hitBoxLeft.getBounds().getBounds2D().getMinY();
|
padBoxY = (short) paddle.hitBoxLeft.getBounds().getBounds2D().getMinY();
|
||||||
padBoxX2 = (short) paddle.hitBoxLeft.getBounds().getBounds2D().getWidth();
|
padBoxX2 = (short) paddle.hitBoxLeft.getBounds().getBounds2D().getWidth();
|
||||||
padBoxY2 = (short) paddle.hitBoxLeft.getBounds().getBounds2D().getHeight();
|
padBoxY2 = (short) paddle.hitBoxLeft.getBounds().getBounds2D().getHeight();
|
||||||
g2.fillRect(padBoxX, padBoxY + (40 - paddle.paddleHeight), padBoxX2, padBoxY2);
|
g2.fillRect(padBoxX, padBoxY + (40 - paddle.height), padBoxX2, padBoxY2);
|
||||||
padBoxX = (short) paddle.hitBoxRight.getBounds().getBounds2D().getMinX();
|
padBoxX = (short) paddle.hitBoxRight.getBounds().getBounds2D().getMinX();
|
||||||
padBoxY = (short) paddle.hitBoxRight.getBounds().getBounds2D().getMinY();
|
padBoxY = (short) paddle.hitBoxRight.getBounds().getBounds2D().getMinY();
|
||||||
padBoxX2 = (short) paddle.hitBoxRight.getBounds().getBounds2D().getWidth();
|
padBoxX2 = (short) paddle.hitBoxRight.getBounds().getBounds2D().getWidth();
|
||||||
padBoxY2 = (short) paddle.hitBoxRight.getBounds().getBounds2D().getHeight();
|
padBoxY2 = (short) paddle.hitBoxRight.getBounds().getBounds2D().getHeight();
|
||||||
g2.fillRect(padBoxX, padBoxY + (40 - paddle.paddleHeight), padBoxX2, padBoxY2);
|
g2.fillRect(padBoxX, padBoxY + (40 - paddle.height), padBoxX2, padBoxY2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Balls
|
// Balls
|
||||||
g2.setColor(vc(11, 1.0f));
|
g2.setColor(vc(11, 1.0f));
|
||||||
for (Ball ball : gameState.ballList) {
|
for (Ball ball : gameState.getBalls()) {
|
||||||
padBoxX = (short) ball.hitBox.getBounds().getBounds2D().getMinX();
|
padBoxX = (short) ball.hitBox.getBounds().getBounds2D().getMinX();
|
||||||
padBoxY = (short) ball.hitBox.getBounds().getBounds2D().getMinY();
|
padBoxY = (short) ball.hitBox.getBounds().getBounds2D().getMinY();
|
||||||
padBoxX2 = (short) ball.hitBox.getBounds().getBounds2D().getWidth();
|
padBoxX2 = (short) ball.hitBox.getBounds().getBounds2D().getWidth();
|
||||||
padBoxY2 = (short) ball.hitBox.getBounds().getBounds2D().getHeight();
|
padBoxY2 = (short) ball.hitBox.getBounds().getBounds2D().getHeight();
|
||||||
g2.fillRect(padBoxX, padBoxY + (40 - ball.ballHeight), padBoxX2, padBoxY2);
|
g2.fillRect(padBoxX, padBoxY + (40 - ball.height), padBoxX2, padBoxY2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bricks
|
// Bricks
|
||||||
g2.setColor(vc(12, 0.5f));
|
g2.setColor(vc(12, 0.5f));
|
||||||
for (Brick brick : gameState.currentLevel.brickList) {
|
for (Brick brick : gameState.getCurrentLevel().brickList) {
|
||||||
padBoxX = (short) brick.hitBox.getBounds().getBounds2D().getMinX();
|
padBoxX = (short) brick.hitBox.getBounds().getBounds2D().getMinX();
|
||||||
padBoxY = (short) brick.hitBox.getBounds().getBounds2D().getMinY();
|
padBoxY = (short) brick.hitBox.getBounds().getBounds2D().getMinY();
|
||||||
padBoxX2 = (short) brick.hitBox.getBounds().getBounds2D().getWidth();
|
padBoxX2 = (short) brick.hitBox.getBounds().getBounds2D().getWidth();
|
||||||
padBoxY2 = (short) brick.hitBox.getBounds().getBounds2D().getHeight();
|
padBoxY2 = (short) brick.hitBox.getBounds().getBounds2D().getHeight();
|
||||||
g2.fillRect(padBoxX, padBoxY + (40 - brick.brickHeight), padBoxX2, padBoxY2);
|
g2.fillRect(padBoxX, padBoxY + (40 - brick.height), padBoxX2, padBoxY2);
|
||||||
|
padBoxX = (short) brick.hitBoxLeft.getBounds().getBounds2D().getMinX();
|
||||||
|
padBoxY = (short) brick.hitBoxLeft.getBounds().getBounds2D().getMinY();
|
||||||
|
padBoxX2 = (short) brick.hitBoxLeft.getBounds().getBounds2D().getWidth();
|
||||||
|
padBoxY2 = (short) brick.hitBoxLeft.getBounds().getBounds2D().getHeight();
|
||||||
|
g2.fillRect(padBoxX, padBoxY + (40 - brick.height), padBoxX2, padBoxY2);
|
||||||
|
padBoxX = (short) brick.hitBoxRight.getBounds().getBounds2D().getMinX();
|
||||||
|
padBoxY = (short) brick.hitBoxRight.getBounds().getBounds2D().getMinY();
|
||||||
|
padBoxX2 = (short) brick.hitBoxRight.getBounds().getBounds2D().getWidth();
|
||||||
|
padBoxY2 = (short) brick.hitBoxRight.getBounds().getBounds2D().getHeight();
|
||||||
|
g2.fillRect(padBoxX, padBoxY + (40 - brick.height), padBoxX2, padBoxY2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
70
src/main/java/dev/boyfailure/vectorbreakout/GameFrame.java
Normal file
70
src/main/java/dev/boyfailure/vectorbreakout/GameFrame.java
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Naomi (boyfailure.dev).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.event.ComponentAdapter;
|
||||||
|
import java.awt.event.ComponentEvent;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The window in which the game is displayed.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public class GameFrame extends JFrame {
|
||||||
|
|
||||||
|
private GameState gameState;
|
||||||
|
private GameDisplay gameDisplay;
|
||||||
|
|
||||||
|
public GameFrame(GameState gameState, GameDisplay gameDisplay) {
|
||||||
|
this.gameState = gameState;
|
||||||
|
this.gameDisplay = gameDisplay;
|
||||||
|
|
||||||
|
// Set the game window's properties
|
||||||
|
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
this.setTitle(this.gameState.getGameName());
|
||||||
|
this.setSize(this.gameState.getWindowResX(), this.gameState.getWindowResY());
|
||||||
|
this.getContentPane().setBackground(Color.black);
|
||||||
|
this.getContentPane().add(this.gameDisplay);
|
||||||
|
|
||||||
|
// Add the component adapter to change vector drawing scale when the window is resized
|
||||||
|
this.addComponentListener(this.getComponentAdapter());
|
||||||
|
|
||||||
|
// Add the key listener to get player input
|
||||||
|
this.addKeyListener(this.gameState.getKeyListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Event listeners ">
|
||||||
|
|
||||||
|
public ComponentAdapter getComponentAdapter() {
|
||||||
|
return new GameComponentAdapter();
|
||||||
|
}
|
||||||
|
class GameComponentAdapter extends ComponentAdapter {
|
||||||
|
public void componentResized(ComponentEvent componentEvent) {
|
||||||
|
GameFrame.this.gameState.setWindowResX((short) GameFrame.this.getBounds().width);
|
||||||
|
GameFrame.this.gameState.setWindowResY((short) GameFrame.this.getBounds().height);
|
||||||
|
GameFrame.this.gameDisplay.setBeamScaleX(GameFrame.this.gameState.getWindowResX() / 800f);
|
||||||
|
GameFrame.this.gameDisplay.setBeamScaleY(GameFrame.this.gameState.getWindowResY() / 600f);
|
||||||
|
if (GameFrame.this.gameDisplay.getBeamScaleX() <= GameFrame.this.gameDisplay.getBeamScaleY()) {GameFrame.this.gameDisplay.setBeamThicknessScale(GameFrame.this.gameDisplay.getBeamScaleX());}
|
||||||
|
else {GameFrame.this.gameDisplay.setBeamThicknessScale(GameFrame.this.gameDisplay.getBeamScaleY());}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,20 @@
|
||||||
package dev.boyfailure.quajra.vectorbreakout;
|
/*
|
||||||
|
* Copyright 2025 Naomi (boyfailure.dev).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
@ -6,58 +22,70 @@ import java.awt.event.KeyEvent;
|
||||||
import java.awt.event.KeyListener;
|
import java.awt.event.KeyListener;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The embeddable game object which contains the main loop and logic.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 20250511
|
||||||
|
*/
|
||||||
public class GameState {
|
public class GameState {
|
||||||
|
|
||||||
public String gameName = "Vector Breakout";
|
/** The name of the game. */
|
||||||
public String gameVersion = "20250511";
|
private String gameName = "Vector Breakout";
|
||||||
|
/** The version of the game. */
|
||||||
|
private String gameVersion = "1.0";
|
||||||
|
/** Determines whether the game has been started. */
|
||||||
private boolean isGameStarted = false;
|
private boolean isGameStarted = false;
|
||||||
|
/** Determines whether the game has been paused. */
|
||||||
private boolean isPaused = false;
|
private boolean isPaused = false;
|
||||||
|
/** Determines whether the debug menu has been enabled. */
|
||||||
private boolean debugMenuEnabled = false;
|
private boolean debugMenuEnabled = false;
|
||||||
public boolean isLost = false;
|
/** Determines whether the game has been lost. */
|
||||||
public boolean movingLeft = false;
|
private boolean isLost = false;
|
||||||
public boolean movingRight = false;
|
/** Determines whether the player is moving left. */
|
||||||
public boolean confettiMode = false;
|
private boolean movingLeft = false;
|
||||||
public boolean collectorActive = false;
|
/** Determines whether the player is moving right. */
|
||||||
public byte lives = 5;
|
private boolean movingRight = false;
|
||||||
private byte chancey = 0;
|
/** Determines whether "Confetti Mode" (long-lasting particles) has been enabled. */
|
||||||
private final byte maxChanceyValue = 16;
|
private boolean confettiMode = false;
|
||||||
public byte ballsOnScreen = 0;
|
/** Determines whether the collector function is running. */
|
||||||
|
private boolean collectorActive = false;
|
||||||
|
/** The number of lives the player has. */
|
||||||
|
private byte lives = 5;
|
||||||
|
/** The target frame rate for the game. */
|
||||||
private short targetFrameRate = 60;
|
private short targetFrameRate = 60;
|
||||||
public short actualFrames = 0;
|
private short actualFrames = 0;
|
||||||
private short actualFrameRate = 0;
|
private short actualFrameRate = 0;
|
||||||
public byte gameTickRate = 60;
|
private byte gameTickRate = 60;
|
||||||
private short internalResX = 800;
|
private short internalResX = 800;
|
||||||
private short internalResY = 600;
|
private short internalResY = 600;
|
||||||
private short windowResX = 1024;
|
private short windowResX = 1280;
|
||||||
private short windowResY = 768;
|
private short windowResY = 960;
|
||||||
public short level = 1;
|
private short level = 1;
|
||||||
public short bricksOnScreen = 0;
|
private short bricksOnScreen = 0;
|
||||||
public int score = 0;
|
private int score = 0;
|
||||||
private long frameCounter = 0;
|
private long frameCounter = 0;
|
||||||
|
|
||||||
public ArrayList<Ball> ballList;
|
private Level currentLevel;
|
||||||
public ArrayList<Particle> particleList;
|
|
||||||
public ArrayList<Paddle> paddleList;
|
|
||||||
public ArrayList<TextElement> textElementList;
|
|
||||||
|
|
||||||
public ArrayList<Ball> ballCollector;
|
private ArrayList<Ball> ballList;
|
||||||
public ArrayList<Particle> particleCollector;
|
private ArrayList<Particle> particleList;
|
||||||
public ArrayList<Paddle> paddleCollector;
|
private ArrayList<Paddle> paddleList;
|
||||||
public ArrayList<TextElement> textElementCollector;
|
private ArrayList<TextElement> textElementList;
|
||||||
public ArrayList<Brick> brickCollector;
|
|
||||||
|
|
||||||
public Level currentLevel;
|
private ArrayList<Ball> ballCollector;
|
||||||
|
private ArrayList<Particle> particleCollector;
|
||||||
|
private ArrayList<Paddle> paddleCollector;
|
||||||
|
private ArrayList<TextElement> textElementCollector;
|
||||||
|
private ArrayList<Brick> brickCollector;
|
||||||
|
|
||||||
// Debug stuffs
|
private LFSR pokey;
|
||||||
public boolean debugSpawnAllBalls = false;
|
|
||||||
public boolean debugUseGiantPaddle = false;
|
|
||||||
public short debugStartLevel = 1;
|
|
||||||
|
|
||||||
public GameState() {
|
public GameState() {
|
||||||
this.initComponents();
|
this.initComponents();
|
||||||
this.showTitleScreen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Event listeners ">
|
||||||
|
|
||||||
public KeyListener getKeyListener() {
|
public KeyListener getKeyListener() {
|
||||||
return new GameKeyListener();
|
return new GameKeyListener();
|
||||||
}
|
}
|
||||||
|
@ -79,37 +107,29 @@ public class GameState {
|
||||||
class GameKeyListener implements KeyListener {
|
class GameKeyListener implements KeyListener {
|
||||||
public void keyPressed(KeyEvent e) {
|
public void keyPressed(KeyEvent e) {
|
||||||
switch(e.getKeyCode()) {
|
switch(e.getKeyCode()) {
|
||||||
case 27: // Escape
|
case 27: // Escape - Toggle debug menu
|
||||||
toggleDebugMenu();
|
toggleDebugMenu();
|
||||||
break;
|
break;
|
||||||
case 10: // Enter
|
case 10: // Enter - Pause/unpause
|
||||||
if (GameState.this.getGameStartedState()) {
|
if (GameState.this.getGameStartedState()) {GameState.this.togglePausedState();}
|
||||||
GameState.this.togglePausedState();
|
|
||||||
if (!GameState.this.getPausedState()) {
|
|
||||||
GameState.this.textElementList.get(6).setVisibility(false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
GameState.this.textElementList.get(6).setVisibility(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 35: // End
|
case 35: // End - Start debug level
|
||||||
if (isLost || !GameState.this.getGameStartedState()) {GameState.this.setGameStartedState(true);GameState.this.newGame(true);}
|
if (isLost || !GameState.this.getGameStartedState()) {GameState.this.setGameStartedState(true);GameState.this.newGame(true);}
|
||||||
break;
|
break;
|
||||||
case 32: // Space
|
case 32: // Space - Start normal game, spawn ball
|
||||||
if (isLost || !GameState.this.getGameStartedState()) {GameState.this.setGameStartedState(true);GameState.this.newGame();}
|
if (isLost || !GameState.this.getGameStartedState()) {GameState.this.setGameStartedState(true);GameState.this.newGame();}
|
||||||
else if (!GameState.this.getPausedState()) {
|
else if (!GameState.this.getPausedState()) {
|
||||||
if (ballsOnScreen < 1) {
|
if (GameState.this.getBalls().size() < 1) {
|
||||||
Ball newBall = new Ball(GameState.this, 200, 300, 7, 7, 0, true);
|
Ball newBall = new Ball(GameState.this, 200, 300, 7, 7, 0, true);
|
||||||
GameState.this.ballList.add(newBall);
|
GameState.this.ballList.add(newBall);
|
||||||
newBall.spawnBall(true);
|
newBall.spawnBall(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 37: // Left
|
case 37: // Left - move left
|
||||||
if (GameState.this.getGameStartedState()) {movingLeft = true;}
|
if (GameState.this.getGameStartedState()) {movingLeft = true;}
|
||||||
break;
|
break;
|
||||||
case 39: // Right
|
case 39: // Right - move right
|
||||||
if (GameState.this.getGameStartedState()) {movingRight = true;}
|
if (GameState.this.getGameStartedState()) {movingRight = true;}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +148,7 @@ public class GameState {
|
||||||
}
|
}
|
||||||
|
|
||||||
class GameStateUpdateListener implements ActionListener {
|
class GameStateUpdateListener implements ActionListener {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public synchronized void actionPerformed(ActionEvent e) {
|
||||||
|
|
||||||
GameState.this.collectorActive = true;
|
GameState.this.collectorActive = true;
|
||||||
GameState.this.ballCollector = new ArrayList<>();
|
GameState.this.ballCollector = new ArrayList<>();
|
||||||
|
@ -145,7 +165,6 @@ public class GameState {
|
||||||
for (Brick brick : GameState.this.currentLevel.brickList) {
|
for (Brick brick : GameState.this.currentLevel.brickList) {
|
||||||
if (brick.getBrokenState()) {
|
if (brick.getBrokenState()) {
|
||||||
GameState.this.brickCollector.add(brick);
|
GameState.this.brickCollector.add(brick);
|
||||||
//GameState.this.currentLevel.brickList.remove(brick);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bricksOnScreen++;
|
bricksOnScreen++;
|
||||||
|
@ -156,14 +175,12 @@ public class GameState {
|
||||||
|
|
||||||
for (Ball ball : GameState.this.ballList) {
|
for (Ball ball : GameState.this.ballList) {
|
||||||
if (!ball.getActiveState()) {
|
if (!ball.getActiveState()) {
|
||||||
//GameState.this.ballList.remove(ball);
|
|
||||||
GameState.this.ballCollector.add(ball);
|
GameState.this.ballCollector.add(ball);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Particle particle: GameState.this.particleList) {
|
for (Particle particle: GameState.this.particleList) {
|
||||||
if (!particle.getActiveState()) {
|
if (!particle.getActiveState()) {
|
||||||
//GameState.this.particleList.remove(particle);
|
|
||||||
GameState.this.particleCollector.add(particle);
|
GameState.this.particleCollector.add(particle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,56 +203,129 @@ public class GameState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void incrementFrameCounter() {
|
//</editor-fold>
|
||||||
this.frameCounter++;
|
|
||||||
}
|
|
||||||
public long getFrameCounter() {
|
|
||||||
return this.frameCounter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void incrementChancey() {
|
//<editor-fold defaultstate="collapsed" desc=" Accessor methods (get/set) ">
|
||||||
this.chancey++;
|
|
||||||
if (this.chancey >= this.maxChanceyValue) {
|
|
||||||
this.chancey = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public byte getChancey() {
|
|
||||||
return this.chancey;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Version information accessors ">
|
||||||
|
/**
|
||||||
|
* Gets the name of the game.
|
||||||
|
* @return the name of the game
|
||||||
|
*/
|
||||||
|
public String getGameName() {
|
||||||
|
return this.gameName;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Gets the version number of the game.
|
||||||
|
* @return the version number of the game
|
||||||
|
*/
|
||||||
|
public String getGameVersion() {
|
||||||
|
return this.gameVersion;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Pokey accessors ">
|
||||||
|
/**
|
||||||
|
* Gets the current instance of "Pokey", the game's LFSR.
|
||||||
|
* @return pokey
|
||||||
|
*/
|
||||||
|
public LFSR getPokey() {
|
||||||
|
return this.pokey;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Tick rate accessors ">
|
||||||
|
/**
|
||||||
|
* Gets the current game tick rate, in Hz.
|
||||||
|
* @return the current game tick rate (in Hz)
|
||||||
|
*/
|
||||||
public byte getGameTickRate() {
|
public byte getGameTickRate() {
|
||||||
return this.gameTickRate;
|
return this.gameTickRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current game tick rate, in Hz.
|
||||||
|
* @param newTickRate the game tick rate, in Hz
|
||||||
|
*/
|
||||||
|
public void setGameTickRate(byte newTickRate) {
|
||||||
|
this.gameTickRate = (byte) newTickRate;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Frame rate accessors ">
|
||||||
|
/**
|
||||||
|
* Gets the target game frame rate, in Hz.
|
||||||
|
* @return the target game frame rate (in Hz)
|
||||||
|
*/
|
||||||
public short getTargetFrameRate() {
|
public short getTargetFrameRate() {
|
||||||
return this.targetFrameRate;
|
return this.targetFrameRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the actual game frame rate, in Hz.
|
||||||
|
* @return the actual game frame rate (in Hz)
|
||||||
|
*/
|
||||||
public short getActualFrameRate() {
|
public short getActualFrameRate() {
|
||||||
return this.actualFrameRate;
|
return this.actualFrameRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increments the frame counter.
|
||||||
|
*/
|
||||||
|
public void incrementFrameCounter() {
|
||||||
|
this.frameCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the frame counter.
|
||||||
|
* @return the value of the frame counter
|
||||||
|
*/
|
||||||
|
public long getFrameCounter() {
|
||||||
|
return this.frameCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the actual frames drawn during the last second.
|
||||||
|
* @return the actual frames drawn during the last second.
|
||||||
|
*/
|
||||||
|
public short getActualFrames() {
|
||||||
|
return this.actualFrames;
|
||||||
|
}
|
||||||
|
public void incrementActualFrames() {
|
||||||
|
this.actualFrames++;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Pause state accessors ">
|
||||||
public boolean getPausedState() {
|
public boolean getPausedState() {
|
||||||
return this.isPaused;
|
return this.isPaused;
|
||||||
}
|
}
|
||||||
public void togglePausedState() {
|
public void togglePausedState() {
|
||||||
this.isPaused = !this.isPaused;
|
this.isPaused = !this.isPaused;
|
||||||
|
if (this.getPausedState()) {this.textElementList.get(6).getVisibleState(true);}
|
||||||
|
else {this.textElementList.get(6).getVisibleState(false);}
|
||||||
}
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Debug menu state accessors ">
|
||||||
public boolean getDebugMenuState() {
|
public boolean getDebugMenuState() {
|
||||||
return this.debugMenuEnabled;
|
return this.debugMenuEnabled;
|
||||||
}
|
}
|
||||||
public void toggleDebugMenu() {
|
public void toggleDebugMenu() {
|
||||||
this.debugMenuEnabled = !this.debugMenuEnabled;
|
this.debugMenuEnabled = !this.debugMenuEnabled;
|
||||||
}
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Game start state accessors ">
|
||||||
public boolean getGameStartedState() {
|
public boolean getGameStartedState() {
|
||||||
return this.isGameStarted;
|
return this.isGameStarted;
|
||||||
}
|
}
|
||||||
public void setGameStartedState(boolean startState) {
|
public void setGameStartedState(boolean startState) {
|
||||||
this.isGameStarted = startState;
|
this.isGameStarted = startState;
|
||||||
}
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Resolution accessors ">
|
||||||
public short getInternalResX() {
|
public short getInternalResX() {
|
||||||
return this.internalResX;
|
return this.internalResX;
|
||||||
}
|
}
|
||||||
|
@ -254,13 +344,79 @@ public class GameState {
|
||||||
public void setWindowResY(short resolution) {
|
public void setWindowResY(short resolution) {
|
||||||
this.windowResY = resolution;
|
this.windowResY = resolution;
|
||||||
}
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
public void onGameTick() {
|
//<editor-fold defaultstate="collapsed" desc=" Lives accessors ">
|
||||||
this.incrementChancey();
|
public byte getLives() {
|
||||||
|
return this.lives;
|
||||||
|
}
|
||||||
|
public void addLives(int livesAdded) {
|
||||||
|
if (livesAdded >= 127) {livesAdded = 127;}
|
||||||
|
else if (livesAdded < 0) {livesAdded = 0;}
|
||||||
|
this.lives += (byte) livesAdded;
|
||||||
|
}
|
||||||
|
public void addLife() {
|
||||||
|
this.addLives(1);
|
||||||
|
}
|
||||||
|
public void removeLife() {
|
||||||
|
this.lives--;
|
||||||
|
if (this.lives < 0) {this.lives = 0;}
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Score accessors ">
|
||||||
|
public int getScore() {
|
||||||
|
return this.score;
|
||||||
|
}
|
||||||
|
public void addScore(int scoreAdded) {
|
||||||
|
this.score += scoreAdded;
|
||||||
|
}
|
||||||
|
public void resetScore() {
|
||||||
|
this.score = 0;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Level accessors ">
|
||||||
|
public short getCurrentLevelID() {
|
||||||
|
return this.level;
|
||||||
|
}
|
||||||
|
public void setCurrentLevelID(short levelID) {
|
||||||
|
this.level = levelID;
|
||||||
|
}
|
||||||
|
public Level getCurrentLevel() {
|
||||||
|
return this.currentLevel;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" List accessors ">
|
||||||
|
public ArrayList<Ball> getBalls() {
|
||||||
|
return this.ballList;
|
||||||
|
}
|
||||||
|
public ArrayList<Particle> getParticles() {
|
||||||
|
return this.particleList;
|
||||||
|
}
|
||||||
|
public ArrayList<Paddle> getPaddles() {
|
||||||
|
return this.paddleList;
|
||||||
|
}
|
||||||
|
public ArrayList<TextElement> getTextElements() {
|
||||||
|
return this.textElementList;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Collector accessors ">
|
||||||
|
public boolean getCollectorActiveState() {
|
||||||
|
return this.collectorActive;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
public synchronized void onGameTick() {
|
||||||
|
|
||||||
if (this.getPausedState()) {return;}
|
if (this.getPausedState()) {return;}
|
||||||
|
|
||||||
// Move player if keys are held
|
// Move player if keys are held
|
||||||
|
try {
|
||||||
for (Paddle paddle : this.paddleList) {
|
for (Paddle paddle : this.paddleList) {
|
||||||
if (this.movingLeft) {
|
if (this.movingLeft) {
|
||||||
paddle.movePaddle(false);
|
paddle.movePaddle(false);
|
||||||
|
@ -272,6 +428,9 @@ public class GameState {
|
||||||
paddle.paddleSpeed = 0;
|
paddle.paddleSpeed = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch(java.util.ConcurrentModificationException except) {
|
||||||
|
System.err.println("ConcurrentModificationException, onGameTick() Paddle iteration " + System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
// Ball logic (movement, collision checks)
|
// Ball logic (movement, collision checks)
|
||||||
try {
|
try {
|
||||||
|
@ -281,18 +440,19 @@ public class GameState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(java.util.ConcurrentModificationException except) {
|
} catch(java.util.ConcurrentModificationException except) {
|
||||||
System.err.println("ConcurrentModificationException, onGameTick() Ball iteration\n"
|
System.err.println("ConcurrentModificationException, onGameTick() Ball iteration " + System.currentTimeMillis());
|
||||||
+ "Resetting ballList ArrayList.");
|
|
||||||
// except.printStackTrace();
|
|
||||||
this.ballList = new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Particles
|
// Particles
|
||||||
|
try {
|
||||||
for (Particle particle : this.particleList) {
|
for (Particle particle : this.particleList) {
|
||||||
if (particle.getActiveState()) {
|
if (particle.getActiveState()) {
|
||||||
particle.update();
|
particle.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch(java.util.ConcurrentModificationException except) {
|
||||||
|
System.err.println("ConcurrentModificationException, onGameTick() Particle iteration " + System.currentTimeMillis());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showTitleScreen() {
|
public void showTitleScreen() {
|
||||||
|
@ -301,7 +461,7 @@ public class GameState {
|
||||||
textElementList.get(2).activateTimer();
|
textElementList.get(2).activateTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gameLose() {
|
public synchronized void gameLose() {
|
||||||
if (this.currentLevel != null) {
|
if (this.currentLevel != null) {
|
||||||
for (Brick brick : this.currentLevel.brickList) {
|
for (Brick brick : this.currentLevel.brickList) {
|
||||||
brick.setBrokenState(true);
|
brick.setBrokenState(true);
|
||||||
|
@ -314,15 +474,15 @@ public class GameState {
|
||||||
}
|
}
|
||||||
for (Paddle paddle : this.paddleList) {
|
for (Paddle paddle : this.paddleList) {
|
||||||
paddle.setActiveState(false);
|
paddle.setActiveState(false);
|
||||||
|
paddle.cullPaddle();
|
||||||
this.paddleCollector.add(paddle);
|
this.paddleCollector.add(paddle);
|
||||||
}
|
}
|
||||||
this.isLost = true;
|
this.isLost = true;
|
||||||
this.ballsOnScreen = 0;
|
this.textElementList.get(3).getVisibleState(false);
|
||||||
this.textElementList.get(3).setVisibility(false);
|
this.textElementList.get(4).getVisibleState(false);
|
||||||
this.textElementList.get(4).setVisibility(false);
|
this.textElementList.get(5).getVisibleState(false);
|
||||||
this.textElementList.get(5).setVisibility(false);
|
this.textElementList.get(8).getVisibleState(true);
|
||||||
this.textElementList.get(8).setVisibility(true);
|
this.textElementList.get(9).getVisibleState(true);
|
||||||
this.textElementList.get(9).setVisibility(true);
|
|
||||||
this.getGameStateUpdateActionListener().actionPerformed(new ActionEvent(this, 0, ""));
|
this.getGameStateUpdateActionListener().actionPerformed(new ActionEvent(this, 0, ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,39 +497,33 @@ public class GameState {
|
||||||
if (debugLevel) {level = 32767;}
|
if (debugLevel) {level = 32767;}
|
||||||
else {level = 1;}
|
else {level = 1;}
|
||||||
frameCounter = 0;
|
frameCounter = 0;
|
||||||
ballsOnScreen = 0;
|
|
||||||
movingLeft = false;
|
movingLeft = false;
|
||||||
movingRight = false;
|
movingRight = false;
|
||||||
if (debugUseGiantPaddle) {this.paddleList.add(new Paddle(this, 0, 500, 800, 60, 0));}
|
|
||||||
else {this.paddleList.add(new Paddle(this, 350, 500, 100, 15, 0));}
|
|
||||||
if (this.debugUseGiantPaddle) {
|
|
||||||
this.paddleList.add(new Paddle(this, 0, 500, 800, 60, 0));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.paddleList.add(new Paddle(this, 350, 500, 100, 15, 0));
|
this.paddleList.add(new Paddle(this, 350, 500, 100, 15, 0));
|
||||||
}
|
this.textElementList.get(0).getVisibleState(false);
|
||||||
this.textElementList.get(0).setVisibility(false);
|
this.textElementList.get(1).getVisibleState(false);
|
||||||
this.textElementList.get(1).setVisibility(false);
|
this.textElementList.get(2).getVisibleState(false);
|
||||||
this.textElementList.get(2).setVisibility(false);
|
this.textElementList.get(3).getVisibleState(true);
|
||||||
this.textElementList.get(3).setVisibility(true);
|
this.textElementList.get(4).getVisibleState(true);
|
||||||
this.textElementList.get(4).setVisibility(true);
|
this.textElementList.get(5).getVisibleState(true);
|
||||||
this.textElementList.get(5).setVisibility(true);
|
|
||||||
textElementList.get(3).setText(String.valueOf(this.score));
|
textElementList.get(3).setText(String.valueOf(this.score));
|
||||||
textElementList.get(4).setText(String.valueOf(this.lives));
|
textElementList.get(4).setText(String.valueOf(this.lives));
|
||||||
textElementList.get(5).setText(String.valueOf(this.level));
|
textElementList.get(5).setText(String.valueOf(this.level));
|
||||||
this.textElementList.get(8).setVisibility(false);
|
this.textElementList.get(8).getVisibleState(false);
|
||||||
this.textElementList.get(9).setVisibility(false);
|
this.textElementList.get(9).getVisibleState(false);
|
||||||
if (debugStartLevel > 1) {level = debugStartLevel;}
|
|
||||||
this.currentLevel = new Level(this, level);
|
this.currentLevel = new Level(this, level);
|
||||||
this.currentLevel.constructLevel();
|
this.currentLevel.constructLevel();
|
||||||
this.updateStaticTextElements();
|
this.updateStaticTextElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initComponents() {
|
public synchronized void initComponents() {
|
||||||
this.ballList = new ArrayList<>();
|
this.ballList = new ArrayList<>();
|
||||||
this.particleList = new ArrayList<>();
|
this.particleList = new ArrayList<>();
|
||||||
this.paddleList = new ArrayList<>();
|
this.paddleList = new ArrayList<>();
|
||||||
this.textElementList = new ArrayList<>();
|
this.textElementList = new ArrayList<>();
|
||||||
|
|
||||||
|
this.pokey = new LFSR();
|
||||||
|
|
||||||
// List of indices
|
// List of indices
|
||||||
textElementList.add(new TextElement(this, "VECTOR BREAKOUT", 2.5f, 67, 280, 15, 2)); // 0 - Title
|
textElementList.add(new TextElement(this, "VECTOR BREAKOUT", 2.5f, 67, 280, 15, 2)); // 0 - Title
|
||||||
textElementList.add(new TextElement(this, "MMXXV BOYFAILURE.DEV", 0.75f, 259, 315, 15, 1)); // 1 - Copyright
|
textElementList.add(new TextElement(this, "MMXXV BOYFAILURE.DEV", 0.75f, 259, 315, 15, 1)); // 1 - Copyright
|
|
@ -1,7 +1,28 @@
|
||||||
package dev.boyfailure.quajra.vectorbreakout;
|
/*
|
||||||
|
* Copyright 2025 Naomi (boyfailure.dev).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invisible regions in each object that dictate when it collides with other objects.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 20250327
|
||||||
|
*/
|
||||||
public class Hitbox {
|
public class Hitbox {
|
||||||
|
|
||||||
private Rectangle2D bounds;
|
private Rectangle2D bounds;
|
98
src/main/java/dev/boyfailure/vectorbreakout/LFSR.java
Normal file
98
src/main/java/dev/boyfailure/vectorbreakout/LFSR.java
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Naomi (boyfailure.dev).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A software implementation of a LFSR-based (linear frequency shift register) pseudo-random number generator.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public class LFSR {
|
||||||
|
|
||||||
|
private static boolean[] originalArray = new boolean[] {true,false,true,true,true,true,true,true,false,true,false,false,false,true,true,false,false};
|
||||||
|
|
||||||
|
private boolean[] bitArray;
|
||||||
|
private int bitCount;
|
||||||
|
private int bitsReturned;
|
||||||
|
private int firstXorIndex;
|
||||||
|
private int secondXorIndex;
|
||||||
|
|
||||||
|
private Timer lfsrTimer;
|
||||||
|
|
||||||
|
public LFSR(int bitCount, int bitsReturned, int firstXorIndex, int secondXorIndex) {
|
||||||
|
this.bitCount = bitCount;
|
||||||
|
this.bitsReturned = bitsReturned;
|
||||||
|
this.firstXorIndex = firstXorIndex;
|
||||||
|
this.secondXorIndex = secondXorIndex;
|
||||||
|
if (bitsReturned > bitCount) {bitsReturned = bitCount;}
|
||||||
|
bitArray = new boolean[bitCount];
|
||||||
|
for (int i = 0; i < bitCount; i++) {
|
||||||
|
if (i < 17) {bitArray[i] = LFSR.originalArray[i];}
|
||||||
|
else {
|
||||||
|
bitArray[i] = bitArray[i - 3] ^ bitArray[i - 8];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.lfsrTimer = new Timer(1, new ActionListener(){public void actionPerformed(ActionEvent e) {LFSR.this.shift();}});
|
||||||
|
this.lfsrTimer.start();
|
||||||
|
}
|
||||||
|
public LFSR() {
|
||||||
|
this(17, 8, 11, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDecimalValue() {
|
||||||
|
int regValue = 0;
|
||||||
|
int bitIndex = this.bitCount - 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < this.bitsReturned; i++) {
|
||||||
|
if (this.bitArray[bitIndex]) {
|
||||||
|
regValue += Math.pow(2, i);
|
||||||
|
}
|
||||||
|
bitIndex--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return regValue;
|
||||||
|
}
|
||||||
|
public int getShiftedDecimalValue() {
|
||||||
|
this.shift();
|
||||||
|
return this.getDecimalValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shift() {
|
||||||
|
for (int i = (this.bitCount - 1); i > 0; i--) {
|
||||||
|
this.bitArray[i] = this.bitArray[i - 1];
|
||||||
|
}
|
||||||
|
this.bitArray[0] = this.bitArray[this.firstXorIndex] ^ this.bitArray[this.secondXorIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBits() {
|
||||||
|
String result = "";
|
||||||
|
for (int i = 0; i < this.bitCount; i++) {
|
||||||
|
if (this.bitArray[i] == true) {
|
||||||
|
result += "1";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result += "0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,28 @@
|
||||||
package dev.boyfailure.quajra.vectorbreakout;
|
/*
|
||||||
|
* Copyright 2025 Naomi (boyfailure.dev).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The progressive levels that contain different brick layouts.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 20250325
|
||||||
|
*/
|
||||||
public class Level {
|
public class Level {
|
||||||
|
|
||||||
short levelID;
|
short levelID;
|
||||||
|
@ -18,7 +39,7 @@ public class Level {
|
||||||
this.gameState = gameState;
|
this.gameState = gameState;
|
||||||
this.levelID = (short) id;
|
this.levelID = (short) id;
|
||||||
|
|
||||||
switch(id) {
|
switch(this.levelID) {
|
||||||
case 1:
|
case 1:
|
||||||
this.levelName = "HELLO WORLD";
|
this.levelName = "HELLO WORLD";
|
||||||
this.levelLayout = new byte[]
|
this.levelLayout = new byte[]
|
||||||
|
@ -29,35 +50,35 @@ public class Level {
|
||||||
this.colorMap = new byte[]
|
this.colorMap = new byte[]
|
||||||
{10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
{10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
||||||
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
||||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12};
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12};
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
this.levelName = "DOUBLE TROUBLE";
|
this.levelName = "DOUBLE TROUBLE";
|
||||||
this.levelLayout = new byte[]
|
this.levelLayout = new byte[]
|
||||||
{4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
{4,4,4,4,4, 4,4,4,4,4,4,4,4, 4,4,4,4,4,4,
|
||||||
3,3,3,3,3,16,3,3,3,3,3,3,3,16,3,3,3,3,3,
|
3,3,3,3,3,16,3,3,3,3,3,3,3,16,3,3,3,3,3,
|
||||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
|
1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1};
|
||||||
this.colorMap = new byte[]
|
this.colorMap = new byte[]
|
||||||
{10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
{10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
||||||
13,13,13,13,13,18,13,13,13,13,13,13,13,18,13,13,13,13,13,
|
13,13,13,13,13,18,13,13,13,13,13,13,13,18,13,13,13,13,13,
|
||||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12};
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12};
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
this.levelName = "THE GAP";
|
this.levelName = "THE GAP";
|
||||||
this.levelLayout = new byte[]
|
this.levelLayout = new byte[]
|
||||||
{5,5,5,5,5,5,5,5,0,0,0,5,5,5,5,5,5,5,5,
|
{5,5,5,5,5, 5,5,5,0,0,0,5,5, 5,5,5,5,5,5,
|
||||||
4,4,4,4,4,4,4,4,0,0,0,4,4,4,4,4,4,4,4,
|
4,4,4,4,4, 4,4,4,0,0,0,4,4, 4,4,4,4,4,4,
|
||||||
3,3,3,3,3,16,3,3,0,0,0,3,3,16,3,3,3,3,3,
|
3,3,3,3,3,16,3,3,0,0,0,3,3,16,3,3,3,3,3,
|
||||||
2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,
|
2,2,2,2,2, 2,2,2,0,0,0,2,2, 2,2,2,2,2,2,
|
||||||
1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1};
|
1,1,1,1,1, 1,1,1,0,0,0,1,1, 1,1,1,1,1,1};
|
||||||
this.colorMap = new byte[]
|
this.colorMap = new byte[]
|
||||||
{14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
|
{14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
|
||||||
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
||||||
13,13,13,13,13,18,13,13,13,13,13,13,13,18,13,13,13,13,13,
|
13,13,13,13,13,18,13,13,13,13,13,13,13,18,13,13,13,13,13,
|
||||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12};
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12};
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
|
@ -70,7 +91,7 @@ public class Level {
|
||||||
this.colorMap = new byte[]
|
this.colorMap = new byte[]
|
||||||
{10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
{10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
||||||
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
||||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12};
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12};
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
|
@ -88,12 +109,12 @@ public class Level {
|
||||||
this.colorMap = new byte[]
|
this.colorMap = new byte[]
|
||||||
{10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
{10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
||||||
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
||||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
||||||
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
||||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12};
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12};
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
|
@ -112,11 +133,11 @@ public class Level {
|
||||||
{14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
|
{14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
|
||||||
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
||||||
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
||||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
||||||
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
||||||
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
|
||||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12};
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12};
|
||||||
break;
|
break;
|
||||||
case 1001:
|
case 1001:
|
||||||
|
@ -130,14 +151,13 @@ public class Level {
|
||||||
this.colorMap = new byte[]
|
this.colorMap = new byte[]
|
||||||
{20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
{20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
|
||||||
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
|
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
|
19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
|
||||||
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20};
|
20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20};
|
||||||
break;
|
break;
|
||||||
case 1002:
|
case 1002:
|
||||||
this.levelName = "I USE ARCH BTW";
|
this.levelName = "I USE ARCH BTW";
|
||||||
this.levelLayout = new byte[]
|
this.levelLayout = new byte[]
|
||||||
//1 2 3 4 5 6 7 8 9 0
|
|
||||||
{0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,
|
{0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,6,6,6,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,6,6,6,0,0,0,0,0,0,0,0,
|
||||||
|
@ -168,17 +188,17 @@ public class Level {
|
||||||
7,1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,
|
7,1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,
|
||||||
1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5};
|
1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5};
|
||||||
this.colorMap = new byte[]
|
this.colorMap = new byte[]
|
||||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
|
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,
|
||||||
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,0,
|
1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18, 0,
|
||||||
2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,0,1,
|
2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18, 0, 1,
|
||||||
3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,0,1,2,
|
3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18, 0, 1, 2,
|
||||||
4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,0,1,2,3,
|
4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18, 0, 1, 2, 3,
|
||||||
5,6,7,8,9,10,11,12,13,14,15,16,17,18,0,1,2,3,4,
|
5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18, 0, 1, 2, 3, 4,
|
||||||
6,7,8,9,10,11,12,13,14,15,16,17,18,0,1,2,3,4,5,
|
6, 7, 8, 9,10,11,12,13,14,15,16,17,18, 0, 1, 2, 3, 4, 5,
|
||||||
7,8,9,10,11,12,13,14,15,16,17,18,0,1,2,3,4,5,6};
|
7, 8, 9,10,11,12,13,14,15,16,17,18, 0, 1, 2, 3, 4, 5, 6};
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.levelName = "LEVEL 404: NOT FOUND (" + levelID + ")";
|
this.levelName = "LEVEL 404: NOT FOUND (" + this.levelID + ")";
|
||||||
this.levelLayout = new byte[]
|
this.levelLayout = new byte[]
|
||||||
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
|
@ -234,9 +254,8 @@ public class Level {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startLevel() {
|
public void startLevel() {
|
||||||
gameState.bricksOnScreen = (short) this.brickList.size();
|
gameState.getTextElements().set(7, new TextElement(gameState, this.levelName, 1, 24, 480, 15, 2, 3000));
|
||||||
gameState.textElementList.set(7, new TextElement(gameState, this.levelName, 1, 24, 480, 15, 2, 3000));
|
gameState.getTextElements().get(7).activateTimer();
|
||||||
gameState.textElementList.get(7).activateTimer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,7 +1,28 @@
|
||||||
package dev.boyfailure.quajra.vectorbreakout;
|
/*
|
||||||
|
* Copyright 2025 Naomi (boyfailure.dev).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customizable game menus.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
public class Menu {
|
public class Menu {
|
||||||
|
|
||||||
public String menuTitle = "Menu";
|
public String menuTitle = "Menu";
|
75
src/main/java/dev/boyfailure/vectorbreakout/Paddle.java
Normal file
75
src/main/java/dev/boyfailure/vectorbreakout/Paddle.java
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Naomi (boyfailure.dev).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The player-controlled paddle that guides balls into bricks.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 20250323
|
||||||
|
*/
|
||||||
|
public class Paddle extends Entity {
|
||||||
|
|
||||||
|
byte paddleColor;
|
||||||
|
byte paddleSpeed = 0;
|
||||||
|
boolean isActive = true;
|
||||||
|
float speedMultiplier = 1;
|
||||||
|
Hitbox hitBoxLeft;
|
||||||
|
Hitbox hitBoxRight;
|
||||||
|
|
||||||
|
private GameState gameState;
|
||||||
|
|
||||||
|
public Paddle(GameState gameState, int x, int y, int width, int height, int paddleColor) {
|
||||||
|
this.gameState = gameState;
|
||||||
|
this.posX = (short) x;
|
||||||
|
this.posY = (short) y;
|
||||||
|
this.width = (short) width;
|
||||||
|
this.height = (short) height;
|
||||||
|
this.paddleColor = (byte) paddleColor;
|
||||||
|
this.hitBox = new Hitbox(x, y, width, height, 4);
|
||||||
|
this.hitBoxLeft = new Hitbox(x, y, width / 5, height, 4);
|
||||||
|
this.hitBoxRight = new Hitbox(x + ((width / 5) * 4), y, width / 5, height, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void movePaddle(boolean direction) {
|
||||||
|
if (this.paddleSpeed <= 15) {this.paddleSpeed += 3;}
|
||||||
|
if (direction) {this.posX += (this.paddleSpeed * this.speedMultiplier);}
|
||||||
|
else {this.posX -= (this.paddleSpeed * this.speedMultiplier);}
|
||||||
|
if (this.posX <= 20) {this.posX = 20;}
|
||||||
|
else if (this.posX >= (gameState.getInternalResX() - this.width - 20)) {this.posX = (short) (gameState.getInternalResX() - this.width - 20);}
|
||||||
|
|
||||||
|
this.hitBox.moveTo(this.posX, this.posY, this.width, this.height);
|
||||||
|
this.hitBoxLeft.moveTo(this.posX, this.posY, this.width / 5, this.height);
|
||||||
|
this.hitBoxRight.moveTo(this.posX + ((this.width / 5) * 4), this.posY, this.width / 5, this.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cullPaddle() {
|
||||||
|
isActive = false;
|
||||||
|
this.posX = 32767;
|
||||||
|
this.posY = 32767;
|
||||||
|
this.hitBox.setBounds(32766, 32766, 32767, 32767);
|
||||||
|
this.hitBoxLeft.setBounds(32766, 32766, 32767, 32767);
|
||||||
|
this.hitBoxRight.setBounds(32766, 32766, 32767, 32767);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getActiveState() {
|
||||||
|
return this.isActive;
|
||||||
|
}
|
||||||
|
public void setActiveState(boolean activeState) {
|
||||||
|
this.isActive = activeState;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,26 @@
|
||||||
package dev.boyfailure.quajra.vectorbreakout;
|
/*
|
||||||
|
* Copyright 2025 Naomi (boyfailure.dev).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small graphical effects that appear on screen.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 20250325
|
||||||
|
*/
|
||||||
public class Particle {
|
public class Particle {
|
||||||
|
|
||||||
byte particleID;
|
byte particleID;
|
||||||
|
@ -32,8 +53,9 @@ public class Particle {
|
||||||
|
|
||||||
public void spawn(int lifetime) {
|
public void spawn(int lifetime) {
|
||||||
this.isActive = true;
|
this.isActive = true;
|
||||||
if (gameState.confettiMode) {this.particleLifetime = 400;}
|
// if (gameState.getConfettiMode()) {this.particleLifetime = 400;}
|
||||||
else {this.particleLifetime = (short) lifetime;}
|
// else {this.particleLifetime = (short) lifetime;}
|
||||||
|
this.particleLifetime = (short) lifetime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
247
src/main/java/dev/boyfailure/vectorbreakout/TextElement.java
Normal file
247
src/main/java/dev/boyfailure/vectorbreakout/TextElement.java
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Naomi (boyfailure.dev).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fields of text that display on screen.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 20250326
|
||||||
|
*/
|
||||||
|
public class TextElement {
|
||||||
|
|
||||||
|
private String text;
|
||||||
|
private boolean active = true;
|
||||||
|
private boolean isVisible = false;
|
||||||
|
private boolean moveUpOnFrame = false;
|
||||||
|
private float textScale = 1;
|
||||||
|
private float vectorThickness = 1;
|
||||||
|
private byte textColor;
|
||||||
|
private short x;
|
||||||
|
private short y;
|
||||||
|
private short duration = 0;
|
||||||
|
private long creationTime;
|
||||||
|
|
||||||
|
private GameState gameState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text elements.
|
||||||
|
* @param gameState the GameState in which the TextElement will reside
|
||||||
|
* @param text the text that will be displayed
|
||||||
|
* @param textScale the size of the text on screen
|
||||||
|
* @param x the x coordinate of the text's origin point
|
||||||
|
* @param y the y coordinate of the text's origin point
|
||||||
|
* @param textColor the color of the text
|
||||||
|
* @param vectorThickness the thickness of the vector lines
|
||||||
|
*/
|
||||||
|
public TextElement(GameState gameState, String text, float textScale, int x, int y, int textColor, float vectorThickness) {
|
||||||
|
this.gameState = gameState;
|
||||||
|
this.text = text;
|
||||||
|
this.textScale = textScale;
|
||||||
|
this.x = (short) x;
|
||||||
|
this.y = (short) y;
|
||||||
|
this.textColor = (byte) textColor;
|
||||||
|
this.vectorThickness = vectorThickness;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text elements with a fadeout timer
|
||||||
|
* @param gameState the GameState in which the TextElement will reside
|
||||||
|
* @param text the text that will be displayed
|
||||||
|
* @param textScale the size of the text on screen
|
||||||
|
* @param x the x coordinate of the text's origin point
|
||||||
|
* @param y the y coordinate of the text's origin point
|
||||||
|
* @param textColor the color of the text
|
||||||
|
* @param vectorThickness the thickness of the vector lines
|
||||||
|
* @param duration how long the text will stay on screen, in milliseconds
|
||||||
|
*/
|
||||||
|
public TextElement(GameState gameState, String text, float textScale, int x, int y, int textColor, float vectorThickness, int duration) {
|
||||||
|
this.gameState = gameState;
|
||||||
|
this.text = text;
|
||||||
|
this.textScale = textScale;
|
||||||
|
this.x = (short) x;
|
||||||
|
this.y = (short) y;
|
||||||
|
this.textColor = (byte) textColor;
|
||||||
|
this.vectorThickness = vectorThickness;
|
||||||
|
this.duration = (short) duration;
|
||||||
|
this.creationTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Accessor methods (get/set) ">
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Active state accessors ">
|
||||||
|
/**
|
||||||
|
* Gets the active status of the TextElement.
|
||||||
|
* @return the active status of the TextElement
|
||||||
|
*/
|
||||||
|
public boolean getActiveState() {
|
||||||
|
return this.active;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets the active status of the TextElement.
|
||||||
|
* @param activeState the active status of the TextElement
|
||||||
|
*/
|
||||||
|
public void setActiveState(boolean activeState) {
|
||||||
|
this.active = activeState;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Visibility state accessors ">
|
||||||
|
/**
|
||||||
|
* Gets the visibility state of the TextElement.
|
||||||
|
* @return the visibility state of the TextElement
|
||||||
|
*/
|
||||||
|
public boolean getVisibleState() {
|
||||||
|
return this.isVisible;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets the visible state of the TextElement.
|
||||||
|
* @param visibleState the visible state of the TextElement
|
||||||
|
*/
|
||||||
|
public void getVisibleState(boolean visibleState) {
|
||||||
|
this.isVisible = visibleState;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Color code accessors ">
|
||||||
|
/**
|
||||||
|
* Gets the color code of the TextElement.
|
||||||
|
* @return the color code of the TextElement
|
||||||
|
*/
|
||||||
|
public byte getColor() {
|
||||||
|
return this.textColor;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets the color code of the TextElement.
|
||||||
|
* @param textColor the color code of the TextElement
|
||||||
|
*/
|
||||||
|
public void setColor(int textColor) {
|
||||||
|
this.textColor = (byte) textColor;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Scaling accessors ">
|
||||||
|
/**
|
||||||
|
* Returns the thickness of the TextElement's vector lines.
|
||||||
|
* @return the thickness of the TextElement's vector lines
|
||||||
|
*/
|
||||||
|
public float getVectorThickness() {
|
||||||
|
return this.vectorThickness;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets the thickness of the TextElement's vector lines.
|
||||||
|
* @param vectorThickness the new thickness of the TextElement's vector lines
|
||||||
|
*/
|
||||||
|
public void setVectorThickness(float vectorThickness) {
|
||||||
|
this.vectorThickness = vectorThickness;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the scale of the text.
|
||||||
|
* @return the scale of the text
|
||||||
|
*/
|
||||||
|
public float getTextScale() {
|
||||||
|
return this.textScale;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets the scale of the text.
|
||||||
|
* @param textScale the new scale of the text
|
||||||
|
*/
|
||||||
|
public void setTextScale(float textScale) {
|
||||||
|
this.textScale = textScale;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Text value accessors ">
|
||||||
|
/**
|
||||||
|
* Gets the text in the TextElement.
|
||||||
|
* @return the text in the TextElement
|
||||||
|
*/
|
||||||
|
public String getText() {
|
||||||
|
return this.text;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Changes the text that the TextElement will display.
|
||||||
|
* @param text the text that the TextElement will display
|
||||||
|
*/
|
||||||
|
public void setText(String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Moves up on frame accessors ">
|
||||||
|
public boolean movesUpOnFrame() {
|
||||||
|
return this.moveUpOnFrame;
|
||||||
|
}
|
||||||
|
public void moveUpOnFrame() {
|
||||||
|
this.moveUpOnFrame = true;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold defaultstate="collapsed" desc=" Position accessors ">
|
||||||
|
public Point getPosition() {
|
||||||
|
return new Point(this.x, this.y);
|
||||||
|
}
|
||||||
|
public short getPositionX() {
|
||||||
|
return this.x;
|
||||||
|
}
|
||||||
|
public short getPositionY() {
|
||||||
|
return this.y;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the TextElement for rendering.
|
||||||
|
*/
|
||||||
|
public void activateTimer() {
|
||||||
|
this.setActiveState(true);
|
||||||
|
long testLong = this.creationTime;
|
||||||
|
if (this.duration > 0) {
|
||||||
|
Timer levelTitleGTFO = new Timer();
|
||||||
|
levelTitleGTFO.schedule(new TimerTask() {
|
||||||
|
public void run() {
|
||||||
|
TextElement.this.getVisibleState(false);
|
||||||
|
}
|
||||||
|
}, this.duration);
|
||||||
|
}
|
||||||
|
this.getVisibleState(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the TextElement for culling.
|
||||||
|
*/
|
||||||
|
public void cull() {
|
||||||
|
this.active = false;
|
||||||
|
this.x = 32767;
|
||||||
|
this.y = 32767;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the text that the TextElement will display.
|
||||||
|
* @param x The x coordinate of the text's origin point.
|
||||||
|
* @param y The y coordinate of the text's origin point.
|
||||||
|
*/
|
||||||
|
public void moveTo(int x, int y) {
|
||||||
|
this.x = (short) x;
|
||||||
|
this.y = (short) y;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Naomi (boyfailure.dev).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dev.boyfailure.vectorbreakout;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The initial code to launch the game.
|
||||||
|
* @author Naomi (boyfailure.dev)
|
||||||
|
* @since 20250323
|
||||||
|
*/
|
||||||
|
public class VectorBreakout {
|
||||||
|
|
||||||
|
public static GameState gameState;
|
||||||
|
public static GameDisplay gameDisplay;
|
||||||
|
public static GameFrame gameFrame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This empty constructor is currently only in here because the main class
|
||||||
|
* constructor generated in new projects on NetBeans 4. Will investigate to
|
||||||
|
* see if this is necessary in JDK 1.5 next time I am using those tools.
|
||||||
|
*/
|
||||||
|
public VectorBreakout() {}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
// Enable OpenGL for hardware acceleration
|
||||||
|
System.setProperty("sun.java2d.opengl", "true");
|
||||||
|
|
||||||
|
// Initialize the components
|
||||||
|
gameState = new GameState();
|
||||||
|
gameDisplay = new GameDisplay(gameState);
|
||||||
|
gameFrame = new GameFrame(gameState, gameDisplay);
|
||||||
|
|
||||||
|
Timer gameTick = new Timer((1000 / gameState.getGameTickRate()), gameState.getGameTickActionListener());
|
||||||
|
gameTick.start();
|
||||||
|
|
||||||
|
Timer frameDisplay = new Timer((1000 / gameState.getTargetFrameRate()), new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
gameState.incrementFrameCounter();
|
||||||
|
gameFrame.repaint();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
frameDisplay.start();
|
||||||
|
|
||||||
|
Timer gameCuller = new Timer(1000, gameState.getGameStateUpdateActionListener());
|
||||||
|
gameCuller.start();
|
||||||
|
|
||||||
|
// Show the game window
|
||||||
|
gameState.showTitleScreen();
|
||||||
|
gameFrame.setVisible(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue