finnvoor / PlaydateKit

Create games for Playdate using Swift.
https://finnvoor.github.io/PlaydateKit/documentation/playdatekit
Creative Commons Zero v1.0 Universal
195 stars 18 forks source link

Deallocating a sprite from another sprite's update loop causes a segfault #99

Open finnvoor opened 3 hours ago

finnvoor commented 3 hours ago

Swift crashes:

class SpriteA: Sprite.Sprite {
    override func update() {
        game.spriteB?.removeFromDisplayList()
        game.spriteB = nil
    }
}

class SpriteB: Sprite.Sprite {}

final class Game: PlaydateGame {
    let spriteA = SpriteA()
    var spriteB: SpriteB? = SpriteB()

    init() {
        spriteA.addToDisplayList()
        spriteB?.addToDisplayList()
    }

    func update() -> Bool {
        Sprite.updateAndDrawDisplayListSprites()
        return true
    }
}

C doesn't:

LCDSprite *spriteA = NULL;
LCDSprite *spriteB = NULL;

static void updateSpriteA(LCDSprite* s)
{
    if (spriteB) {
        pd->sprite->removeSprite(spriteB);
        spriteB = NULL;
    }
}

void setupGame(void)
{
    spriteA = pd->sprite->newSprite();
    pd->sprite->setUpdateFunction(spriteA, updateSpriteA);

    spriteB = pd->sprite->newSprite();

    pd->sprite->addSprite(spriteA);
    pd->sprite->addSprite(spriteB);
}

int update(void* ud)
{
    pd->sprite->updateAndDrawSprites();
    return 1;
}
finnvoor commented 2 hours ago

Crash caused by this unsafeBitcast: https://github.com/finnvoor/PlaydateKit/blob/b0e54b43d90e87b1ddd47170705bdafc144cdd5e/Sources/PlaydateKit/Core/Sprite.swift#L20