1

I'm trying to build a night sky with thousands of blinking stars as a background for a simple game I want to make, but I'm getting a lot of performance problems. I want to achieve it to move at a fluid 60fps but I'm very far from it.

At first I though of using an svg container. This is what I did:

<html>
    <head>
         <meta charset="utf-8"/>
         <style>
             @keyframes star_blink {
                 100% {opacity: 0;}
             }
         </style>
    </head>
    <body>
        <svg id="canvas" width="1000" height="1000" style="background:black" />
        <script>

        const svgns = "http://www.w3.org/2000/svg";

        var svg = document.getElementById("canvas");

        var create_star = () => {
            var star_element = document.createElementNS(svgns, "rect");
            star_element.setAttributeNS(null, "width", Math.random() < 0.85 ? 1 : 2);
            star_element.setAttributeNS(null, "height", Math.random() < 0.85 ? 1 : 2);
            star_element.setAttributeNS(null, "x", Math.random() * 1000);
            star_element.setAttributeNS(null, "y", Math.random() * 1000);
            var max_opacity = Math.random() * 0.8;
            var min_opacity = Math.random() * max_opacity;
            var transition_time = Math.random() * 10;
            while (transition_time < 0.5) {transition_time = Math.random() * 10;}
            star_element.setAttributeNS(null, "style", "stroke:white; fill:white; opacity: " + max_opacity + "; animation: star_blink " + transition_time + "s infinite alternate;");
            svg.appendChild(star_element)
        }

        for (var i=0; i<10000; i++) {
            create_star();
        }

        </script>

    </body>
</html>

Performance is really bad, I'm getting around 20fps, so is not acceptable is I want to add more objects moving on top of it.

Then I thought of moving to use phaserjs:

<html>
    <head>
         <meta charset="utf-8"/>
         <script src="https://cdnjs.cloudflare.com/ajax/libs/phaser-ce/2.11.1/phaser.js"></script>
         <script>
            var game = new Phaser.Game(1000, 1000, Phaser.WEBGL, 'phaser-example', { create: create, update: update });

            var stars = [];
            var planets = [];

            function random_rectangle_size() {
                var dice = Math.random();
                return dice < 0.7 ? 1 : dice < 0.9 ? 2 : dice < 0.98 ? 3 : 4;
            }

            class Star {
                constructor() {
                    this.blinking_time = Math.random() * 3000;
                    while(this.blinking_time < 500) {this.blinking_time = Math.random() * 3000}
                    this.posX = Math.random() * 1000
                    this.posY = Math.random() * 1000
                    this.graphics = game.add.graphics(this.posX, this.posY);
                    this.graphics.beginFill(0xFFFFFF, (Math.random() * 0.8 + 0.2) * 0.8);
                    this.graphics.drawRect(0, 0, random_rectangle_size(), random_rectangle_size());
                    this.graphics.endFill();

                    game.add.tween(this.graphics).to({alpha: Math.random() * 0.4}, this.blinking_time, Phaser.Easing.Linear.None, true, 0, -1, true)

                }
            }


            function create() {
                 for(var i=0; i<10000; i++) {
                     stars.push(new Star())
                 }
            }

            function update() {}

         </script>
    </head>
    <body>
    </body>
</html>

I get around 30fps there. A little better but still very far away from my objective.

Is it impossible to do what I want? How can I improve performance here? Should I abandon the idea of using javascript and the browser, and use a traditional game engine?

Enuff
  • 457
  • 5
  • 21
  • 1
    [Poor performance - SVG animations](https://stackoverflow.com/questions/32363714/poor-performance-svg-animations) – Andreas Oct 06 '18 at 09:49
  • For Phaser, you should try migrating from Graphics to Sprites. Last I checked, using Sprites results in better performance. – James Skemp Oct 06 '18 at 18:50
  • 1
    If you use phaser v3 you might get better performance? It has a custom renderer, and the pipeline got updated in 3.12 (it's v3.14 as of this comment) so it might be faster. This example might be similar to what you need: http://labs.phaser.io/edit.html?src=src\game%20objects\graphics\Many%20Line%20Stars.js – Fabadiculous Oct 08 '18 at 00:48
  • Tried to convert to sprites but the browser crash during the conversion. Guess there are too many items – Enuff Oct 09 '18 at 06:01
  • You're totally right @Fabadiculous. Switching to phaser 3 was the solution. I can now render all the stars I want without frame drop. Performance is amazing. Thanks – Enuff Oct 09 '18 at 06:05

1 Answers1

2

Posting answer mentioned in comments above, for future readers.

Phaser v3 has a custom renderer compared to v2 which is built on Pixi. As of version 3.12 the render pipeline for graphics was overhauled so that it is faster, and more efficient when rendering graphics, both individually, and when mixed with rendering sprites. Details can be found in the changelog for phaser v3.12 and also Phaser World issue 124

An example of rendering and tweening many graphics objects can be seen on the examples page here

Fabadiculous
  • 554
  • 6
  • 11