Punch, kick, and out-think your opponent. Coding questions show up at four moments in the fight, and you answer them with your attack buttons.
On a phone? Turn it sideways. Touch buttons appear once the fight starts, and the A B C D buttons answer the questions.
Graphics
| Serpent.py | Undefined.js | Controller | |
|---|---|---|---|
| Move | A D | ← → | Stick or d-pad |
| Jump | W | ↑ | Stick or d-pad up |
| Block | S | ↓ | L2 / LT |
| Attacks | UIJK | 7845 numpad | □△✕○ |
| Throw | G | 2 numpad | L1 / LB |
| Special | H | 1 numpad | R3 / stick click |
| Amplify | O | 3 numpad | R2 / RT |
| Fatal Blow | P | 9 numpad | L3 / stick click |
| Double or nothing | L | 6 numpad | R1 / RB |
Top row of the attack grid is the light and heavy sword slash, bottom row is the light and heavy spin cut. Hold block to guard. The same four buttons answer A, B, C and D. Against the CPU you can also use the arrows and numpad. Esc pauses, M mutes.
Only up close, and a guard is no defence — a throw goes straight through a block, which is what stops blocking being a free ride. You can't throw from the air or out of hitstun. Hold back as you throw to put them down behind you instead of in front, for a bit more damage. When a throw grabs, the screen flashes white: that's a 0.35 second window for the one being held to tap Throw themselves and break out. Miss it and you go up, over, and down.
Each fighter has two, done on a motion: back, forward then the first attack button, and down, back then the second — the whole motion inside 0.4 seconds. The Special button does the same thing without the motion, and does the second move if you hold block while pressing it. Specials cost nothing, but pressing Amplify while one is still coming out spends a bar of meter to make it hit harder and land bigger. Projectiles can be blocked for chip damage, and two of them thrown at once cancel each other out.
Two hits stand the opponent up; a third one staggers them, and a third heavy one puts them on the floor. Amplify spends one bar of the meter under your health to launch them instead, and while they're up there every hit keeps them up — a little less each time, so the juggle always comes down. They bounce off the ground, lie there, and get up briefly untouchable. The meter fills whenever you land a hit or take one.
The fighters and the stage are pixel art by two artists who put their work out for everyone to use. The fight is built around it.
Both fighters are based on LuizMelo's Martial Hero sprites, modified. Serpent.py from Martial Hero, Undefined.js from Martial Hero 2. Idle, run, jump, fall, both attacks, take-hit and death are the original animations; the block, launcher, cast, grab, throw and Fatal Blow strips were built from those frames.
Released under CC0. Credit isn't required — it's here because the art deserves it.
The woods and the animated shop come from the Oak Woods environment pack. The night tint, embers and lighting are drawn on top at run time.
Free for personal and commercial use with credit; not for resale or redistribution.
This build
Canvas 2D engine, fighting system, question moments, CPU opponent, HUD and the synthesised sound effects — no sound files, no animation libraries, no network calls once the page has loaded.
Fonts: Grenze, Grenze Gotisch and JetBrains Mono, served by Google Fonts.
The 2D sprite fighter this one is modelled on is Divak-ar/mortal-kombat, which is where these two art packs were first put together. The code here was written from scratch.
This game needs a 2D canvas, which this browser has turned off or doesn't support. Open it in a recent version of Chrome, Firefox or Edge.