Every frame—
- If enough time has elapsed since the last star, create a star at a slight random offset from the middle of the screen. You can get the x and y components of a random point on a circle by (as @Philipp mentions), using
sin
and cos
on a random angle between 0 and 2π radians (= 360°).
- Multiply the x and y value of each star by 1+ε to taste of ε. I used 1.005. This makes stars move away from the middle, faster the further they are from the middle.
- Clear the screen, to prepare for rendering.
- Draw a circle for each star at its position, with a radius scaled to its distance from the middle of the screen.
- Remove stars that have moved outside the window.
Here's a demo in a runnable JavaScript snippet, using HTML Canvas to render:
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let middle = { x: canvas.width / 2, y: canvas.height / 2 }
// Each star is stored as an { x, y } object representing
// its offset from the middle of the screen
function canvasStarPosition(star) {
return { x: middle.x + star.x,
y: middle.y + star.y }
}
function starSize(star) {
// Size is proportional to distance from the middle
return Math.max(Math.abs(star.x), Math.abs(star.y)) / 100
}
function drawStar(ctx, star) {
let { x, y } = canvasStarPosition(star)
let r = starSize(star)
ctx.fillStyle = 'white'
ctx.beginPath()
ctx.arc(x, y, r, 0, 2*Math.PI)
ctx.fill()
}
let start = 0
let stars = []
let timeSinceLastStar = Infinity
let starInterval = 10000 // milliseconds
function makeStar() {
let angle = Math.random() * 2*Math.PI
stars.push({
x : Math.cos(angle),
y : Math.sin(angle)
})
}
function step(timestamp) {
if (!start) start = timestamp
var progress = timestamp - start
// Create a new star if it's been long enough since
// the previous one
timeSinceLastStar += progress
if (timeSinceLastStar > starInterval) {
timeSinceLastStar = 0
makeStar()
}
ctx.clearRect(0,0,canvas.width, canvas.height)
stars.forEach((s) => {
// Increase the star's distance from the middle
// proportionally to its current distance
s.x *= 1.05
s.y *= 1.05
drawStar(ctx, s)
})
// Remove stars outside the view boundary
let i = stars.length;
while (--i) {
let {x, y} = canvasStarPosition(stars[i])
if (x < 0 || x > canvas.width || y < 0 || y > canvas.height) {
stars.splice(i, 1)
}
}
window.requestAnimationFrame(step)
}
window.requestAnimationFrame(step)
<body style="background:black">
<canvas id="canvas" width="600" height="150"></canvas>
</body>