2020-12-14 02:10:27 +00:00
|
|
|
function hooray()
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
var SCREEN_WIDTH = window.innerWidth,
|
2020-08-19 16:55:41 +00:00
|
|
|
SCREEN_HEIGHT = window.innerHeight,
|
|
|
|
mousePos = {
|
2020-10-31 14:01:03 +00:00
|
|
|
x: 400,
|
2020-12-14 02:10:27 +00:00
|
|
|
y: 300
|
2020-08-19 16:55:41 +00:00
|
|
|
},
|
|
|
|
// create canvas
|
2020-10-31 14:01:03 +00:00
|
|
|
canvas = document.createElement("canvas"),
|
|
|
|
context = canvas.getContext("2d"),
|
2020-08-19 16:55:41 +00:00
|
|
|
particles = [],
|
|
|
|
rockets = [],
|
|
|
|
MAX_PARTICLES = 400,
|
|
|
|
colorCode = 0;
|
|
|
|
|
2020-10-31 14:01:03 +00:00
|
|
|
// init
|
2020-12-14 02:10:27 +00:00
|
|
|
$(document).ready(function ()
|
|
|
|
{
|
2020-08-19 16:55:41 +00:00
|
|
|
document.body.appendChild(canvas);
|
|
|
|
canvas.width = SCREEN_WIDTH;
|
|
|
|
canvas.height = SCREEN_HEIGHT;
|
|
|
|
setInterval(launch, 800);
|
|
|
|
setInterval(loop, 1000 / 50);
|
2020-10-31 14:01:03 +00:00
|
|
|
});
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-10-31 14:01:03 +00:00
|
|
|
// update mouse position
|
2020-12-14 02:10:27 +00:00
|
|
|
$(document).mousemove(function (e)
|
|
|
|
{
|
2020-08-19 16:55:41 +00:00
|
|
|
e.preventDefault();
|
|
|
|
mousePos = {
|
2020-10-31 14:01:03 +00:00
|
|
|
x: e.clientX,
|
2020-12-14 02:10:27 +00:00
|
|
|
y: e.clientY
|
2020-08-19 16:55:41 +00:00
|
|
|
};
|
2020-10-31 14:01:03 +00:00
|
|
|
});
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-10-31 14:01:03 +00:00
|
|
|
// launch more rockets!!!
|
2020-12-14 02:10:27 +00:00
|
|
|
$(document).mousedown(function (e)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < 5; i++)
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
launchFrom((Math.random() * SCREEN_WIDTH * 2) / 3 + SCREEN_WIDTH / 6);
|
2020-08-19 16:55:41 +00:00
|
|
|
}
|
2020-10-31 14:01:03 +00:00
|
|
|
});
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
function launch()
|
|
|
|
{
|
2020-08-19 16:55:41 +00:00
|
|
|
launchFrom(mousePos.x);
|
2020-10-31 14:01:03 +00:00
|
|
|
}
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
function launchFrom(x)
|
|
|
|
{
|
|
|
|
if (rockets.length < 10)
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
var rocket = new Rocket(x);
|
|
|
|
rocket.explosionColor = Math.floor((Math.random() * 360) / 10) * 10;
|
|
|
|
rocket.vel.y = Math.random() * -3 - 4;
|
|
|
|
rocket.vel.x = Math.random() * 6 - 3;
|
|
|
|
rocket.size = 8;
|
|
|
|
rocket.shrink = 0.999;
|
|
|
|
rocket.gravity = 0.01;
|
|
|
|
rockets.push(rocket);
|
2020-08-19 16:55:41 +00:00
|
|
|
}
|
2020-10-31 14:01:03 +00:00
|
|
|
}
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
function loop()
|
|
|
|
{
|
2020-08-19 16:55:41 +00:00
|
|
|
// update screen size
|
2020-12-14 02:10:27 +00:00
|
|
|
if (SCREEN_WIDTH != window.innerWidth)
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
canvas.width = SCREEN_WIDTH = window.innerWidth;
|
2020-08-19 16:55:41 +00:00
|
|
|
}
|
2020-12-14 02:10:27 +00:00
|
|
|
if (SCREEN_HEIGHT != window.innerHeight)
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
canvas.height = SCREEN_HEIGHT = window.innerHeight;
|
2020-08-19 16:55:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// clear canvas
|
|
|
|
context.fillStyle = "rgba(0, 0, 0, 0.05)";
|
|
|
|
context.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
|
|
|
|
|
|
var existingRockets = [];
|
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
for (var i = 0; i < rockets.length; i++)
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
// update and render
|
|
|
|
rockets[i].update();
|
|
|
|
rockets[i].render(context);
|
|
|
|
|
|
|
|
// calculate distance with Pythagoras
|
|
|
|
var distance = Math.sqrt(
|
|
|
|
Math.pow(mousePos.x - rockets[i].pos.x, 2) +
|
|
|
|
Math.pow(mousePos.y - rockets[i].pos.y, 2)
|
|
|
|
);
|
|
|
|
|
|
|
|
// random chance of 1% if rockets is above the middle
|
|
|
|
var randomChance =
|
|
|
|
rockets[i].pos.y < (SCREEN_HEIGHT * 2) / 3
|
|
|
|
? Math.random() * 100 <= 1
|
|
|
|
: false;
|
|
|
|
|
|
|
|
/* Explosion rules
|
2020-08-19 16:55:41 +00:00
|
|
|
- 80% of screen
|
|
|
|
- going down
|
|
|
|
- close to the mouse
|
|
|
|
- 1% chance of random explosion
|
|
|
|
*/
|
2020-10-31 14:01:03 +00:00
|
|
|
if (
|
|
|
|
rockets[i].pos.y < SCREEN_HEIGHT / 5 ||
|
|
|
|
rockets[i].vel.y >= 0 ||
|
|
|
|
distance < 50 ||
|
|
|
|
randomChance
|
2020-12-14 02:10:27 +00:00
|
|
|
)
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
rockets[i].explode();
|
2020-12-14 02:10:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
existingRockets.push(rockets[i]);
|
|
|
|
}
|
2020-08-19 16:55:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rockets = existingRockets;
|
|
|
|
|
|
|
|
var existingParticles = [];
|
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
for (var i = 0; i < particles.length; i++)
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
particles[i].update();
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-10-31 14:01:03 +00:00
|
|
|
// render and save particles that can be rendered
|
2020-12-14 02:10:27 +00:00
|
|
|
if (particles[i].exists())
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
particles[i].render(context);
|
|
|
|
existingParticles.push(particles[i]);
|
|
|
|
}
|
2020-08-19 16:55:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// update array with existing particles - old particles should be garbage collected
|
|
|
|
particles = existingParticles;
|
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
while (particles.length > MAX_PARTICLES)
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
particles.shift();
|
2020-08-19 16:55:41 +00:00
|
|
|
}
|
2020-10-31 14:01:03 +00:00
|
|
|
}
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
function Particle(pos)
|
|
|
|
{
|
2020-08-19 16:55:41 +00:00
|
|
|
this.pos = {
|
2020-10-31 14:01:03 +00:00
|
|
|
x: pos ? pos.x : 0,
|
2020-12-14 02:10:27 +00:00
|
|
|
y: pos ? pos.y : 0
|
2020-08-19 16:55:41 +00:00
|
|
|
};
|
|
|
|
this.vel = {
|
2020-10-31 14:01:03 +00:00
|
|
|
x: 0,
|
2020-12-14 02:10:27 +00:00
|
|
|
y: 0
|
2020-08-19 16:55:41 +00:00
|
|
|
};
|
2020-10-31 14:01:03 +00:00
|
|
|
this.shrink = 0.97;
|
2020-08-19 16:55:41 +00:00
|
|
|
this.size = 2;
|
|
|
|
|
|
|
|
this.resistance = 1;
|
|
|
|
this.gravity = 0;
|
|
|
|
|
|
|
|
this.flick = false;
|
|
|
|
|
|
|
|
this.alpha = 1;
|
|
|
|
this.fade = 0;
|
|
|
|
this.color = 0;
|
2020-10-31 14:01:03 +00:00
|
|
|
}
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
Particle.prototype.update = function ()
|
|
|
|
{
|
2020-08-19 16:55:41 +00:00
|
|
|
// apply resistance
|
|
|
|
this.vel.x *= this.resistance;
|
|
|
|
this.vel.y *= this.resistance;
|
|
|
|
|
|
|
|
// gravity down
|
|
|
|
this.vel.y += this.gravity;
|
|
|
|
|
|
|
|
// update position based on speed
|
|
|
|
this.pos.x += this.vel.x;
|
|
|
|
this.pos.y += this.vel.y;
|
|
|
|
|
|
|
|
// shrink
|
|
|
|
this.size *= this.shrink;
|
|
|
|
|
|
|
|
// fade out
|
|
|
|
this.alpha -= this.fade;
|
2020-10-31 14:01:03 +00:00
|
|
|
};
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
Particle.prototype.render = function (c)
|
|
|
|
{
|
|
|
|
if (!this.exists())
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
return;
|
2020-08-19 16:55:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
c.save();
|
|
|
|
|
2020-10-31 14:01:03 +00:00
|
|
|
c.globalCompositeOperation = "lighter";
|
2020-08-19 16:55:41 +00:00
|
|
|
|
|
|
|
var x = this.pos.x,
|
2020-10-31 14:01:03 +00:00
|
|
|
y = this.pos.y,
|
|
|
|
r = this.size / 2;
|
2020-08-19 16:55:41 +00:00
|
|
|
|
|
|
|
var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
|
|
|
|
gradient.addColorStop(0.1, "rgba(255,255,255," + this.alpha + ")");
|
2020-10-31 14:01:03 +00:00
|
|
|
gradient.addColorStop(
|
|
|
|
0.8,
|
|
|
|
"hsla(" + this.color + ", 100%, 50%, " + this.alpha + ")"
|
|
|
|
);
|
2020-08-19 16:55:41 +00:00
|
|
|
gradient.addColorStop(1, "hsla(" + this.color + ", 100%, 50%, 0.1)");
|
|
|
|
|
|
|
|
c.fillStyle = gradient;
|
|
|
|
|
|
|
|
c.beginPath();
|
2020-10-31 14:01:03 +00:00
|
|
|
c.arc(
|
|
|
|
this.pos.x,
|
|
|
|
this.pos.y,
|
|
|
|
this.flick ? Math.random() * this.size : this.size,
|
|
|
|
0,
|
|
|
|
Math.PI * 2,
|
|
|
|
true
|
|
|
|
);
|
2020-08-19 16:55:41 +00:00
|
|
|
c.closePath();
|
|
|
|
c.fill();
|
|
|
|
|
|
|
|
c.restore();
|
2020-10-31 14:01:03 +00:00
|
|
|
};
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
Particle.prototype.exists = function ()
|
|
|
|
{
|
2020-08-19 16:55:41 +00:00
|
|
|
return this.alpha >= 0.1 && this.size >= 1;
|
2020-10-31 14:01:03 +00:00
|
|
|
};
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
function Rocket(x)
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
Particle.apply(this, [
|
|
|
|
{
|
2020-08-19 16:55:41 +00:00
|
|
|
x: x,
|
2020-12-14 02:10:27 +00:00
|
|
|
y: SCREEN_HEIGHT
|
|
|
|
}
|
2020-10-31 14:01:03 +00:00
|
|
|
]);
|
2020-08-19 16:55:41 +00:00
|
|
|
|
|
|
|
this.explosionColor = 0;
|
2020-10-31 14:01:03 +00:00
|
|
|
}
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-10-31 14:01:03 +00:00
|
|
|
Rocket.prototype = new Particle();
|
|
|
|
Rocket.prototype.constructor = Rocket;
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
Rocket.prototype.explode = function ()
|
|
|
|
{
|
2020-08-19 16:55:41 +00:00
|
|
|
var count = Math.random() * 10 + 80;
|
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
for (var i = 0; i < count; i++)
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
var particle = new Particle(this.pos);
|
|
|
|
var angle = Math.random() * Math.PI * 2;
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-10-31 14:01:03 +00:00
|
|
|
// emulate 3D effect by using cosine and put more particles in the middle
|
|
|
|
var speed = Math.cos((Math.random() * Math.PI) / 2) * 15;
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-10-31 14:01:03 +00:00
|
|
|
particle.vel.x = Math.cos(angle) * speed;
|
|
|
|
particle.vel.y = Math.sin(angle) * speed;
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-10-31 14:01:03 +00:00
|
|
|
particle.size = 10;
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-10-31 14:01:03 +00:00
|
|
|
particle.gravity = 0.2;
|
|
|
|
particle.resistance = 0.92;
|
|
|
|
particle.shrink = Math.random() * 0.05 + 0.93;
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-10-31 14:01:03 +00:00
|
|
|
particle.flick = true;
|
|
|
|
particle.color = this.explosionColor;
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-10-31 14:01:03 +00:00
|
|
|
particles.push(particle);
|
2020-08-19 16:55:41 +00:00
|
|
|
}
|
2020-10-31 14:01:03 +00:00
|
|
|
};
|
2020-08-19 16:55:41 +00:00
|
|
|
|
2020-12-14 02:10:27 +00:00
|
|
|
Rocket.prototype.render = function (c)
|
|
|
|
{
|
|
|
|
if (!this.exists())
|
|
|
|
{
|
2020-10-31 14:01:03 +00:00
|
|
|
return;
|
2020-08-19 16:55:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
c.save();
|
|
|
|
|
2020-10-31 14:01:03 +00:00
|
|
|
c.globalCompositeOperation = "lighter";
|
2020-08-19 16:55:41 +00:00
|
|
|
|
|
|
|
var x = this.pos.x,
|
2020-10-31 14:01:03 +00:00
|
|
|
y = this.pos.y,
|
|
|
|
r = this.size / 2;
|
2020-08-19 16:55:41 +00:00
|
|
|
|
|
|
|
var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
|
|
|
|
gradient.addColorStop(0.1, "rgba(255, 255, 255 ," + this.alpha + ")");
|
|
|
|
gradient.addColorStop(1, "rgba(0, 0, 0, " + this.alpha + ")");
|
|
|
|
|
|
|
|
c.fillStyle = gradient;
|
|
|
|
|
|
|
|
c.beginPath();
|
2020-10-31 14:01:03 +00:00
|
|
|
c.arc(
|
|
|
|
this.pos.x,
|
|
|
|
this.pos.y,
|
|
|
|
this.flick ? (Math.random() * this.size) / 2 + this.size / 2 : this.size,
|
|
|
|
0,
|
|
|
|
Math.PI * 2,
|
|
|
|
true
|
|
|
|
);
|
2020-08-19 16:55:41 +00:00
|
|
|
c.closePath();
|
|
|
|
c.fill();
|
|
|
|
|
|
|
|
c.restore();
|
2020-10-31 14:01:03 +00:00
|
|
|
};
|
|
|
|
}
|