5.1 KiB
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 transparanmanifest.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
fpsdari 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
stridedari 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, danemittersmelengkapi manifest. Koordinat emitter relatif anchor, bukan koordinat layar.- Salto, facing flip, dan transform viewport tidak boleh menyebabkan per-state scale yang berbeda.