module Eagle
Overview
Eagle is a 2D and 3D game engine written in Crystal. This page is the API reference; each type explains what it's for and shows how to use it.
Where to start
AppandEagle.runopen a window and run your game loop.Graphicsdraws shapes, sprites and text immediately, in the style of LÖVE.Node,Node2DandSceneTreebuild a Godot-style scene of objects that update and draw themselves.Inputreads keys, mouse and gamepads, and maps them to named actions.
By topic
- 2D:
Sprite2D,AnimatedSprite2D,Camera2D,TileMap,Particles2D,Polygon2D,CanvasLayer - 3D:
Node3D,MeshInstance3D,Camera3D,DirectionalLight3D,Mesh,Material,Scene3D - Physics:
RigidBody2D,KinematicBody2D,Area2D,Physics2D, and their 3D versions - UI:
Control,Button,Label,Slider,TextInput,VBox,Theme - Audio:
Sound,Voice,AudioPlayer,Audio - Assets:
Assets,Texture,Image,Font,Shader - Timing:
Clock,Timer,Tween - Math:
Vec2,Vec3,Rect,Color,Mathf,Transform2D,Quat
A complete game
class Game < App
@player = Sprite2D.new(Texture.new(Image.circle(24, Color::YELLOW)), Vec2.new(480, 270))
@score = 0
def load : Nil
Input.map "left", Key::A, Key::Left
Input.map "right", Key::D, Key::Right
SceneTree.root.add(@player)
end
def update(dt : Float32) : Nil
@player.x += Input.axis("left", "right") * 300 * dt
@score += 1 if Input.pressed?(Key::Space)
end
def draw(g : Graphics) : Nil
g.print("score #{@score}", 10, 10, scale: 2)
end
end
Eagle.run(Game, title: "My Game", width: 960, height: 540)
Defined in:
eagle.creagle/assets/assets.cr
eagle/assets/codecs/bmp.cr
eagle/assets/codecs/png.cr
eagle/assets/codecs/qoi.cr
eagle/assets/codecs/zlib.cr
eagle/assets/image.cr
eagle/audio/audio.cr
eagle/audio/vorbis.cr
eagle/audio/wav.cr
eagle/core/clock.cr
eagle/core/engine.cr
eagle/core/error.cr
eagle/core/events.cr
eagle/core/log.cr
eagle/core/node.cr
eagle/core/scene_tree.cr
eagle/core/script.cr
eagle/core/signal.cr
eagle/core/tween.cr
eagle/core/window.cr
eagle/gpu/device.cr
eagle/gpu/gl33.cr
eagle/graphics/canvas.cr
eagle/graphics/default_font_data.cr
eagle/graphics/font.cr
eagle/graphics/graphics.cr
eagle/graphics/shader.cr
eagle/graphics/texture.cr
eagle/graphics/truetype.cr
eagle/graphics3d/material.cr
eagle/graphics3d/mesh.cr
eagle/graphics3d/renderer3d.cr
eagle/input/input.cr
eagle/input/keys.cr
eagle/lib/gl.cr
eagle/math/color.cr
eagle/math/mat4.cr
eagle/math/math.cr
eagle/math/quat.cr
eagle/math/rect.cr
eagle/math/transform2d.cr
eagle/math/vec2.cr
eagle/math/vec3.cr
eagle/nodes/animated_sprite2d.cr
eagle/nodes/audio_player.cr
eagle/nodes/camera2d.cr
eagle/nodes/node2d.cr
eagle/nodes/node3d.cr
eagle/nodes/particles2d.cr
eagle/nodes/physics3d_nodes.cr
eagle/nodes/physics_nodes.cr
eagle/nodes/shapes2d.cr
eagle/nodes/sprite2d.cr
eagle/nodes/tilemap.cr
eagle/nodes/timer.cr
eagle/physics/body2d.cr
eagle/physics/collision2d.cr
eagle/physics/physics2d.cr
eagle/physics/physics3d.cr
eagle/physics/shapes2d.cr
eagle/physics/world2d.cr
eagle/platform/base.cr
eagle/platform/sdl.cr
eagle/ui/control.cr
eagle/ui/theme.cr
eagle/ui/widgets.cr
eagle/version.cr
Constant Summary
-
DEFAULT_FONT_GLYPHS =
".....\n.....\n.....\n.....\n.....\n.....\n.....\n\n..#..\n..#..\n..#..\n..#..\n..#..\n.....\n..#..\n\n.#.#.\n.#.#.\n.#.#.\n.....\n.....\n.....\n.....\n\n.#.#.\n.#.#.\n#####\n.#.#.\n#####\n.#.#.\n.#.#.\n\n..#..\n.####\n#.#..\n.###.\n..#.#\n####.\n..#..\n\n##...\n##..#\n...#.\n..#..\n.#...\n#..##\n...##\n\n.##..\n#..#.\n#.#..\n.#...\n#.#.#\n#..#.\n.##.#\n\n.##..\n..#..\n.#...\n.....\n.....\n.....\n.....\n\n...#.\n..#..\n.#...\n.#...\n.#...\n..#..\n...#.\n\n.#...\n..#..\n...#.\n...#.\n...#.\n..#..\n.#...\n\n.....\n..#..\n#.#.#\n.###.\n#.#.#\n..#..\n.....\n\n.....\n..#..\n..#..\n#####\n..#..\n..#..\n.....\n\n.....\n.....\n.....\n.....\n.##..\n..#..\n.#...\n\n.....\n.....\n.....\n#####\n.....\n.....\n.....\n\n.....\n.....\n.....\n.....\n.....\n.##..\n.##..\n\n.....\n....#\n...#.\n..#..\n.#...\n#....\n.....\n\n.###.\n#...#\n#..##\n#.#.#\n##..#\n#...#\n.###.\n\n..#..\n.##..\n..#..\n..#..\n..#..\n..#..\n.###.\n\n.###.\n#...#\n....#\n...#.\n..#..\n.#...\n#####\n\n#####\n...#.\n..#..\n...#.\n....#\n#...#\n.###.\n\n...#.\n..##.\n.#.#.\n#..#.\n#####\n...#.\n...#.\n\n#####\n#....\n####.\n....#\n....#\n#...#\n.###.\n\n..##.\n.#...\n#....\n####.\n#...#\n#...#\n.###.\n\n#####\n....#\n...#.\n..#..\n.#...\n.#...\n.#...\n\n.###.\n#...#\n#...#\n.###.\n#...#\n#...#\n.###.\n\n.###.\n#...#\n#...#\n.####\n....#\n...#.\n.##..\n\n.....\n.##..\n.##..\n.....\n.##..\n.##..\n.....\n\n.....\n.##..\n.##..\n.....\n.##..\n..#..\n.#...\n\n...#.\n..#..\n.#...\n#....\n.#...\n..#..\n...#.\n\n.....\n.....\n#####\n.....\n#####\n.....\n.....\n\n.#...\n..#..\n...#.\n....#\n...#.\n..#..\n.#...\n\n.###.\n#...#\n....#\n...#.\n..#..\n.....\n..#..\n\n.###.\n#...#\n#.###\n#.#.#\n#.###\n#....\n.###.\n\n.###.\n#...#\n#...#\n#####\n#...#\n#...#\n#...#\n\n####.\n#...#\n#...#\n####.\n#...#\n#...#\n####.\n\n.###.\n#...#\n#....\n#....\n#....\n#...#\n.###.\n\n###..\n#..#.\n#...#\n#...#\n#...#\n#..#.\n###..\n\n#####\n#....\n#....\n####.\n#....\n#....\n#####\n\n#####\n#....\n#....\n####.\n#....\n#....\n#....\n\n.###.\n#...#\n#....\n#.###\n#...#\n#...#\n.####\n\n#...#\n#...#\n#...#\n#####\n#...#\n#...#\n#...#\n\n.###.\n..#..\n..#..\n..#..\n..#..\n..#..\n.###.\n\n..###\n...#.\n...#.\n...#.\n...#.\n#..#.\n.##..\n\n#...#\n#..#.\n#.#..\n##...\n#.#..\n#..#.\n#...#\n\n#....\n#....\n#....\n#....\n#....\n#....\n#####\n\n#...#\n##.##\n#.#.#\n#.#.#\n#...#\n#...#\n#...#\n\n#...#\n#...#\n##..#\n#.#.#\n#..##\n#...#\n#...#\n\n.###.\n#...#\n#...#\n#...#\n#...#\n#...#\n.###.\n\n####.\n#...#\n#...#\n####.\n#....\n#....\n#....\n\n.###.\n#...#\n#...#\n#...#\n#.#.#\n#..#.\n.##.#\n\n####.\n#...#\n#...#\n####.\n#.#..\n#..#.\n#...#\n\n.####\n#....\n#....\n.###.\n....#\n....#\n####.\n\n#####\n..#..\n..#..\n..#..\n..#..\n..#..\n..#..\n\n#...#\n#...#\n#...#\n#...#\n#...#\n#...#\n.###.\n\n#...#\n#...#\n#...#\n#...#\n#...#\n.#.#.\n..#..\n\n#...#\n#...#\n#...#\n#.#.#\n#.#.#\n#.#.#\n.#.#.\n\n#...#\n#...#\n.#.#.\n..#..\n.#.#.\n#...#\n#...#\n\n#...#\n#...#\n#...#\n.#.#.\n..#..\n..#..\n..#..\n\n#####\n....#\n...#.\n..#..\n.#...\n#....\n#####\n\n.###.\n.#...\n.#...\n.#...\n.#...\n.#...\n.###.\n\n.....\n#....\n.#...\n..#..\n...#.\n....#\n.....\n\n.###.\n...#.\n...#.\n...#.\n...#.\n...#.\n.###.\n\n..#..\n.#.#.\n#...#\n.....\n.....\n.....\n.....\n\n.....\n.....\n.....\n.....\n.....\n.....\n#####\n\n.#...\n..#..\n...#.\n.....\n.....\n.....\n.....\n\n.....\n.....\n.###.\n....#\n.####\n#...#\n.####\n\n#....\n#....\n#.##.\n##..#\n#...#\n#...#\n####.\n\n.....\n.....\n.###.\n#....\n#....\n#...#\n.###.\n\n....#\n....#\n.##.#\n#..##\n#...#\n#...#\n.####\n\n.....\n.....\n.###.\n#...#\n#####\n#....\n.###.\n\n..##.\n.#..#\n.#...\n###..\n.#...\n.#...\n.#...\n\n.....\n.....\n.####\n#...#\n.####\n....#\n.###.\n\n#....\n#....\n#.##.\n##..#\n#...#\n#...#\n#...#\n\n..#..\n.....\n.##..\n..#..\n..#..\n..#..\n.###.\n\n...#.\n.....\n..##.\n...#.\n...#.\n#..#.\n.##..\n\n#....\n#....\n#..#.\n#.#..\n##...\n#.#..\n#..#.\n\n.##..\n..#..\n..#..\n..#..\n..#..\n..#..\n.###.\n\n.....\n.....\n##.#.\n#.#.#\n#.#.#\n#...#\n#...#\n\n.....\n.....\n#.##.\n##..#\n#...#\n#...#\n#...#\n\n.....\n.....\n.###.\n#...#\n#...#\n#...#\n.###.\n\n.....\n.....\n####.\n#...#\n####.\n#....\n#....\n\n.....\n.....\n.####\n#...#\n.####\n....#\n....#\n\n.....\n.....\n#.##.\n##..#\n#....\n#....\n#....\n\n.....\n.....\n.####\n#....\n.###.\n....#\n####.\n\n.#...\n.#...\n###..\n.#...\n.#...\n.#..#\n..##.\n\n.....\n.....\n#...#\n#...#\n#...#\n#..##\n.##.#\n\n.....\n.....\n#...#\n#...#\n#...#\n.#.#.\n..#..\n\n.....\n.....\n#...#\n#...#\n#.#.#\n#.#.#\n.#.#.\n\n.....\n.....\n#...#\n.#.#.\n..#..\n.#.#.\n#...#\n\n.....\n.....\n#...#\n#...#\n.####\n....#\n.###.\n\n.....\n.....\n#####\n...#.\n..#..\n.#...\n#####\n\n..##.\n.#...\n.#...\n#....\n.#...\n.#...\n..##.\n\n..#..\n..#..\n..#..\n..#..\n..#..\n..#..\n..#..\n\n.##..\n...#.\n...#.\n....#\n...#.\n...#.\n.##..\n\n.....\n.....\n.#..#\n#.#.#\n#..#.\n.....\n....." -
Built-in 5x7 pixel font, ASCII 32..126. Each glyph is 7 rows of 5 columns. Authored for Eagle; public domain.
-
VERSION =
"0.1.0" -
Eagle's version, following semantic versioning.
Class Method Summary
-
.app : App
The running app.
-
.config : Config
The active configuration.
-
.g : Graphics
Short alias for
.graphics. -
.graphics : Graphics
The 2D drawing context, the same object passed to
App#draw. -
.handle_event(ev : Event) : Nil
Routes one event through
Input, the app and the scene tree right away. -
.init(app_class : App.class, **opts) : Nil
Opens the window and GPU and constructs app_class, without entering the loop.
-
.init(app : App = App.new, **opts, &factory : -> App) : Nil
Opens everything with a placeholder, then builds the real app with factory.
-
.init(app : App = App.new, **opts) : Nil
Opens the window and GPU and calls
App#load, without entering the loop. -
.initialized? : Bool
True after the window and GPU are open.
-
.inject(*events : Event) : Nil
Queues synthetic events for the next frame.
-
.log : Log
Eagle's logger, a standard Crystal
Lognamed "eagle". -
.platform : Platform::Base
The platform backend (SDL on desktop, the browser on the web).
-
.platform? : Platform::Base | Nil
The platform backend, or
nilbeforeEagle.run. -
.quit : Nil
Asks the loop to stop after the current frame.
-
.run(app : App = App.new, **opts) : Nil
Opens the window, calls
App#load, runs the main loop until quit, then shuts down. -
.run(**opts, &block : App -> ) : Nil
Creates a plain
App, lets the block attach hooks withApp#on_drawand friends, then runs it. -
.run(app_class : App.class, **opts) : Nil
Runs a game given its class.
-
.running? : Bool
True while the main loop is running.
-
.screenshot(path : String | Nil = nil) : Image
Reads the current frame back from the GPU and returns it as an
Image. -
.setup_logging : Nil
Sets the log level from the
EAGLE_LOGenvironment variable (debug, info, warn, error or off). -
.shutdown : Nil
Closes the window and frees GPU, audio and asset resources.
-
.step : Nil
Runs exactly one frame: input, fixed updates, update, tweens, audio and drawing.
Macro Summary
-
embed_assets(dir = "assets")
Bakes every file under dir into the executable at compile time, so the game runs with no files beside it.
Class Method Detail
Routes one event through Input, the app and the scene tree right away. Most code should use .inject.
Opens the window and GPU and constructs app_class, without entering the loop.
Drive frames with .step and finish with .shutdown.
Opens everything with a placeholder, then builds the real app with factory.
Opens the window and GPU and calls App#load, without entering the loop.
Use it in tests and tools, then call .step to advance frames and .shutdown when done.
Eagle.init(title: "test", hidden: true)
3.times { Eagle.step }
image = Eagle.screenshot
Eagle.shutdown
Queues synthetic events for the next frame. They go through the same path as real
input, so Input, App#input and nodes all see them. Use it for tests, demos and replays.
Eagle.inject(KeyEvent.new(Key::Space, pressed: true))
Eagle's logger, a standard Crystal Log named "eagle". Set EAGLE_LOG=debug for more output.
Eagle.log.info { "level loaded" }
Eagle.log.debug { "spawned enemy" }
The platform backend (SDL on desktop, the browser on the web). Raises if Eagle isn't running.
You rarely need it; Window, Input and Audio wrap it.
Asks the loop to stop after the current frame. App#unload runs during shutdown.
Opens the window, calls App#load, runs the main loop until quit, then shuts down.
Named arguments set Config fields.
class Game < App
end
Eagle.run(Game.new, title: "Hi", width: 800, height: 600)
On the web the browser drives frames, so this returns right away.
Runs a game given its class. The app is constructed after the window and GPU exist, so instance-variable initializers can create textures, fonts and sounds. This is the recommended form.
class Game < App
@logo = Texture.new(Image.circle(32, Color::WHITE)) # safe: the GPU is ready
end
Eagle.run(Game, title: "Hi")
Reads the current frame back from the GPU and returns it as an Image. Saves a PNG if you give a path.
Eagle.screenshot("shot.png") if Input.pressed?(Key::F12)
Sets the log level from the EAGLE_LOG environment variable (debug, info, warn, error or off).
The default is info. Eagle.run calls this for you.
Closes the window and frees GPU, audio and asset resources. .run calls it for you.
Runs exactly one frame: input, fixed updates, update, tweens, audio and drawing.
.run calls this in a loop. Call it yourself after .init to drive the engine from tests.
Macro Detail
Bakes every file under dir into the executable at compile time, so the game runs with no files beside it. Web builds need this, because the browser can't read your disk. Put it at the top level of your main file:
Eagle.embed_assets("assets")
Texture.load("res://player.png") # served from memory
Paths inside dir become res:// paths.