| name | fxgl-topdown |
| description | Build a top-down 2D game in FXGL — disable gravity for the physics world, implement 8-direction normalized movement, bind the camera to follow the player with world bounds, aim and fire projectiles toward the mouse cursor, spawn a melee attack hitbox in the facing direction, trigger NPC interactions on proximity, handle area/room transitions at screen edges, display a minimap with entity dots, and load Tiled TMX tile-based worlds. Use this skill when building a Zelda-style adventure, twin-stick shooter, top-down RPG, arena shooter, or any bird's-eye-view 2D game.
|
| triggers | ["top-down","bird's eye","8-direction","twin-stick","top-down RPG","Zelda-style","arena shooter","no gravity","top-down movement","aim at mouse"] |
| compatibility | Java 17+, FXGL 21.x
|
| category | fxgl/game-types |
| tags | ["fxgl","java","javafx","game-types","topdown"] |
| metadata | {"author":"fxgl-skills","version":"1.0","fxgl-version":"21.1"} |
| allowed-tools | ["Read","Write","Edit","Bash"] |
FXGL Top-Down 2D
World Without Gravity
@Override
protected void initPhysics() {
getPhysicsWorld().setGravity(0, 0);
}
Player Entity (8-Direction)
@Spawns("player")
public Entity newPlayer(SpawnData data) {
PhysicsComponent physics = new PhysicsComponent();
physics.setBodyType(BodyType.DYNAMIC);
physics.setFixedRotation(true);
FixtureDef fd = new FixtureDef();
fd.setFriction(0.0f);
fd.setDensity(1.0f);
physics.addFixtureDef(fd);
return entityBuilder(data)
.type(EntityType.PLAYER)
.view("player.png")
.bbox(BoundingShape.circle(14))
.with(physics)
.with(new CollidableComponent(true))
.with(new TopDownPlayerComponent())
.build();
}
TopDownPlayerComponent — 8-Direction Movement
public class TopDownPlayerComponent extends Component {
private PhysicsComponent physics;
private ;
{
, dy = ;
(getInput().isHeld(KeyCode.W) || getInput().isHeld(KeyCode.UP)) dy -= ;
(getInput().isHeld(KeyCode.S) || getInput().isHeld(KeyCode.DOWN)) dy += ;
(getInput().isHeld(KeyCode.A) || getInput().isHeld(KeyCode.LEFT)) dx -= ;
(getInput().isHeld(KeyCode.D) || getInput().isHeld(KeyCode.RIGHT)) dx += ;
(dx != && dy != ) {
dx *= ;
dy *= ;
}
physics.setVelocityX(dx * MOVE_SPEED);
physics.setVelocityY(dy * MOVE_SPEED);
(dx != || dy != ) {
entity.setRotation(Math.toDegrees(Math.atan2(dy, dx)));
}
}
}