swirlinggalaxy-rianto112
Version:
This project generates a swirling galaxy effect using JavaScript.
303 lines (251 loc) • 7.76 kB
JavaScript
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);
const ctx = canvas.getContext('2d');
const { width, height } = canvas;
const stars = [];
const numStars = 1000;
for (let i = 0; i < numStars; i++) {
stars.push({
x: Math.random() * width,
y: Math.random() * height,
radius: Math.random() * 1.5,
color: `rgba(255, 255, 255, ${Math.random()})`
});
}
function drawStars() {
ctx.clearRect(0, 0, width, height);
stars.forEach(star => {
ctx.beginPath();
ctx.arc(star.x, star.y, star.radius, 0, Math.PI * 2);
ctx.fillStyle = star.color;
ctx.fill();
});
}
function updateStars() {
stars.forEach(star => {
star.x += Math.random() * 0.25 - 0.125;
star.y += Math.random() * 0.25 - 0.125;
if (star.x < 0 || star.x > width) {
star.x = Math.random() * width;
}
if (star.y < 0 || star.y > height) {
star.y = Math.random() * height;
}
});
}
function animate() {
updateStars();
drawStars();
requestAnimationFrame(animate);
}
animate();
var tools={
captureMouse:function(canvas){
var mouse = {x:0,y:0};
this.on(canvas,"mousemove",function(evt){
var rect = canvas.getBoundingClientRect();
mouse.x = evt.clientX - rect.left * (canvas.width / rect.width);
mouse.y = evt.clientY - rect.top * (canvas.height / rect.height);
});
return mouse;
},
on:function(ele,evt,call){
ele.addEventListener(evt,call);
}
};
function extendObj(child){
for(var i in Obj){
child.prototype[i] = Obj[i];
}
}
function Pool(createFun,iniFun){
this.create = createFun;
this.ini = iniFun;
this.pool = [];
}
Pool.prototype.take=function(){
if(this.pool.length == 0){
this.pool.push(this.create());
}
return this.pool.pop();
}
Pool.prototype.to=function(one){
this.ini(one);
this.pool.push(one);
}
String.prototype.format = function(){
var args = arguments;
return this.replace(/\{(\d+)\}/g,function(m,i){
return args[i];
});
}
function include(){
for(var i=0;i<arguments.length;i++){
var path = arguments[i];
document.write("<script src='{0}.js'></script>".format(path));
}
}
function Point(x, y) {
this.x = x;
this.y = y;
}
function Rect(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
Point.V0 = new Point(0, 0);
var Scale = Point;
function Vector(angle, size) {
this.angle = angle;
this.size = size;
this.x = Math.cos(angle) * size;
this.y = Math.sin(angle) * size;
}
Vector.V0 = new Vector(0, 0);
function Obj(position, speed) {
this.position = position;
this.speed = speed;
this.powers = [];
this.power = new Vector(0, 0);
}
Obj.prototype.mass = 1;
Obj.prototype.showPosition = function () {
log("x:" + this.position.x + ",y:" + this.position.y);
}
Obj.prototype.draw = function (context) {
};
Obj.prototype.reComputer = function () {
this.speed.x += this.power.x;
this.speed.y += this.power.y;
this.position.x += this.speed.x;
this.position.y += this.speed.y;
}
/**
* 向物体增加一个力
* @param power
*/
Obj.prototype.addPower = function (power) {
this.power.x += power.x / this.mass;
this.power.y += power.y / this.mass;
this.powers.push(power);
}
function Game(rect, canvas) {
this.objs = [];
this.rect = rect;
this.context = canvas.getContext('2d');
this.canvas = canvas;
}
Game.prototype.getMouse = function () {
return tools.captureMouse(this.canvas);
};
Game.prototype.on = function (evt, callback) {
tools.on(this.canvas, evt, callback);
}
Game.prototype.addObj = function (obj) {
this.objs.push(obj);
}
Game.prototype.reFrame = function () {
var i, len;
for (var i = 0, len = this.objs.length; i < len; i++) {
this.objs[i].draw(this.context);
}
}
Game.prototype.start = function () {
var rect = this.rect;
this.context.clearRect(rect.x, rect.y, rect.width, rect.height);
this.CheckBorder();
this.CheckCollision();
this.reFrame();
}
Game.prototype.CheckBorder = function () {
var i, len, obj, pos, rect = this.rect;
for (i = 0, len = this.objs.length; i < len; i++) {
obj = this.objs[i];
pos = obj.position;
if (pos.x - obj.radius <= rect.x) {
obj.speed.x *= -0.7;
pos.x = obj.radius;
}
else if (pos.x + obj.radius >= rect.width) {
obj.speed.x *= -0.7;
pos.x = rect.width - obj.radius;
}
else if (pos.y - obj.radius <= rect.y) {
obj.speed.y *= -0.7;
pos.y =obj.radius;
}
else if (pos.y + obj.radius >= rect.height) {
obj.speed.y *= -0.7;
pos.y = rect.height - obj.radius;
}
}
}
function checkCollision (ball0, ball1) {
var dx = ball1.position.x - ball0.position.x,
dy = ball1.position.y - ball0.position.y,
dist = Math.sqrt(dx * dx + dy * dy);
//collision handling code here
if (dist < ball0.radius + ball1.radius) {
//calculate angle, sine, and cosine
var angle = Math.atan2(dy, dx),
sin = Math.sin(angle),
cos = Math.cos(angle),
//rotate ball0's position
x0 = 0,
y0 = 0,
//rotate ball1's position
x1 = dx * cos + dy * sin,
y1 = dy * cos - dx * sin,
//rotate ball0's velocity
vx0 = ball0.speed.x * cos + ball0.speed.y * sin,
vy0 = ball0.speed.y * cos - ball0.speed.x * sin,
//rotate ball1's velocity
vx1 = ball1.speed.x * cos + ball1.speed.y * sin,
vy1 = ball1.speed.y * cos - ball1.speed.x * sin,
//collision reaction
vxTotal = vx0 - vx1;
x1 = ball0.radius + ball1.radius;
vx0 = ((ball0.mass - ball1.mass) * vx0 + 2 * ball1.mass * vx1) /
(ball0.mass + ball1.mass);
vx1 = vxTotal + vx0;
x0 += vx0;
x1 += vx1;
//rotate positions back
var x0Final = x0 * cos - y0 * sin,
y0Final = y0 * cos + x0 * sin,
x1Final = x1 * cos - y1 * sin,
y1Final = y1 * cos + x1 * sin;
//adjust positions to actual screen positions
ball1.position.x = ball0.position.x + x1Final;
ball1.position.y = ball0.position.y + y1Final;
ball0.position.x = ball0.position.x + x0Final;
ball0.position.y = ball0.position.y + y0Final;
//rotate velocities back
ball0.speed.x = vx0 * cos - vy0 * sin;
ball0.speed.y = vy0 * cos + vx0 * sin;
ball1.speed.x = vx1 * cos - vy1 * sin;
ball1.speed.y = vy1 * cos + vx1 * sin;
}
}
Game.prototype.CheckCollision = function () {
var a, b, i, len, j;
for (i = 0, len = this.objs.length; i < len ; i++) {
a = this.objs[i];
for (j = i + 1; j < len; j++) {
b = this.objs[j];
var dx = b.position.x - a.position.x;
var dy = b.position.y - a.position.y;
var r = Math.sqrt(dx * dx + dy * dy);
if (r <= (a.radius + b.radius)) {
checkCollision(a,b);
}
}
}
}
Game.prototype.delObj = function (index) {
var len = this.objs.length;
this.objs[index] = this.objs[len - 1];
this.objs.length = len - 1;
}