diff --git a/TODO b/TODO new file mode 100644 index 0000000..e69de29 diff --git a/public/static/img/turrets/01/normal.png b/public/static/img/turrets/01/0.png similarity index 100% rename from public/static/img/turrets/01/normal.png rename to public/static/img/turrets/01/0.png diff --git a/public/static/img/turrets/02/normal.png b/public/static/img/turrets/02/0.png similarity index 100% rename from public/static/img/turrets/02/normal.png rename to public/static/img/turrets/02/0.png diff --git a/public/static/img/turrets/02/launched.png b/public/static/img/turrets/02/1.png similarity index 100% rename from public/static/img/turrets/02/launched.png rename to public/static/img/turrets/02/1.png diff --git a/public/static/js/wingbase/assets.js b/public/static/js/wingbase/assets.js index ce094da..8529fa9 100644 --- a/public/static/js/wingbase/assets.js +++ b/public/static/js/wingbase/assets.js @@ -13,10 +13,11 @@ Game.prototype.loadAssets = _ => { }, turrets: { '01': { - small: 'img/turrets/01/normal.png' + '0': 'img/turrets/01/0.png' }, '02': { - small: 'img/turrets/02/normal.png' + '0': 'img/turrets/02/0.png', + '1': 'img/turrets/02/1.png' } }, projectiles: { diff --git a/public/static/js/wingbase/gui/weapons.js b/public/static/js/wingbase/gui/weapons.js index 6370617..f4ef661 100644 --- a/public/static/js/wingbase/gui/weapons.js +++ b/public/static/js/wingbase/gui/weapons.js @@ -13,12 +13,12 @@ GUI.prototype.Weapons = class { this.element.innerHTML = ''; ship.fixtures.forEach((fixture, i) => { - if (!fixture.type) return; + if (!fixture.fixture) return; let div = document.createElement('div'); div.classList.add('weapon'); if (ship.activeFixture == i) div.classList.add('active'); - let img = `url(/img/turrets/${fixture.type}/normal.png)`; + let img = `url(/img/turrets/${fixture.fixture}/normal.png)`; div.style.backgroundImage = img; this.element.appendChild(div); }); diff --git a/public/static/js/wingbase/net.js b/public/static/js/wingbase/net.js index ed26652..1b512a6 100644 --- a/public/static/js/wingbase/net.js +++ b/public/static/js/wingbase/net.js @@ -17,7 +17,6 @@ class Net { }); this.socket.on('update', data => { - window.q = data; game.world.update(data); }); diff --git a/public/static/js/wingbase/player.js b/public/static/js/wingbase/player.js index 4b6fd44..a4ef47e 100644 --- a/public/static/js/wingbase/player.js +++ b/public/static/js/wingbase/player.js @@ -15,7 +15,7 @@ class Player { let packet = {}; packet.thrust = ['w', 'a', 'd', 's'].map(k => +input.keys.held[k] || 0); - packet.fire = [1, 3].map(k => +input.mouse.pressed[k] || 0); + packet.fire = [1, 1, 3].map(k => +input.mouse.pressed[k] || 0); packet.aim = [ +input.mouse.wx.toFixed(2), +input.mouse.wy.toFixed(2) diff --git a/public/static/js/wingbase/render/body.js b/public/static/js/wingbase/render/body.js index 30d318f..c6d1d4c 100644 --- a/public/static/js/wingbase/render/body.js +++ b/public/static/js/wingbase/render/body.js @@ -9,18 +9,15 @@ class BodyRenderer { let pos = body.pos; let x = pos.x * SCALE; let y = pos.y * SCALE; - let vx = -game.world.center.x; - let vy = -game.world.center.y; let pallet = this.pallet; let context = pallet.context; - pallet.view(vx, vy, false, 0); pallet.view(x, y, false, pos.r); for (let f of body.fixtures) { if (!f.fixture || !f.hidden) continue; - let img = game.assets.images.turrets[f.fixture].small; + let img = game.assets.images.turrets[f.fixture][f.state]; this.pallet.image(img, f.x - 32, f.y - 32, f.angle); } @@ -36,12 +33,11 @@ class BodyRenderer { for (let f of body.fixtures) { if (!f.fixture || f.hidden) continue; - let img = game.assets.images.turrets[f.fixture].small; + let img = game.assets.images.turrets[f.fixture][f.state]; this.pallet.image(img, f.x - 32, f.y - 32, f.angle); } pallet.restore(); - pallet.restore(); } diff --git a/public/static/js/wingbase/render/discharge.js b/public/static/js/wingbase/render/discharge.js new file mode 100644 index 0000000..f56b221 --- /dev/null +++ b/public/static/js/wingbase/render/discharge.js @@ -0,0 +1,21 @@ +class DischargeRenderer { + constructor(renderer) { + this.pallet = renderer.pallet; + this.canvas = this.pallet.canvas; + this.context = this.pallet.context; + } + + render(discharge) { + let x = discharge.x * SCALE; + let y = discharge.y * SCALE; + + let pallet = this.pallet; + let context = this.context; + + pallet.view(x, y, false, discharge.r); + + pallet.square('#f00', 0, 0, 2); + + pallet.restore(); + } +} diff --git a/public/static/js/wingbase/render/render.js b/public/static/js/wingbase/render/render.js index 533181d..bbd5091 100644 --- a/public/static/js/wingbase/render/render.js +++ b/public/static/js/wingbase/render/render.js @@ -16,6 +16,7 @@ class Renderer { window.addEventListener('resize', _ => pallet.fillScreen(1000, 600)); this.bodyRenderer = new BodyRenderer(this); + this.dischargeRenderer = new DischargeRenderer(this); } render(state) { @@ -53,10 +54,20 @@ class Renderer { this.renderGrid(); + let vx = -game.world.center.x; + let vy = -game.world.center.y; + this.pallet.view(vx, vy, false, 0); + for (var id in game.world.bodies) { this.bodyRenderer.render(game.world.bodies[id]); } + for (var id in game.world.discharges) { + this.dischargeRenderer.render(game.world.discharges[id]); + } + + this.pallet.restore(); + this.effects.forEach(effect => { effect.render(); }); @@ -76,8 +87,10 @@ class Renderer { let cw = this.canvas.width; let ch = this.canvas.height; - var gridx = cx % 50; - var gridy = cy % 50; + let gridx = cx % 50; + let gridy = cy % 50; + let lastBlue = false; + this.pallet.opacity(0.05); for (var x = gridx - cw / 2 - 50; x < cw + 50; x += 50) { for (var y = gridy - ch / 2 - 50; y < ch + 50; y += 50) { @@ -85,10 +98,18 @@ class Renderer { var wy = ((-cy + y) / SCALE) | 0; var b = game.world.bounds; if (wx > b.right || wx < b.left || wy > b.bottom || wy < b.top) { - this.pallet.opacity(0.2); + if (!lastBlue) { + this.pallet.opacity(0.2); + lastBlue = true; + } this.pallet.outline('#8af', x, y, 51, 51, 1); - this.pallet.opacity(0.05); - } else this.pallet.outline('#fff', x, y, 51, 51, 1); + } else { + if (lastBlue) { + this.pallet.opacity(0.05); + lastBlue = false; + } + this.pallet.outline('#fff', x, y, 51, 51, 1); + } } } this.pallet.opacity(1); diff --git a/public/static/js/wingbase/world/body.js b/public/static/js/wingbase/world/body.js index 3f77737..f3d7645 100644 --- a/public/static/js/wingbase/world/body.js +++ b/public/static/js/wingbase/world/body.js @@ -9,6 +9,11 @@ class Body { this.id = data.id this.frame = data.frame; this.fixtures = data.fixtures; + this.fixtures = this.fixtures.map(f => { + f.x *= 32; + f.y *= 32; + return f; + }); this.b2body = false; this.updated = 0; this.bodyClass = data.class; @@ -49,7 +54,7 @@ class Body { this.fixtures.forEach(fixture => { let obj = {}; this.interface.fixtures.order.forEach(v => obj[v] = data.shift()); - + fixture.angle = obj.angle; fixture.state = obj.state; }); diff --git a/public/static/js/wingbase/world/discharge.js b/public/static/js/wingbase/world/discharge.js new file mode 100644 index 0000000..8c7468d --- /dev/null +++ b/public/static/js/wingbase/world/discharge.js @@ -0,0 +1,51 @@ +//@10 + +class Discharge { + constructor(data) { + this.interface = { + order: ['x', 'y'], + size: 2 + }; + this.xvel = data.xvel; + this.yvel = data.yvel; + this.r = data.r; + this.id = data.id; + this.updated = 0; + + this.update(data.delta.slice(1)); + } + + getPos() { + return this.pos; + } + + applyForce(x, y) { + var b = this.b2body; + b.ApplyForce(new b2Vec2(x, y), b.GetWorldCenter()); + } + + applyTorque(f) { + this.b2body.ApplyTorque(f); + } + + update(data) { + let values = {}; + console.log(data); + this.interface.order.forEach(v => values[v] = data.shift()); + this.x = values.x; + this.y = values.y; + this.updated = 10; + } + + tick() { + this.x += this.xvel; + this.y += this.yvel; + } + + get pos() { + return { + x: this.x, + y: this.y + }; + } +} diff --git a/public/static/js/wingbase/world/world.js b/public/static/js/wingbase/world/world.js index 6b0ee3c..a6eb408 100644 --- a/public/static/js/wingbase/world/world.js +++ b/public/static/js/wingbase/world/world.js @@ -3,6 +3,7 @@ const SCALE = 32; class World { constructor() { this.bodies = {}; + this.discharges = {}; this.playerShip = false; this.physics = new Physics(); @@ -15,6 +16,15 @@ class World { } add(data) { + if(data.form != 'body') console.log(data); + if (data.form == 'body') { + this.addBody(data); + } else if (data.form == 'discharge') { + this.addDischarge(data); + } + }; + + addBody(data) { var body; if (data.type == 'asteroid') body = new Asteroid(data); if (data.type == 'ship') body = new Ship(data); @@ -24,11 +34,18 @@ class World { this.bodies[body.id] = body; this.physics.createBody(body); - }; + } + + addDischarge(data) { + var discharge; + discharge = new Discharge(data); + this.discharges[discharge.id] = discharge; + } remove(id) { this.physics.removeBody(this.bodies[id]); delete this.bodies[id]; + delete this.discharges[id]; }; clear() { @@ -43,13 +60,14 @@ class World { while (i < data.length) { let id = data[i++]; let body = this.bodies[id]; + let discharge = this.discharges[id]; - if (!body) { - game.net.send('requestBodyData', id); - return; + if (body) { + body.update(data.slice(i, i + body.interface.size)); + } else if (discharge) { + discharge.update(data.slice(i, i + 2)); } - body.update(data.slice(i, i + body.interface.size)); i += body.interface.size; } }; @@ -66,6 +84,10 @@ class World { for (var i in this.bodies) { this.bodies[i].tick(); } + + for (var i in this.discharges) { + this.discharges[i].tick(); + } }; get center() { diff --git a/server/game/room/world/body/body.js b/server/game/room/world/body/body.js index d521c1d..39e88ee 100644 --- a/server/game/room/world/body/body.js +++ b/server/game/room/world/body/body.js @@ -121,6 +121,7 @@ class Body { packFull() { let packet = { + form: 'body', type: this.type, class: this.class, id: this.id, @@ -140,6 +141,10 @@ class Body { return {}; } + getWorldPos(pos) { + return this.b2body.GetWorldPoint(new b2Vec2(pos.x, pos.y), {}); + } + get awake() { if (this.b2body.IsAwake()) { this.sleepTime = 0; diff --git a/server/game/room/world/body/ship.js b/server/game/room/world/body/ship.js index a6a1c9d..e349c57 100644 --- a/server/game/room/world/body/ship.js +++ b/server/game/room/world/body/ship.js @@ -58,26 +58,12 @@ class Ship extends Body { this.thrust.right = packet.thrust[2]; packet.fire.forEach((m, i) => m ? this.mounts[i].fire(m) : 0); - - if (packet.fire[0] && this.grapple) { - this.grapple.release(); - } else if (packet.fire[0] && !this.grapple) { - if (this.grapple) { - this.grapple.retract(); - } else { - this.launchGrapple(this.aim.x, this.aim.y); - } - } } launchMissile() { this.world.spawner.spawnMissile(this); } - launchGrapple(x, y) { - this.grapple = this.world.spawner.spawnGrapple(this, x, y); - } - tickType() { if (this.thrust.forward) { let power = this.power.forward; diff --git a/server/game/room/world/body/turret/blaster.js b/server/game/room/world/body/turret/blaster.js index c825caa..c666cb5 100644 --- a/server/game/room/world/body/turret/blaster.js +++ b/server/game/room/world/body/turret/blaster.js @@ -1,7 +1,7 @@ 'use strict'; const Fixture = require('./fixture.js'); -const Laser = require('./shot/laser.js'); +const Laser = require('./discharge/laser.js'); class Blaster extends Fixture { constructor(mount, data) { @@ -9,10 +9,7 @@ class Blaster extends Fixture { } fire() { - let data = { - speed: 1 - - }; + this.body.world.spawner.spawnLaser(this); } } diff --git a/server/game/room/world/body/turret/discharge/beam.js b/server/game/room/world/body/turret/discharge/beam.js new file mode 100644 index 0000000..a34f982 --- /dev/null +++ b/server/game/room/world/body/turret/discharge/beam.js @@ -0,0 +1,11 @@ +'use strict'; + +const Discharge = require('./discharge.js'); + +class Beam extends Discharge { + constructor() { + super(); + } +} + +module.exports = Beam; diff --git a/server/game/room/world/body/turret/discharge/bullet.js b/server/game/room/world/body/turret/discharge/bullet.js new file mode 100644 index 0000000..789a7ab --- /dev/null +++ b/server/game/room/world/body/turret/discharge/bullet.js @@ -0,0 +1,11 @@ +'use strict'; + +const Discharge = require('./discharge.js'); + +class Bullet extends Discharge { + constructor() { + super(); + } +} + +module.exports = Bullet; diff --git a/server/game/room/world/body/turret/discharge/discharge.js b/server/game/room/world/body/turret/discharge/discharge.js new file mode 100644 index 0000000..a07c47b --- /dev/null +++ b/server/game/room/world/body/turret/discharge/discharge.js @@ -0,0 +1,49 @@ +'use strict'; + +class Discharge { + constructor(fixture, data) { + this.x = data.x; + this.y = data.y; + this.xvel = data.xvel; + this.yvel = data.yvel; + this.r = data.r; + + this.lifetime = data.lifetime || 100; + this.fixture = fixture; + + // Might just make it this.world later if it turns out I need it more. + this.id = this.fixture.body.world.room.generateId(); + } + + destroy() { + this.fixture.body.world.removeDischarge(this); + } + + packDelta() { + // TODO: Implement some sort of delta interface for discharges that is + // derived from the fixture so it's efficient. + return [this.id, this.x, this.y]; + } + + packFull() { + // TODO: Create creation interface using fixture then send this as + // an array. + return { + form: 'discharge', + id: this.id, + x: this.x, + y: this.y, + r: this.r, + xvel: this.xvel, + yvel: this.yvel, + delta: this.packDelta() + } + } + + tick() { + if (this.lifetime-- <= 0) + this.destroy(); + } +} + +module.exports = Discharge; diff --git a/server/game/room/world/body/turret/discharge/laser.js b/server/game/room/world/body/turret/discharge/laser.js new file mode 100644 index 0000000..750adb5 --- /dev/null +++ b/server/game/room/world/body/turret/discharge/laser.js @@ -0,0 +1,11 @@ +'use strict'; + +const Discharge = require('./discharge.js'); + +class Laser extends Discharge { + constructor(fixture, data) { + super(fixture, data); + } +} + +module.exports = Laser; diff --git a/server/game/room/world/body/turret/fixture.js b/server/game/room/world/body/turret/fixture.js index 26168e8..fdabb39 100644 --- a/server/game/room/world/body/turret/fixture.js +++ b/server/game/room/world/body/turret/fixture.js @@ -11,6 +11,7 @@ class Fixture { this._angle = mount.traversal ? mount.traversal.cw : 0; this.mount = mount; + this.body = this.mount.body; } destruct() { diff --git a/server/game/room/world/body/turret/grapple.js b/server/game/room/world/body/turret/grapple.js index ea2cfbe..16c43ef 100644 --- a/server/game/room/world/body/turret/grapple.js +++ b/server/game/room/world/body/turret/grapple.js @@ -5,10 +5,20 @@ const Fixture = require('./fixture.js'); class Grapple extends Fixture { constructor(mount, data) { super(mount, data); + + this.grapple = false; } - fire() { - + fire(value) { + if (this.state == 1) { + this.grapple.release(); + this.state = 0; + } else { + let x = this.body.aim.x; + let y = this.body.aim.y; + this.state = 1; + this.grapple = this.body.world.spawner.spawnGrapple(this, x, y); + } } } diff --git a/server/game/room/world/body/turret/mount.js b/server/game/room/world/body/turret/mount.js index 89a08a1..5e275c1 100644 --- a/server/game/room/world/body/turret/mount.js +++ b/server/game/room/world/body/turret/mount.js @@ -6,13 +6,13 @@ const Grapple = require('./grapple.js'); const traits = require('../../traits/fixtures.json'); class Mount { - constructor(ship, data, fixture) { - //this.ship = ship; + constructor(body, data, fixture) { + this.body = body; this.type = data.type || 'turret'; this.size = data.size || 0; this.hidden = data.hidden || 'false'; - this.position = { + this.pos = { x: data.pos[0], y: data.pos[1] } @@ -63,8 +63,8 @@ class Mount { packFull() { return { - x: this.position.x, - y: this.position.y, + x: this.pos.x, + y: this.pos.y, hidden: this.hidden, fixture: this.fixture ? this.fixture.id : 0 }; diff --git a/server/game/room/world/body/turret/shot/beam.js b/server/game/room/world/body/turret/shot/beam.js deleted file mode 100644 index ae055de..0000000 --- a/server/game/room/world/body/turret/shot/beam.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -const Shot = require('./shot.js'); - -class Beam extends Shot { - constructor() { - super(); - } -} - -module.exports = Beam; diff --git a/server/game/room/world/body/turret/shot/bullet.js b/server/game/room/world/body/turret/shot/bullet.js deleted file mode 100644 index 0ce0886..0000000 --- a/server/game/room/world/body/turret/shot/bullet.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -const Shot = require('./shot.js'); - -class Bullet extends Shot { - constructor() { - super(); - } -} - -module.exports = Bullet; diff --git a/server/game/room/world/body/turret/shot/laser.js b/server/game/room/world/body/turret/shot/laser.js deleted file mode 100644 index b5cfd00..0000000 --- a/server/game/room/world/body/turret/shot/laser.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -const Shot = require('./shot.js'); - -class Laser extends Shot { - constructor() { - super(); - } -} - -module.exports = Laser; diff --git a/server/game/room/world/body/turret/shot/shot.js b/server/game/room/world/body/turret/shot/shot.js deleted file mode 100644 index 04f2d74..0000000 --- a/server/game/room/world/body/turret/shot/shot.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -class Shot { - constructor(pos) { - - } - - tick() { - - } -} - -module.exports = Shot; diff --git a/server/game/room/world/index.js b/server/game/room/world/index.js index 7157129..c32a7ff 100644 --- a/server/game/room/world/index.js +++ b/server/game/room/world/index.js @@ -11,6 +11,7 @@ class World { this.physics = new Physics(); this.spawner = new Spawner(this); this.bodies = new Set(); + this.discharges = new Set(); this.asteroids = new Set(); this.copulae = new Set(); this.players = new Set(); @@ -73,6 +74,11 @@ class World { projectile.connect(); } + addDischarge(discharge) { + this.discharges.add(discharge); + this.room.broadcast('create', discharge.packFull()); + } + addBody(body) { this.bodies.add(body); if (body.type == 'asteroid') this.asteroids.add(body); @@ -147,6 +153,11 @@ class World { this.room.broadcast('destroy', copula.id); } + removeDischarge(discharge) { + this.discharges.delete(discharge); + this.room.broadcast('destroy', discharge.id); + } + weld(bodyA, bodyB, point) { this.physics.weld(bodyA, bodyB, point); } @@ -162,18 +173,21 @@ class World { tick() { this.physics.step(); - let tickBodies = (set, interval, canSleep) => { + let tickBodies = (set, interval, forceInterval) => { set.forEach(body => { - if (this.tickCount % interval == 0 && body.awake) + let force = this.tickCount % forceInterval == 0; + if ((this.tickCount % interval == 0 && body.awake) || force) body.applyDelta(); body.tick(); }); }; tickBodies(this.ships, 1); - tickBodies(this.asteroids, 1); + tickBodies(this.asteroids, 1, 100); tickBodies(this.projectiles, 1); + this.discharges.forEach(d => d.tick()); + if (Date.now() - this.tpsStart > 5000) { this.tps = this.tpsCount / 5 | 0; this.tpsCount = 0; diff --git a/server/game/room/world/spawner.js b/server/game/room/world/spawner.js index 1b1911f..d85d0c2 100644 --- a/server/game/room/world/spawner.js +++ b/server/game/room/world/spawner.js @@ -3,7 +3,7 @@ const Asteroid = require('./body/asteroid.js'); const Grapple = require('./body/projectile/grapple.js'); const Missile = require('./body/projectile/missile.js'); -const Laser = require('./body/turret/shot/laser.js'); +const Laser = require('./body/turret/discharge/laser.js'); class Spawner { constructor(world) { @@ -35,38 +35,46 @@ class Spawner { return missile; } - spawnGrapple(ship, x, y) { - let sx = ship.center.x; - let sy = ship.center.y; - let dx = x - sx; - let dy = y - sy; + spawnGrapple(fixture, x, y) { + let fixturePos = fixture.body.getWorldPos(fixture.mount.pos); + let fx = fixturePos.x; + let fy = fixturePos.y; + let dx = x - fx; + let dy = y - fy; let a = Math.atan2(dy, dx); let pos = { - x: sx + Math.cos(a) * 1, - y: sy + Math.sin(a) * 1, + x: fx + Math.cos(a) * 1, + y: fy + Math.sin(a) * 1, r: a, - xvel: ship.vel.x, - yvel: ship.vel.y + xvel: fixture.body.vel.x, + yvel: fixture.body.vel.y }; - let grapple = new Grapple(this.world, pos, ship); + let grapple = new Grapple(this.world, pos, fixture.body); this.world.addProjectile(grapple); return grapple; } - spawnLaser(ship) { - let r = ship.pos.r; - let ox = Math.cos(r) * 0.7; - let oy = Math.sin(r) * 0.7; - let pos = { - x: ship.center.x + ox, - y: ship.center.y + oy, - r: r, - xvel: ship.vel.x, - yvel: ship.vel.y + spawnLaser(fixture) { + let r = fixture.angle; + let a = fixture.body.pos.r + fixture.angle; + let fixturePos = fixture.mount.pos; + let f = { + x: fixturePos.x + Math.cos(r) * 0.3, + y: fixturePos.y + Math.sin(r) * 0.3 }; - let missile = new Missile(this.world, pos, ship); - this.world.addProjectile(missile); - return missile; + let vx = Math.cos(a) * 0.5; + let vy = Math.sin(a) * 0.5; + let spawnPos = fixture.body.getWorldPos(f); + let pos = { + x: spawnPos.x, + y: spawnPos.y, + r: r, + xvel: fixture.body.vel.x + vx, + yvel: fixture.body.vel.y + vy + }; + let laser = new Laser(fixture, pos); + this.world.addDischarge(laser); + return laser; } } diff --git a/server/game/room/world/traits/ships.json b/server/game/room/world/traits/ships.json index e4255af..bc899f6 100644 --- a/server/game/room/world/traits/ships.json +++ b/server/game/room/world/traits/ships.json @@ -19,21 +19,21 @@ ], "mounts": [ { - "pos": [18, 4], + "pos": [0.5625, 0.125], "type": "fixed", "size": 0, "traversal": [0, 0], "hidden": true }, { - "pos": [18, 28], + "pos": [0.5625, 0.875], "type": "fixed", "size": 0, "traversal": [0, 0], "hidden": true }, { - "pos": [6, 16], + "pos": [0.1875, 0.5], "type": "fixed", "size": 1, "traversal": [3.14, 0],