Jump to content

Separating Draw and Game State


cmagoun
 Share

Recommended Posts

Greetings, I am just learning pixijs and I have a question:

I am experimenting with writing a game, using pixi as the rendering engine. In my game I am trying as best as possible to have the act of drawing be a function of the game state. So, instead of issuing commands and changing the position and texture of individual sprites, I just alter the entities in my game, and the draw system knows how to draw them.

Currently, this is implemented by a system that runs in between the game state being updated, and pixi rendering the stage. Something like this:

function gameLoop() {
    requestAnimationFrame(gameLoop);
    update();
    draw();
    app.render(app.stage);
}

Where game draw essentially removes children from the stage, loops through entities that need to be drawn, creates sprites with the correct properties, and re-adds them to the stage. In practice this looks like:

draw() {
    this.container.removeChildren();

    const entities = this.game.entities();
    entities.forEach(e => {
        const sprite = this.spriteMap.getSprite(e, this.game.cm);
        this.container.addChild(sprite);
    });
}

Is there a performance hit to removing/adding sprites to the scene each frame? Is there a better way to do this, while still avoiding having the game logic directly manipulate sprite positions/textures?

Link to comment
Share on other sites

Thanks for the reply -- I appreciate any help I can get!

Following your example, I changed my scene-drawing code to look like this:


drawEntities() {
    const entities = this.game.cm.entitiesWith("sprite", DIRTY);
    entities.forEach(e => {
        const sprite = this.spriteMap.getSprite(e, this.game.cm);
            
        if(e.isToBeDestroyed())  {this.container.removeChild(sprite); return;}     
        this.container.addChild(sprite);
    });
}

spriteMap.getSprite  handles setting the sprite properties based on the entity's current state.

In addition, I added a dirty check on my entities that allows me see ONLY entities that need to be redrawn. In addition, I added isToBeDestroyed() which keeps track of who needs to be removed from the container. I do have one other question: I am using container.addChild when a sprite needs to be redrawn. It doesn't seem like there are any bad effects to adding the same sprite over and over to the container. Indeed, it seems like the length of the container's children stays constant as I redraw. Are PIXI Sprites somehow keyed so as not to be duplicated within a container? I am very pleased that this syntax works, but I am curious.

Link to comment
Share on other sites

That's completely different code. I recommend to read https://mitpress.mit.edu/books/introduction-algorithms-third-edition .

"children[j++] = children" is not addChild. Single removeChild takes O(N) time. 

Also, "game.cm.entitiesWith" - i dont know anything about it. I work with children of container.

Link to comment
Share on other sites

To answer your original question: Yes, adding/removing all your sprites every frame is expensive. Instead, track state and only change the minimum amount you have to. If a sprite exists between two frames, then it shouldn't be removed then added again.

Ivan's example was to show you he isn't changing the scene tree at all unless he needs to. When something dies, it gets removed. When it is new, it gets added. Otherwise, no change.

Link to comment
Share on other sites

Yes, I see that, and based on Ivan's example, I am no longer clearing the scene and then re-adding the sprites. 

Instead, I am checking for entities that have been changed since the last frame, refreshing their sprite's properties (that is the "getSprite" call).

I am still using add/removeChild at the moment, and the performance is fine right now because my scenes are small. I am unlikely to have 100s of moving sprites. My case is a turn-based board-gameish game, so maybe 20 things moving at the most? That means almost no entities are "dirty" in a loop, and I am thus only iterating over the 6 or so things that are moving at any given time. If my situation changes, I will roll up the children array as Ivan showed.

Thanks again for the assistance,

Chris

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...