10

I call a "primitive" an object rendered with drawCircle(), drawRect(), …

Considering that:

  1. The positions of the primitives change (with constraint (1))
  2. The objects represented by the primitives* are frequently created/destroyed

What is the fastest way to draw multiple instances of the same primitives at different locations:

  • Creating a graphics object, adding it to the container once for all, clearing it each frame, and calling multiples drawSomething() on it with different positions each frame ?
  • Creating a graphics object for each primitive each frame, calling a single drawSomething() into it, and adding it to the container at a specified position ?
  • Another solution ?

For the sake of clarity, if I have bullets simply rendered with drawCircle(), and knowing that I receive the complete state of the game each frame (that is the constraint (1)), what is the fastest way to render them all ?

(1): I do not know that at instant t bullet 1 is at position p1 and at instant t+1 bullet 1 is at position p2. But I do know that at instant t there is a bullet at position p1 and at instant t+1 there is a bullet at position p2.

Jim
  • 416
  • 2
  • 4
  • 16

1 Answers1

12

I would go with option 3: Another Solution.

It is generally better to use Bitmap Sprites when possible, since they are more optimized for the GPU. (More info here https://github.com/pixijs/pixi.js/issues/1390)

You can easily render your primitive graphics into a reusable texture.

// Render a circle to a texture
var texture = new PIXI.RenderTexture(renderer, 16, 16);
var graphics = new PIXI.Graphics();
graphics.beginFill(0x44FFFF);
graphics.drawCircle(8, 8, 8);
graphics.endFill();
texture.render(graphics);

Then create a sprite from the texture

var s = new PIXI.Sprite(texture);

Here's an example that creates multiple sprites from a single texture.

http://jsfiddle.net/gzh14bcn/

Notice how this code doesn't even require an update function to redraw each frame. You just render the stage once at the end.

So if you have multiple bullets, you can just create a Sprite for each bullet and update it's position as it moves. Once it's off screen, remove reference to it and the GC will clean it up.

If you want to optimize even further, you should consider using an Object Pool for your bullets. https://en.wikipedia.org/wiki/Object_pool_pattern

Karmacon
  • 3,128
  • 1
  • 18
  • 20
  • It seems to be a better approach, indeed. Thank you for the suggestion. – Jim Aug 18 '15 at 19:55
  • @Karmacon you say : Once it's off screen, remove reference to it and the GC will clean it up. By remove reference, is it sufficient to set renderable property to false (`s.renderable = false`) or is it another thing? I would like to reduce memory footprint when bullets goes off screen, but must be ready to be redrawn as soon as object is inside screen. – user305883 Sep 14 '17 at 21:34
  • 1
    @user305883 renderable prevents an object from being drawn, which is good, but there may still be reference to it so it won't be marked for garbage collection. If you want to completely remove reference to an object, you need to remove it from its parent, remove event listeners, and nullify any variable referencing it `stage.removeChild(s); s=null;` If you're reusing the same bullet object, like in an object pool, you do not need to do this. Just set `s.renderable = false;` – Karmacon Sep 14 '17 at 22:57
  • @Karmacon thank you for explanation - a last thing about possibility to improve drawing same instances from object pool: reading here https://github.com/pixijs/pixi.js/wiki/v4-Tips,-Tricks,-and-Pitfalls , suppose need to render a bullet texture only when it is visible on viewport: a type of bullet is a container with its own texture. If bullet's off the viewport, does it make sense to set it bullet.renderable = false and destroy its texture, not destroy the baseTexture; then reload bullet's texture from baseTexture when bullet is on viewport? Would it be a legit use of destroy() ? – user305883 Sep 15 '17 at 06:53