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?