| name | fxgl-breakout |
| description | Build a Breakout or Arkanoid style game in FXGL — control a paddle horizontally, keep a ball at constant speed, bounce it off walls, paddle, and bricks, load brick layouts from level data, angle the reflection based on paddle hit position, handle lives and bottom-drain loss, spawn falling power-ups, and finish the level when all breakable bricks are destroyed.
|
| triggers | ["breakout","arkanoid","paddle ball","brick breaker","multiball","paddle bounce","brick hp","power-up drop","lose life on drain"] |
| compatibility | Java 17+, FXGL 21.x. Uses FXGL 2D physics and collision handlers.
|
| category | fxgl/game-types |
| tags | ["fxgl","java","javafx","game-types","breakout"] |
| metadata | {"author":"fxgl-skills","version":"1.0","fxgl-version":"21.1"} |
| allowed-tools | ["Read","Write","Edit","Bash"] |
FXGL Breakout / Arkanoid
Core Setup
Use these entity roles:
PADDLE — kinematic horizontal controller
BALL — dynamic body with manual speed correction
BRICK — static collidable block with optional HP
POWERUP — falling collectible
DRAIN — bottom sensor that costs a life
Paddle Entity
@Spawns("paddle")
public Entity newPaddle(SpawnData data) {
var physics = new PhysicsComponent();
physics.setBodyType(BodyType.KINEMATIC);
return entityBuilder(data)
.type(EntityType.PADDLE)
.bbox(BoundingShape.box(120, 20))
.with(physics)
.collidable()
.build();
}
@Override
protected void initInput() {
onMouseMove(e -> {
double x = clamp(e.getX() - paddle.getWidth() / 2.0, 0, getAppWidth() - paddle.getWidth());
paddle.setX(x);
});
}
Ball Entity and Constant Speed
private static final double BALL_SPEED = 420;
@Spawns("ball")
public Entity newBall(SpawnData data) {
var physics = new ();
physics.setBodyType(BodyType.DYNAMIC);
();
fd.setRestitution();
fd.setFriction();
physics.addFixtureDef(fd);
entityBuilder(data)
.type(EntityType.BALL)
.bbox(BoundingShape.circle())
.with(physics)
.collidable()
.with( ())
.build();
}
{
PhysicsComponent physics;
{
physics.setLinearVelocity(BALL_SPEED * , -BALL_SPEED);
}
{
physics.getLinearVelocity();
(v.magnitude() == ) {
physics.setLinearVelocity(BALL_SPEED * , -BALL_SPEED);
;
}
v.normalize().multiply(BALL_SPEED);
physics.setLinearVelocity(corrected);
}
}