After getting the two-player co-op mode up and running in Raptor: Call of the Shadows, we turned our attention to polishing the experience. Four commits later, both players can now fly side by side with distinct ship colors, comfortable controls, and fully independent shooting. Here is what changed.
Commit 1: Colorize Player Two Blue
With two identical red jets on screen, it was impossible to tell which ship belonged to which player. The solution: recolor Player 2’s ship from red to blue.
Raptor uses a VGA 256-color palette. The ship sprites use palette indices 32-44 for their red tones — a 13-color ramp from bright to dark. We mapped these 1:1 to palette indices 112-124, a steel-blue ramp with a similar brightness curve.
The implementation works by intercepting the sprite data after it is loaded from the GLB archive. A new function, RAP_RemapSprite(), walks the GFX_SPRITE segments inside the sprite blob and remaps every pixel byte that falls in the red range to its blue equivalent. These remapped copies are stored in a separate p2_ship[] array, and the rendering loop checks the player index to decide which version to draw. Player 1 keeps the original red sprites from the cache; Player 2 gets the blue copies.

Two players flying together — the foundation for the visual improvements that followed.
Commit 2: Change Keybinding for Player Two
The original two-player key layout assigned Enter, Right Shift, and Space as Player 2’s fire, special fire, and weapon-switch keys. This had two problems:
- Ergonomics: Enter is far from the WASD cluster, making it awkward to move and shoot simultaneously.
- Key conflicts: Right Shift and Space were also bound to Player 1’s Mega Fire and Change Special respectively, meaning one keypress would trigger actions for both players.
The fix was simple: reassign Player 2’s action keys to C (fire), V (special fire), and B (change weapon). These sit right below WASD, keeping everything within easy reach of the left hand, and they don’t overlap with any of Player 1’s default bindings (Ctrl, Alt, Space, Right Shift).
Commit 3: Fixed Simultaneous Shooting
Even after rebinding the keys, we noticed that Player 1 could interrupt Player 2’s shooting. When Player 1 fired, Player 2’s shots would simply not come out.
The root cause was in the fire-rate cooldown system. Each weapon type has a SHOT_LIB struct with a cur_shoot counter that enforces the minimum interval between shots. The problem: this counter was a single shared variable. When Player 1 fired the forward guns, cur_shoot was set to the cooldown value, and when Player 2 tried to fire the same weapon type a frame later, the check if (lib->cur_shoot) return FALSE would reject the shot.
The fix was to change cur_shoot from a single INT to a two-element array INT cur_shoot[2], indexed by cur_player. Now each player has an independent cooldown timer, and both can fire freely at the same time.
As an additional safeguard, we also added a direct call to IPT_GetButtons() in the main game loop. Previously, button state was only updated by a timer interrupt service, which could miss frames under DOSBox emulation. Polling buttons synchronously every frame ensures input is never dropped.
Commit 4: Fixed Shooting Animation for Player 2
The final bug: when Player 2 fired, the muzzle flash animation appeared on Player 1’s ship instead of Player 2’s.
The shooting animation (A_PLAYER_SHOOT) has a playerflag that tells the engine to position it relative to the player’s ship. The display code used the global cur_player variable to look up the ship position — but at display time, cur_player was always reset to 0 (Player 1). So every muzzle flash ended up on Player 1’s ship regardless of who actually fired.
The fix was to add a player field to the ANIMS struct. When an animation is created, it records which player spawned it (cur->player = cur_player). At display time, the code now uses cur->player instead of the global cur_player to look up the correct ship position.
Summary
These four commits transformed the two-player mode from a rough prototype into something genuinely playable:
| Commit | Problem | Fix |
|---|---|---|
| colorize player two blue | Both jets look identical | Remap red palette indices to blue for P2 sprites |
| change keybinding for player two | Awkward keys, conflicts with P1 | Reassign P2 fire keys to C/V/B |
| fixed simultaneous shooting | P1 firing blocks P2 | Per-player fire-rate cooldown array |
| fixed shooting animation | P2 muzzle flash on P1’s ship | Store owner player in animation struct |
All changes touched only 7 files with about 120 lines of new code. The game now runs with full two-player co-op under DOSBox on macOS — compiled from source using Open Watcom v2 cross-compilation on Apple Silicon.