<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>五彩纸屑射击</title>
<style>
body {
width: 100vw;
min-height: 100vh;
font-family: 'Inconsolata', monospace;
overflow: hidden;
}
#canvas {
display: block;
cursor: pointer;
}
.hint {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
pointer-events: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
opacity: 0;
visibility: hidden;
-webkit-animation: fade-in 1s ease-out 1s forwards, fade-out 1s ease-out 5s forwards;
animation: fade-in 1s ease-out 1s forwards, fade-out 1s ease-out 5s forwards;
}
.hint > h1 {
font-size: 32px;
color: #fff;
}
@-webkit-keyframes fade-in {
0% {
opacity: 0;
visibility: hidden;
}
100% {
opacity: 1;
visibility: visible;
}
}
@keyframes fade-in {
0% {
opacity: 0;
visibility: hidden;
}
100% {
opacity: 1;
visibility: visible;
}
}
@-webkit-keyframes fade-out {
0% {
opacity: 1;
visibility: visible;
}
100% {
opacity: 0;
visibility: hidden;
}
}
@keyframes fade-out {
0% {
opacity: 1;
visibility: visible;
}
100% {
opacity: 0;
visibility: hidden;
}
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<div class="hint" id="hint">
<h1>Click.</h1>
</div>
<script>
var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}var getRandom = function getRandom(min, max) {
return Math.random() * (max - min) + min;
};
var getRandomInt = function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
};
var getRandomColor = function getRandomColor() {
var colors = [
'rgba(231, 76, 60, 1)', // red
'rgba(241, 196, 15, 1)', // yellow
'rgba(46, 204, 113, 1)', // green
'rgba(52, 152, 219, 1)', // blue
'rgba(155, 89, 182, 1)' // purple
];
return colors[getRandomInt(0, colors.length)];
};
// Particle
var
Particle = function () {
function Particle(system, x, y) {_classCallCheck(this, Particle);
this.system = system;
this.universe = this.system.world.universe;
this.x = x;
this.y = y;
this.color = getRandomColor();
this.life = 1;
this.aging = getRandom(0.99, 0.999); // 0.99, 0.999 || 0.999, 0.9999
this.r = getRandomInt(8, 16);
this.speed = getRandom(3, 8);
this.velocity = [
getRandom(-this.speed, this.speed),
getRandom(-this.speed, this.speed)];
}_createClass(Particle, [{ key: 'update', value: function update(
dt) {
this.life *= this.aging;
if (
this.r < 0.1 ||
this.life === 0 ||
this.x + this.r < 0 ||
this.x - this.r > this.universe.width ||
this.y + this.r < 0 ||
this.y - this.r > this.universe.height)
{
this.system.removeObject(this);
}
this.r *= this.life;
this.x += this.velocity[0];
this.y += this.velocity[1];
} }, { key: 'render', value: function render(
ctx) {
// Main circle
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
ctx.fill();
ctx.closePath();
var r = this.color.match(/([0-9]+)/g)[0];
var g = this.color.match(/([0-9]+)/g)[1];
var b = this.color.match(/([0-9]+)/g)[2];
// Gradient
var spread = 1.5;
var gradient = ctx.createRadialGradient(
this.x, this.y, this.r,
this.x, this.y, this.r * spread);
gradient.addColorStop(0, 'rgba(' + r + ', ' + g + ', ' + b + ', 0.3)');
gradient.addColorStop(1, 'rgba(' + r + ', ' + g + ', ' + b + ', 0)');
ctx.globalCompositeOperation = 'lighter';
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r * spread, 0, 2 * Math.PI, false);
ctx.fill();
ctx.closePath();
ctx.globalCompositeOperation = 'source-over';
// Aberration
var offset = this.r * 0.5;
var color = 'rgba(' + g + ', ' + b + ', ' + r + ', 0.3)';
ctx.globalCompositeOperation = 'lighter';
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(this.x + offset, this.y + offset, this.r, 0, 2 * Math.PI, false);
ctx.fill();
ctx.closePath();
ctx.globalCompositeOperation = 'source-over';
} }]);return Particle;}();
// Crown
var
Crown = function () {
function Crown(system, x, y) {_classCallCheck(this, Crown);
this.system = system;
this.x = x;
this.y = y;
this.r = getRandomInt(15, 20); // 5, 20
this.mod = 1.1;
this.life = 1;
this.aging = getRandom(0.83, 0.88);
this.speed = getRandom(4, 5);
this.color = {
r: getRandomInt(236, 242),
g: getRandomInt(196, 241),
b: getRandomInt(195, 242) };
this.angle1 = Math.PI * getRandom(0, 2);
this.angle2 = this.angle1 + Math.PI * getRandom(0.1, 0.5);
}_createClass(Crown, [{ key: 'update', value: function update(
dt) {
this.life *= this.aging;
if (this.life <= 0.0001) this.system.removeObject(this);
this.r += Math.abs(1 - this.life) * this.speed;
this.x1 = this.x + this.r * Math.cos(this.angle1);
this.y1 = this.y + this.r * Math.sin(this.angle1);
this.angle3 = this.angle1 + (this.angle2 - this.angle1) / 2;
this.x2 = this.x + this.r * this.mod * Math.cos(this.angle3);
this.y2 = this.y + this.r * this.mod * Math.sin(this.angle3);
} }, { key: 'render', value: function render(
ctx) {
var gradient = ctx.createRadialGradient(
this.x, this.y, this.r * 0.9,
this.x, this.y, this.r);
gradient.addColorStop(0, 'rgba(' + this.color.r + ', ' + this.color.g + ', ' + this.color.b + ', ' + this.life + ')');
gradient.addColorStop(1, 'rgba(' + this.color.r + ', ' + this.color.g + ', ' + this.color.b + ', ' + this.life * 0.5 + ')');
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, this.angle1, this.angle2, false);
ctx.quadraticCurveTo(this.x2, this.y2, this.x1, this.y1);
ctx.fill();
ctx.closePath();
} }]);return Crown;}();
// Explosion
var
Explosion = function () {
function Explosion(world, x, y) {_classCallCheck(this, Explosion);
this.world = world;
this.x = x;
this.y = y;
this.objects = [];
var particles = getRandomInt(30, 80); // 10, 30 amount of particles
var crowns = particles * getRandom(0.3, 0.5);
while (crowns-- > 0) {this.addCrown();}
while (particles-- > 0) {this.addParticle();}
}_createClass(Explosion, [{ key: 'update', value: function update(
dt) {
this.objects.forEach(function (obj) {
if (obj) obj.update(dt);
});
if (this.objects.length <= 0) {
this.world.clearExplosion(this);
}
} }, { key: 'render', value: function render(
ctx) {
this.objects.forEach(function (obj) {
if (obj) obj.render(ctx);
});
} }, { key: 'addCrown', value: function addCrown()