← All examples
Rendering · Input
Moving Box
The smallest playable game
The example linked from the project README's own quick-start: a single WASD-controlled box drawn with IRenderer::DrawRect.
It's deliberately minimal — one entity, no ECS, no assets — to show the shortest path from Application<TGame> to something on screen that responds to a player.
Controls
- W A S D Move the box

Run it yourself
build just this example
cmake --build --preset windows-debug --target moving_box
# binary lands under bin/ (e.g. bin/Debug/moving_box.exe on Windows)
See Installation for the full build setup.
Source
examples/moving_box/MovingBox.hpp
#pragma once
#include <ASGE/ASGE.hpp>
class MovingBox
{
asge::math::Float2 m_Position{ asge::math::Float2::Zero() };
asge::math::Float2 m_Dimension{ 50.0f, 50.0f };
float m_Speed{250.0f};
bool m_Up{false};
bool m_Down{false};
bool m_Left{false};
bool m_Right{false};
public:
void Update(float inDeltaTime);
void Render(asge::video::IRenderer& inRender);
void OnKeyboardEvent(asge::event::KeyboardEvent const& inKeyEvent);
};
examples/moving_box/MovingBox.cpp
#include "MovingBox.hpp"
void MovingBox::Update(float inDeltaTime)
{
auto dir = asge::math::Float2::Zero();
if (m_Left) dir.x() -= 1.0f;
if (m_Right) dir.x() += 1.0f;
if (m_Up) dir.y() -= 1.0f;
if (m_Down) dir.y() += 1.0f;
m_Position += dir * m_Speed * inDeltaTime;
}
void MovingBox::Render(asge::video::IRenderer &inRender)
{
inRender.DrawRect(
asge::math::Rect{ m_Position.x(), m_Position.y(), m_Dimension.x(), m_Dimension.y() },
{255, 0, 0, 255},
true
);
}
void MovingBox::OnKeyboardEvent(asge::event::KeyboardEvent const &inKeyEvent)
{
bool pressed = inKeyEvent.s_Type == asge::event::EventType::KEYBOARD_KEY_PRESSED;
switch (inKeyEvent.s_Keycode)
{
case asge::input::Keycode::W: m_Up = pressed; break;
case asge::input::Keycode::S: m_Down = pressed; break;
case asge::input::Keycode::A: m_Left = pressed; break;
case asge::input::Keycode::D: m_Right = pressed; break;
default: break;
}
}
examples/moving_box/MovingBoxGame.cpp
#include "MovingBoxGame.hpp"
std::optional<asge::game::state::Transition<int>>
MovingBoxState::Update(float inDeltaTime, [[maybe_unused]] asge::input::InputState const& inInput)
{
m_Box.Update( inDeltaTime );
return std::nullopt;
}
void MovingBoxState::Render(asge::video::IRenderer &inRenderer)
{
inRenderer.Clear({ 0, 0, 0, 255 });
m_Box.Render( inRenderer );
}
void MovingBoxState::OnSystemEvent(asge::event::SystemEvent const &inSysEvent)
{
auto const* keyEvent = inSysEvent.TryGet<asge::event::KeyboardEvent>();
if (!keyEvent) return;
m_Box.OnKeyboardEvent( *keyEvent );
}
MovingBoxGame::MovingBoxGame(asge::video::IRenderer& inRenderer, asge::audio::AudioDevice& inAudioDev)
: Game(inRenderer, inAudioDev)
{
SetInitialState(0);
}
std::unique_ptr<MovingBoxGame::StateType> MovingBoxGame::CreateState([[maybe_unused]] int inId)
{
return std::make_unique<MovingBoxState>();
}