diff --git a/assets/images/originals/superkart/blackwind.png b/assets/images/originals/superkart/blackwind.png new file mode 100644 index 0000000..fc96c28 Binary files /dev/null and b/assets/images/originals/superkart/blackwind.png differ diff --git a/assets/images/originals/superkart/croc.png b/assets/images/originals/superkart/croc.png new file mode 100644 index 0000000..8ef262f Binary files /dev/null and b/assets/images/originals/superkart/croc.png differ diff --git a/assets/images/originals/superkart/dv8-2-303.png b/assets/images/originals/superkart/dv8-2-303.png new file mode 100644 index 0000000..c35da4e Binary files /dev/null and b/assets/images/originals/superkart/dv8-2-303.png differ diff --git a/assets/images/originals/superkart/gerome.png b/assets/images/originals/superkart/gerome.png new file mode 100644 index 0000000..2e9a7c7 Binary files /dev/null and b/assets/images/originals/superkart/gerome.png differ diff --git a/assets/images/originals/superkart/kona.png b/assets/images/originals/superkart/kona.png new file mode 100644 index 0000000..cf13a81 Binary files /dev/null and b/assets/images/originals/superkart/kona.png differ diff --git a/assets/images/originals/superkart/mario.png b/assets/images/originals/superkart/mario.png new file mode 100644 index 0000000..1d09290 Binary files /dev/null and b/assets/images/originals/superkart/mario.png differ diff --git a/assets/images/originals/superkart/racer-dv-8-2303.psd b/assets/images/originals/superkart/racer-dv-8-2303.psd new file mode 100644 index 0000000..c4da8ca Binary files /dev/null and b/assets/images/originals/superkart/racer-dv-8-2303.psd differ diff --git a/assets/images/originals/superkart/smasher.png b/assets/images/originals/superkart/smasher.png new file mode 100644 index 0000000..ff16213 Binary files /dev/null and b/assets/images/originals/superkart/smasher.png differ diff --git a/assets/images/originals/superkart/zanthor.png b/assets/images/originals/superkart/zanthor.png new file mode 100644 index 0000000..4077f83 Binary files /dev/null and b/assets/images/originals/superkart/zanthor.png differ diff --git a/assets/images/superkart/racer-blackwind.png b/assets/images/superkart/racer-blackwind.png new file mode 100644 index 0000000..cb703b2 Binary files /dev/null and b/assets/images/superkart/racer-blackwind.png differ diff --git a/assets/images/superkart/racer-blackwind.psd b/assets/images/superkart/racer-blackwind.psd new file mode 100644 index 0000000..a83befa Binary files /dev/null and b/assets/images/superkart/racer-blackwind.psd differ diff --git a/assets/images/superkart/racer-croc.png b/assets/images/superkart/racer-croc.png new file mode 100644 index 0000000..50d4faa Binary files /dev/null and b/assets/images/superkart/racer-croc.png differ diff --git a/assets/images/superkart/racer-croc.psd b/assets/images/superkart/racer-croc.psd new file mode 100644 index 0000000..3e3a94f Binary files /dev/null and b/assets/images/superkart/racer-croc.psd differ diff --git a/assets/images/superkart/racer-dv-8-2303.png b/assets/images/superkart/racer-dv-8-2303.png new file mode 100644 index 0000000..f608c0e Binary files /dev/null and b/assets/images/superkart/racer-dv-8-2303.png differ diff --git a/assets/images/superkart/racer-dv-8-2303.psd b/assets/images/superkart/racer-dv-8-2303.psd new file mode 100644 index 0000000..803fafc Binary files /dev/null and b/assets/images/superkart/racer-dv-8-2303.psd differ diff --git a/assets/images/superkart/racer-fireball.png b/assets/images/superkart/racer-fireball.png new file mode 100644 index 0000000..d120c1e Binary files /dev/null and b/assets/images/superkart/racer-fireball.png differ diff --git a/assets/images/superkart/racer-fireball.psd b/assets/images/superkart/racer-fireball.psd new file mode 100644 index 0000000..b233475 Binary files /dev/null and b/assets/images/superkart/racer-fireball.psd differ diff --git a/assets/images/superkart/racer-gerome.png b/assets/images/superkart/racer-gerome.png new file mode 100644 index 0000000..02ddc91 Binary files /dev/null and b/assets/images/superkart/racer-gerome.png differ diff --git a/assets/images/superkart/racer-gerome.psd b/assets/images/superkart/racer-gerome.psd new file mode 100644 index 0000000..37a676b Binary files /dev/null and b/assets/images/superkart/racer-gerome.psd differ diff --git a/assets/images/superkart/racer-kona.png b/assets/images/superkart/racer-kona.png new file mode 100644 index 0000000..28d55c8 Binary files /dev/null and b/assets/images/superkart/racer-kona.png differ diff --git a/assets/images/superkart/racer-kona.psd b/assets/images/superkart/racer-kona.psd new file mode 100644 index 0000000..fa7c550 Binary files /dev/null and b/assets/images/superkart/racer-kona.psd differ diff --git a/assets/images/superkart/racer-mario.png b/assets/images/superkart/racer-mario.png new file mode 100644 index 0000000..03b9f21 Binary files /dev/null and b/assets/images/superkart/racer-mario.png differ diff --git a/assets/images/superkart/racer-mario.psd b/assets/images/superkart/racer-mario.psd new file mode 100644 index 0000000..eb64834 Binary files /dev/null and b/assets/images/superkart/racer-mario.psd differ diff --git a/assets/images/superkart/racer-smasher.png b/assets/images/superkart/racer-smasher.png new file mode 100644 index 0000000..c5e4a88 Binary files /dev/null and b/assets/images/superkart/racer-smasher.png differ diff --git a/assets/images/superkart/racer-smasher.psd b/assets/images/superkart/racer-smasher.psd new file mode 100644 index 0000000..c3c6347 Binary files /dev/null and b/assets/images/superkart/racer-smasher.psd differ diff --git a/assets/images/superkart/racer-zanthor.png b/assets/images/superkart/racer-zanthor.png new file mode 100644 index 0000000..c5e0af2 Binary files /dev/null and b/assets/images/superkart/racer-zanthor.png differ diff --git a/assets/images/superkart/racer-zanthor.psd b/assets/images/superkart/racer-zanthor.psd new file mode 100644 index 0000000..59c9629 Binary files /dev/null and b/assets/images/superkart/racer-zanthor.psd differ diff --git a/data/superkart-artwork.json b/data/superkart-artwork.json index 33dd5d8..d6cf33f 100644 --- a/data/superkart-artwork.json +++ b/data/superkart-artwork.json @@ -5,13 +5,14 @@ "supplied - set the path once the PNG exists and the game uses it with no", "code changes. Loaded lazily on game entry via src/data/assetManifest.js.", "", - "racerSheets - one spritesheet per racer, 18 frames of 64x64 in a single row", - " (1152x64 png). Frames 0..15 are the kart seen from 16 view angles:", + "racerSheets - one spritesheet per racer, 10 frames of 64x64 in a single row", + " (640x64 png). Frames 0..7 are the kart seen from 8 view angles:", " frame 0 = viewed square from BEHIND, rotating CLOCKWISE (seen from above)", - " in 22.5-degree steps - frame 4 = kart's left side, frame 8 = head-on,", - " frame 12 = right side. Frames 16/17 are optional player-view lean frames", - " (16 = leaning left, 17 = leaning right); if the sheet is only 16 frames", - " wide the game reuses frame 0 with a tilt instead.", + " in 45-degree steps - frame 2 = kart's left side, frame 4 = head-on,", + " frame 6 = right side (1/3/5/7 are the diagonal in-between views). Frames", + " 8/9 are optional player-view lean frames (8 = leaning left, 9 = leaning", + " right); if the sheet is only 8 frames wide the game reuses frame 0 with", + " a tilt instead.", " Transparent background, kart centered, wheels touching the frame bottom.", "", "themeSheets - one 8-frame sheet per location theme, 64x64 frames in a row", @@ -29,15 +30,15 @@ " overdrive, emp, coins), then frame 7 = item box, frame 8 = coin." ], "racerSheets": { - "mario": { "key": "superkart-kart-mario", "path": null, "frameWidth": 64, "frameHeight": 64, "angles": 16 }, - "kona": { "key": "superkart-kart-kona", "path": null, "frameWidth": 64, "frameHeight": 64, "angles": 16 }, - "fireball": { "key": "superkart-kart-fireball", "path": null, "frameWidth": 64, "frameHeight": 64, "angles": 16 }, - "smasher": { "key": "superkart-kart-smasher", "path": null, "frameWidth": 64, "frameHeight": 64, "angles": 16 }, - "croc": { "key": "superkart-kart-croc", "path": null, "frameWidth": 64, "frameHeight": 64, "angles": 16 }, - "gerome": { "key": "superkart-kart-gerome", "path": null, "frameWidth": 64, "frameHeight": 64, "angles": 16 }, - "blackwind": { "key": "superkart-kart-blackwind", "path": null, "frameWidth": 64, "frameHeight": 64, "angles": 16 }, - "dv-8-2303": { "key": "superkart-kart-dv-8-2303", "path": null, "frameWidth": 64, "frameHeight": 64, "angles": 16 }, - "zanthor": { "key": "superkart-kart-zanthor", "path": null, "frameWidth": 64, "frameHeight": 64, "angles": 16 } + "mario": { "key": "superkart-kart-mario", "path": "assets/images/superkart/racer-mario.png", "frameWidth": 64, "frameHeight": 64, "angles": 8 }, + "kona": { "key": "superkart-kart-kona", "path": "assets/images/superkart/racer-kona.png", "frameWidth": 64, "frameHeight": 64, "angles": 8 }, + "fireball": { "key": "superkart-kart-fireball", "path": "assets/images/superkart/racer-fireball.png", "frameWidth": 64, "frameHeight": 64, "angles": 8 }, + "smasher": { "key": "superkart-kart-smasher", "path": "assets/images/superkart/racer-smasher.png", "frameWidth": 64, "frameHeight": 64, "angles": 8 }, + "croc": { "key": "superkart-kart-croc", "path": "assets/images/superkart/racer-croc.png", "frameWidth": 64, "frameHeight": 64, "angles": 8 }, + "gerome": { "key": "superkart-kart-gerome", "path": "assets/images/superkart/racer-gerome.png", "frameWidth": 64, "frameHeight": 64, "angles": 8 }, + "blackwind": { "key": "superkart-kart-blackwind", "path": "assets/images/superkart/racer-blackwind.png", "frameWidth": 64, "frameHeight": 64, "angles": 8 }, + "dv-8-2303": { "key": "superkart-kart-dv-8-2303", "path": "assets/images/superkart/racer-dv-8-2303.png", "frameWidth": 64, "frameHeight": 64, "angles": 8 }, + "zanthor": { "key": "superkart-kart-zanthor", "path": "assets/images/superkart/racer-zanthor.png", "frameWidth": 64, "frameHeight": 64, "angles": 8 } }, "themeSheets": { "beach": { "key": "superkart-theme-beach", "path": null, "frameWidth": 64, "frameHeight": 64 }, diff --git a/src/games/superkart/SuperKartGame.js b/src/games/superkart/SuperKartGame.js index a8e84af..73a35e0 100644 --- a/src/games/superkart/SuperKartGame.js +++ b/src/games/superkart/SuperKartGame.js @@ -27,7 +27,7 @@ import { rasterizeTrack, drawMinimapCanvas, buildKartSheetCanvas, buildItemSheetCanvas, buildBackdropCanvas, buildDecorSheetCanvas, } from './SuperKartRaster.js'; -import { SuperKartMode7, Mode7Backdrop, MODE7 } from './SuperKartMode7.js'; +import { SuperKartMode7, Mode7Backdrop, MODE7, KART_ROT_FRAMES } from './SuperKartMode7.js'; const FONT = 'm6x11, "Julius Sans One"'; const TIMES_KEY = 'superkart-times'; @@ -646,7 +646,7 @@ export default class SuperKartGame extends Phaser.Scene { let frame = null; if (tag === 'kart') { wx = ref.x; wy = ref.y; - frame = this.mode7.angleFrame(ref.spinMs > 0 ? ref.heading + ref.spinSpin : ref.heading); + frame = this.mode7.angleFrame(ref.spinMs > 0 ? ref.heading + ref.spinSpin : ref.heading, KART_ROT_FRAMES); visible = ref.rescueMs <= 0; } else if (tag === 'box') { visible = ref.respawnAt <= state.timeMs; @@ -706,17 +706,17 @@ export default class SuperKartGame extends Phaser.Scene { renderPlayerKart(kart) { const s = this.playerSprite; const sheet = this.textures.get(this.kartTexKey(kart.racer.id)); - const hasLean = sheet.frameTotal > 17; + const hasLean = sheet.frameTotal > KART_ROT_FRAMES + 1; const inputs = this.readInputs(); let frame = 0; let angle = 0; if (kart.spinMs > 0) { - frame = Math.floor((this.raceState.timeMs / 60)) % 16; + frame = Math.floor((this.raceState.timeMs / 60)) % KART_ROT_FRAMES; } else if (kart.drifting) { - frame = kart.driftDir > 0 ? 1 : 15; + frame = kart.driftDir > 0 ? 1 : KART_ROT_FRAMES - 1; angle = kart.driftDir * 6; } else if (inputs.steer !== 0 && hasLean) { - frame = inputs.steer < 0 ? 16 : 17; + frame = inputs.steer < 0 ? KART_ROT_FRAMES : KART_ROT_FRAMES + 1; } else if (inputs.steer !== 0) { angle = inputs.steer * 5; } diff --git a/src/games/superkart/SuperKartMode7.js b/src/games/superkart/SuperKartMode7.js index 7b425fd..7ed5923 100644 --- a/src/games/superkart/SuperKartMode7.js +++ b/src/games/superkart/SuperKartMode7.js @@ -29,6 +29,12 @@ export const MODE7 = { spriteBase: 34, // world size (units) a 1.0-scale 64px sprite frame represents }; +// Racer spritesheet rotation-frame count — the single source of truth for +// the 8-view-angle kart art contract (data/superkart-artwork.json, the +// procedural fallback in SuperKartRaster.js, and the frame math below all +// derive from this instead of a repeated magic number). +export const KART_ROT_FRAMES = 8; + const FRAG = ` precision mediump float; @@ -153,8 +159,8 @@ export class SuperKartMode7 { }; } - // View-angle frame for a kart heading (16-frame sheets, frame 0 = rear view). - angleFrame(heading, angles = 16) { + // View-angle frame for a kart heading (8-frame sheets, frame 0 = rear view). + angleFrame(heading, angles = KART_ROT_FRAMES) { let rel = (heading - this.cam.angle) % TAU; if (rel < 0) rel += TAU; return Math.round((rel / TAU) * angles) % angles; diff --git a/src/games/superkart/SuperKartRaster.js b/src/games/superkart/SuperKartRaster.js index 1c71f91..a10d0b4 100644 --- a/src/games/superkart/SuperKartRaster.js +++ b/src/games/superkart/SuperKartRaster.js @@ -9,6 +9,7 @@ // data/superkart-artwork.json are still path:null. import { sampleAt, STRIPE_LEN, CURB_WIDTH } from './SuperKartTrack.js'; +import { KART_ROT_FRAMES } from './SuperKartMode7.js'; export const TRACK_TEXTURE_SIZE = 2048; @@ -275,18 +276,18 @@ export function drawMinimapCanvas(model, size = 220) { // ── Procedural fallback sprites ───────────────────────────────────────────── -// 18-frame kart rotation strip (16 view angles + 2 lean frames) drawn as a +// 10-frame kart rotation strip (8 view angles + 2 lean frames) drawn as a // simple tinted kart. Frame 0 = seen from behind, rotating clockwise — the // same contract as drop-in racer sheets in data/superkart-artwork.json. export function buildKartSheetCanvas(color, frame = 64) { - const angles = 16; + const angles = KART_ROT_FRAMES; const canvas = makeCanvas(frame * (angles + 2), frame); const ctx = canvas.getContext('2d'); for (let i = 0; i < angles; i += 1) { drawKart(ctx, i * frame + frame / 2, frame / 2, (i * Math.PI * 2) / angles, color, frame, 0); } - drawKart(ctx, 16 * frame + frame / 2, frame / 2, 0, color, frame, -0.35); - drawKart(ctx, 17 * frame + frame / 2, frame / 2, 0, color, frame, 0.35); + drawKart(ctx, angles * frame + frame / 2, frame / 2, 0, color, frame, -0.35); + drawKart(ctx, (angles + 1) * frame + frame / 2, frame / 2, 0, color, frame, 0.35); return canvas; } diff --git a/src/games/superkart/sprites.md b/src/games/superkart/sprites.md index fa47c9f..0de0336 100644 --- a/src/games/superkart/sprites.md +++ b/src/games/superkart/sprites.md @@ -26,17 +26,21 @@ All racer/theme/item art needs a **transparent background**. | `zanthor` | Zanthor | - **Frame size:** 64×64 -- **Layout:** 18 frames in a single row → **1152×64 px** +- **Layout:** 10 frames in a single row → **640×64 px** - **File:** set `racerSheets..path` in `data/superkart-artwork.json` -- **Frames 0–15** — the kart viewed from 16 angles, rotating **clockwise as - seen from above**, in 22.5° steps: +- **Frames 0–7** — the kart viewed from 8 angles, rotating **clockwise as + seen from above**, in 45° steps: - frame 0 = dead-on from **behind** - - frame 4 = kart's left side - - frame 8 = head-on (facing the viewer) - - frame 12 = kart's right side -- **Frames 16–17** — optional player-view lean frames (16 = leaning left, - 17 = leaning right), used only for the player's fixed on-screen kart while - steering. If the sheet is only 16 frames wide, the game reuses frame 0 with + - frame 1 = diagonal, between behind and left + - frame 2 = kart's left side + - frame 3 = diagonal, between left and head-on + - frame 4 = head-on (facing the viewer) + - frame 5 = diagonal, between head-on and right + - frame 6 = kart's right side + - frame 7 = diagonal, between right and behind +- **Frames 8–9** — optional player-view lean frames (8 = leaning left, + 9 = leaning right), used only for the player's fixed on-screen kart while + steering. If the sheet is only 8 frames wide, the game reuses frame 0 with a programmatic tilt instead — fine to skip. - Kart centered horizontally in each frame, wheels touching the bottom edge (world sprites are anchored a bit above the frame's bottom, not dead