Game Development
Draft provides game development capabilities through its performance and cross-platform support.
Overview
Section titled “Overview”Draft’s native compilation, no-GC design, and cross-platform support make it suitable for game development.
Getting Started
Section titled “Getting Started”Create Game Project
Section titled “Create Game Project”draft new my-game --template gamecd my-gameProject structure:
my-game/├── draft.toml├── assets/│ ├── sprites/│ ├── sounds/│ └── shaders/├── src/│ ├── main.draft│ ├── game.draft│ ├── player.draft│ └── enemy.draft└── draft.tomlGame Loop
Section titled “Game Loop”import game
action main() @engine = @game#Engine::new("My Game", 800, 600)
@engine#on_start(fn() => load_assets() spawn_player() fin action.)
@engine#on_update(fn(@dt) => update_physics(@dt) update_entities(@dt) check_collisions() fin action.)
@engine#on_render(fn() => clear_screen() draw_entities() draw_ui() fin action.)
@engine#run()fin action.Entities
Section titled “Entities”import game
record Entity x: Float y: Float vx: Float vy: Float sprite: Sprite health: Intfin record.
impl Entity action update(@self: mut Entity, @dt: Float) @self#x = @self#x + @self#vx * @dt @self#y = @self#y + @self#vy * @dt fin action.
action draw(@self: Entity) @game#draw_sprite(@self#sprite, @self#x, @self#y) fin action.fin impl.Sprites
Section titled “Sprites”import game
action load_sprites() @player_sprite = @game#load_sprite("assets/player.png") @enemy_sprite = @game#load_sprite("assets/enemy.png") @bullet_sprite = @game#load_sprite("assets/bullet.png")fin action.
action draw_player(@player: Entity) @game#draw_sprite(@player#sprite, @player#x, @player#y)fin action.import game
action handle_input(@player: mut Entity) if @game#key_pressed(@game#KEY_LEFT) @player#vx = -200 else if @game#key_pressed(@game#KEY_RIGHT) @player#vx = 200 else @player#vx = 0 fin if.
if @game#key_pressed(@game#KEY_SPACE) shoot(@player) fin if.fin action.Gamepad
Section titled “Gamepad”import game
action handle_gamepad() @pad = @game#gamepad(0)
if @pad#button_pressed(@game#BUTTON_A) jump() fin if.
@axis_x = @pad#axis(@game#AXIS_LEFT_X) @axis_y = @pad#axis(@game#AXIS_LEFT_Y)fin action.Physics
Section titled “Physics”import game
action update_physics(@dt: Float) for @entity in @entities @entity#vy = @entity#vy + @game#GRAVITY * @dt @entity#x = @entity#x + @entity#vx * @dt @entity#y = @entity#y + @entity#vy * @dt fin for.fin action.Collision Detection
Section titled “Collision Detection”import game
action check_collisions() for @bullet in @bullets for @enemy in @enemies if @game#collides(@bullet, @enemy) @enemy#health = @enemy#health - 1 @bullets#remove(@bullet) fin if. fin for. fin for.fin action.Collision Shapes
Section titled “Collision Shapes”import game
@rect = @game#Rect::new(@x, @y, @width, @height)@circle = @game#Circle::new(@x, @y, @radius)
if @game#rect_collides(@rect_a, @rect_b) handle_collision()fin if.
if @game#circle_collides(@circle_a, @circle_b) handle_collision()fin if.import game
action load_audio() @jump_sound = @game#load_sound("assets/jump.wav") @explosion_sound = @game#load_sound("assets/explosion.wav") @bgm = @game#load_music("assets/bgm.ogg")fin action.
action play_sounds() @game#play_sound(@jump_sound) @game#play_music(@bgm, loop: true)fin action.Particles
Section titled “Particles”import game
action create_explosion(@x: Float, @y: Float) @emitter = @game#ParticleEmitter::new() @emitter#position(@x, @y) @emitter#count(100) @emitter#speed(100, 300) @emitter#life(0.5, 1.5) @emitter#color(@game#RED, @game#YELLOW) @emitter#emit()fin action.Camera
Section titled “Camera”import game
action setup_camera() @camera = @game#Camera::new() @camera#follow(@player) @camera#zoom(2.0) @camera#bounds(0, 0, 2000, 2000)fin action.Tilemaps
Section titled “Tilemaps”import game
action load_level() @tilemap = @game#Tilemap::new("assets/level1.tmx") @tilemap#layer("background") @tilemap#layer("collision") @tilemap#layer("foreground")fin action.
action draw_tilemap() @game#draw_tilemap(@tilemap, @camera#x, @camera#y)fin action.import game
action draw_hud() @game#draw_text("Score: " + string(@score), 10, 10) @game#draw_text("Lives: " + string(@lives), 10, 30) @game#draw_health_bar(@player#health, 10, 50, 200, 20)fin action.Scene Management
Section titled “Scene Management”import game
action main() @engine = @game#Engine::new("My Game", 800, 600)
@engine#add_scene("menu", fn() => MenuScene::new()) @engine#add_scene("game", fn() => GameScene::new()) @engine#add_scene("gameover", fn() => GameOverScene::new())
@engine#switch_scene("menu") @engine#run()fin action.Shaders
Section titled “Shaders”import game
action load_shaders() @shader = @game#Shader::new() @shader#vertex("assets/shaders/vertex.glsl") @shader#fragment("assets/shaders/fragment.glsl") @game#use_shader(@shader)fin action.Networking (Multiplayer)
Section titled “Networking (Multiplayer)”import gameimport websocket
action connect_to_server() @ws = @websocket#connect("ws://game-server.example.com") @ws#on_message(fn(@data) => handle_network_message(@data) fin action.)fin action.
action send_position(@x: Float, @y: Float) @ws#send(json#stringify({ "type", "position", "x", @x, "y", @y }))fin action.Save System
Section titled “Save System”import gameimport json
action save_game() @save_data = { "level", @current_level, "score", @score, "lives", @lives, "position", {@player#x, @player#y} } @game#save("save.dat", @json#stringify(@save_data))fin action.
action load_game() @data = @game#load("save.dat") @save = @json#parse(@data) @current_level = @save["level"] @score = @save["score"]fin action.Performance Tips
Section titled “Performance Tips”Object Pooling
Section titled “Object Pooling”import game
record BulletPool bullets: Array<Bullet> active: Intfin record.
impl BulletPool action new(@size: Int) -> BulletPool @bullets = [] for @i in 0..@size @bullets#push(Bullet::new()) fin for. return BulletPool { bullets: @bullets, active: 0 } fin action.
action get(@self: mut BulletPool) -> Bullet? if @self#active < @self#bullets#length @bullet = @self#bullets[@self#active] @self#active = @self#active + 1 return @bullet fin if. return none fin action.fin impl.Spatial Partitioning
Section titled “Spatial Partitioning”import game
action setup_spatial_hash() @grid = @game#SpatialHash::new(64) @// Cell size for @entity in @entities @grid#insert(@entity) fin for.fin action.
action query_nearby(@x: Float, @y: Float, @radius: Float) -> Array<Entity> return @grid#query(@x, @y, @radius)fin action.Building
Section titled “Building”Desktop
Section titled “Desktop”draft build --target native --releasedraft build --target wasm --releaseMobile
Section titled “Mobile”draft build --target mobile --releaseDeployment
Section titled “Deployment”@// Desktopdraft deploy --target windowsdraft deploy --target macosdraft deploy --target linux
@// Webdraft deploy --target wasm --hosting itch.io
@// Mobiledraft deploy --target iosdraft deploy --target androidPerformance Targets
Section titled “Performance Targets”| Metric | Target |
|---|---|
| Frame rate | 60 FPS |
| Frame time | < 16ms |
| Draw calls | < 1000 |
| Memory | < 256 MB |
| Load time | < 3s |
