Planet Blupi — Game Overview

What Is Planet Blupi?

Planet Blupi is a real-time strategy / puzzle-adventure game developed by Swiss company Epsitec SA, originally released in 1997 for Windows. Epsitec later open-sourced the game.

The player controls one or more Blupi — small yellow creatures — on a 200×200 isometric grid. The goal is to build infrastructure, gather resources, and satisfy mission-specific win conditions while fending off enemies (spiders, viruses, robots, tanks, electro towers).


Gameplay Pillars

Pillar Description
Build Construct huts, laboratories, factories, fences, towers, boats, jeeps, armour
Gather Chop wood, mine stone / iron ore, pick flowers, cultivate crops
Defend Fight spiders, viruses, robots, tanks using dynamite, mines, armour
Complete missions Each world file embeds a Term struct with win conditions

Technical Summary

Property Value
Language C++ (ISO C++98 style, Win32 API)
Original engine Win32 / DirectDraw / DirectSound / MCI (AVI)
Compatibility layer Free Direct (DirectDraw/DirectSound → SDL3), Free API (Win32 → cross-platform)
Platforms Windows (original), Linux (ported), Web/Emscripten (ported), Android (experimental)
Resolution Fixed 640×480 pixels
Colour depth 8-bit palette (256 colours) on original hardware; 32-bit via SDL3 layer
Grid 200×200 cells (isometric projection)
Cell size 60×30 pixels in isometric projection

Main Game Loop

WinMain()
  │
  ├─ initialise (CEvent, CDecor, CSound, CPixmap, CMovie)
  │
  └─ Windows message loop
        │
        ├─ WM_TIMER → CEvent::Step()
        │     ├─ CDecor::BlupiStep()   ← character logic (1 tick = 50 ms)
        │     ├─ CDecor::MoveStep()    ← decoration animations
        │     └─ redraw scene
        │
        ├─ WM_LBUTTONDOWN / WM_MOUSEMOVE / WM_LBUTTONUP
        │     └─ CEvent::EventPos() → cell selection, action trigger
        │
        └─ WM_PHASE_* → CEvent::ChangePhase() → screen switch

The game tick is driven by a timer with an interval of 50 ms (configurable via Timer= in config.def). Each tick calls BlupiStep() and MoveStep() once.


Coordinate System

The game uses an isometric projection. Relationship between grid and screen coordinates:

Game window: 640×480 px
Drawing surface: 480×450 px, offset (144, 15) from top-left corner

Grid cell (cel.x, cel.y)  →  screen pixel (px, py):
  px = (cel.x - celCoin.x) * DIMCELX/2 - (cel.y - celCoin.y) * DIMCELX/2 + POSDRAWX + DIMDRAWX/2
  py = (cel.x - celCoin.x) * DIMCELY/2 + (cel.y - celCoin.y) * DIMCELY/2 + POSDRAWY

Functions:
  CDecor::ConvCelToPos(cel)   → pixel position
  CDecor::ConvPosToCel(pos)   → grid cell

m_celCoin holds the cell at the top-left corner of the visible viewport (scroll position).


Key Constants

LXIMAGE    = 640    // game window width
LYIMAGE    = 480    // game window height

POSDRAWX   = 144   // x-offset of game drawing area
POSDRAWY   = 15    // y-offset of game drawing area
DIMDRAWX   = 480   // width of game drawing area
DIMDRAWY   = 450   // height of game drawing area

POSMAPX    = 8     // minimap x position
POSMAPY    = 15    // minimap y position
DIMMAPX    = 128   // minimap width
DIMMAPY    = 128   // minimap height

MAXCELX    = 200   // grid width (cells)
MAXCELY    = 200   // grid height (cells)

DIMCELX    = 60    // cell width in pixels
DIMCELY    = 30    // cell height in pixels

DIMOBJX    = 120   // max object sprite width
DIMOBJY    = 120   // max object sprite height

DIMBLUPIX  = 60    // Blupi sprite width
DIMBLUPIY  = 60    // Blupi sprite height
SHIFTBLUPIY = 5    // Blupi upward shift (z-order correction)

DIMBUTTONX = 40    // toolbar button width
DIMBUTTONY = 40    // toolbar button height

POSSTATX   = 12    // statistics panel x position
POSSTATY   = 220   // statistics panel y position

MAXBLUPI   = 100   // max simultaneous characters (Blupi + all enemies)
MAXMOVE    = 100   // max simultaneous animated decorations
MAXBUTTON  = 40    // max toolbar buttons
MAXUSED    = 50    // max visited cells remembered per character
MAXLIST    = 10    // max queued commands per character

MAXENERGY  = 4000  // maximum Blupi energy
MAXFIRE    = 400   // maximum fire intensity

FOGHIDE    = 4     // fog icon threshold below which cell is hidden