fighting-konoha/guide/sprite-runtime.md

5.1 KiB
Raw Permalink Blame History

Memakai Atlas di Game

Kontrak proyek terbaru: gameplay-standard.md dan character-workflow.md. Saat ini loader masih satu karakter ARCO; format baru tidak otomatis menjadi registry multi-karakter.

Atlas yang sudah lolos QA masih bisa terlihat salah kalau cara menggambarnya keliru. Aturan di sini berlaku untuk canvas 2D, Phaser, PixiJS, Godot, Unity, dll.

File yang dipakai

  • sprite-sheet-alpha.png — semua frame, latar transparan
  • manifest.json — koordinat tiap frame

Salin keduanya dari run (hasil compose-atlas), bukan dari frames/. Setiap kali atlas di-compose ulang, salin ulang keduanya bersamaan.

Bila game dibuka lewat file:// (tanpa server), fetch JSON diblok browser: bungkus manifest jadi file JS (window.SPRITE_MANIFEST = {...}) yang dibuat otomatis dari manifest.json — jangan diedit manual.

Baca koordinat dari manifest, jangan menebak grid

const r = manifest.frame_layout.rows[state][frameIndex];   // {x, y, w, h}
const fps = manifest.animation.rows[state].fps;
const loop = manifest.animation.rows[state].loop;

Jumlah frame per gerakan bisa berubah setelah curation — selalu ambil dari manifest.

Anchor di kaki

Frame sudah disejajarkan sehingga kaki berada di:

anchorX = cellWidth / 2
anchorY = cellHeight - safe_margin_y      // dari manifest.cell

Posisi karakter di dunia game = posisi kaki. Gambar frame dengan offset (-anchorX, -anchorY).

ctx.save();
ctx.translate(Math.round(x), Math.round(y));   // x,y = kaki
ctx.scale(facing, 1);                           // facing: 1 kanan, -1 kiri
ctx.drawImage(sheet, r.x, r.y, r.w, r.h, -anchorX, -anchorY, r.w, r.h);
ctx.restore();
  • Flip kiri/kanan di sekitar anchor (bukan di sekitar pojok sel) → karakter tidak "teleport" saat berbalik.
  • Semua sprite digambar menghadap kanan; arah kiri selalu hasil flip.

Jangan menambah blur di runtime

Aturan Canvas 2D Lainnya
Matikan smoothing ctx.imageSmoothingEnabled = false + CSS image-rendering: pixelated Phaser pixelArt: true; Pixi SCALE_MODES.NEAREST; Godot filter Nearest; Unity Filter Mode Point, Compression None
Posisi dibulatkan Math.round(x) saat menggambar (simulasi boleh float) "pixel snap" / round di shader
Skala sprite lokal konstan 1× pada ARCO; jangan mengubah skala per pose sama
Proyeksi viewport seragam Dunia dapat diproyeksikan fractional untuk responsif, tetapi x/y memakai rasio yang sama jangan meregangkan badan
Efek tidak mengubah ukuran tubuh Tanpa squash/stretch per state; VFX terpisah sama

Kalau salah satu dilanggar, frame yang sudah rapi di atlas bisa terlihat berbeda ketajamannya di layar — gejalanya persis seperti masalah ukuran frame.

Kecepatan animasi

  • Pakai fps dari manifest sebagai default untuk gerakan di tempat (idle, serang, hurt).

  • Jalan/lari: frame maju berdasarkan jarak yang ditempuh, supaya kaki yang menapak tidak meluncur:

    // stride = jarak satu siklus penuh (2 langkah) ≈ 2 × jarak kaki saat menapak (lihat measure_atlas.py)
    walkPhase += dt * (Math.abs(vx) / stride) * frameCount;
    frame = Math.floor(walkPhase) % frameCount;
    

    Ukur stride dari atlas (jarak kaki terbesar × 2), jangan ditebak. Kalau hasil fps terlalu lambat/cepat, ubah kecepatan gerak karakter, bukan fps-nya. Contoh: orc stride 208 px, jalan 170 px/s → ±4.9 fps.

    Nilai dari lebar siluet kaki adalah estimate, bukan pengukuran stride same-foot contact yang terverifikasi. Runtime ARCO memakai estimate tersebut; jangan menyebutnya gait yang sudah tersertifikasi mulus. Periksa pose contact/passing dan pergantian kaki secara visual.

  • Gerakan non-loop (loop: false) berhenti di frame terakhir, lalu kembali ke idle.

Hitbox dari data, bukan tebakan

Ukur jangkauan senjata dari atlas (bounding box alpha tiap frame relatif anchor) dan simpan sebagai angka di kode. Setelah atlas di-compose ulang dengan skala berbeda, ukur ulang hitbox.

Checklist integrasi

  • Atlas dan manifest disalin bersamaan dari run terbaru
  • Anchor = (cellWidth/2, cellHeight − safe_margin_y)
  • Flip dengan scale(-1, 1) di anchor
  • Smoothing mati, posisi sprite dibulatkan, skala tubuh konstan dan proyeksi viewport seragam
  • Kecepatan walk ikut kecepatan gerak

Playback khusus ARCO yang menjadi baseline

  • Jump menahan satu pose atletis pada rise/apex/fall; tidak replay crouch di udara.
  • Doublejump memutar satu tuck pose360° dalam 0,28 s. Baca pivot lokal dan world-pivot dari metrics, lalu ukur ulang untuk karakter baru.
  • Skill I menampilkan pose persiapan/tembak sebelum projectile release, lalu melepas input saat peluru keluar; tidak menunggu frame recovery nominal habis.
  • Ultimate menggunakan pose cast 0,50 s, sementara drone/cut-in memakai timeline terpisah2,85 s. Jangan mengunci owner sepanjang durasi efek.
  • MECHA_METRICS.playback, states, dan emitters melengkapi manifest. Koordinat emitter relatif anchor, bukan koordinat layar.
  • Salto, facing flip, dan transform viewport tidak boleh menyebabkan per-state scale yang berbeda.