Remaking a Hit Steam Game from Scratch in 3D
I played MECCHA CHAMELEON for 6 hours straight
It was a Tuesday. I had work to do. Instead, I played this hide-and-seek game about chameleons until 2 AM. The concept is genius: you're a white lizard. Steal colors from the environment. Paint yourself. Strike a pose. Hold still. And pray the seeker walks right past you.
I woke up the next morning thinking "I could build this." Not because I thought I'd do it better — the original is fantastic — but because I wanted to understand how it worked. What does a color-sampling system actually look like in code? How do you make an AI seeker that's fun to play against? How do you sync paint state over the network?
So I did it. From scratch. In Godot 4.7. This is the story of that rebuild.
The core loop
The game has two roles: hiders and a seeker. A round goes like this:
1. Hide phase — Hiders explore the stage, steal surface colors by looking at walls/floors and pressing the sample button, paint their body parts, pick a pose, and find a hiding spot. The seeker's screen is blocked during this phase. 2. Seek phase — The seeker is released. They walk around looking for anything that doesn't blend in. Aim at a hider and tag them. Misses cost you 5 seconds off the clock. 3. Results — Points awarded. Survivors get bonus points for high camo scores. Seeker gets points per catch + a bonus for finding everyone.
Then roles rotate and you do it again. Simple to explain, deceptively deep to play.
Built entirely from primitives
Just like Oliver's Planes, I didn't touch Blender. Every chameleon is built from spheres, capsules, and prisms. The _build_body() function in lizard.gd places five paintable regions — body, head, tail, legs, and crest — plus googly eyes that never change color (they're always white, which is the tell that gives you away if you look closely enough).
The stages are built from Godot's CSG primitives and StaticBody3D nodes with color metadata. Each surface stores its color in a col meta field, so the sampling system can read it via raycast.
Two versions
I actually built two versions. The 3D version is the main event — full 3D movement, third-person camera, 5 explorable stages. But I also made a lighter 2D edition for lower-end devices. Both share the same network backend and the same room system. You can't cross-play (the game physics are too different), but the server doesn't care which version connects.
The tech stack
Here's what main.gd orchestrates:
extends Node3D
## Round orchestration: practice (vs AI) and online multiplayer.
## Online protocol is the same host-authoritative design proven by the 2D
## remake: host (= roster[0]) drives cfg/phase/clock/result over the generic
## `relay` route; the seeker is catch-authoritative for tags.
var world: Stage3D
var ui: UI
var me: Lizard = null
var lizards := {} # id -> Lizard (everyone incl. me + AI)
var roster: Array = []
var am_host := false
var pending_paints := {} # id -> colors (paint may arrive before cfg spawn)
var time_left := 0.0
var timer_running := falseOne file handles practice mode (vs AI), online multiplayer, the web test bridge, phase transitions, spawning, and results. It's 826 lines and I won't pretend that's clean architecture. It's a monolith. But it works, and for a game jam–paced project, "it works" beats "it's elegant" every time.
Practice mode vs online
Practice mode spawns 3 AI hiders (named Kero, Momo, and Pablo) at random spots around the stage. Each AI paints itself from the surfaces near its spawn point with some random jitter — the difficulty setting controls how sloppy the jitter is:
var jit: float = [0.11, 0.055, 0.02][GS.diff]On easy difficulty, the AI's paint is off by up to 11% per channel. You can spot them easily. On hard, it's just 2% — nearly perfect camouflage. Finding them becomes genuinely difficult.
Online mode uses the same phase flow but replaces AI with real players. The host (first player in the roster) drives all the timing: when to switch from hide to seek, when the round ends, how long each phase lasts. Other players just receive instructions and sync their state.
The thing that surprised me most
Building the game was straightforward. What surprised me was how much the social layer matters. In practice mode against AI, the game is a puzzle — find the hiders, tag them, done. In online mode with friends, it becomes something completely different. People scream when they get found. They brag about their camo percentage. They intentionally paint themselves bright pink as a power move. The game's soul lives in the multiplayer, not the mechanics.
Clearly a fan project
I want to be clear: this is an unofficial fan remake. It's labeled as such in the game, on the website, everywhere. The original MECCHA CHAMELEON on Steam is the real deal and you should play it. My version exists because I wanted to learn, and because the concept is so good it deserves to exist on the web where anyone can try it without installing anything.
Written by Oliver
Indie game developer building 3D web experiences in Godot and Next.js. I write about creative coding, procedural generation, and game feel.