From 4959519f3919d14262737f98e5c5c11f34f9fae4 Mon Sep 17 00:00:00 2001 From: asraelite Date: Sat, 3 Mar 2018 15:58:51 +0000 Subject: [PATCH] Add ship movement --- dist/img/celestials/green_0.svg | 38 ++++----- dist/img/modules/light_thruster.svg | 83 ++++++++++---------- dist/img/modules/light_thruster_on.svg | 103 +++++++++++++++++++++++++ js/assets.mjs | 5 +- js/consts.mjs | 2 +- js/data.mjs | 3 + js/game/control.mjs | 25 ++++++ js/game/events.mjs | 1 + js/game/index.mjs | 9 ++- js/game/player.mjs | 7 ++ js/graphics/world.mjs | 17 ++-- js/world/body.mjs | 9 +++ js/world/module.mjs | 29 ++++++- js/world/ship.mjs | 20 ++++- js/world/spawn.mjs | 4 +- 15 files changed, 278 insertions(+), 77 deletions(-) create mode 100644 dist/img/modules/light_thruster_on.svg create mode 100644 js/game/control.mjs create mode 100644 js/game/player.mjs diff --git a/dist/img/celestials/green_0.svg b/dist/img/celestials/green_0.svg index f0357e2..6d07600 100644 --- a/dist/img/celestials/green_0.svg +++ b/dist/img/celestials/green_0.svg @@ -25,9 +25,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="0.7" - inkscape:cx="356.31215" - inkscape:cy="358.21593" + inkscape:zoom="1.4" + inkscape:cx="249.24893" + inkscape:cy="380.139" inkscape:document-units="mm" inkscape:current-layer="layer1" showgrid="false" @@ -44,7 +44,7 @@ image/svg+xml - + @@ -54,52 +54,52 @@ id="layer1" transform="translate(25.294481,-146.20324)"> - + id="g918" + style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"> + style="stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none"> + diff --git a/dist/img/modules/light_thruster.svg b/dist/img/modules/light_thruster.svg index 53f0088..1c0bf3b 100644 --- a/dist/img/modules/light_thruster.svg +++ b/dist/img/modules/light_thruster.svg @@ -25,11 +25,11 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="2.8" - inkscape:cx="54.726513" - inkscape:cy="10.343454" + inkscape:zoom="7.9195959" + inkscape:cx="59.772356" + inkscape:cy="7.3948782" inkscape:document-units="mm" - inkscape:current-layer="layer1" + inkscape:current-layer="g828" showgrid="true" inkscape:window-width="1366" inkscape:window-height="714" @@ -60,41 +60,44 @@ inkscape:groupmode="layer" id="layer1" transform="translate(-85.489576,-133.78125)"> - - - - - - + + + + + + + + diff --git a/dist/img/modules/light_thruster_on.svg b/dist/img/modules/light_thruster_on.svg new file mode 100644 index 0000000..89ec80c --- /dev/null +++ b/dist/img/modules/light_thruster_on.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/js/assets.mjs b/js/assets.mjs index 18120a9..16da8cd 100644 --- a/js/assets.mjs +++ b/js/assets.mjs @@ -11,7 +11,10 @@ export const images = { small: 'modules/small_fuel_tank.svg' }, thruster: { - light: 'modules/light_thruster.svg' + light: { + off: 'modules/light_thruster.svg', + on: 'modules/light_thruster_on.svg', + } } }, celestials: { diff --git a/js/consts.mjs b/js/consts.mjs index 6918296..5f9fa41 100644 --- a/js/consts.mjs +++ b/js/consts.mjs @@ -13,6 +13,6 @@ export const STAR_DENSITY = (SECTOR_SIZE ** 2) / 10000; export const GRAVITATIONAL_CONSTANT = 0.01; // Perspective constraints. Higher zoom value = closer. export const MIN_ZOOM = 1; -export const MAX_ZOOM = 30; +export const MAX_ZOOM = 100; export const DEFAULT_ZOOM = 10; export const ZOOM_SPEED = 0.01; diff --git a/js/data.mjs b/js/data.mjs index 85039cc..734e948 100644 --- a/js/data.mjs +++ b/js/data.mjs @@ -5,6 +5,7 @@ export const modules = { tooltip: 'A small, simple capsule. Provides just enough ' + 'rotational power for a small rocket.', type: 'capsule', + id: 'small', mass: 2, rotation: 0.1 } @@ -14,6 +15,7 @@ export const modules = { name: 'Small Fuel Tank', tooltip: 'A small flimsy tank with enough fuel for a short trip.', type: 'fuel', + id: 'small', mass: 1, capacity: 3 } @@ -24,6 +26,7 @@ export const modules = { tooltip: 'Powerful enough to lift a small ship, but not much ' + 'more. Not very efficient.', type: 'thruster', + id: 'light', mass: 2, thrust: 10, isp: 200 diff --git a/js/game/control.mjs b/js/game/control.mjs new file mode 100644 index 0000000..0267289 --- /dev/null +++ b/js/game/control.mjs @@ -0,0 +1,25 @@ +import * as input from '../input.mjs'; +import * as player from './player.mjs'; + +export const mapping = { + thrust: 'KeyW', + left: 'KeyA', + right: 'KeyD' +}; + +export function tick() { + let held = input.keyCode.held; + let pressed = input.keyCode.pressed; + + if (held[mapping.thrust]) { + player.ship.applyThrust({ forward: 1 }); + } + + if (held[mapping.left]) { + player.ship.applyThrust({ turnLeft: 1 }); + } + + if (held[mapping.right]) { + player.ship.applyThrust({ turnRight: 1 }); + } +} diff --git a/js/game/events.mjs b/js/game/events.mjs index 11a84c0..a3ba9f1 100644 --- a/js/game/events.mjs +++ b/js/game/events.mjs @@ -1,6 +1,7 @@ import * as game from './index.mjs'; import * as graphics from '../graphics/index.mjs'; import * as world from '../world/index.mjs'; +import * as player from './player.mjs'; export function startGame() { game.changeView('game'); diff --git a/js/game/index.mjs b/js/game/index.mjs index e614f8e..dc0cffb 100644 --- a/js/game/index.mjs +++ b/js/game/index.mjs @@ -4,6 +4,8 @@ import * as assets from '../assets.mjs'; import * as input from '../input.mjs'; import * as world from '../world/index.mjs'; import * as events from './events.mjs'; +import * as control from './control.mjs'; +import * as player from './player.mjs'; export let state; @@ -35,11 +37,16 @@ export function changeView(view) { if (view == 'game') { world.init(); + player.init(); } } async function tick() { - if (state.view == 'game') world.tick(); + if (state.view == 'game') { + world.tick(); + control.tick(); + } + gui.tick(); graphics.render(); input.tick(); diff --git a/js/game/player.mjs b/js/game/player.mjs new file mode 100644 index 0000000..aeec9e0 --- /dev/null +++ b/js/game/player.mjs @@ -0,0 +1,7 @@ +import * as world from '../world/index.mjs'; + +export let ship; + +export function init() { + ship = world.playerShip; +} diff --git a/js/graphics/world.mjs b/js/graphics/world.mjs index 764cd7d..748b5b9 100644 --- a/js/graphics/world.mjs +++ b/js/graphics/world.mjs @@ -8,15 +8,14 @@ export function render() { } function renderShip(ship) { - context.fillStyle = 'red'; - //context.fillRect(ship.x, ship.y, 10, 10); - let size = 1; - context.drawImage(assets.modules.capsule.small, ship.x, ship.y, - size, size); - context.drawImage(assets.modules.fuel.small, ship.x, ship.y + size, - size, size); - context.drawImage(assets.modules.thruster.light, ship.x, - ship.y + size * 2, size, size); + context.save(); + context.translate(ship.x, ship.y); + context.rotate(ship.r); + let [cx, cy] = ship.com; + ship.modules.forEach(m => { + context.drawImage(m.currentImage, m.x - cx, m.y - cy, 1, 1); + }); + context.restore(); } const celestialImages = { diff --git a/js/world/body.mjs b/js/world/body.mjs index d759eaa..09e5c72 100644 --- a/js/world/body.mjs +++ b/js/world/body.mjs @@ -8,12 +8,15 @@ export default class Body { this.xvel = 0; this.yvel = 0; this.rvel = 0; + this.rfriction = 0.9; this.mass = mass; } tickMotion() { this.x += this.xvel; this.y += this.yvel; + this.r += this.rvel; + this.rvel *= this.rfriction; } tickGravity(bodies) { @@ -40,4 +43,10 @@ export default class Body { this.xvel = 0; this.yvel = 0; } + + applyDirectionalForce(x, y, r) { + this.xvel += (x * Math.cos(this.r) - y * Math.sin(this.r)) / this.mass; + this.yvel += (y * Math.cos(this.r) - x * Math.sin(this.r)) / this.mass; + this.rvel += r / this.mass; + } } diff --git a/js/world/module.mjs b/js/world/module.mjs index 324ea29..053fbfd 100644 --- a/js/world/module.mjs +++ b/js/world/module.mjs @@ -1,7 +1,10 @@ +import {images as assets} from '../assets.mjs'; + export default class Module { constructor(x, y, { name = 'Unnamed Module', type = 'block', + id = 'unknown', mass = 1, // Fuel filled = false, @@ -13,7 +16,31 @@ export default class Module { this.name = name; this.type = type; this.mass = mass; + this.id = id; + this.images = assets.modules[this.type][this.id]; // Fuel - this.fuel = filled ? fuelCapacity : 0; + if (this.type == 'fuel') { + this.fuel = filled ? fuelCapacity : 0; + } else if (this.type == 'thruster') { + this.power = 0; + } + } + + reset() { + if (this.type == 'thruster') { + this.power = 0; + } + } + + get currentImage() { + if (this.type == 'thruster') { + return this.power > 0 ? this.images.on : this.images.off; + } else { + return this.images; + } + } + + get com() { + return [this.x + 0.5, this.y + 0.5]; } } diff --git a/js/world/ship.mjs b/js/world/ship.mjs index 046544f..3eb00be 100644 --- a/js/world/ship.mjs +++ b/js/world/ship.mjs @@ -14,6 +14,7 @@ export default class Ship extends Body { this.tickMotion(); this.tickGravity(world.celestials); this.resolveCollisions(); + this.modules.forEach(m => m.reset()); } addModule(x, y, properties, options) { @@ -29,11 +30,12 @@ export default class Ship extends Body { refreshShape() { let points = []; - this.modules.forEach(m => points.push([m.x, m.y, m.mass])); + this.modules.forEach(m => points.push([...m.com, m.mass])); this.mass = points.reduce((a, [,,b]) => a + b, 0); - this.com = points.reduce(([ax, ay], b) => - [ax + b.x * b.mass, ay + b.y * b.mass], [0, 0]) + this.com = points.reduce(([ax, ay], [bx, by, bm]) => + [ax + bx * bm, ay + by * bm], [0, 0]) .map(x => x / this.mass); + window.q = points; } resolveCollisions() { @@ -45,4 +47,16 @@ export default class Ship extends Body { } }) } + + applyThrust({ forward = 0, left = 0, right = 0, back = 0, + turnLeft = 0, turnRight = 0}) { + let turnForce = (turnRight - turnLeft) / 20; + this.applyDirectionalForce(0, -forward / 30, turnForce); + + this.modules.forEach(m => { + if (m.type !== 'thruster') return; + m.power = forward; + }); + + } } diff --git a/js/world/spawn.mjs b/js/world/spawn.mjs index 6d98dca..92cfa3f 100644 --- a/js/world/spawn.mjs +++ b/js/world/spawn.mjs @@ -5,7 +5,7 @@ import {modules} from '../data.mjs'; import * as world from './index.mjs'; export function player() { - let ship = new Ship(0, 0); + let ship = new Ship(0, -45); ship.addModule(0, 0, modules.capsule.small); ship.addModule(0, 1, modules.fuel.small, { filled: true }); ship.addModule(0, 2, modules.thruster.light); @@ -15,7 +15,7 @@ export function player() { } export function startPlanet() { - return celestial(-40, 10, 40, { + return celestial(0, 0, 40, { density: 1, type: 'green' });