Hello World¶
Let's build your first interactive Heaps application - a simple game where you click to spawn bouncing sprites.
Basic Application Structure¶
Every Heaps application extends hxd.App
:
class Main extends hxd.App {
override function init() {
// Called once when app starts
}
override function update(dt:Float) {
// Called every frame
// dt = delta time in seconds
}
static function main() {
new Main();
}
}
Display Your First Sprite¶
class Main extends hxd.App {
var player : h2d.Bitmap;
override function init() {
// Create a colored square
var tile = h2d.Tile.fromColor(0xFF0000, 32, 32);
player = new h2d.Bitmap(tile, s2d);
// Center it on screen
player.x = s2d.width * 0.5 - 16;
player.y = s2d.height * 0.5 - 16;
}
}
The s2d
property is your 2D scene - everything displayed must be added to it.
Make It Move¶
Add movement in the update loop:
class Main extends hxd.App {
var player : h2d.Bitmap;
var velocity = 200.0; // pixels per second
override function init() {
var tile = h2d.Tile.fromColor(0xFF0000, 32, 32);
player = new h2d.Bitmap(tile, s2d);
player.center(); // Centers the tile pivot
player.x = s2d.width * 0.5;
player.y = s2d.height * 0.5;
}
override function update(dt:Float) {
// Move right
player.x += velocity * dt;
// Wrap around screen
if (player.x > s2d.width + 16) {
player.x = -16;
}
}
}
Delta Time
Multiply movement by dt
to ensure consistent speed regardless of framerate.
Add Input¶
Heaps provides easy access to keyboard and mouse:
class Main extends hxd.App {
var player : h2d.Bitmap;
var speed = 200.0;
override function init() {
var tile = h2d.Tile.fromColor(0x00FF00, 32, 32);
player = new h2d.Bitmap(tile, s2d);
player.center();
player.x = s2d.width * 0.5;
player.y = s2d.height * 0.5;
}
override function update(dt:Float) {
// Keyboard input
if (hxd.Key.isDown(hxd.Key.LEFT)) player.x -= speed * dt;
if (hxd.Key.isDown(hxd.Key.RIGHT)) player.x += speed * dt;
if (hxd.Key.isDown(hxd.Key.UP)) player.y -= speed * dt;
if (hxd.Key.isDown(hxd.Key.DOWN)) player.y += speed * dt;
// Mouse position
player.rotation = Math.atan2(
s2d.mouseY - player.y,
s2d.mouseX - player.x
);
}
}
Interactive Demo¶
Here's a complete interactive demo:
class Main extends hxd.App {
var squares : Array<Square> = [];
override function init() {
// Display instructions
var text = new h2d.Text(hxd.res.DefaultFont.get(), s2d);
text.text = "Click to spawn squares!";
text.x = 10;
text.y = 10;
// Change background
engine.backgroundColor = 0x1a1a2e;
}
override function update(dt:Float) {
// Spawn on click
if (hxd.Key.isPressed(hxd.Key.MOUSE_LEFT)) {
spawnSquare(s2d.mouseX, s2d.mouseY);
}
// Update all squares
for (square in squares) {
square.update(dt);
}
// Remove off-screen squares
squares = squares.filter(s -> s.y < s2d.height + 50);
}
function spawnSquare(x:Float, y:Float) {
var square = new Square(s2d);
square.x = x;
square.y = y;
squares.push(square);
}
static function main() {
new Main();
}
}
class Square extends h2d.Bitmap {
var velocity : Float;
var gravity = 500.0;
var hue : Float;
public function new(parent:h2d.Object) {
// Random colored square
hue = Math.random();
var color = hxd.Math.colorHSV(hue, 0.8, 0.9);
var tile = h2d.Tile.fromColor(color, 16, 16);
super(tile, parent);
center();
// Random upward velocity
velocity = -Math.random() * 300 - 100;
// Random rotation speed
rotation = Math.random() * Math.PI;
}
public function update(dt:Float) {
// Physics
velocity += gravity * dt;
y += velocity * dt;
// Spin
rotation += dt * 2;
// Fade based on hue
alpha = 1 - (y / 600);
}
}
Understanding the Code¶
Display Objects¶
h2d.Object
- Base class for all 2D display objectsh2d.Bitmap
- Displays a single tile/imageh2d.Text
- Renders texts2d
- The root 2D scene
Game Loop¶
init()
- Setup your game stateupdate(dt)
- Update logic each framedt
- Time since last frame in seconds
Input¶
hxd.Key.isDown()
- Check if key is heldhxd.Key.isPressed()
- Check if key was just presseds2d.mouseX/mouseY
- Current mouse position
Build and Run¶
Save as src/Main.hx
and build:
Exercises¶
Try these modifications:
- Change Colors: Make squares cycle through colors as they fall
- Add Particles: Spawn multiple small squares on click
- Add Sound: Play a sound effect on spawn (hint:
hxd.Res.sound.play()
) - Add Text: Display the number of squares on screen
Common Patterns¶
Object Pooling¶
var pool : Array<Square> = [];
function getSquare() : Square {
if (pool.length > 0) {
return pool.pop();
}
return new Square(s2d);
}
function recycleSquare(s:Square) {
s.visible = false;
pool.push(s);
}
Screen Boundaries¶
// Keep object on screen
obj.x = Math.max(0, Math.min(s2d.width - obj.width, obj.x));
obj.y = Math.max(0, Math.min(s2d.height - obj.height, obj.y));
Simple Timer¶
var timer = 0.0;
var interval = 1.0; // 1 second
override function update(dt:Float) {
timer += dt;
if (timer >= interval) {
timer -= interval;
// Do something every second
}
}
Next Steps¶
Now that you understand the basics, let's look at Project Structure → to organize larger games.