Player 1: Player 2 move / crouch / jump: W A S D arrow keys light / medium / heavy punch: F G H I O P light / medium / heavy kick: V B N K L ; block: hold away from the opponent same training overlay: T back to menu: R Menu: W/S picks a row, A/D changes it, SPACE starts. Specials (QCF = down, down-forward, forward): QCF + punch: EMBER SHOT — a fireball forward, down, down-forward + punch: SKYBREAKER — invulnerable rising uppercut QCF + kick: CYCLONE HEEL — advancing spin kick QCB + punch: your character's signature HCF + heavy punch: TEMPEST DRIVE — super, needs a full meter Crouching gives a different move on every button, so six keys are fifteen normals. Jumping attacks are overheads and must be blocked standing; lows must be blocked crouching. On hit you can chain light → medium → heavy → special → super.
A real 2D fighting game in Scratch: six buttons, hold back to block, motion inputs, frame data you can read off the screen, and footsies that reward whiff punishing. Two original fighters — KESTREL (96 HP, fast, a lunging palm) and BULWARK (118 HP, slow, a shoulder charge). Best of three rounds, 60 seconds each, versus a second player at the same keyboard or versus the AI at three difficulties. FRAME DATA Full table in FRAMEDATA.md, generated by tools/mkgame.py from the same file the game loads. The shape of it: | | startup | active | recovery | on block | |---|--:|--:|--:|--:| | JAB | 3 | 2 | 6 | ±0 | | STRAIGHT | 5 | 3 | 9 | −2 | | HOOK | 8 | 3 | 15 | −6 | | ROUNDHOUSE | 10 | 4 | 17 | −8 | | SWEEP | 7 | 3 | 17 | −10 | | SKYBREAKER | 3 | 10 | 24 | −21 | | TEMPEST DRIVE | 6 | 8 | 26 | −17 | The engine runs at Scratch's 30 fps, so one frame is 1/30 s and these numbers are about half what a 60 fps game would print for the same feel. A 3-frame jab is 100 ms. THE INTERESTING BITS Moves are data, not scripts. A move is 26 numbers in a flat list — startup, active, recovery, damage, hitstun, blockstun, a hitbox rectangle, a cancel level, a pushback, two pose ids — generated by tools/mkgame.py. The move driver is 40 lines and knows nothing about any particular move: it advances a counter, reads six numbers, schedules a pose lerp, and ends. This is the decision the whole project rests on. A fighter whose moves are ad-hoc scripts cannot be balanced, cannot be debugged, and cannot show you its own frame data. Hurtboxes are derived from the pose, every frame. The interpolated skeleton is built first and the hurtbox is a rectangle around the body line: waist centre for x, the floor for the bottom, the top of the head for the top. Nothing is a per-state constant. The measured consequence, printed by the generator: standing hurtbox top 89px, crouching 64px (28% shorter) whiffs over a crouch: ROUNDHOUSE (box starts 66px) Ducking a roundhouse works because of geometry, not because of a rule. Turn on training mode and you can watch the green box shrink as you crouch. Motion recognition is a table, not a nest of ifs. The input buffer holds 18 frames of facing-relative numpad directions. A motion is a list of steps, each step a string of the digits that satisfy it, and matching walks the buffer oldest-to-newest advancing a pointer. The middle step of a quarter-circle-forward is "236", so a clean 2-3-6 roll works and so does a sloppy 2-6, and the whole thing has to complete inside that motion's own frame window. Encoding the leniency as data is why adding half-circles and dragon punches took no changes to the matcher. The super shares a button with the fireball. Command rows are scanned in order and the first affordable legal match wins, so the super is listed above the fireball with a meter cost of 100 and the meter check is what decides between them. No modifier key, no special case. Cancels require a connect, which is what makes whiff punishing real. You may cancel into something of a strictly higher level, no earlier than the active frames, and only if the move hit or was blocked. A whiffed roundhouse is therefore 17 frames of nothing, and the training readout will tell you exactly how many. The fighters are drawn with the pen. All original - code, art and sound. See Inside is open.