Scene-Starlight/Star.js

115 lines
3.0 KiB
JavaScript

"use strict";
import Vector from './Vector';
import random from './Random';
class Star
{
constructor(inCanvas, inPosition, inSize)
{
this.canvas = inCanvas;
this.position = inPosition; // The position
this.rotation = 0; // The rotation
this.rotationStep = 0; // The amount (in rads / sec) the star turns by
this.scale = 1;
this.alpha = 1; // The opacity
this.pointCount = 5; // The number of points
this.startSize = inSize; // The initial radius
this.size = this.startSize; // The current radius
this.innerRingRatio = 0.5; // The radius of the inner ring (for the inner points)
this.twinkleSize = 2; // The size multiplier when twinkling
this.twinkling = false; // Whether we're twinkling
this.twinkleDuration = 1; // The duration of a twinkle (in seconds)
this.twinkleTimer = 0; // The current point along the twinkle we are at now
this.colour = "white"; // The colour of the star
}
/**
* The step around a circle (in radians) between each point (both inner and
* outer) on the star.
* Used by recalculatePoints().
* @return {number} The step around a circle between each point on the star.
*/
get pointStep()
{
return (Math.PI * 2) / (this.pointCount * 2);
}
get innerRingSize()
{
return this.innerRingRatio * this.size;
}
recalculatePoints()
{
this.points = [];
for (let n = 0, i = 0; n < Math.PI * 2; n += this.pointStep, i++)
{
let currentSize = i % 2 == 0 ? this.size : this.innerRingSize;
this.points.push(new Vector(
currentSize * Math.cos(Math.PI * 2 * (n / (Math.PI * 2)) - Math.PI / 2),
currentSize * Math.sin(Math.PI * 2 * (n / (Math.PI * 2)) - Math.PI / 2)
));
}
}
update(dt)
{
// Rotate (slowly I hope)
this.rotation += this.rotationStep * dt;
if(this.rotation > Math.PI * 2)
this.rotation -= Math.PI * 2;
if(this.rotation < 0)
this.rotation += Math.PI * 2;
// Randomly begin a twinkle
if(!this.twinkling && dt != 0 && Math.floor(random(0, 50000)*dt) == 0)
this.twinkling = true;
if(this.twinkling)
{
// Calculate the new size quadratically
let sizeMultiplier = (1 - Math.pow(2*(this.twinkleTimer / this.twinkleDuration) - 1, 2));
sizeMultiplier *= this.twinkleSize;
// Go from 0 - size to 1 - (size + 1) (because a size of 0 makes things disappear)
sizeMultiplier += 1;
this.scale = sizeMultiplier;
this.twinkleTimer += dt;
if(this.twinkleTimer >= this.twinkleDuration)
this.twinkling = false, this.twinkleTimer = 0;
}
}
render(context)
{
if(!(this.points instanceof Array))
this.recalculatePoints();
context.save();
context.translate(this.position.x, this.position.y);
context.rotate(this.rotation);
context.scale(this.scale, this.scale);
context.beginPath();
context.moveTo(this.points[0].x, this.points[0].y);
for (let point of this.points) {
context.lineTo(point.x, point.y);
}
context.closePath();
context.globalAlpha = this.alpha;
context.fillStyle = this.colour;
context.fill();
context.restore();
}
}
export default Star;