diff options
Diffstat (limited to '2026/games_submissions/crm148')
| -rw-r--r-- | 2026/games_submissions/crm148/LICENSE | 8 | ||||
| -rw-r--r-- | 2026/games_submissions/crm148/color.js | 31 | ||||
| -rw-r--r-- | 2026/games_submissions/crm148/control.js | 78 | ||||
| -rw-r--r-- | 2026/games_submissions/crm148/cosmos.js | 109 | ||||
| -rw-r--r-- | 2026/games_submissions/crm148/game.js | 101 | ||||
| -rw-r--r-- | 2026/games_submissions/crm148/index.html | 49 | ||||
| -rw-r--r-- | 2026/games_submissions/crm148/pulse.js | 105 | ||||
| -rw-r--r-- | 2026/games_submissions/crm148/ship.js | 178 | ||||
| -rw-r--r-- | 2026/games_submissions/crm148/star.js | 79 | ||||
| -rw-r--r-- | 2026/games_submissions/crm148/util.js | 28 | ||||
| -rw-r--r-- | 2026/games_submissions/crm148/vec2.js | 61 | ||||
| -rw-r--r-- | 2026/games_submissions/crm148/view.js | 32 |
12 files changed, 859 insertions, 0 deletions
diff --git a/2026/games_submissions/crm148/LICENSE b/2026/games_submissions/crm148/LICENSE new file mode 100644 index 0000000..af43641 --- /dev/null +++ b/2026/games_submissions/crm148/LICENSE @@ -0,0 +1,8 @@ +Copyright 2026 crm + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/2026/games_submissions/crm148/color.js b/2026/games_submissions/crm148/color.js new file mode 100644 index 0000000..8e8ba11 --- /dev/null +++ b/2026/games_submissions/crm148/color.js @@ -0,0 +1,31 @@ + +const lerp = (start, end, t) => start + (end - start) * t; + +export default class Color { + r = 0; + g = 0; + b = 0; + constructor(r, g, b) { + this.r = r; + this.g = g; + this.b = b; + } + + to_string() { + return `rgb(${this.r}, ${this.g}, ${this.b})`; + + } + + static interpolate(color1, color2, t) { + const r = Math.round(lerp(color1.r, color2.r, t)); + const g = Math.round(lerp(color1.g, color2.g, t)); + const b = Math.round(lerp(color1.b, color2.b, t)); + + return new Color(r,g,b); + } + static PlayerColor = new Color(150, 200, 150); + static StarDim = new Color(0x77, 0x11, 0x11); + static StarColor = new Color(0xbb, 0x33, 0x33); + static StarBright = new Color(0xbb, 0x33, 0x33); + static PulseColor = new Color(0xcc, 0x22, 0x22); +} diff --git a/2026/games_submissions/crm148/control.js b/2026/games_submissions/crm148/control.js new file mode 100644 index 0000000..7e93e13 --- /dev/null +++ b/2026/games_submissions/crm148/control.js @@ -0,0 +1,78 @@ + +import Vec2 from './vec2.js'; +import { globalView } from './view.js'; + +var gCosmos; +var view; + + + +/// Game state +function victory() { + window.parent.postMessage({op: "done", win: true}); + shutdown(); +} + +function death() { + window.parent.postMessage({op: "done", win: false}); + shutdown(); +} + +function shutdown() { + gCosmos.stop(); + gameCanvas.removeEventListener('mousedown', mousedown); + gameCanvas.removeEventListener('mouseup', mouseup); +} + + + +/// Input +function initInput(cosmos) { + gameCanvas.addEventListener('mousedown', mousedown); + gameCanvas.addEventListener('mouseup', mouseup); + gCosmos = cosmos; + view = globalView(); +} + +function mousedown(ev) { + var ship = gCosmos.player; + ship.inputTarget(getMouseCoord(ev)); + ship.inputThrust(1.0); + gameCanvas.addEventListener('mousemove', mousemove); +} + +function mouseup(ev) { + var ship = gCosmos.player; + gameCanvas.removeEventListener('mousemove', mousemove); + ship.inputThrust(0.0); +} + +function mousemove(ev) { + var ship = gCosmos.player; + ship.inputTarget(getMouseCoord(ev)); +} + +function getMouseCoord(ev) { + var coord = view.unproject(new Vec2(ev.clientX, ev.clientY)); + return coord; +} + + +var debugInfo = {}; +function debugKey(k, v) { + debugInfo[k] = v; +} +function getDebugInfo() { + return debugInfo; +} + + + +/// Exports +export { + initInput, + victory, + death, + debugKey, + getDebugInfo, +} diff --git a/2026/games_submissions/crm148/cosmos.js b/2026/games_submissions/crm148/cosmos.js new file mode 100644 index 0000000..0b14946 --- /dev/null +++ b/2026/games_submissions/crm148/cosmos.js @@ -0,0 +1,109 @@ +import { + victory, + getDebugInfo, + debugKey, +} from './control.js'; +import Ship from './ship.js'; +import Star from './star.js'; + +import Vec2 from './vec2.js'; +import { drawSquare } from './util.js'; +import { globalView } from './view.js'; + +var view; + +class Cosmos { + pulses = []; + star; + player; + running; + + dissipated; + dissipated_target; + dissipated_target_base = 50; + + gravity = .008; + thresh_crit = 5.00; + max_size = (Math.min(gameCanvas.width, gameCanvas.height) / 2) + 100; + pulse_min_str = 7; + pulse_max_str = 20; + pulse_vel_base = 70.0; + + angle = 1; + omega = 1.0; + + init(difficulty) { + view = globalView(); + const STRAD = 9; + const DIFFMUL = 3; + var starRadius = STRAD + difficulty * DIFFMUL; + this.star = new Star(starRadius, difficulty); + this.pulses = []; + this.player = Ship.AboveRadius(starRadius, this.max_size); + this.dissipated = 0; + this.dissipated_target = this.dissipated_target_base + 1 * (difficulty * 1.2); + this.omega = 1.0 + (0.2 * difficulty); + this.running = true; + } + + stop() { + this.running = false; + // console.log('stop the world'); + } + + dissipate(energy) { + this.dissipated += energy; + debugKey('dissipated', this.dissipated); + } + + update(dt) { + this.angle = (this.angle + this.omega * dt) % (2 * Math.PI); + this.player.update(dt); + this.star.update(dt); + this.pulses.forEach((p) => p.update(dt)); + this.pulses = this.pulses.filter((p) => { return p.is_alive() }); + if (this.dissipated > this.dissipated_target) { + victory(); + } + } + + render() { + ctx.fillStyle = "#151515"; + ctx.strokeStyle = "#eeeeee"; + ctx.fillRect(0,0, gameCanvas.width, gameCanvas.height); + this.star.render(ctx); + this.pulses.forEach((p) => p.render(ctx)); + this.player.render(ctx); + // debugP.textContent = JSON.stringify(getDebugInfo()); + + // this.renderSpin(); + } + + renderSpin() { + ctx.fillStyle = "#ff1515"; + ctx.strokeStyle = "#ff1515"; + var p = view.project(new Vec2(Math.cos(this.angle), + Math.sin(this.angle)).scale(this.star.radius + 5)); + drawSquare(ctx, p, 4); + var center = view.project(Vec2.zero()); + var radius = center.sub(p).length(); + + ctx.beginPath(); + ctx.arc(center.x, center.y, radius, -this.angle, -this.angle - 0.4, true); + ctx.stroke(); + } +} + +var theCosmos = new Cosmos(); +var ctx = gameCanvas.getContext("2d"); + +window.cosmos = theCosmos; + +function getCosmos() { + return theCosmos; +} + +export { + Cosmos, + getCosmos, +} diff --git a/2026/games_submissions/crm148/game.js b/2026/games_submissions/crm148/game.js new file mode 100644 index 0000000..00f1cc6 --- /dev/null +++ b/2026/games_submissions/crm148/game.js @@ -0,0 +1,101 @@ + +import { View, globalView } from './view.js'; +import { getCosmos } from './cosmos.js'; +import Vec2 from './vec2.js'; + +import { victory, death, initInput, getDebugInfo } from './control.js'; + +startButton.onclick = function (ev) { + window.postMessage({op:"start", difficulty: 1}); +} + +plusButton.onclick = function(ev) { + window.testAngle += 0.1; +} + +minusButton.onclick = function(ev) { + window.testAngle -= 0.1; +} + +testButton.onclick = function (ev) { + if (!cosmos) { + cosmos = getCosmos(); + cosmos.init(1); + initInput(cosmos); + } + + cosmos.running = false; + cosmos.player.state = 'start_testing'; + + cosmos.pulses = [ + new Pulse(Math.PI / 4, Math.PI, 70, 0, 30), + ]; + + cosmos.update(0); + cosmos.render(); + + // if (!cosmos.running) { + // if (lasttime === undefined) { + // render(0); + // lasttime = undefined; + // starttime = undefined; + // } else { + // render(lasttime); + // } + // } +} + +var cosmos; + +function start(difficulty) { + cosmos = getCosmos(); + cosmos.init(difficulty); + initInput(cosmos); + + window.requestAnimationFrame(render); + // TODO: set up mouse input listener, remove it on game over + window.parent.postMessage({op: "started", verb: "dodge!"}); +} + +// input - mouse click +// point the ship and thrust +// add particle (time, position, velocity) +// expire the particles - maybe wait until all of them are over time limit so +// new ones keep the old ones alive +// fade to black and keep it there +// smoke on the grey background of space + +// TODO: game is over after some amount of energy (increases with difficulty) is +// expelled from the star +function nop() { + ; +} + +var starttime; +var lasttime; +// var start = startGame; + +function render(timestamp) { + if (starttime === undefined) { + starttime = timestamp; + lasttime = starttime; + } else { + nop(); + } + // const elapsed = timestamp - starttime; + const dt = (timestamp - lasttime) / 1000.0; + cosmos.update(dt); + cosmos.render(); + lasttime = timestamp; + if (cosmos.running) { + window.requestAnimationFrame(render); + } else { + // console.log('over'); + } +} + + +export { + start, +} + diff --git a/2026/games_submissions/crm148/index.html b/2026/games_submissions/crm148/index.html new file mode 100644 index 0000000..b4364ca --- /dev/null +++ b/2026/games_submissions/crm148/index.html @@ -0,0 +1,49 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> + <title>In Between The Iframes</title> + <style> + * { + margin: 0px; + padding: 0px; + } + body { + font-size: 10px; + } + #game-test { + width: 100%; + height: 100%; + } + .debugStuff { + display: none; + } + </style> + <script type="module"> + import * as game from './game.js'; + // console.log(window.innerWidth); + window.addEventListener("message", ev => { + switch (ev.data.op) { + case "start": + game.start(ev.data.difficulty); + break; + default: console.log(`unknown event: ${ev}`); break; + } + });; + window.parent.postMessage({op: "ready"}); + </script> + </head> + <body> + <canvas id="gameCanvas" width="240" height="160"></canvas> + <p class="debugStuff"> + <a href="#" id="startButton">Start</a> + </p> + <p class="debugStuff"> + <a href="#" id="testButton">Test</a> + <a href="#" id="plusButton">+</a> + <a href="#" id="minusButton">–</a> + </p> + <p id="debugP"></p> + </body> +</html> diff --git a/2026/games_submissions/crm148/pulse.js b/2026/games_submissions/crm148/pulse.js new file mode 100644 index 0000000..3a0b951 --- /dev/null +++ b/2026/games_submissions/crm148/pulse.js @@ -0,0 +1,105 @@ + +import { getCosmos } from './cosmos.js'; +import { randomAngle, toDegreesInt, normalizeAngle } from './util.js'; +import { globalView } from './view.js'; +import Vec2 from './vec2.js'; +import Color from './color.js'; + +var cosmos; + +export default class Pulse { + angle0; + angle1; + radius; + maxradius = Math.sqrt((gameCanvas.width * gameCanvas.width) + + (gameCanvas.height * gameCanvas.height)) / 2; + velocity; + state = 'state_growing'; + energy; + + constructor(angle0, arcLength, radius, velocity, energy) { + this.angle0 = normalizeAngle(angle0); + this.angle1 = normalizeAngle(angle0 + arcLength); + this.radius = radius; + this.velocity = velocity; + this.energy = energy; + if (!cosmos) { + cosmos = getCosmos(); + } + } + + static StrengthPulse(radius, strength) { + if (!cosmos) { + cosmos = getCosmos(); + } + // console.log('pulse strength',strength); + var str_factor = 0.8 * (strength / cosmos.pulse_max_str); + return new Pulse(cosmos.angle, + (2 * Math.PI) * str_factor, + radius, + cosmos.pulse_vel_base * str_factor, + strength + ); + } + + + contains(p, tolerance) { + var angle = Math.atan2(p.y, p.x); + if (Math.abs(p.length() - this.radius) < 2) { + var da1 = toDegreesInt(normalizeAngle(angle - this.angle0)); + var da2 = toDegreesInt(normalizeAngle(this.angle1 - angle)); + // console.log('da1:', da1, 'da2:', da2); + if (da1 > 0 && da2 > 0) { + return true; + } + } + return false; + } + + + render(ctx) { + const view = globalView(); + const center = view.project(Vec2.zero()); + ctx.strokeStyle = Color.PulseColor.to_string(); + ctx.beginPath(); + ctx.arc(center.x, center.y, this.radius, -this.angle0, -this.angle1, true); + ctx.stroke(); + } + + update(dt) { + if (this[this.state]) { + this[this.state](dt); + } + } + + intensity = 0; + launch_intensity = 2; + + state_birth(dt) { + this.intensity += dt; + if (this.intensity > this.launch_intensity) { + this.state = 'state_growing'; + } + } + + state_growing(dt) { + this.radius += this.velocity * dt; + if (this.radius > this.maxradius) { + this.state = 'state_dying'; + } + } + + state_dying(dt) { + cosmos.dissipate(this.energy); + this.state = 'state_dead'; + } + + state_dead(dt) { + } + + is_alive() { + return this.state !== 'state_dead'; + } +} + +window.Pulse = Pulse; diff --git a/2026/games_submissions/crm148/ship.js b/2026/games_submissions/crm148/ship.js new file mode 100644 index 0000000..cc9d571 --- /dev/null +++ b/2026/games_submissions/crm148/ship.js @@ -0,0 +1,178 @@ + +import Vec2 from './vec2.js'; +import { randomAngle, toDegreesInt, normalizeAngle, drawSquare } from './util.js'; +import { getCosmos } from './cosmos.js'; +import { globalView } from './view.js'; +import Color from './color.js'; +import { death, debugKey } from './control.js'; + +var cosmos; +var view; + +window.testAngle = Math.PI / 4; + +const max_thrust_factor = 6; + +class Ship { + pos; + vel; + thrust = 0; + max_thrust; + heading = 0; + + state = 'state_living'; + death_counter = 0; + death_thresh = 0.3; + + constructor(pos, vel, heading) { + cosmos = getCosmos(); + view = globalView(); + this.pos = pos; + this.heading = heading; + this.vel = vel; + this.max_thrust = cosmos.gravity * max_thrust_factor; + debugKey('ship', this); + } + + static AboveRadius(radius, max_size) { + cosmos = getCosmos(); + // var altitude = radius + Math.random() * (max_size - radius) + var altitude = radius + (0.25 + Math.random() * 0.125) * (max_size - radius) + var angle = randomAngle(); + // var angle = Math.PI / 2; + var pos = Vec2.fromHeadingLength(angle, altitude); + var vel = pos.ofLength(cosmos.gravity * 70.0); + var ship = new Ship(pos, vel, angle); + return ship; + } + + + + /// Behavior + update(dt) { + if (this[this.state]) { + this[this.state](dt); + } + } + + state_living(dt) { + this.applyPhysics(dt); + var death = this.checkDeath(); + if (death) { + this.state = 'state_dying'; + } + } + + state_dying(dt) { + this.death_counter += dt; + // console.log('death_counter', this.death_counter); + if (this.death_counter > this.death_thresh) { + this.state = 'state_dead'; + } + } + + state_dead(dt) { + death(); + } + + + start_testing(dt) { + this.state = 'state_testing'; + this.pos = Vec2.fromHeadingLength(window.testAngle, 70); + // this.pos = view.unproject(new Vec2(3 / 4 * gameCanvas.width, gameCanvas.height / 2)); + this.state_testing(dt); + } + + state_testing(dt) { + debugKey('ship', this); + var death = this.checkDeath(); + debugKey('death', death); + } + + + + /// Physics + applyPhysics(dt) { + var grav = this.pos.ofLength(-cosmos.gravity); + var thrust = Vec2.fromHeadingLength(this.heading, this.thrust * this.max_thrust); + var forces = grav.add(thrust); + this.pos = this.pos.add(this.vel); + this.vel = this.vel.add(forces); + } + + checkDeath() { + return this.checkBoundary() || + this.checkStar() || + this.checkPulses(); + } + + checkBoundary() { + if (Math.max(Math.abs(this.pos.x), Math.abs(this.pos.y)) > cosmos.max_size) { + return true; + } + return false; + } + + checkStar() { + const altitude = this.pos.length(); + if (altitude < cosmos.star.radius) { + return true; + } + return false; + } + + checkPulses() { + var angle = this.pos.heading(); + var altitude = this.pos.length(); + for (var p of cosmos.pulses) { + if (p.contains(this.pos, 2)) { + return true; + } + } + return false; + } + + + + /// Control + inputTarget(coord) { + var rel = coord.sub(this.pos); + debugKey('rel', rel); + this.heading = rel.heading(); + } + + inputThrust(thrust) { + this.thrust = thrust; + } + + + + /// Rendering + getColor() { + var color = Color.PlayerColor.to_string(); + if (this.state === 'state_dying') { + color = '#ff1515'; + } + return color; + } + + render(ctx) { + var sPos = view.project(this.pos); + var color = this.getColor(); + ctx.fillStyle = color; + ctx.strokeStyle = color; + + drawSquare(ctx, sPos, 3); + + var sHeading = new Vec2(Math.cos(this.heading), Math.sin(this.heading)).add(sPos); + drawSquare(ctx, sHeading, 2); + ctx.beginPath(); + ctx.moveTo(sPos.x, sPos.y); + ctx.lineTo(sHeading.x, sHeading.y); + ctx.stroke(); + } +} + + + +export default Ship; diff --git a/2026/games_submissions/crm148/star.js b/2026/games_submissions/crm148/star.js new file mode 100644 index 0000000..78173a8 --- /dev/null +++ b/2026/games_submissions/crm148/star.js @@ -0,0 +1,79 @@ + +import { getCosmos } from './cosmos.js'; +import { globalView } from './view.js'; +import Vec2 from './vec2.js'; +import Color from './color.js'; +import Pulse from './pulse.js'; + +var cosmos; + +export default class Star { + pos = Vec2.zero(); + radius; + + difficulty_mult = 0.2; + growth_base = 3; + + pulses = []; + state = 'state_glowing'; + + energy = 5; + growth_rate; + + constructor(radius, difficulty) { + cosmos = getCosmos(); + this.radius = radius; + const diff_adjust = 1.0 + difficulty * this.difficulty_mult; + this.growth_rate = this.growth_base + diff_adjust; + } + + update(dt) { + this.energy += dt * this. growth_rate; + if (this[this.state]) { + this[this.state](dt); + } + } + + state_glowing(dt) { + if (this.energy > cosmos.thresh_crit) { + this.state = 'state_critical'; + } + } + + // Multiply the energy by a random value + // If the result is over the threshold, dump that energy into a pulse + state_critical(dt) { + var rand = 0.1 + 0.8 * Math.random(); + var strength = Math.min(rand * this.energy, cosmos.pulse_max_str); + if (strength > cosmos.pulse_min_str) { + this.energy -= strength; + cosmos.pulses.push(Pulse.StrengthPulse(this.radius, strength)); + } + } + + getColor() { + var color = Color.StarColor; + switch (this.state) { + case 'state_glowing': + color = Color.interpolate(Color.StarDim, + Color.StarBright, + this.energy / cosmos.thresh_crit); + break; + case 'state_critical': + color = Color.StarBright; + break; + } + return color.to_string(); + } + + render(ctx) { + const view = globalView(); + var s_pos = view.project(this.pos); + var surface_vec = view.project(new Vec2(this.radius, this.pos.y)); + var s_rad = surface_vec.x - s_pos.x; + ctx.fillStyle = this.getColor(); + ctx.beginPath(); + ctx.arc(s_pos.x, s_pos.y, s_rad, 0, 2 * Math.PI); + ctx.fill(); + } +} diff --git a/2026/games_submissions/crm148/util.js b/2026/games_submissions/crm148/util.js new file mode 100644 index 0000000..e91c5e4 --- /dev/null +++ b/2026/games_submissions/crm148/util.js @@ -0,0 +1,28 @@ +function randomAngle() { + return Math.random() * Math.PI * 2; +} + +function toDegrees(radians) { + return radians * 180 / Math.PI; +} + +function toDegreesInt(radians) { + return Math.floor(toDegrees(radians)); +} + +function normalizeAngle(radians) { + return (radians + Math.PI) % (2 * Math.PI) - Math.PI; +} + +function drawSquare(ctx, v2, size) { + const off = size / 2; + ctx.fillRect(v2.x - off, v2.y - off, size, size); +} + +export { + randomAngle, + toDegrees, + toDegreesInt, + normalizeAngle, + drawSquare, +} diff --git a/2026/games_submissions/crm148/vec2.js b/2026/games_submissions/crm148/vec2.js new file mode 100644 index 0000000..230dad9 --- /dev/null +++ b/2026/games_submissions/crm148/vec2.js @@ -0,0 +1,61 @@ + +export default class Vec2 { + constructor(x, y) { + this.x = x; + this.y = y; + } + + static zero() { + return new Vec2(0, 0); + } + + static fromHeading(radians) { + return new Vec2(Math.cos(radians), Math.sin(radians)); + } + + static fromHeadingLength(radians, length) { + return Vec2.fromHeading(radians).scale(length); + } + + length() { + return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2)); + } + + heading() { + return Math.atan2(this.y, this.x); + } + + scale(factor) { + this.x *= factor; + this.y *= factor; + return this; + } + + scaled(factor) { + return new Vec2(this.x * factor, this.y * factor); + } + + ofLength(newLength) { + return this.normalized().scale(newLength); + } + + add(v2) { + return new Vec2(this.x + v2.x, this.y + v2.y); + } + + sub(v2) { + return new Vec2(this.x - v2.x, this.y - v2.y); + } + + normalize() { + var len = this.length(); + this.x = this.x / len; + this.y = this.y / len; + return this; + } + + normalized() { + var len = this.length(); + return new Vec2(this.x / len, this.y / len); + } +} diff --git a/2026/games_submissions/crm148/view.js b/2026/games_submissions/crm148/view.js new file mode 100644 index 0000000..1d2fb5c --- /dev/null +++ b/2026/games_submissions/crm148/view.js @@ -0,0 +1,32 @@ + +import Vec2 from './vec2.js'; + +class View { + center = Vec2.zero(); + zoom = 1.0; + + // Convert game coordinate to canvas coordinate + project(vec2) { + return new Vec2( + (gameCanvas.width / 2) + ((vec2.x - this.center.x) * this.zoom), + (gameCanvas.height / 2) - ((vec2.y - this.center.y) * this.zoom)); + } + // Covert canvas coordinate to game coordinate + unproject(vec2) { + return new Vec2( + this.center.x + (vec2.x - (gameCanvas.width / 2)) / this.zoom, + this.center.y - (vec2.y - (gameCanvas.height/2)) / this.zoom); + } +} + +function globalView() { + return gView; +} + +var gView = new View(); +window.view = gView; + +export { + View, + globalView, +} |
