Skip to content

Repository files navigation

FACE BRAWL

Upload a face. AI turns it into pixel art. Smash it. · Léelo en español

Made by Marabunta Labs · play it at https://face-brawl.vercel.app

A browser fighting game where you are the fighter: you give it a photo (or take one with your webcam or phone) and your face is detected, cut out, turned into pixel art and glued on a boxer's body. Every hit you take then damages the real photo: bruises, swollen eyes, cuts with blood. 1P vs CPU, 2 players, and an Arcade ladder. Everything runs in the browser: no server, no build step, your photos never leave your device.

Run it

npm start        # or: python3 -m http.server 8080
# open http://localhost:8080

Any static file server works (the game is plain ES modules). The first time you need an internet connection (MediaPipe model and runtime are loaded from a CDN); without it the face editor opens with default features.

Features

  • Face pipeline – MediaPipe Face Landmarker (468 points) finds the face, you can fine-tune it in an editor; the background is cut out along the outline (plus the hair, segmented by MediaPipe hair_segmenter); the result is painted with 5 realistic damage stages (bruises that multiply the skin colour, swollen eyelids, bleeding cuts) and pixelated to 40×40 (48×48 with hair) with one shared palette. A "no pixelation (HD)" mode renders at 3×.
  • Two sprite bodies – Boxer PRO and Female boxer, headless pixel-art frames (idle, jab, cross, uppercut, kick, walk, jump, block, hit, KO, win) with your face attached at the neck. The body skin tone follows your face and can be changed by hand (6 tones).
  • Moves – punch chain jab → cross → uppercut (press punch again; the uppercut needs the cross to land), forward + punch = cross, kick, sweep (block + kick), grab (block + punch), dash (double tap), parry, air attacks, and the SUPER rush: with a full bar the fighter charges, dashes at the rival and traps them in a flurry of punches ending in an uppercut.
  • Modes – 1 player vs CPU (easy / normal / hard), 2 players (in both, each fighter can be a photo, a saved/sample character picked from the face chips, or a 🎲 random one), Arcade ladder (your saved faces and coloured clones; until you save some, it uses the sample rivals in assets/demo-rivals/). Saved characters, rankings and stats are kept in the browser (localStorage).
  • Stages – 6 built-in stages (4 procedural, 2 AI-made pixel-art backdrops) or your own photo turned into a stage (fixed floor, adjustable zoom and framing).
  • Phone as controller or camera – scan a QR code and the phone becomes a gamepad (pad.html) or sends photos of faces / places (photo.html). Direct WebRTC connection (PeerJS); internet is only needed to pair.
  • Languages – English and Spanish, picked from the browser language and changeable in ⚙ Settings. Adding a language takes one file (see below).
  • Replay recording (share or save the last fight as video), remappable keys, music (WebAudio, no files).

Controls

P1 P2
Move A / D ← / →
Jump / Block W / S ↑ / ↓
Punch / Kick / Super F / G / H K / L / J

Against the CPU both key sets work. Pause: Esc or P. Keys can be remapped in ⚙ Settings.

Phone controller and photos

"📱 Phone as controller" shows a QR (one per player in 2P mode); the 📱 PHONE buttons next to each face slot and the stage card show a QR that opens photo.html.

  • Deployed online (HTTPS): the phone does not need to be on the same Wi-Fi. The two devices find each other through the free public PeerJS broker and then talk directly (WebRTC), so it works from mobile data too. HTTPS also gives the phone a live camera preview with a face guide. In rare cases (strict mobile carriers / corporate networks) a direct connection cannot be opened; PeerJS's public service also offers relay (TURN) servers as a fallback, and if it still fails try the same Wi-Fi or run your own PeerJS server (the new Peer() calls in js/remote.js, js/pad.js, js/photo.js).
  • Running on localhost: the phone cannot reach "localhost", so type your computer's LAN IP (e.g. 192.168.1.20:8080) in the dialog; both devices must be on the same Wi-Fi and the phone opens its camera app (live preview needs HTTPS).

Deploying

The game is a static site (no build step). Publish the repository root anywhere that serves static files over HTTPS.

Vercel (what this repo is set up for): import the GitHub repository, Framework Preset: Other, leave the build command empty and the output directory as the root. vercel.json adds clean URLs, cache and security headers (camera allowed for the page itself). Other hosts work too: GitHub Pages (Settings → Pages → deploy from main / root, .nojekyll included), Netlify, Cloudflare Pages.

Search engines (SEO): index.html ships the title, description, canonical URL, Open Graph / Twitter cards, JSON-LD (VideoGame) and a crawlable description; sitemap.xml, robots.txt, a web manifest and the icons / social image (assets/social/) are included. The files contain the placeholder address https://face-brawl.vercel.app: once you know the real URL run

node scripts/set-site-url.mjs https://your-real-domain.com

and commit. Then add the site in Google Search Console and submit sitemap.xml. HTTPS is needed for the phone camera preview and the webcam.

The repository includes a few sample photos of public figures (test-faces/, and their pixel-art versions in assets/menu-faces/ and assets/demo-rivals/) for demonstration. Delete those folders if you prefer: the title screen then falls back to built-in cartoon faces.

Privacy and license

Photos are processed in the browser and never uploaded (details in legal.html). Code and artwork are MIT licensed (LICENSE); third-party components are listed in THIRD_PARTY_NOTICES.md.

Project structure

index.html, style.css      game shell and styles
pad.html, photo.html       phone pages (gamepad / photo sender)
anim-editor.html           developer lab (see below)
legal.html                 privacy and terms
js/
  main.js                  UI glue: slots, menus, dialogs, arcade flow
  menu.js, menufx.js       screen navigation and animated synthwave background
  game.js                  fight engine: attacks, AI, HUD, effects, replay
  sprite_bodies.js         loads the sprite bodies, finds the neck, tints skin
  face.js, landmarks.js    face detection → cutout → pixel art
  framer.js, cutout.js     feature editor and background cutout
  damage.js, expr.js       damage stages and facial expressions
  stage.js, stages.js      photo → stage, built-in stages and floors
  roster.js, rosterui.js   saved characters and stats
  remote.js, pad.js, photo.js   phone connection (PeerJS)
  i18n.js, locales/        translations (en.js is the reference)
  rig.js, body.js, outfits.js, pixelbody.js, characters.js
                           procedural (non-sprite) bodies, kept for future use
assets/
  sprites/boxer, sprites/female   PNG frames of each body (transparent, headless)
  stages/                  AI-generated backdrops

Adding a language

  1. Copy js/locales/en.js to js/locales/xx.js and translate the values (keep the keys and {placeholders}).
  2. Add one line to LANGS in js/i18n.js: xx: { name: 'Native name', load: async () => (await import('./locales/xx.js')).default }.

Missing keys fall back to English. The picker in ⚙ Settings lists every language in LANGS.

Developer lab

anim-editor.html runs the real engine on a page: live fights with pause / slow motion, expressions × damage stages, wounds, clones, stages, the face pipeline and the body animation sheet. Add your own sample photos in test-faces/ and list their file names in test-faces/faces.json, or upload one in the page. ?body=female opens it with the female body. ?classic on the game URL shows every menu screen stacked and without animations (used by automated tests).

Credits and notes

  • Sprites and stage backdrops were generated with AI image models and cleaned up with scripts (transparent background, slicing, neck detection); the face and damage code is original.
  • Face models: MediaPipe (Face Landmarker and Hair Segmenter), loaded from a CDN.
  • Phone pairing: PeerJS, QR codes: qrcode, both from a CDN.
  • Font: Press Start 2P (Google Fonts).
  • The sample faces are photos of public figures used for demonstration only; no endorsement or affiliation is implied. If you are pictured and want your photo removed, open an issue and it will be taken down.

Releases

Packages

Contributors

Languages