feat(WIP, paused): 2.5D turn-based RPG + hit VFX — PSP VFX unresolved#16
Draft
doodlewind wants to merge 3 commits into
Draft
feat(WIP, paused): 2.5D turn-based RPG + hit VFX — PSP VFX unresolved#16doodlewind wants to merge 3 commits into
doodlewind wants to merge 3 commits into
Conversation
A new game, framework/games/rpgbattle3d.js: a 2.5D JRPG duel — a real 3D arena rendered with a fixed 3/4 camera, two skinned KayKit Knight instances (hero tinted blue, enemy red), and a classic command-menu turn loop. - Asset: KayKit "Character Pack: Adventurers" Knight by Kay Lousberg — CC0 (public domain), committed under assets/vendor/kaykit-knight/ (+ LICENSE + CREDITS). ONE model is baked and instanced twice (hero + tinted enemy) to stay in the soldier-class memory budget (the baked module is 0.64 MB, Fox-class). - Bake: framework/bake/bake-gltf.ts gains a clip allow-list (asset packs ship dozens of clips) + bakeRpgHero() baking only the 5 combat clips (Idle, Walking_A, Attack, Hit, Death) at 128px / boneLimit 8 -> assets-rpg-hero.ts. - Combat (deterministic, ctx.rng + frame timers): INTRO -> PLAYER (command menu) -> WINDUP/IMPACT/RECOVER -> ENEMY (AI) -> ... -> VICTORY/DEFEAT. Stats (HP/MP/ATK/DEF/SPD), SPD turn order, Attack / Power Strike (MP) / Defend / Potion, a damage formula with seeded variance + 12.5% crit, floating damage numbers, attacker lunge + target hit flash, HP/MP bars + nameplates drawn over the 3D pass. - Golden: framework/test/golden.ts gains a deterministic rpgbattle3d SPEC; the .dc3d draw-list golden captures the skinned characters (the software oracle is vertex-colour only, so the .png shows arena + HUD; WebGL/PSP show the models). bun run test green (golden + .dc3d + cross-host button contract). Verified in WebGL: hero left / enemy right facing each other, Power Strike lands a crit, HP/MP update. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Flashy melee hit effects for rpgbattle3d, built on a new engine feature. Engine — additive blending for the 3D layer (it had only opaque rendering, so cutout sprites washed to white blobs): - g3d.ts: OP_SET_BLEND wire op (0x0008) + CommandEncoder.setBlend(); Material.blend='add'. - scene3d.ts: brackets additive nodes with OP_SET_BLEND in BOTH paths — the OP-stream emit() (web/raster) and the native walkDynamic() (PSP, routed through the post stream). - web/engine.js: gl additive (blendFunc ONE,ONE, premultiplied) + depth-write off. - runtime/src/gfx3d.rs: sceGuBlendFunc(Add, Fix, Fix) + depth mask off on the PSP host. - runtime-3ds + contract.ts: OP_SET_BLEND declared for cross-host wire parity (3 hosts, 16 wire constants, contract green). raster3d skips it (oracle ignores textures anyway). VFX: - bake-vfx.ts: bakes CC0 sprite sheets into PREMULTIPLIED RGBA frames (so additive reproduces the soft glow). assets-vfx.ts = VFX_BOOM (22f) + VFX_SPARK (9f). - Assets (CC0, committed under assets/vendor/vfx/ + CREDITS): StumpyStrust "Explosion Sheet" + kurohina "Spark effect". - rpgbattle3d.js: a camera-facing additive billboard plays the explosion at the struck fighter on IMPACT (bigger on a crit), plus hit-stop (FSM freeze), a shake bump, and a screen-edge flash. Verified gorgeous in WebGL (a crit fireball glows over the scene). bun run test green (golden + .dc3d + wire/button contract). Deterministic: VFX timing is frame-stepped, hit-stop is fixed-length. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…mic-node registration Partial fixes toward the additive hit VFX rendering on PSP (works on web; renders as a white box on PSP). NOT yet resolved — development paused here. - bake-vfx: VFX frames baked at 64x64 (power-of-two; the PSP GE requires pow2 textures — 48px rendered white). Web is unaffected (handles NPOT). - rpgbattle3d.js: the VFX billboard stays VISIBLE and is hidden via scale=0 between hits, so the PSP native buildFlat (which walks once) registers it as a dynamic root; quad gets a normal so GE lighting renders it deterministically. After these, the node DRAWS on PSP but still as an untextured/unblended white quad — the native post-stream rigid textured+ additive draw path needs deeper work. bun run test green (web golden + .dc3d + wire/button contract). See the PR description for status + the original goal. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR set out to do
framework/games/rpgbattle3d.js): a real 3D arena + a fixed ¾ camera, two skinned KayKit Knight instances (hero blue / enemy red, CC0), and a classic command-menu turn loop (HP/MP, Attack/Power Strike/Defend/Potion, crits, floating damage numbers). Works on web and PSP.OP_SET_BLENDwire op; web + PSP + 3DS const + contract) and an additive billboard that plays a CC0 explosion (StumpyStrust) on the struck fighter, with hit-stop + shake + screen-flash. Verified gorgeous in WebGL.✅ Done & verified
bun run testgreen (golden +.dc3ddraw-list + cross-host wire/button contract).⛔ Known issue (UNRESOLVED — why this is paused)
The hit VFX renders as a white box on PSP (it's perfect on web). The additive billboard goes through the PSP native render path (
renderNative→postOP stream), and that path isn't applying the texture + additive blend to a dynamic rigid quad — it draws a bare white quad.Fixes attempted (committed):
buildFlatonly registers dynamic nodes once, while the VFX node started hidden → never drawn. Fixed by keeping it registered and hiding viascale=0. Now the node draws on PSP (progress).post-stream rigid textured+additive OP_DRAW path needs deeper work (texture sampler + blend state for that specific draw path, which was built for skinned characters, not rigid sprites).postOP_DRAW for a rigid textured mesh: confirmOP_BIND_TEXTURE/apply_textureactually enablesTexture2Dfor it, and thatOP_SET_BLEND(sceGuBlendFunc Add/Fix) takes effect — likely the textured rigid path inruntime/src/gfx3d.rs(vs. the staticsceneAddpath which does texture correctly).post.🤖 Generated with Claude Code