Skip to content
Rishad Rahman
All work

Graphics · Three OpenGL programs

Graphics & Python Games

Three small PyOpenGL programs: a house in the rain, an arcade catcher drawn with a hand-written line algorithm, and a 3D survival shooter.

Stack

  • Python
  • PyOpenGL
  • GLUT
  • NumPy

RainFall

A 2D house under animated, wind-bent rain, with keyboard control over the weather.

  • Python
  • PyOpenGL
  • NumPy

A house drawn from OpenGL polygons and line loops (walls, roof, door with a knob, two windows) on wet grass with elliptical puddles. A hundred raindrops fall continuously. The arrow keys tilt the rain to simulate wind, and W / S brighten or darken the sky.

def render_bent_rain():    global drop_positions, rain_direction    glColor3f(0.0, 0.5, 1.0)    glLineWidth(2)     glBegin(GL_LINES)    for i, pos in enumerate(drop_positions):        bent_x = pos[0] + np.sin(rain_direction) * (1 - pos[1])        length = np.random.uniform(0.05, 0.08)        glVertex2f(bent_x, pos[1])        glVertex2f(bent_x + np.sin(rain_direction) * 0.02, pos[1] - length)    glEnd()     # Fall speed    drop_positions[:, 1] -= 0.025     # Reset drops when they go below the screen (vectorised with NumPy)    reset_indices = drop_positions[:, 1] < -1    drop_positions[reset_indices, 1] = 1    drop_positions[reset_indices, 0] = np.random.uniform(-1, 1, np.sum(reset_indices))
The horizontal offset grows with distance fallen, (1 − y), which is what makes the rain bend rather than slide.

DiamondCatcher

Catch falling diamonds with a paddle. Every line on screen is drawn pixel by pixel.

  • Python
  • PyOpenGL
  • GLUT

Diamonds of random colors fall from random positions. Arrow keys move the catcher, and on-screen restart, pause/play and exit buttons respond to the mouse. The fall speed increases every two catches, and a miss ends the round.

The interesting part is how it draws. It doesn't use OpenGL's line primitives: every shape (diamonds, catcher, buttons) is made of lines rasterised with a hand-written midpoint line algorithm, emitting single GL_POINTS. The midpoint algorithm only handles slopes between 0 and 1 (zone 0), so each line is first classified into one of eight zones, transformed into zone 0, drawn there, and each pixel is transformed back.

zoneinto zone 0pixel back
0(x, y)(x, y)
1(y, x)(y, x)
2(y, −x)(−y, x)
3(−x, y)(−x, y)
4(−x, −y)(−x, −y)
5(−y, −x)(−y, −x)
6(−y, x)(y, −x)
7(x, −y)(x, −y)
Zone 0 (slope 0–1, moving right) is the only case the incremental algorithm handles directly. Every other zone is mapped there and back by swapping or negating coordinates.
DiamondCatcher.pySource (opens GitHub in a new tab)
def MPLDraw(x1, y1, x2, y2, zone):    dx = x2 - x1    dy = y2 - y1    incE = 2 * dy    incNE = 2 * (dy - dx)    d = 2 * dy - dx    x = x1    y = y1    while x < x2:        drawasZero(x, y, zone)   # map the zone-0 pixel back to its real zone        if d < 0:            d += incE            x += 1        else:            d += incNE            x += 1            y += 1
Integer-only decision variable d: no floating point and no division per pixel.

Survival-Barrage

A 3D survival shooter with an animated character, switchable cameras and an auto-aim cheat mode.

  • Python
  • PyOpenGL
  • GLU
  • GLUT

Enemies continuously pursue the player inside a bounded arena. The player character has moving limbs and a rotating gun, and bullets are tested for collision against enemies. You start with five lives, and the game also ends after ten missed shots, which rewards aiming over spraying.

  • Perspective projection (gluPerspective, 60° field of view) with gluLookAt cameras.
  • Right-click switches between third-person and first-person views, and the arrow keys adjust camera height and angle.
  • Cheat mode (C) enables auto-aim and auto-fire, plus an optional auto-following first-person camera (V).
↑ ↓ to move · Enter to open