Haaf’s Game Engine - HGE - sits in a narrow but useful corner of the 2D engine world. It is not a general-purpose platform trying to cover every case. It is a C++ framework for hardware-accelerated 2D rendering, with a direct API that leaves the underlying work visible.
We maintain the HGE documentation portal here at Relish Games, and we regularly hear from developers who want to try HGE but are not sure where to begin. This page is the practical route in, from download to drawing your first sprites.
Why HGE still makes sense in 2026
HGE remains relevant for a simple reason: it does a small set of things well.
- Direct hardware access. HGE uses DirectX for rendering, so you get close-to-metal performance without managing GPU state by hand.
- Small footprint. The engine is compact enough to understand properly, which matters if you dislike black boxes.
- Native C++. If C++ is already your language, the fit is natural. There is no scripting layer and no VM overhead.
- Focused scope. Sprite rendering, particle effects, audio and input cover the core needs of many 2D games without drifting into feature bloat.
- Active documentation. The comprehensive API reference covers every function and constant.
The trade-off is plain enough. HGE is Windows-focused and assumes C++ competence. If you need cross-platform support from the start, or prefer a higher-level language, another engine will be the better fit. But if you are building a Windows 2D game in C++ and want tight control with little overhead, HGE still earns its place.
Getting set up
Prerequisites
- Visual Studio 2022 or later. Community edition is fine.
- Windows 10/11 SDK, which comes with Visual Studio.
- C++ knowledge. You should already be comfortable with pointers, classes and basic memory management.
- DirectX runtime. On modern Windows installs, this is usually already there.
Download
Go to the HGE downloads page and download the latest package. It includes the core engine libraries, with both static and dynamic linking options, plus header files, sample projects, the particle editor tool and documentation.
Project setup
- Create a new empty C++ project in Visual Studio.
- Add the HGE include directory to the project’s include paths.
- Add the HGE library directory to the linker paths.
- Link against
hge.libandhgehelp.lib. - Copy
hge.dllto the output directory.
The core loop
HGE uses a straightforward pattern: you provide callback functions, and the engine calls them when needed.
Minimal application
The basic shape of every HGE application is shown below:
#include <hge.h>
HGE *hge = nullptr;
bool FrameFunc()
{
// Game logic goes here
// Return true to exit the application
if (hge->Input_GetKeyState(HGEK_ESCAPE))
return true;
return false;
}
bool RenderFunc()
{
hge->Gfx_BeginScene();
hge->Gfx_Clear(0);
// Rendering goes here
hge->Gfx_EndScene();
return false;
}
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
hge = hgeCreate(HGE_VERSION);
hge->System_SetState(HGE_FRAMEFUNC, FrameFunc);
hge->System_SetState(HGE_RENDERFUNC, RenderFunc);
hge->System_SetState(HGE_TITLE, "My First HGE Game");
hge->System_SetState(HGE_WINDOWED, true);
hge->System_SetState(HGE_SCREENWIDTH, 800);
hge->System_SetState(HGE_SCREENHEIGHT, 600);
hge->System_SetState(HGE_USESOUND, false);
if (hge->System_Initiate())
{
hge->System_Start();
}
hge->System_Shutdown();
hge->Release();
return 0;
}
That gives you a window, a cleared screen and Escape to quit. Not glamorous, but it is the right starting point.
How the flow fits together
The System_Initiate call sets up the window and rendering context. System_Start enters the main loop, which calls your FrameFunc for logic and RenderFunc for drawing on each frame. System_Shutdown tears everything down at the end.
The system state constants handle everything from window size to audio settings and logging behaviour. They are the main configuration mechanism, so they are worth learning early.
Loading and rendering sprites
Getting images on screen is the heart of most 2D work, and HGE keeps that part direct.
HTEXTURE tex;
hgeSprite *sprite;
// In your initialisation:
tex = hge->Texture_Load("player.png");
sprite = new hgeSprite(tex, 0, 0, 64, 64);
sprite->SetHotSpot(32, 32); // Center the origin
// In your render function:
sprite->Render(400, 300); // Draw at position (400, 300)
The hgeSprite class handles texture mapping, colour modulation, rotation and scaling. That makes it the basic building block for anything visual.
Sprite sheets and animation
Animated characters usually live in sprite sheets, where one texture contains multiple animation frames.
// Create sprites for each frame
hgeSprite *walkFrames[4];
for (int i = 0; i < 4; i++)
{
walkFrames[i] = new hgeSprite(tex, i * 64, 0, 64, 64);
}
// In frame function, advance animation
animTimer += hge->Timer_GetDelta();
if (animTimer > 0.1f) // 10 fps animation
{
currentFrame = (currentFrame + 1) % 4;
animTimer = 0;
}
// In render function
walkFrames[currentFrame]->Render(playerX, playerY);
The particle system
One of HGE’s strongest built-in features is its particle system. Fire, explosions, magic spells and drifting dust all add visual weight without a lot of code.
hgeParticleSystem *particles;
// Load a particle preset (created with the particle editor)
particles = new hgeParticleSystem("explosion.psi", sprite);
particles->Fire();
// In frame function
particles->Update(hge->Timer_GetDelta());
// In render function
particles->Render();
The bundled particle editor is the useful part here. You design the effect visually, export a preset, then wire it into the game code. Creative work stays in the editor. Integration stays in code. That split suits this kind of tool well.
Audio basics
HGE supports both sound effects and music.
// Enable sound in system state
hge->System_SetState(HGE_USESOUND, true);
// Load and play
HEFFECT snd = hge->Effect_Load("laser.wav");
hge->Effect_Play(snd);
// Music (streaming)
HSTREAM music = hge->Stream_Load("theme.ogg");
hge->Stream_Play(music, true); // true = loop
The music playback functions stream from disk, which matters for background music that should not sit in memory all day.
Resource management
Once a project starts growing, hand-managing textures, sounds and other assets gets messy fast. HGE’s resource management system loads resources from script files.
; resources.res
Texture player = player.png
Texture enemies = enemies_sheet.png
Sound laser = sfx/laser.wav
Music theme = music/main_theme.ogg
That keeps resource paths out of the code and makes asset swaps painless enough that you do not need a recompilation just to change a file location.
Common patterns
Delta time movement
Movement should always be multiplied by delta time if you want frame-rate-independent motion.
float dt = hge->Timer_GetDelta();
playerX += velocityX * dt;
playerY += velocityY * dt;
Blend modes
HGE’s blend mode system controls how sprites combine with the background. Additive blending suits glowing effects, alpha blending handles transparency, and multiplicative blending is the one to reach for shadows.
Render lines and primitives
For debugging, or for deliberately minimal visuals, Gfx_RenderLine draws lines directly. It is handy for collision boxes, pathfinding visualisation and HUD elements.
A sensible learning path
Start small. Get the minimal app running first - window, clear screen, quit on Escape. Then load and render a single sprite so the texture loading and coordinate system stop being abstract. After that, add movement and input, then try the particle editor and integrate one effect. Audio comes next: sound effects on actions, looping background music. Only then build a tiny game such as Pong, Breakout or a simple shooter to make the pieces work together.
The HGE overview page shows how these parts fit together, and the demo collection gives finished examples of each feature.
What HGE handles beyond the basics
Once the foundations are in place, HGE also supports more advanced work:
- Custom shaders for visual effects
- Distortion meshes for water, heat haze and warping
- Texture render targets for post-processing
- Collision detection using sprite bounding boxes and pixel-perfect methods
The engine gives you the primitives. The rest is down to what you build with them.
Visit the full HGE documentation for the complete API reference, explore the demos for ideas, or join the forum to talk to other HGE developers.