UNPKG

stage-js

Version:

2D HTML5 Rendering and Layout

384 lines (342 loc) 7.64 kB
import Stage from "../../src"; import bezier from "../common/bezier"; import "./textures"; let actions = {}; let levels = {}; levels[1] = function () { let math = Stage.math; let runway = [ [-66, -111], [132, -2], ]; let station1 = [52, 120]; let station2 = [-38, 68]; let station3 = [-141, 2]; let station4 = [-78, -91]; let path = function () { return [ actions.enter([-500, math.random(-200, 200)]), actions.land(runway), actions.taxi(station1), actions.taxi(station2), actions.delay(1000), actions.taxi(station3), actions.taxi(station4), actions.stop(), actions.taxi(runway[0]), actions.takeoff(runway, [500, math.random(-300, 300)]), ]; }; return { addPlane: function (plane) { plane.queue(path()); }, delay: function () { return math.random() * 3000 + 5000; }, }; }; function Game(ui) { let items = []; let removeing = []; let selected = null; let level; this.start = function (l) { level = levels[l](); ui.map(l); loop(); }; function loop() { let plane = new Plane(); level.addPlane(plane); addPlane(plane); ui.timeout(loop, level.delay()); } this.click = function () { if (selected) { selected.deselect(); selected = null; } }; this.tick = function (t) { for (let i = 0; i < items.length; i++) { let item = items[i]; item.tick(t); } let obj; while ((obj = removeing.pop())) { delPlane(obj); } }; function addPlane(plane) { items.push(plane); plane.ui.add(); return this; } function delPlane(plane) { let i = items.indexOf(plane); if (i >= 0) { items.splice(i, 1); } plane.ui.remove(); return this; } function Plane() { this.a = 0; this.x = 0; this.y = 0; this.z = 0; this.s = 0.1; let queue = []; this.ui = ui.plane(this); this.queue = function () { let list = Array.prototype.concat.apply([], arguments); queue.push.apply(queue, list); return this; }; this.tick = function (t) { if (queue.length) { let done = queue[0](t, this); if (done) { queue.shift(); if (typeof done == "object" || typeof done == "function") { queue.unshift(done); } } this.ui.update(); } }; this.move = function (x, y, t, speed) { let dx = x - this.x; let dy = y - this.y; let d = Math.sqrt(dx * dx + dy * dy); let m = (this.s * speed * t) / d; let nx, ny; if (m >= 1) { nx = x; ny = y; } else { nx = this.x + dx * m; ny = this.y + dy * m; } return this.reloc(nx, ny) && m >= 1; }; this.reloc = function (x, y) { let dx = x - this.x; let dy = y - this.y; this.a = Math.atan2(dy, dx); for (let i = 0; i < items.length; i++) { let that = items[i]; if (this == that) { continue; } dx = x - that.x; dy = y - that.y; if (dx * dx + dy * dy < 240) { if (this.z == 0 && that.z == 0) { return false; } else { this.remove(); that.remove(); ui.explode(this); ui.explode(that); return false; } } } (this.x = x), (this.y = y); return true; }; this.remove = function () { removeing.push(this); return this; }; this.click = function () { if (queue.length) { let action = queue[0]; action.click && action.click(); } // selected && selected.deselect(); // this.select(); return true; }; this.select = function () { selected = this; this.isActive = true; this.ui.update(); // for ( var id in this.state.links) { // var state = this.state.links[id].end; // state.select(); // } return this; }; this.deselect = function () { this.isActive = false; this.ui.update(); return this; }; } } actions.enter = function (enter) { return function (t, item) { item.x = enter[0]; item.y = enter[1]; return true; }; }; actions.land = function (rw) { let fn = null, p = {}; return function (t, item) { item.z = 1; if (!fn) { let points = [ [item.x, item.y], [item.x, item.y], [2 * rw[0][0] - 1 * rw[1][0], 2 * rw[0][1] - 1 * rw[1][1]], rw[0], ]; fn = travel(bezier(points)); } if (fn(t, 0.1, p) & item.reloc(p.x, p.y)) { return function (t, item) { item.z = 0.5; if (item.move(rw[1][0], rw[1][1], t, 0.6)) { return true; } }; } }; }; actions.takeoff = function (rw, exit) { return function (t, item) { item.z = 0.5; if (item.move(rw[1][0], rw[1][1], t, 2)) { let fn = null, p = {}; return function (t, item) { item.z = 1; if (!fn) { let points = [ rw[1], [2 * rw[1][0] - 1 * rw[0][0], 2 * rw[1][1] - 1 * rw[0][1]], [exit[0], exit[1]], [exit[0], exit[1]], ]; fn = travel(bezier(points)); } if (fn(t, 0.1, p) & item.reloc(p.x, p.y)) { item.remove(); return true; } }; } }; }; actions.taxi = function (to) { return function (t, item) { item.z = 0; if (item.move(to[0], to[1], t, 0.4)) { return true; } }; }; actions.delay = function (time) { return function (t, item) { item.z = 0; while ((time -= t) > 0) { return false; } return true; }; }; actions.stop = function (time) { let cont = false; let action = function (t, item) { item.z = 0; return cont; }; action.click = function () { cont = true; }; return action; }; function travel(fn, e) { e = e || 0.01; let prog = 0; return function (t, speed, xy) { xy = fn(prog, xy); let x = xy.x, y = xy.y; xy = fn(prog + e, xy); let dx = xy.x - x, dy = xy.y - y; prog += (e * (t * speed)) / Math.sqrt(dx * dx + dy * dy); xy = fn(prog, xy); return prog >= 1; }; } let stage = Stage.mount(); stage.background("#222222"); stage.viewbox(1024, 1024, "out-crop").pin("align", -0.5); stage.MAX_ELAPSE = 20; Stage.sprite("bg").appendTo(stage).pin("handle", 0.5); let map; let game = new Game({ map: function (l) { map && stage.remove(map); map = Stage.sprite("map-" + l) .pin({ align: 0, handle: 0.5, }) .appendTo(stage); }, plane: function (obj) { let ui = Stage.sprite("plane").pin("handle", 0.5); ui.on("click", function () { return obj.click(); }); return { add: function () { ui.appendTo(stage); }, update: function () { ui.offset(obj).rotate(obj.a); }, remove: function (obj) { ui.remove(); }, }; }, timeout: function (fn, delay) { stage.timeout(fn, delay); }, explode: function (obj) { Stage.sprite("explode") .appendTo(stage) .pin({ handle: 0.5, offsetX: obj.x, offsetY: obj.y, alpha: 0.1, }) .tween(100) .pin({ alpha: 1, }) .tween(500) .pin({ alpha: 0, }) .remove(); }, }); stage.on("click", function () { game.click(); }); stage.tick(function (t) { game.tick(t); return true; }); game.start(1);