Skip to content
Rishad Rahman
All work

Graphics · 3D game, no engine

BombArena

A 3D Bomberman-style arena game in Python and PyOpenGL, built without a game engine: bombs, power-ups, enemies and a multi-phase boss.

Stack

  • Python
  • PyOpenGL
  • GLUT
  • NumPy
game engines: OpenGL and GLUT only
0
game engines: OpenGL and GLUT only
power-ups: bombs, range, speed
3
power-ups: bombs, range, speed
boss phases before victory
3
boss phases before victory
BombArena in boss mode: a wide circular arena of pale blue destructible blocks, the white player in the center and a red boss with dark eyes to the right.

What it does

You control a bomber in a circular arena. Place bombs to clear blocks, collect the power-ups they drop, and avoid both the explosions and the alien enemies that roam the arena. Survive long enough and a boss arrives. Defeat it to win.

BombArena main arena from a high camera: rows of blue blocks on a pale circular floor.
The arena
BombArena with cheat mode enabled.
Cheat mode
KeyAction
W A S DMove
SpacePlace a bomb
CToggle cheat mode (invincibility)
PRestart after game over
EscQuit

Building without an engine

With no engine, everything an engine normally provides had to be written by hand. All mutable state lives in a single GameState object, and GLUT drives the program through callbacks:

Input

keyboard / keyboard_up
Add or remove keys from keys_pressed

glutIdleFunc(update)

update()
elapsed = now − last_update → particles, explosions, fireballs → player move (can_move_to) → enemies, boss → power-ups

glutDisplayFunc(display)

display()
Arena, obstacles, player, enemies, boss, bombs, explosions, particles, HUD text
glutMainLoop() owns the loop; the game only supplies callbacks.
  • Input: keyboard and keyboard_up maintain a set of held keys, so movement stays smooth and diagonal movement works, instead of relying on key-repeat events.
  • Update: each tick computes elapsed time, so bomb fuses and movement run on real time rather than frame count.
  • Rendering: the player, enemies and boss are composed from small draw_cube, draw_sphere and draw_cylinder helpers in immediate-mode OpenGL, with lighting enabled and a particle system for the boss phase.

Arena generation and collision

The arena is a square grid clipped to a circle: a cell exists only if the whole obstacle fits inside the arena radius. Obstacles are sampled from the free cells at a fixed density, the spawn cell is always kept clear, and enemies only spawn on cells that are neither obstacles nor the spawn.

Collision is distance-based. That suits a circular arena and round characters, and is cheap enough to check against every obstacle each frame:

def can_move_to(x, z):    if math.sqrt(x*x + z*z) > ARENA_RADIUS - 0.4:        return False     # Check obstacle collisions    for obstacle in game.obstacles:        ox, _, oz = obstacle        dist = math.sqrt((x - ox)**2 + (z - oz)**2)        if dist < CELL_SIZE * 0.8:  # Collision detected            return False     return True

Bombs, explosions and scoring

The player moves freely, but bombs snap to the grid. That keeps the classic Bomberman feel and makes it simple to stop two bombs from sharing a cell:

def place_bomb():    # Check if player has bombs available    active_bomb_count = len([b for b in game.active_bombs if b[3] > 0])    if active_bomb_count >= game.player_bombs:        return     # Round to nearest grid cell    x, y, z = game.player_pos    grid_x = round(x / CELL_SIZE) * CELL_SIZE    grid_z = round(z / CELL_SIZE) * CELL_SIZE     # Check if bomb already exists at this location    for bomb in game.active_bombs:        bx, _, bz, _, _ = bomb        if abs(bx - grid_x) < 0.1 and abs(bz - grid_z) < 0.1:            return     bomb = [grid_x, y, grid_z, BOMB_TIMER, game.player_range]    game.active_bombs.append(bomb)

When a fuse runs out, the blast radius is the player's range × cell size. It destroys blocks (+50, with a chance to drop one of three power-ups), kills enemies (+200), damages the boss (+500), and ends the game if it reaches the player, unless cheat mode is on. Explosions linger for half a second after detonation so they stay visible.

The boss fight

The boss shoots fireballs, takes several bomb hits to bring down, and changes the mood of the arena with a snow particle effect. When it is defeated it comes back twice with fresh health. Each time it respawns at a random point that is inside the arena, clear of obstacles and at least five units from the player, with a fallback to the center if 100 attempts fail. Only the third defeat wins the game.

↑ ↓ to move · Enter to open