Skip to content

Clear a sprite's image when its bitmap is cleared (runtime 20261113.1) - #83

Open
Xehanort88 wants to merge 1 commit into
Psychronic-Games:mainfrom
Xehanort88:pr/sprite-null-bitmap
Open

Xehanort88 wants to merge 1 commit into
Psychronic-Games:mainfrom
Xehanort88:pr/sprite-null-bitmap

Conversation

@Xehanort88

Copy link
Copy Markdown
Contributor

Problem

A party member who leaves the battle line mid-fight keeps standing on the battlefield in their last pose. "Leaving the battle line" means a state that hides them, a capture or banish mechanic, anything that drops them from battleMembers(). The status window, target lists and turn order all drop them correctly; only the field sprite stays.

Spriteset_Battle.updateActors rebinds actor sprites by index, so the slot that falls off the end gets setBattler(undefined). Sprite_Actor.setBattler then sets _mainSprite.bitmap = null, and Sprite.prototype._onBitmapChange blanks the sprite with this.texture.frame = new Rectangle(). Under Pixi v8, assigning texture.frame updates neither the UVs nor the source. The texture still samples the old bitmap with UV x1 = 1, so the old frame keeps rendering. The v5-v7 path relied on the frame setter refreshing the texture, which v8 no longer does.

Change

runtime/reactor_core_display.js, Sprite.prototype._onBitmapChange, v8 path only:

  • When the bitmap is cleared, the sprite returns to an empty texture of its own (PIXICreateTexture(Sprite._emptyBaseTexture, new Rectangle()), flagged __rrSpriteOwned), which is how initialize() starts. The sprite-owned texture it replaces is destroyed, as _refresh already does; the bitmap's source is not touched.
  • A texture whose frame is already 0x0 draws nothing and is kept, so initialize(), which calls this with a fresh empty texture, does not allocate twice.
  • The v5-v7 branch is unchanged.

template/Demo/js/reactor_core_display.js gets the same change. The runtime revision goes to 20261113.1 in both reactor_main.js copies, with an editor/CHANGELOG.md entry.

Verification

  • New test editor/tests/sprite-null-bitmap.test.cjs vm-loads the real Sprite (with pixi_compat.js and Rectangle) on Pixi v8. It checks that clearing leaves the sprite on its own empty texture with zero UVs and that the replaced owned texture is destroyed, and that reassigning a bitmap draws it again. It also checks that a bitmap-less sprite builds exactly one texture. The clearing test fails on main before this change and passes after.
  • npm test:
    • On a fork tree that includes this change, failing test names matched a worktree at the same HEAD without it, apart from one concurrency flake in each direction. Run alone, the flaky file failed identically in both trees.
    • On this branch, which is current upstream/main plus this commit, the 58 test files that load reactor_core_display.js or the runtime revision fail only the same 7 environment-dependent names they fail without the change.
  • Native NW.js battle (SDK build, a VisuStella-heavy project with 131 plugins enabled):
    • A captured or banished actor's sprite disappears.
    • A released actor reappears in the party row.
    • An actor KO'd while removed lies in its slot when it returns.
    • Battle-end cleanup is unchanged, with no console errors.
    • Before the change, both hidden actors stood on the field.

Limits

  • Only Sprite is changed. TilingSprite._onBitmapChange has the same texture.frame = new Rectangle() pattern for a cleared bitmap and was not touched or tested here.
  • The empty base texture shim exposes no shared source, so each blank texture gets its own empty source, exactly as initialize() already does per sprite.

🤖 Generated with Claude Code

Under Pixi v8, Sprite._onBitmapChange blanked a sprite by assigning
texture.frame, which updates neither the UVs nor the source, so the sprite
kept drawing its old bitmap. An actor sprite whose battler left
battleMembers() mid-battle (a captured or banished party member) therefore
stayed on the field in its last pose while the status window, target lists
and turn order had already dropped it.

The v8 path now returns the sprite to an empty texture of its own, as
initialize() starts with, and destroys the sprite-owned texture it replaces.
A texture whose frame is already 0x0 is kept, so construction does not
allocate twice. The v5-v7 path is unchanged.

editor/tests/sprite-null-bitmap.test.cjs vm-loads the real Sprite on Pixi v8;
its clearing test fails on the previous runtime. Verified in a native NW.js
battle: captured and banished actors vanish, a released actor reappears, a
KO'd one lies in its slot. npm test failing names match a HEAD worktree apart
from one concurrency flake in each direction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant