From d7e2ed8b9d24dd21f10b8b3ef20a3543d5a943c7 Mon Sep 17 00:00:00 2001 From: Dorian Date: Sat, 7 Mar 2026 11:41:02 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20super=20mode=20humans=20=E2=80=94=20shi?= =?UTF-8?q?rtless,=20ridiculous=20muscles,=20gleaming=20teeth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Win rate >0.9 triggers super mode: - Shirtless with full muscle anatomy (traps, pecs, 6-pack abs, v-lines) - Massive bulging biceps with veins and separation lines - Thick bull neck with sternocleidomastoid definition - Round deltoid shoulder caps - Quad and calf definition through pants - Big gleaming white grin with tooth sparkle in all poses - Championship belt instead of regular belt - No glasses or beard (too cool for that) Co-Authored-By: Claude Opus 4.6 --- frontend/src/game/sprites/human.ts | 316 +++++++++++++++++++++++++---- 1 file changed, 271 insertions(+), 45 deletions(-) diff --git a/frontend/src/game/sprites/human.ts b/frontend/src/game/sprites/human.ts index 67ab00e..60c16b3 100644 --- a/frontend/src/game/sprites/human.ts +++ b/frontend/src/game/sprites/human.ts @@ -183,8 +183,9 @@ export function generateHumanSpriteSheet( const isShort = wr < 0.25 const isSwole = wr > 0.75 const isSuperHero = wr > 0.85 - const hasBeard = wr < 0.35 ? true : rng() > 0.6 - const hasGlasses = wr < 0.4 ? true : rng() > 0.5 + const isSuperMode = wr > 0.9 + const hasBeard = wr < 0.35 ? true : isSuperMode ? false : rng() > 0.6 + const hasGlasses = wr < 0.4 ? true : isSuperMode ? false : rng() > 0.5 const hasStains = wr < 0.3 const hasCheetos = wr < 0.2 const hasCape = isSuperHero @@ -237,15 +238,15 @@ export function generateHumanSpriteSheet( const ground = 126 // ground line // Body dimensions (3x base, adjusted by physique) - const bodyW = isFat ? 42 : isSwole ? 36 : 27 - const bodyH = isShort ? 24 : isSwole ? 33 : 30 - const headW = isFat ? 30 : isSwole ? 28 : 27 + const bodyW = isFat ? 42 : isSuperMode ? 44 : isSwole ? 36 : 27 + const bodyH = isShort ? 24 : isSuperMode ? 36 : isSwole ? 33 : 30 + const headW = isFat ? 30 : isSuperMode ? 26 : isSwole ? 28 : 27 const headH = isFat ? 27 : 24 - const legH = isShort ? 18 : isSwole ? 30 : 27 - const legW = isFat ? 14 : isSwole ? 12 : 9 - const armW = isSwole ? 9 : 6 - const armH = isShort ? 15 : isSwole ? 24 : 21 - const neckH = 3 + const legH = isShort ? 18 : isSuperMode ? 33 : isSwole ? 30 : 27 + const legW = isFat ? 14 : isSuperMode ? 14 : isSwole ? 12 : 9 + const armW = isSuperMode ? 14 : isSwole ? 9 : 6 + const armH = isShort ? 15 : isSuperMode ? 27 : isSwole ? 24 : 21 + const neckH = isSuperMode ? 5 : 3 const feetY = ground - 4 const legsTop = feetY - legH @@ -300,6 +301,39 @@ export function generateHumanSpriteSheet( fill(rl + legW - 2, legsTop + yOff + 2, 2, legH - 4, legColorDk, ox, oy) px(rl + 2, legsTop + Math.floor(legH / 2) + yOff, lighten(legColor, 10), ox, oy) + // Super mode: quad definition lines visible through pants + if (isSuperMode) { + const quadY = legsTop + yOff + 3 + const quadH = Math.floor(legH * 0.5) + // Left quad outer sweep + for (let iy = quadY; iy < quadY + quadH; iy++) { + const bulge = Math.round(Math.sin((iy - quadY) / quadH * Math.PI) * 2) + px(ll - 1, iy, legColor, ox, oy) + if (bulge > 0) px(ll - 2, iy, legColor, ox, oy) + } + // Right quad outer sweep + for (let iy = quadY; iy < quadY + quadH; iy++) { + const bulge = Math.round(Math.sin((iy - quadY) / quadH * Math.PI) * 2) + px(rl + legW, iy, legColor, ox, oy) + if (bulge > 0) px(rl + legW + 1, iy, legColor, ox, oy) + } + // Quad separation line (vastus medialis) + for (let iy = quadY + 2; iy < quadY + quadH - 2; iy++) { + px(ll + Math.floor(legW / 2), iy, legColorDk, ox, oy) + px(rl + Math.floor(legW / 2), iy, legColorDk, ox, oy) + } + // Calf definition (lower leg) + const calfY = legsTop + yOff + Math.floor(legH * 0.6) + const calfH = Math.floor(legH * 0.3) + for (let iy = calfY; iy < calfY + calfH; iy++) { + const bulge = Math.round(Math.sin((iy - calfY) / calfH * Math.PI) * 1.5) + if (bulge > 0) { + px(ll - 1, iy, legColor, ox, oy) + px(rl + legW, iy, legColor, ox, oy) + } + } + } + // Socks visible (between pants and shoes) if (!costume.onesie) { fill(ll, feetY + yOff - 3, legW, 3, '#ffffff', ox, oy) @@ -326,43 +360,122 @@ export function generateHumanSpriteSheet( const bx = cx - Math.floor(bodyW / 2) + xOff const by = bodyTop + yOff - const torsoColor = costume.onesie ? (costume.hat || shirtColor) : shirtColor - const torsoDk = costume.onesie ? darken(costume.hat || shirtColor, 15) : shirtDark + if (isSuperMode) { + // === SHIRTLESS SUPER MODE — ridiculous muscles === + roundBox(bx, by, bodyW, bodyH, skinTone, ox, oy) - roundBox(bx, by, bodyW, bodyH, torsoColor, ox, oy) - // Body shading (right side darker) - for (let iy = by + 2; iy < by + bodyH - 2; iy++) { - px(bx + bodyW - 2, iy, torsoDk, ox, oy) - px(bx + bodyW - 3, iy, torsoDk, ox, oy) - px(bx + 1, iy, lighten(torsoColor, 8), ox, oy) // left highlight - } - - // Zipper for onesies - if (costume.onesie) { + // Body shading for (let iy = by + 2; iy < by + bodyH - 2; iy++) { - px(cx + xOff, iy, darken(torsoColor, 25), ox, oy) - px(cx + 1 + xOff, iy, darken(torsoColor, 20), ox, oy) + px(bx + bodyW - 2, iy, skinDark, ox, oy) + px(bx + bodyW - 3, iy, skinMid, ox, oy) + px(bx + 1, iy, skinLight, ox, oy) } + + // === TRAPS (massive neck-to-shoulder muscles) === + fill(bx + 4, by, bodyW - 8, 4, skinTone, ox, oy) + fill(bx + 2, by + 1, 4, 3, skinMid, ox, oy) // left trap + fill(bx + bodyW - 6, by + 1, 4, 3, skinMid, ox, oy) // right trap + // Trap definition lines + px(bx + 6, by + 2, skinDark, ox, oy) + px(bx + bodyW - 7, by + 2, skinDark, ox, oy) + + // === PECS (two big slabs) === + const pecY = by + 5 + const pecW = Math.floor(bodyW / 2) - 4 + const pecH = 7 + // Left pec + roundBox(bx + 3, pecY, pecW, pecH, skinLight, ox, oy) + fill(bx + 4, pecY + pecH - 2, pecW - 2, 2, skinMid, ox, oy) // underboob shadow + px(bx + 5, pecY + 1, lighten(skinTone, 20), ox, oy) // highlight + // Right pec + roundBox(bx + bodyW - 3 - pecW, pecY, pecW, pecH, skinLight, ox, oy) + fill(bx + bodyW - 2 - pecW, pecY + pecH - 2, pecW - 2, 2, skinMid, ox, oy) + px(bx + bodyW - 2 - pecW, pecY + 1, lighten(skinTone, 20), ox, oy) + // Pec gap (sternum line) + for (let iy = pecY; iy < pecY + pecH; iy++) px(cx + xOff, iy, skinDark, ox, oy) + + // === ABS (6-pack, 3 rows of 2) === + const absTop = pecY + pecH + 2 + const absW = 6 + const absH = 4 + for (let row = 0; row < 3; row++) { + const ay = absTop + row * (absH + 1) + // Left ab + roundBox(cx + xOff - absW - 1, ay, absW, absH, skinLight, ox, oy) + px(cx + xOff - absW, ay + 1, lighten(skinTone, 18), ox, oy) // highlight + // Right ab + roundBox(cx + xOff + 1, ay, absW, absH, skinLight, ox, oy) + px(cx + xOff + 2, ay + 1, lighten(skinTone, 18), ox, oy) + // Center line + px(cx + xOff, ay + 1, skinDark, ox, oy) + px(cx + xOff, ay + 2, skinDark, ox, oy) + } + // Linea alba (center line connecting abs) + for (let iy = absTop; iy < absTop + 3 * (absH + 1); iy++) px(cx + xOff, iy, skinDark, ox, oy) + + // === V-LINES (obliques leading into pants) === + const vStart = absTop + 3 * (absH + 1) + for (let i = 0; i < 4; i++) { + px(cx + xOff - 5 - i, vStart + i, skinDark, ox, oy) + px(cx + xOff + 5 + i, vStart + i, skinDark, ox, oy) + } + + // === VEINS (because why not) === + // Chest vein + px(bx + 6, pecY + 2, darken(skinTone, 5), ox, oy) + px(bx + 7, pecY + 3, darken(skinTone, 5), ox, oy) + px(bx + 8, pecY + 3, darken(skinTone, 5), ox, oy) + // Bicep veins drawn in arm section + + // Championship belt + fill(bx, by + bodyH - 4, bodyW, 4, '#ffd700', ox, oy) + fill(bx + 1, by + bodyH - 3, bodyW - 2, 2, '#daa520', ox, oy) + // Belt plate + fill(cx - 5 + xOff, by + bodyH - 5, 10, 5, '#ffd700', ox, oy) + fill(cx - 4 + xOff, by + bodyH - 4, 8, 3, '#ffffff', ox, oy) // plate face + fill(cx - 2 + xOff, by + bodyH - 3, 4, 1, '#ffd700', ox, oy) // star/emblem + // Side gems + px(bx + 4, by + bodyH - 3, '#ff2222', ox, oy) + px(bx + bodyW - 5, by + bodyH - 3, '#4488ff', ox, oy) } else { - // Collar - fill(bx + 3, by, bodyW - 6, 3, darken(shirtColor, 10), ox, oy) - fill(bx + Math.floor(bodyW / 2) - 2, by, 4, 4, skinTone, ox, oy) // V-neck + const torsoColor = costume.onesie ? (costume.hat || shirtColor) : shirtColor + const torsoDk = costume.onesie ? darken(costume.hat || shirtColor, 15) : shirtDark - // Shirt pattern (bigger at 3x) - const patCx = cx + xOff - const patCy = by + Math.floor(bodyH / 2) + 2 - // Draw a big emblem - fill(patCx - 4, patCy - 4, 8, 8, darken(torsoColor, 8), ox, oy) - fill(patCx - 3, patCy - 3, 6, 6, secondaryColor, ox, oy) - fill(patCx - 2, patCy - 2, 4, 4, lighten(secondaryColor, 15), ox, oy) - px(patCx, patCy, '#ffffff', ox, oy) + roundBox(bx, by, bodyW, bodyH, torsoColor, ox, oy) + // Body shading (right side darker) + for (let iy = by + 2; iy < by + bodyH - 2; iy++) { + px(bx + bodyW - 2, iy, torsoDk, ox, oy) + px(bx + bodyW - 3, iy, torsoDk, ox, oy) + px(bx + 1, iy, lighten(torsoColor, 8), ox, oy) // left highlight + } + + // Zipper for onesies + if (costume.onesie) { + for (let iy = by + 2; iy < by + bodyH - 2; iy++) { + px(cx + xOff, iy, darken(torsoColor, 25), ox, oy) + px(cx + 1 + xOff, iy, darken(torsoColor, 20), ox, oy) + } + } else { + // Collar + fill(bx + 3, by, bodyW - 6, 3, darken(shirtColor, 10), ox, oy) + fill(bx + Math.floor(bodyW / 2) - 2, by, 4, 4, skinTone, ox, oy) // V-neck + + // Shirt pattern (bigger at 3x) + const patCx = cx + xOff + const patCy = by + Math.floor(bodyH / 2) + 2 + // Draw a big emblem + fill(patCx - 4, patCy - 4, 8, 8, darken(torsoColor, 8), ox, oy) + fill(patCx - 3, patCy - 3, 6, 6, secondaryColor, ox, oy) + fill(patCx - 2, patCy - 2, 4, 4, lighten(secondaryColor, 15), ox, oy) + px(patCx, patCy, '#ffffff', ox, oy) + } + + // Belt + fill(bx, by + bodyH - 3, bodyW, 3, '#443322', ox, oy) + fill(cx - 2 + xOff, by + bodyH - 3, 5, 3, '#ffcc00', ox, oy) // buckle + px(cx + xOff, by + bodyH - 2, '#ffffff', ox, oy) // buckle highlight } - // Belt - fill(bx, by + bodyH - 3, bodyW, 3, '#443322', ox, oy) - fill(cx - 2 + xOff, by + bodyH - 3, 5, 3, '#ffcc00', ox, oy) // buckle - px(cx + xOff, by + bodyH - 2, '#ffffff', ox, oy) // buckle highlight - // Food stains (losers) if (hasStains) { fill(bx + 4, by + 6, 3, 2, '#cc8822', ox, oy) @@ -378,15 +491,47 @@ export function generateHumanSpriteSheet( } // ===== NECK ===== - fill(cx - 4 + xOff, neckTop + yOff, 8, neckH, skinTone, ox, oy) - px(cx + 3 + xOff, neckTop + yOff + 1, skinDark, ox, oy) + if (isSuperMode) { + // Thick bull neck + fill(cx - 7 + xOff, neckTop + yOff, 14, neckH, skinTone, ox, oy) + // Neck muscle lines (sternocleidomastoid) + px(cx - 4 + xOff, neckTop + yOff + 1, skinDark, ox, oy) + px(cx - 3 + xOff, neckTop + yOff + 2, skinDark, ox, oy) + px(cx + 4 + xOff, neckTop + yOff + 1, skinDark, ox, oy) + px(cx + 3 + xOff, neckTop + yOff + 2, skinDark, ox, oy) + // Neck vein + px(cx + 5 + xOff, neckTop + yOff, darken(skinTone, 8), ox, oy) + px(cx + 5 + xOff, neckTop + yOff + 1, darken(skinTone, 8), ox, oy) + } else { + fill(cx - 4 + xOff, neckTop + yOff, 8, neckH, skinTone, ox, oy) + px(cx + 3 + xOff, neckTop + yOff + 1, skinDark, ox, oy) + } // ===== ARMS ===== const armAttach = by + 3 const armLx = bx - armW - 2 const armRx = bx + bodyW + 2 - const armSkin = costume.onesie ? (costume.hat || shirtColor) : skinTone - const armSkinDk = costume.onesie ? darken(costume.hat || shirtColor, 15) : skinDark + const armSkin = isSuperMode ? skinTone : costume.onesie ? (costume.hat || shirtColor) : skinTone + const armSkinDk = isSuperMode ? skinDark : costume.onesie ? darken(costume.hat || shirtColor, 15) : skinDark + + // Shoulder caps for super mode (drawn before arms so they overlap) + if (isSuperMode) { + // Massive round deltoids + const dY = armAttach - 2 + // Left delt + for (let dy = 0; dy < 6; dy++) { + const dw = 6 - Math.abs(dy - 2) + fill(armLx - dw + armW, dY + dy, dw + 2, 1, dy < 3 ? skinLight : skinTone, ox, oy) + } + // Right delt + for (let dy = 0; dy < 6; dy++) { + const dw = 6 - Math.abs(dy - 2) + fill(armRx - 2, dY + dy, dw + 2, 1, dy < 3 ? skinLight : skinTone, ox, oy) + } + // Delt-arm separation line + px(armLx + armW - 1, armAttach + 2, skinDark, ox, oy) + px(armRx, armAttach + 2, skinDark, ox, oy) + } if (isCheer) { const armUpH = Math.round(Math.abs(Math.sin(t * Math.PI)) * 12) + 6 @@ -435,6 +580,50 @@ export function generateHumanSpriteSheet( px(armLx + armW - 1, iy, armSkinDk, ox, oy) px(armRx + armW - 1, iy, armSkinDk, ox, oy) } + + // Super mode: bulging biceps, veins, forearm definition + if (isSuperMode) { + // Bicep bulge (outer swell on both arms) + const bicepY = armAttach + 3 + const bicepH = Math.floor(armH * 0.4) + // Left arm bulge + for (let iy = bicepY; iy < bicepY + bicepH; iy++) { + const swell = Math.round(Math.sin((iy - bicepY) / bicepH * Math.PI) * 3) + for (let s = 0; s < swell; s++) { + px(armLx - 1 - s, iy, skinTone, ox, oy) + } + if (swell > 1) px(armLx - swell, iy, skinMid, ox, oy) // shadow edge + } + // Right arm bulge + for (let iy = bicepY; iy < bicepY + bicepH; iy++) { + const swell = Math.round(Math.sin((iy - bicepY) / bicepH * Math.PI) * 3) + for (let s = 0; s < swell; s++) { + px(armRx + armW + s, iy, skinTone, ox, oy) + } + if (swell > 1) px(armRx + armW + swell - 1, iy, skinMid, ox, oy) + } + // Bicep-tricep separation line + const sepX1 = armLx + Math.floor(armW / 2) + const sepX2 = armRx + Math.floor(armW / 2) + for (let iy = bicepY + 1; iy < bicepY + bicepH - 1; iy++) { + px(sepX1, iy, skinDark, ox, oy) + px(sepX2, iy, skinDark, ox, oy) + } + // Veins (wiggly lines down the arms) + for (let v = 0; v < 8; v++) { + const vy = armAttach + 4 + v * 2 + const wobble = Math.round(Math.sin(v * 1.2) * 1) + px(armLx + 2 + wobble, vy, darken(skinTone, 8), ox, oy) + px(armRx + armW - 3 + wobble, vy, darken(skinTone, 8), ox, oy) + } + // Forearm taper definition + const frmY = armAttach + Math.floor(armH * 0.6) + px(armLx + 1, frmY, skinDark, ox, oy) + px(armLx + 1, frmY + 1, skinDark, ox, oy) + px(armRx + armW - 2, frmY, skinDark, ox, oy) + px(armRx + armW - 2, frmY + 1, skinDark, ox, oy) + } + // Hands fill(armLx, armAttach + armH - 4, armW + 1, 4, skinTone, ox, oy) fill(armRx - 1, armAttach + armH - 4, armW + 1, 4, skinTone, ox, oy) @@ -639,7 +828,24 @@ export function generateHumanSpriteSheet( // Mouth const mY = hy + Math.floor(headH * 0.72) - if (isCheer) { + if (isCheer && isSuperMode) { + // SUPER MODE CHEER: massive blinding grin + fill(cx - 7 + xOff, mY - 1, 14, 6, '#000000', ox, oy) // huge mouth + fill(cx - 6 + xOff, mY - 1, 12, 3, '#ffffff', ox, oy) // top teeth + fill(cx - 5 + xOff, mY + 3, 10, 2, '#ffffff', ox, oy) // bottom teeth + fill(cx - 5 + xOff, mY + 2, 10, 1, '#cc4444', ox, oy) // tongue peeking + // Tooth lines + for (let ti = 0; ti < 6; ti++) px(cx - 6 + ti * 2 + xOff, mY, '#dddddd', ox, oy) + // Gleam sparkles on both sides + px(cx - 9 + xOff, mY - 2, '#ffffff', ox, oy) + px(cx - 8 + xOff, mY - 3, '#ffffff', ox, oy) + px(cx - 10 + xOff, mY - 3, '#ffffff', ox, oy) + px(cx - 9 + xOff, mY - 4, '#ffffff', ox, oy) + px(cx + 9 + xOff, mY - 2, '#ffffff', ox, oy) + px(cx + 8 + xOff, mY - 3, '#ffffff', ox, oy) + px(cx + 10 + xOff, mY - 3, '#ffffff', ox, oy) + px(cx + 9 + xOff, mY - 4, '#ffffff', ox, oy) + } else if (isCheer) { // Big grin with teeth fill(cx - 5 + xOff, mY, 10, 4, '#000000', ox, oy) fill(cx - 4 + xOff, mY, 8, 2, '#ffffff', ox, oy) // teeth @@ -655,6 +861,26 @@ export function generateHumanSpriteSheet( // Yelling fill(cx - 4 + xOff, mY, 8, 5, '#000000', ox, oy) fill(cx - 3 + xOff, mY, 6, 2, '#ffffff', ox, oy) + } else if (isSuperMode) { + // Super mode idle: big confident grin with gleaming teeth + fill(cx - 6 + xOff, mY, 12, 5, '#000000', ox, oy) // wide mouth + // Top teeth row — big, white, perfect + fill(cx - 5 + xOff, mY, 10, 2, '#ffffff', ox, oy) + // Individual tooth lines + for (let ti = 0; ti < 5; ti++) px(cx - 5 + ti * 2 + xOff, mY + 1, '#dddddd', ox, oy) + // Bottom teeth + fill(cx - 4 + xOff, mY + 3, 8, 1, '#ffffff', ox, oy) + // Tooth gleam / sparkle + px(cx - 4 + xOff, mY, '#ffffee', ox, oy) + px(cx + 2 + xOff, mY, '#ffffee', ox, oy) + // Sparkle star near mouth + px(cx + 7 + xOff, mY - 1, '#ffffff', ox, oy) + px(cx + 8 + xOff, mY - 2, '#ffffff', ox, oy) + px(cx + 6 + xOff, mY - 2, '#ffffff', ox, oy) + px(cx + 7 + xOff, mY - 3, '#ffffff', ox, oy) + // Dimples + px(cx - 7 + xOff, mY + 1, skinDark, ox, oy) + px(cx + 7 + xOff, mY + 1, skinDark, ox, oy) } else { // Neutral / slight smile fill(cx - 3 + xOff, mY, 6, 2, '#0a0a0a', ox, oy)