You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

378 lines
11 KiB

import createjs from "./createjs-2015.11.26.combined";
import red from "./red.png";
import yellow from "./yellow.png";
import green from "./green.png";
import bubble from "./bubble.png";
import flash from "./flash.png";
import magnet from "./magnet.png";
import needle from "./needle.png";
import Matter from "matter-js";
import Ring from "./ring";
import "./water.css";
const width = 1868;
const height = 1096;
const throttle = (t, e) => {
var i = null;
return function (r) {
var n = +new Date();
if (!(null != i && n - i <= e)) return (i = n), t.apply(this, [r]);
};
};
const loadImg = (src) =>
new Promise((resolve) => {
const img = new Image();
img.onload = () => resolve(img);
img.src = src;
});
class Queue {
constructor() {
this.map = {};
}
async loadManifest(manifest) {
const imgs = await Promise.all(manifest.map(({ src }) => loadImg(src)));
manifest.forEach((file, i) => {
this.map[file.id] = imgs[i];
});
}
getResult(id) {
return this.map[id];
}
}
export default class Waterful {
preload() {
const queue = new Queue();
this._queue = queue;
const manifest = [
{
id: "ring_red",
src: red,
},
{
id: "ring_yellow",
src: yellow,
},
{
id: "ring_green",
src: green,
},
{
id: "bubble",
src: bubble,
},
{
id: "flashAnim",
src: flash,
},
{
id: "magnetAnim",
src: magnet,
},
{
id: "needle",
src: needle,
},
];
return queue.loadManifest(manifest);
}
init(options) {
this.steps = 100;
this._options = options;
this._options.callbacks.step(this.steps);
this.enlarging = false;
this.magneting = false;
this.addForceLeft = false;
this.addForceRight = false;
this._score = {
left: options.score.left || [],
right: options.score.right || [],
};
Object.defineProperty(this._score, "total", {
get: function () {
return this.left.length + this.right.length;
},
});
this._idleBubbles = { left: [], right: [] };
this.totalRings =
this._score.total + options.red + options.yellow + options.green;
this.initStage(options.container);
this.initRings(options);
this.eventBinding(options.container);
this.getBubbleLeft = throttle(() => {
if (this._idleBubbles.left.length) return this._idleBubbles.left.shift();
const bubble = new createjs.Sprite(
new createjs.SpriteSheet({
images: [this._queue.getResult("bubble")],
frames: { width: 320, height: 480 },
animations: { run: [0, 14, null, 0.3] },
})
);
bubble.x = 0;
bubble.y = height / 2;
bubble.on(
"animationend",
function () {
this._stage.removeChild(bubble), this._idleBubbles.left.push(bubble);
}.bind(this)
);
return bubble;
}, 300);
this.getBubbleRight = throttle(() => {
if (this._idleBubbles.right.length)
return this._idleBubbles.right.shift();
var bubble = new createjs.Sprite(
new createjs.SpriteSheet({
images: [this._queue.getResult("bubble")],
frames: { width: 320, height: 480 },
animations: { run: [0, 14, null, 0.3] },
})
);
bubble.x = width;
bubble.y = height / 2;
bubble.scaleX = -1;
bubble.on(
"animationend",
function () {
this._stage.removeChild(bubble), this._idleBubbles.right.push(bubble);
}.bind(this)
);
return bubble;
}, 300);
}
initStage(container) {
const drawNeedle = (game, x) => {
const sheet = new createjs.SpriteSheet({
images: [game._queue.getResult("needle")],
frames: { width: 182, height: 659 },
});
const sprite = new createjs.Sprite(sheet);
sprite.x = x;
sprite.y = 334;
return sprite;
};
const drawFlash = (game, x) => {
const sheet = new createjs.SpriteSheet({
images: [game._queue.getResult("flashAnim")],
frames: { width: 332, height: 168 },
animations: { run: { frames: [0, 1, 2, 3, 4], speed: 0.2 } },
});
const sprite = new createjs.Sprite(sheet);
const bounds = sprite.getBounds();
sprite.regX = bounds.width / 2;
sprite.regY = bounds.height / 2;
sprite.x = x;
sprite.y = 334;
sprite.scaleX = 3;
sprite.scaleY = 3;
sprite.on("animationend", function () {
game._stage.removeChild(this);
});
return sprite;
};
const { Engine, World, Bodies, Events } = Matter;
const engine = (this._engine = Engine.create());
engine.world.gravity.y = 0.2;
World.add(engine.world, [
Bodies.rectangle(width / 2, 0, width, 1, { isStatic: true }),
Bodies.rectangle(width / 2, height, width, 1, { isStatic: true }),
Bodies.rectangle(0, height / 2, 1, height, { isStatic: true }),
Bodies.rectangle(width, height / 2, 1, height, { isStatic: true }),
Bodies.rectangle(602, 530, 1, 380, { isStatic: true }),
Bodies.rectangle(634, 530, 1, 380, { isStatic: true }),
Bodies.rectangle(1188, 530, 1, 380, { isStatic: true }),
Bodies.rectangle(1220, 530, 1, 380, { isStatic: true }),
Bodies.circle(616, 764, 90, { isStatic: true }),
Bodies.circle(1200, 764, 90, { isStatic: true }),
Bodies.rectangle(618, 906, 74, 100, { isStatic: true }),
Bodies.rectangle(1204, 906, 74, 100, { isStatic: true }),
Bodies.rectangle(618, 340, 32, 1, { isStatic: true, friction: 0 }),
Bodies.rectangle(1204, 340, 32, 1, { isStatic: true, friction: 0 }),
]),
Engine.run(engine),
Events.on(this._engine, "beforeUpdate", () => {
let force;
if (this.addForceLeft || this.addForceRight) {
if (this.addForceLeft) {
force = 1;
this.addForceLeft = false;
}
if (this.addForceRight) {
force = -1;
this.addForceRight = false;
}
this._rings.forEach((ring) => {
if (ring.active) {
const { x, y } = ring.body.position;
Matter.Body.applyForce(
ring.body,
{ x, y },
{ x: 0.3 * force, y: -0.4 }
);
Matter.Body.setAngularVelocity(ring.body, (force * Math.PI) / 24);
}
});
}
});
const canvas = document.createElement("canvas");
canvas.className = "watercanvas";
canvas.width = width;
canvas.height = height;
container.appendChild(canvas);
this._stage = new createjs.Stage(canvas);
this._needles = {};
const leftNeedle = (this._needles.left = drawNeedle(this, 524));
const rightNeedle = (this._needles.right = drawNeedle(this, 1106));
this._stage.addChild(leftNeedle, rightNeedle);
this._flashAnim = {
left: drawFlash(this, 616),
right: drawFlash(this, 1204),
};
}
initRings(options) {
this._rings = [];
this._staticRings = [];
this._score.left.forEach((ring, i) => {
this.addStaticRing(ring, i, "left");
});
this._score.right.forEach((ring, i) => {
this.addStaticRing(ring, i, "right");
});
this.addRing("ring_red", options.red);
this.addRing("ring_yellow", options.yellow);
this.addRing("ring_green", options.green);
if (options.priceRing && this._rings[0]) {
const ring = this._rings[0];
Matter.Body.setPosition(ring.body, { x: 206, y: 216 }),
(ring.active = true);
}
this._stage.update();
}
addStaticRing(t, e, i) {
var r = new createjs.SpriteSheet({
images: [waterful._queue.getResult("ring_" + t)],
frames: { width: 62, height: 62 },
}),
n = new createjs.Sprite(r),
s = n.getBounds();
(n.regX = s.width / 2),
(n.regY = s.height / 2),
(n.x = "left" === i ? 206 : 455),
(n.y = 380 - 14 * e),
n.gotoAndStop(0),
this._stage.addChild(n),
this._staticRings.push(n);
}
addRing(name, max) {
const getX = () => {
const x = 1670 * Math.random() + 90;
return (x > 523 && x < 705) || (x > 1106 && x < 1292) ? getX() : x;
};
let bodies = [];
for (let i = 0; i < max; i++) {
const x = getX();
const y = 1200 * Math.random() + 150;
const ring = new Ring(x, y, 80, name, this);
this._rings.push(ring);
this._stage.addChild(ring.texture);
bodies.push(ring.body);
}
Matter.World.add(this._engine.world, bodies);
}
eventBinding(container) {
container.querySelector(".button.left").addEventListener("click", (t) => {
if (this.steps) {
this.steps--;
this._options.callbacks.step(this.steps);
} else return;
t.preventDefault(), (this.addForceLeft = true);
var e = this.getBubbleLeft();
e && (this._stage.addChild(e), e.gotoAndPlay("run"));
});
container.querySelector(".button.right").addEventListener("click", (t) => {
if (this.steps) {
this.steps--;
this._options.callbacks.step(this.steps);
} else return;
t.preventDefault(), (this.addForceRight = true);
var e = this.getBubbleRight(this);
e && (e && this._stage.addChild(e), e.gotoAndPlay("run"));
});
createjs.Ticker.timingMode = createjs.Ticker.RAF;
createjs.Ticker.setFPS(60);
createjs.Ticker.addEventListener(
"tick",
function (t) {
if (!t.paused) {
for (var e = 0; e < this._rings.length; e++)
this._rings[e].update(this);
if (this.gamma)
for (var e = 0; e < this._staticRings.length; e++) {
if (this.gamma < 0) {
var i = this._staticRings[e].x - 0.1;
i < 200 && (i = 200), i > 400 && i < 448 && (i = 448);
} else if (this.gamma > 0) {
var i = this._staticRings[e].x + 0.1;
i > 213 && i < 300 && (i = 213), i > 462 && (i = 462);
}
this._staticRings[e].x = i;
}
this._stage.update(t);
}
}.bind(this)
);
}
score(t, e) {
"left" === t
? this._score.left.push(e)
: "right" === t && this._score.right.push(e),
this._stage.addChild(this._flashAnim[t]),
this._flashAnim[t].gotoAndPlay("run");
var i = this._options;
i.callbacks.score(this._score),
this._score.total === this.totalRings && i.callbacks.end(this._score);
}
restart(t) {
this.steps = 100;
this._options.callbacks.step(this.steps);
(this._score = { left: [], right: [] }),
(this.enlarging = false),
(this.magneting = false),
(this.addForceLeft = false),
(this.addForceRight = false),
this._rings.forEach(
function (t) {
this._stage.removeChild(t.texture),
t.body && Matter.World.remove(this._engine.world, t.body);
}.bind(this)
),
this._staticRings.forEach(
function (t) {
this._stage.removeChild(t);
}.bind(this)
),
this.initRings(t);
}
pause() {
createjs.Ticker.pause = true;
for (var t = 0; t < this._rings.length; t++) {
var e = this._rings[t].body;
e && Matter.Sleeping.set(e, true);
}
}
resume() {
createjs.Ticker.pause = false;
for (var t = 0; t < this._rings.length; t++) {
var e = this._rings[t].body;
e && Matter.Sleeping.set(e, false);
}
}
}