Skip to content
This repository was archived by the owner on Dec 24, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,22 @@ spotless {
formatAnnotations()
}
}

// enable flexible constructors (preview feature)
tasks.withType(JavaCompile).configureEach {
options.compilerArgs += "--enable-preview"
}

tasks.withType(Test).configureEach {
jvmArgs += "--enable-preview"
}

tasks.withType(JavaExec).configureEach {
jvmArgs += "--enable-preview"
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(24)
}
}
18 changes: 16 additions & 2 deletions src/main/java/com/github/codestorm/bounceverse/Bounceverse.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.dsl.FXGL;
import com.github.codestorm.bounceverse.factory.BallFactory;
import com.github.codestorm.bounceverse.factory.BrickFactory;
import com.github.codestorm.bounceverse.factory.SceneFactory;
import com.github.codestorm.bounceverse.factory.WallFactory;
import com.github.codestorm.bounceverse.systems.LaunchOption;
import com.github.codestorm.bounceverse.systems.physics.CollisionSystem;
import java.io.IOException;
Expand Down Expand Up @@ -93,13 +95,25 @@ protected void initSettings(GameSettings settings) {
@Override
protected void initGame() {
FXGL.getGameWorld().addEntityFactory(new BrickFactory());
FXGL.getGameWorld().addEntityFactory(new BallFactory());
FXGL.getGameWorld().addEntityFactory(new WallFactory());

var brick1 = FXGL.spawn("normalBrick", 100, 100);
var brick2 = FXGL.spawn("normalBrick", 200, 200);
WallFactory.spawnWalls();

// var brick1 = FXGL.spawn("normalBrick", 100, 100);
// var brick2 = FXGL.spawn("normalBrick", 200, 200);

for (int i = 1; i <= 6; i++) {
for (int j = 1; j <= 10; j++) {
FXGL.spawn("normalBrick", 85 * j, 35 * i);
}
}
FXGL.spawn("ball");
}

@Override
protected void initPhysics() {
FXGL.getPhysicsWorld().setGravity(0, 0);
CollisionSystem.getInstance().apply();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.github.codestorm.bounceverse.components._old.ball;

import com.almasb.fxgl.entity.component.Component;
import com.almasb.fxgl.physics.PhysicsComponent;
import javafx.geometry.Point2D;

/**
*
*
* <h1>Ball Component</h1>
*
* <p>This component adds movement and interaction behavior to a {@code Ball} entity.
*
* <p>By default,
*
* <ul>
* <li>The ball moves with a velocity of 200.
* <li>The ball bounces when it collides with walls.
* </ul>
*
* @author minngoc1213
*/
public class BallComponent extends Component {
public static final int SPEED = 500;

private PhysicsComponent physics;
private Point2D velocity = new Point2D(SPEED, SPEED);

@Override
public void onUpdate(double tpf) {
var v = physics.getLinearVelocity();

double vx = v.getX();
double vy = v.getY();

// avoid ball stick to wall
if (Math.abs(vx) < 50) {
vx = (vy >= 0) ? 50 : -50;
}

// avoid ball stick to wall
if (Math.abs(vy) < 50) {
vy = (vx >= 0) ? 50 : -50;
}

Point2D velocity = new Point2D(vx, vy);

// avoid ball spin
physics.setLinearVelocity(velocity.normalize().multiply(SPEED));
physics.setAngularVelocity(0);
physics.getEntity().setRotation(0);
}

@Override
public void onAdded() {
physics.setOnPhysicsInitialized(
() -> physics.setLinearVelocity(velocity));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.github.codestorm.bounceverse.factory;

import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.EntityFactory;
import com.almasb.fxgl.entity.SpawnData;
import com.almasb.fxgl.entity.Spawns;
import com.almasb.fxgl.physics.PhysicsComponent;
import com.almasb.fxgl.physics.box2d.dynamics.BodyType;
import com.almasb.fxgl.physics.box2d.dynamics.FixtureDef;
import com.github.codestorm.bounceverse.components._old.ball.BallComponent;
import com.github.codestorm.bounceverse.data.types.EntityType;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;

/**
*
*
* <h1><b>Ball Factory</b></h1>
*
* <p>This class defines and spawns a new {@code Ball} entity in the game world.
*
* <p>By default, the spawned ball has:
*
* <ul>
* <li>Radius = 25
* <li>Position: (x = 50, y = 50)
* <li>Color: Red
* </ul>
*
* @author minngoc1213
*/
public class BallFactory implements EntityFactory {
public static final int RADIUS = 10;

@Spawns("ball")
public Entity spawnBall(SpawnData data) {
PhysicsComponent physics = new PhysicsComponent();

var fixture = new FixtureDef();
fixture.setDensity(1.0f);
fixture.setFriction(0f);
fixture.setRestitution(1f);

physics.setFixtureDef(fixture);
physics.setBodyType(BodyType.DYNAMIC);

// set ball doesn't rotate
physics.setOnPhysicsInitialized(
() -> {
physics.setAngularVelocity(0);
physics.getBody().setFixedRotation(true);
physics.getBody().setLinearDamping(0f);
physics.getBody().setAngularDamping(0f);
});

return FXGL.entityBuilder(data)
.type(EntityType.BALL)
.at(400, 500)
.viewWithBBox(new Circle(RADIUS, Color.RED))
.collidable()
.with(physics)
.with(new BallComponent())
.anchorFromCenter()
.buildAndAttach();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
import com.almasb.fxgl.entity.SpawnData;
import com.almasb.fxgl.entity.Spawns;
import com.almasb.fxgl.entity.component.Component;
import com.almasb.fxgl.physics.PhysicsComponent;
import com.almasb.fxgl.physics.box2d.dynamics.BodyType;
import com.almasb.fxgl.physics.box2d.dynamics.FixtureDef;
import com.github.codestorm.bounceverse.components.properties.brick.BrickHealth;
import com.github.codestorm.bounceverse.data.tags.entities.ForBrick;
import com.github.codestorm.bounceverse.data.tags.requirements.OptionalTag;
Expand All @@ -26,8 +29,8 @@
* @see EntityFactory
*/
public final class BrickFactory implements EntityFactory {
private static final int DEFAULT_WIDTH = 80;
private static final int DEFAULT_HEIGHT = 30;
public static final int DEFAULT_WIDTH = 80;
public static final int DEFAULT_HEIGHT = 30;
private static final Color DEFAULT_COLOR = Color.LIGHTBLUE;
private static final int DEFAULT_HP = 1;

Expand All @@ -45,10 +48,21 @@ public final class BrickFactory implements EntityFactory {
private static <OptionalBrickComponent extends Component & ForBrick & OptionalTag>
Entity newBrick(
Point2D pos, int hp, Rectangle view, OptionalBrickComponent... components) {
PhysicsComponent physics = new PhysicsComponent();

FixtureDef fixture = new FixtureDef();
fixture.setFriction(0f);
fixture.setRestitution(1f);

physics.setFixtureDef(fixture);
physics.setBodyType(BodyType.STATIC);

return FXGL.entityBuilder()
.type(EntityType.BRICK)
.at(pos)
.viewWithBBox(view)
.collidable()
.with(physics)
.with(new BrickHealth(hp))
.with(components)
.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.github.codestorm.bounceverse.factory;

import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.EntityFactory;
import com.almasb.fxgl.entity.components.CollidableComponent;
import com.almasb.fxgl.physics.BoundingShape;
import com.almasb.fxgl.physics.PhysicsComponent;
import com.almasb.fxgl.physics.box2d.dynamics.BodyType;
import com.almasb.fxgl.physics.box2d.dynamics.FixtureDef;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;

/**
*
*
* <h1><b>Wall Factory</b></h1>
*
* <p>This class spawns Wall entity for the game world.
*
* <p>By default, 4 walls top, left, bottom, right will be spawn at the beginning.
*
* @author minngoc1213
*/
public class WallFactory implements EntityFactory {

/**
* Create new Entity Wall with ing-game physic.
*
* @param x coordinate X of wall
* @param y coordinate Y of wall
* @param width width of wall
* @param height height of wall
* @return Wall entity at (x, y)
*/
public static Entity createWall(double x, double y, double width, double height) {
Rectangle rect = new Rectangle(width, height);
rect.setFill(Color.GRAY);

PhysicsComponent physics = new PhysicsComponent();

FixtureDef fixture = new FixtureDef();
fixture.setFriction(0f);
fixture.setRestitution(1f);

physics.setFixtureDef(fixture);
physics.setBodyType(BodyType.STATIC);

return FXGL.entityBuilder()
.at(x, y)
.view(rect)
.bbox(BoundingShape.box(width, height))
.with(physics)
.with(new CollidableComponent(true))
.anchorFromCenter()
.build();
}

/** Spawn 4 walls top, left, bottom, right. */
public static void spawnWalls() {
double w = FXGL.getAppWidth();
double h = FXGL.getAppHeight();

double thickness = 5;

FXGL.getGameWorld().addEntity(createWall(0, 0, w, thickness));
FXGL.getGameWorld().addEntity(createWall(0, h - thickness, w, thickness));
FXGL.getGameWorld().addEntity(createWall(0, 0, thickness, h));
FXGL.getGameWorld().addEntity(createWall(w - thickness, 0, thickness, h));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package com.github.codestorm.bounceverse.systems.physics;

import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.physics.CollisionHandler;
import com.almasb.fxgl.physics.PhysicsWorld;
import com.github.codestorm.bounceverse.components.properties.brick.BrickHealth;
import com.github.codestorm.bounceverse.data.types.EntityType;
import com.github.codestorm.bounceverse.systems.System;

/**
Expand Down Expand Up @@ -40,6 +46,18 @@ public void apply() {
// coin.removeFromWorld();
// }
// });

PhysicsWorld physics = FXGL.getPhysicsWorld();

physics.addCollisionHandler(
new CollisionHandler(EntityType.BALL, EntityType.BRICK) {
@Override
protected void onCollisionBegin(Entity ball, Entity brick) {
// decrease hp on collision
var brickHealth = brick.getComponent(BrickHealth.class);
brickHealth.getHealth().damage(1);
}
});
}

private CollisionSystem() {}
Expand Down
Loading