Spaces:
Running
Running
Share the sprite-sheet slicer with auto-battler (web/sheet.js from src/render/spriteSheet.js)
Browse filestiny.js now imports the same slicer (Pixi injected) instead of reimplementing it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- web/sheet.js +20 -0
- web/tiny.js +4 -4
web/sheet.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// src/render/spriteSheet.js
|
| 2 |
+
var SHEET_ROWS = 4;
|
| 3 |
+
var cellOf = (height) => Math.round(height / SHEET_ROWS);
|
| 4 |
+
function sliceGridWith(pixi, texture, cell = cellOf(texture.source.height)) {
|
| 5 |
+
const { Texture, Rectangle } = pixi;
|
| 6 |
+
const src = texture.source;
|
| 7 |
+
const rows = Math.max(1, Math.round(src.height / cell));
|
| 8 |
+
const cols = Math.max(1, Math.round(src.width / cell));
|
| 9 |
+
return Array.from({ length: rows }, (_, r) => Array.from({ length: cols }, (_2, c) => new Texture({ source: src, frame: new Rectangle(c * cell, r * cell, cell, cell) })));
|
| 10 |
+
}
|
| 11 |
+
var rowFramesWith = (pixi, texture, row = 0) => {
|
| 12 |
+
const g = sliceGridWith(pixi, texture);
|
| 13 |
+
return g[row] ?? g[0];
|
| 14 |
+
};
|
| 15 |
+
export {
|
| 16 |
+
SHEET_ROWS,
|
| 17 |
+
cellOf,
|
| 18 |
+
rowFramesWith,
|
| 19 |
+
sliceGridWith
|
| 20 |
+
};
|
web/tiny.js
CHANGED
|
@@ -4,6 +4,9 @@
|
|
| 4 |
// exposed here — so the UI chrome is 100% Gradio, the rendering is Pixi.
|
| 5 |
import * as PIXI from 'https://cdn.jsdelivr.net/npm/pixi.js@8/dist/pixi.min.mjs'
|
| 6 |
import { makeTeamBattle, step, FIELD } from '/web/engine.js'
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
// Run cb when an element with `id` appears (Gradio renders after our head runs).
|
| 9 |
function whenEl(id, cb) {
|
|
@@ -57,10 +60,7 @@ whenEl('sprite-stage', async (el) => {
|
|
| 57 |
const c = map[slug]; if (!c) return
|
| 58 |
const url = spriteUrl(c[anim] || c.idle); if (!url) return
|
| 59 |
const tex = await PIXI.Assets.load(url); tex.source.scaleMode = 'nearest'
|
| 60 |
-
const
|
| 61 |
-
const cols = Math.max(1, Math.round(tex.source.width / cell))
|
| 62 |
-
const frames = Array.from({ length: cols }, (_, i) =>
|
| 63 |
-
new PIXI.Texture({ source: tex.source, frame: new PIXI.Rectangle(i * cell, 0, cell, cell) }))
|
| 64 |
if (sprite) { app.stage.removeChild(sprite); sprite.destroy() }
|
| 65 |
sprite = new PIXI.AnimatedSprite(frames)
|
| 66 |
sprite.anchor.set(0.5, 0.92); sprite.loop = true; sprite.animationSpeed = 0.12
|
|
|
|
| 4 |
// exposed here — so the UI chrome is 100% Gradio, the rendering is Pixi.
|
| 5 |
import * as PIXI from 'https://cdn.jsdelivr.net/npm/pixi.js@8/dist/pixi.min.mjs'
|
| 6 |
import { makeTeamBattle, step, FIELD } from '/web/engine.js'
|
| 7 |
+
// Shared sprite-sheet slicer — ONE source with the auto-battler
|
| 8 |
+
// (src/render/spriteSheet.js, esbuilt to /web/sheet.js).
|
| 9 |
+
import { sliceGridWith } from '/web/sheet.js'
|
| 10 |
|
| 11 |
// Run cb when an element with `id` appears (Gradio renders after our head runs).
|
| 12 |
function whenEl(id, cb) {
|
|
|
|
| 60 |
const c = map[slug]; if (!c) return
|
| 61 |
const url = spriteUrl(c[anim] || c.idle); if (!url) return
|
| 62 |
const tex = await PIXI.Assets.load(url); tex.source.scaleMode = 'nearest'
|
| 63 |
+
const frames = sliceGridWith(PIXI, tex)[0] // shared slicer, row 0 (front-right)
|
|
|
|
|
|
|
|
|
|
| 64 |
if (sprite) { app.stage.removeChild(sprite); sprite.destroy() }
|
| 65 |
sprite = new PIXI.AnimatedSprite(frames)
|
| 66 |
sprite.anchor.set(0.5, 0.92); sprite.loop = true; sprite.animationSpeed = 0.12
|