Brett Owers
← All Projects

Grid Commander

Archived

February 1, 2024

The first iteration of Tenlach — a real-time, card-based tactical combat game on a grid, inspired by Mega Man Battle Network. How the game is played, how a grid game is composed in code, and a deep dive into rollback netcode — the networking architecture that makes real-time multiplayer feel fair even with latency.

Purpose

Grid Commander was the first playable attempt at the Tenlach concept: a real-time battle game on a 3x6 grid where players select attack chips from a deck and fight in real time. This version got further than any previous attempt — characters moved, attacks fired, chips were selected. The networking was the next unsolved problem.

Stack

FlutterFlameDartGame DevelopmentMultiplayerNetworking

What I Learned

  • How Mega Man Battle Network plays: two players face off on a 3x6 grid (3 rows, 6 columns — each player controls their 3x3 half). Movement is real-time — you press a direction and your character moves one tile. Attacks are chip-based: at the start of each round, you open a chip select screen showing 5 random chips from your deck. You pick chips that share a code letter or chip type (you can select B-B-B or Cannon-Cannon-Cannon but not B-A-Cannon). Selected chips load into your active queue. During combat, you fire chips one at a time — each has a unique attack pattern (straight shot, area blast, sword slash, heal, trap). Combat continues in real time until the next chip select phase.
  • Composing a grid game in code requires three layers: (1) The Grid Model — a 2D array of cells, each with occupancy state (empty, player, obstacle, hazard), terrain type (normal, cracked, broken, ice, lava), and any active effects. (2) The Entity System — characters, projectiles, and effects that exist on the grid, each with position, hitbox, movement speed, and state (idle, moving, attacking, stunned). (3) The Timing System — a game clock that drives movement ticks, attack frames, and chip select phases. Everything snaps to the grid. No sub-tile positions.
  • Attack patterns on a grid are defined as relative coordinate sets. A straight shot: [(1,0), (2,0), (3,0)] — three tiles forward. A wide slash: [(1,-1), (1,0), (1,1)] — three tiles in a row one column ahead. An area bomb: [(1,-1), (1,0), (1,1), (2,-1), (2,0), (2,1)] — a 2x3 block. Each chip stores its pattern, damage, element, and timing (startup frames, active frames, recovery frames). The grid makes collision detection trivial: if an attack pattern tile overlaps an occupied tile, it is a hit.
  • Rollback netcode is the gold standard for real-time multiplayer fighting games and action games. The problem it solves: in an online game, player inputs travel over the network and arrive with latency (20-200ms). Without rollback, you either delay everyone's inputs (input delay netcode — responsive but makes the game feel sluggish) or you show each player a different game state (lockstep — synchronized but any packet loss freezes the game).
  • Rollback netcode works differently: each client runs the game simulation locally and immediately, using predicted inputs for the remote player (assume they continue doing what they were last doing). When the real remote input arrives — potentially several frames late — the game "rolls back" to the frame where the input should have been applied, re-simulates forward with the correct input, and snaps to the corrected state. If the prediction was right (it usually is), the player sees no correction. If the prediction was wrong, there is a brief visual snap — but the game is always responsive because your own inputs are never delayed.
  • Implementing rollback requires: deterministic simulation (same inputs must produce identical state on every client — no floating point divergence, no random without shared seeds), state snapshots (save the full game state every frame so you can roll back to any point), input serialization (compact encoding of player inputs to minimize network traffic), and a resimulation budget (rolling back 7+ frames and replaying them all in one render tick — the CPU cost of correctness).

Key Insights

  • Rollback netcode is why modern fighting games feel good online and older ones felt terrible. Street Fighter V launched with input delay netcode and the community revolted. Guilty Gear Strive launched with rollback netcode and it felt nearly identical to offline play. The technical architecture directly determined the player experience. This is true of all software: the networking model you choose dictates the user experience in ways that no amount of UI polish can override.
  • Grid-based combat is a design constraint that produces strategic depth. By limiting movement to discrete tiles, every position choice is meaningful. You cannot dodge by a pixel — you dodge by a tile, which means the attacker can predict where you will go. This creates a meta-game of reads and predictions that approaches rock-paper-scissors at the micro level while maintaining spatial strategy at the macro level. The constraint IS the game.
  • Grid Commander getting further than Go Table Talk or Tenlach's Go backend is evidence that the right tech stack matters. Flutter + Flame for the game client, with familiar Dart for game logic, produced more progress than the Go-based server-first approach. The lesson from the Go API boilerplate entry ("new language + new domain = two unknowns") was finally applied: use a familiar language for the new domain.
  • The Tenlach / Grid Commander concept now lives in the Hot Potato Games pipeline as Sod Tori — a tactical grid battle game. The core DNA is the same: grid-based, tactical, real-time. The tech stack has solidified around Flutter/Flame. The rollback netcode research from this entry will be directly applicable. Every iteration of this idea — Tenlach, Grid Commander, Sod Tori — inherits the lessons of the previous one.
#game-development#Flame#Flutter#grid-combat#Mega-Man-Battle-Network#rollback-netcode#multiplayer#Tenlach#Sod-Tori#Hot-Potato-Games#fighting-game#real-time

This post was composed through a conversation between Brett Owers and Claude Code (Anthropic). The content reflects Brett's recollection of each project and the lessons drawn from it. Some details may be approximate or omitted — the purpose is to paint an honest picture of a software engineer's development over time, not to serve as a precise historical record.