diff --git a/public/js/starbugs/net.js b/public/js/starbugs/net.js index 402e9dd..1de6a50 100644 --- a/public/js/starbugs/net.js +++ b/public/js/starbugs/net.js @@ -16,11 +16,16 @@ function Net() { this.socket.on('update', function(data) { game.world.update(data); + window.q = data; }); this.socket.on('world', function(data) { game.world.clear(); - game.world.playerShipId = data; + console.log(data); + game.world.playerShipId = data.playerShipId; + for (var i in data.bodies) { + game.world.add(data.bodies[i]); + } }); }; @@ -31,4 +36,8 @@ function Net() { right: move[2] }); } + + this.send = function(msg, data) { + this.socket.emit(msg, data); + } } diff --git a/public/js/starbugs/render/asteroids.js b/public/js/starbugs/render/asteroids.js new file mode 100644 index 0000000..f37470e --- /dev/null +++ b/public/js/starbugs/render/asteroids.js @@ -0,0 +1,22 @@ +function renderAsteroid(pallet, body) { + var pos = body.getPos(); + var x = pos.x * SCALE; + var y = pos.y * SCALE; + var vx = -game.world.getCenter().x; + var vy = -game.world.getCenter().y; + + pallet.view(x + vx, y + vy, false, body.r); + + var context = pallet.context; + var points = body.frame[0]; + context.beginPath(); + context.moveTo(points[0][0], points[0][1]); + for (var i = 1; i < points.length; i++) { + context.lineTo(points[i][0], points[i][1]); + } + context.closePath(); + context.strokeStyle = '#fff'; + context.stroke(); + + pallet.restore(); +} diff --git a/public/js/starbugs/render/render.js b/public/js/starbugs/render/render.js index fee5e5f..f2273c6 100644 --- a/public/js/starbugs/render/render.js +++ b/public/js/starbugs/render/render.js @@ -51,6 +51,8 @@ function Renderer() { if (body.bodyType == 'ship') { renderShip(pallet, body); + } else if (body.bodyType == 'asteroid') { + renderAsteroid(pallet, body); } else { pallet.rect('#338', body.x, body.y, 10, 10); } diff --git a/public/js/starbugs/render/ships.js b/public/js/starbugs/render/ships.js index 84101ac..c1c524e 100644 --- a/public/js/starbugs/render/ships.js +++ b/public/js/starbugs/render/ships.js @@ -6,8 +6,8 @@ function renderShip(pallet, ship) { var thr8 = game.assets.images.ships[ship.hull].thrust8; //pallet.view(ship.x, ship.y, false, ship.r); var pos = ship.getPos(); - var x = pos.x + 16; - var y = pos.y + 16; + var x = pos.x; + var y = pos.y; var vx = -game.world.getCenter().x; var vy = -game.world.getCenter().y; diff --git a/public/js/starbugs/world/Untitled Document b/public/js/starbugs/world/Untitled Document deleted file mode 100644 index 4d33b2c..0000000 --- a/public/js/starbugs/world/Untitled Document +++ /dev/null @@ -1,3 +0,0 @@ -function Body() { - -} diff --git a/public/js/starbugs/world/asteroid.js b/public/js/starbugs/world/asteroid.js new file mode 100644 index 0000000..68d1729 --- /dev/null +++ b/public/js/starbugs/world/asteroid.js @@ -0,0 +1,21 @@ +function Asteroid(data) { + this.id = data.id; + this.x = data.delta[0]; + this.y = data.delta[1]; + this.r = data.delta[2]; + this.bodyType = 'asteroid'; + this.frame = data.frame; + + this.getPos = function() { + return { + x: this.x, + y: this.y + }; + } + + this.update = function(data) { + this.x = data[0]; + this.y = data[1]; + this.r = data[4]; + } +} diff --git a/public/js/starbugs/world/ship.js b/public/js/starbugs/world/ship.js index e991133..a9024fe 100644 --- a/public/js/starbugs/world/ship.js +++ b/public/js/starbugs/world/ship.js @@ -1,8 +1,11 @@ -function Ship(id) { - this.id = id; - this.x = 0; - this.y = 0; - this.r = 0; +function Ship(data) { + this.id = data.id; + this.x = data.delta[0]; + this.y = data.delta[1]; + this.r = data.delta[4]; + this.xvel = data.delta[2]; + this.yvel = data.delta[3]; + this.rvel = data.delta[5]; this.hull = '01'; this.move = []; this.lastMove = []; @@ -21,6 +24,14 @@ function Ship(id) { } } + this.update = function (data) { + this.x = data[0]; + this.y = data[1]; + this.xvel = data[2]; + this.yvel = data[3]; + this.r = data[4]; + } + this.updateMove = function() { if (JSON.stringify(this.move) != JSON.stringify(this.lastMove) || true) { game.net.update(this.move); diff --git a/public/js/starbugs/world/world.js b/public/js/starbugs/world/world.js index 53aff9a..0d5bbdc 100644 --- a/public/js/starbugs/world/world.js +++ b/public/js/starbugs/world/world.js @@ -22,6 +22,19 @@ function World() { return { x: x, y: y }; } + this.add = function(data) { + var body; + if (data.type == 'asteroid') body = new Asteroid(data); + if (data.type == 'ship') body = new Ship(data); + if (data.type == 'structure') body = new Structure(data); + + this.bodies[body.id] = body; + } + + this.remove = function(id) { + delete this.bodies[id]; + } + this.clear = function() { this.bodies = {}; this.playerShip = false; @@ -32,15 +45,14 @@ function World() { for (var id in data) { if (!this.bodies[id]) { - this.bodies[id] = new Ship(id); + game.net.send('requestBodyData', id); + continue; } var body = this.bodies[id]; - body.x = data[id][0]; - body.y = data[id][1]; - body.r = data[id][2]; - + body.update(data[id]); + if (data[id].destroy) delete this.bodies[id]; } } } diff --git a/server/game/player.js b/server/game/player.js index 5b1bbd4..69d8627 100644 --- a/server/game/player.js +++ b/server/game/player.js @@ -25,8 +25,8 @@ class Player { }); } - sendWorld() { - this.connection.send('world', this.ship.id); + sendWorld(data) { + this.connection.send('world', data); } sendUpdate() { diff --git a/server/game/room/index.js b/server/game/room/index.js index 8136588..fdac584 100644 --- a/server/game/room/index.js +++ b/server/game/room/index.js @@ -20,7 +20,7 @@ class Room { this.players.add(player); this.setTeam(player, this.teamA.size > this.teamB.size ? 'b' : 'a'); this.world.addPlayer(player); - player.sendWorld(); + this.sendWorld(player); } remove(player) { @@ -42,7 +42,17 @@ class Room { self.players.forEach(player => player.sendUpdate()); } + sendWorld(player) { + let data = { + playerShipId: player.ship.id, + bodies: Array.from(this.world.bodies).map(b => b.packFull()) + }; + + player.sendWorld(data); + } + start() { + this.world.populate(); this.world.start(); this.interval = setInterval(_ => this.update(this), 1 / 60); } diff --git a/server/game/room/world/asteroid.js b/server/game/room/world/asteroid.js index e69de29..a724f0b 100644 --- a/server/game/room/world/asteroid.js +++ b/server/game/room/world/asteroid.js @@ -0,0 +1,39 @@ +'use strict'; + +const Body = require('./body.js'); + +class Asteroid extends Body { + constructor(world, pos, size) { + super(world); + + this.x = pos.x; + this.y = pos.y; + this.type = 'asteroid'; + + this.size = size; + this.frame = this.randomFrame(); + } + + randomFrame() { + let s = this.size; + let l = (Math.random() * 4 + 4) | 0; + let build = Array(l).fill().map(_ => Math.random() * Math.PI * 2); + build = build.sort().map(a => [Math.cos(a) * s, Math.sin(a) * s]); + return [build]; + } + + packTypeDelta() { + return []; + } + + packFull() { + return { + type: 'asteroid', + id: this.id, + frame: this.frame, + delta: this.packDelta() + } + } +} + +module.exports = Asteroid; diff --git a/server/game/room/world/body.js b/server/game/room/world/body.js index 9bd21ba..5a7efab 100644 --- a/server/game/room/world/body.js +++ b/server/game/room/world/body.js @@ -10,14 +10,14 @@ class Body { this.y = 0; this.r = 0; this.b2body = false; - this.type = 'dynamic'; + this.type = 'asteroid'; this.health = 1; this.world = world; this.id = uuid.v4().slice(0, 8); } applyDelta() { - this.world.applyDelta(this.id, this.pack()); + this.world.applyDelta(this.id, this.packDelta()); } applyForce(x, y, center) { @@ -29,11 +29,22 @@ class Body { this.b2body.ApplyTorque(f); } - pack() { + packDelta() { let pos = this.b2body.GetPosition(); + let vel = this.b2body.GetLinearVelocity(); let rot = this.b2body.GetAngleRadians(); + let rvel = this.b2body.GetAngularVelocity(); - return [pos.x, pos.y, rot]; + // Simple array to save bandwidth. + return [pos.x, pos.y, vel.x, vel.y, rot, rvel].concat(this.packTypeDelta()); + } + + packTypeDelta() { + throw new Error('Attempt to pack raw body.'); + } + + packFull() { + throw new Error('Attempt to pack raw body.'); } } diff --git a/server/game/room/world/index.js b/server/game/room/world/index.js index fe77e38..66ca51e 100644 --- a/server/game/room/world/index.js +++ b/server/game/room/world/index.js @@ -1,5 +1,6 @@ 'use strict'; +const Asteroid = require('./asteroid.js'); const Physics = require('./physics.js'); const Ship = require('./ship.js'); @@ -15,17 +16,42 @@ class World { addPlayer(player) { this.players.add(player); - let ship = new Ship(this, player); + let pos = { + x: player.team == 'b' ? 200 : 0, + y: 0 + }; + let ship = new Ship(this, pos, player); player.ship = ship; - this.ships.set(player, ship); + this.addShip(ship); + } + + addShip(ship) { + this.ships.set(ship.player, ship); this.bodies.add(ship); this.physics.createBody(ship); } + addAsteroid(asteroid) { + this.asteroids.add(asteroid); + this.bodies.add(asteroid); + this.physics.createBody(asteroid); + } + applyDelta(body, data) { this.players.forEach(player => player.delta[body] = data); } + populate() { + for (var i = 0; i < 20; i++) { + let pos = { + x: Math.random() * 2000 - 200, + y: Math.random() * 500 - 250 + }; + let asteroid = new Asteroid(this, pos, Math.random() * 50 + 10); + this.addAsteroid(asteroid); + } + } + removePlayer(player) { this.removeBody(player.ship); this.ships.delete(player); diff --git a/server/game/room/world/physics.js b/server/game/room/world/physics.js index ae6ba26..b0b0c5d 100644 --- a/server/game/room/world/physics.js +++ b/server/game/room/world/physics.js @@ -10,13 +10,31 @@ const Box2D = require('box2d-html5'); const b2Vec2 = Box2D.b2Vec2; +Box2D.b2Settings.b2_linearSleepTolerance = 0.0002; + class Physics { constructor() { this.world = new Box2D.b2World(new b2Vec2(0, 0), false); this.toRemove = []; + + let onContact = contact => { + let bodya = contact.GetFixtureA().GetBody().GetUserData(); + let bodyb = contact.GetFixtureB().GetBody().GetUserData(); + + bodya.applyDelta(); + bodyb.applyDelta(); + } + + let listener = new Box2D.b2ContactListener(); + listener.BeginContact = onContact; + listener.EndContact = onContact; + + this.world.SetContactListener(listener); } createBody(body) { + //console.log(Object.keys(Box2D.b2Settings).sort()); + //console.log(Box2D.b2Settings.b2_linearSleepTolerance = 0.002); let s = SCALE; let bodyDef = new Box2D.b2BodyDef(); bodyDef.userData = body; @@ -25,19 +43,19 @@ class Physics { bodyDef.active = true; bodyDef.linearVelocity = new b2Vec2(body.xvel / s || 0, body.yvel / s || 0); bodyDef.angularVelocity = body.rvel || 0; - bodyDef.linearDamping = 0.001; - bodyDef.angularDamping = 0.001; - bodyDef.type = body.type == 'static' ? + bodyDef.linearDamping = body.type == 'ship' ? 0.001 : 0.0003; + bodyDef.angularDamping = body.type == 'ship' ? 0.001 : 0.0003; + bodyDef.type = body.type == 'structure' ? Box2D.b2BodyType.b2_staticBody : Box2D.b2BodyType.b2_dynamicBody; - if (body.player) bodyDef.allowSleep = false; + if (body.player || true) bodyDef.allowSleep = false; let b2body = this.world.CreateBody(bodyDef); let fixtureDef = new Box2D.b2FixtureDef(); fixtureDef.density = 10; fixtureDef.friction = 1; - fixtureDef.restitution = 0; + fixtureDef.restitution = 1; - for (var poly of body.structure) { + for (var poly of body.frame) { poly = poly.map(vertex => new b2Vec2(vertex[0] / s, vertex[1] / s)); fixtureDef.shape = new Box2D.b2PolygonShape(); fixtureDef.shape.SetAsArray(poly, poly.length); @@ -45,6 +63,7 @@ class Physics { } body.b2body = b2body; + //console.log(Object.keys(b2body).sort()); } step() { diff --git a/server/game/room/world/ship.js b/server/game/room/world/ship.js index 43b4eca..7eb458b 100644 --- a/server/game/room/world/ship.js +++ b/server/game/room/world/ship.js @@ -6,12 +6,21 @@ const hulls = require('./traits/hulls.json'); const Body = require('./body.js'); class Ship extends Body { - constructor(world, player, build) { + constructor(world, pos, player, build) { super(world); this.build = build || defaults.spawnShip.build; this.player = player; - this.structure = hulls[this.build.hull]; + this.frame = hulls[this.build.hull]; + this.type = 'ship'; + + this.thrust = { + forward: 0, + left: 0, + right: 0 + } + + this.power = this.build.power; } move(data) { @@ -25,20 +34,36 @@ class Ship extends Body { } if (data.forward) { - let power = 0.002; + let power = this.power.forward; let x = Math.cos(this.b2body.GetAngleRadians()) * power; let y = Math.sin(this.b2body.GetAngleRadians()) * power; this.applyForce(x, y); } if (data.left) { - this.applyTorque(-0.0001); + this.applyTorque(-this.power.rotation); } if (data.right) { - this.applyTorque(0.0001); + this.applyTorque(this.power.rotation); } } + + packTypeDelta() { + let t = this.thrust; + + return [t.forward, t.left, t.right]; + } + + packFull() { + return { + type: 'ship', + id: this.id, + team: this.player.team, + build: this.build, + delta: this.packDelta() + }; + } } module.exports = Ship; diff --git a/server/game/room/world/fixture.js b/server/game/room/world/structure.js similarity index 100% rename from server/game/room/world/fixture.js rename to server/game/room/world/structure.js diff --git a/server/game/room/world/traits/defaults.json b/server/game/room/world/traits/defaults.json index 00e3d96..2584ea2 100644 --- a/server/game/room/world/traits/defaults.json +++ b/server/game/room/world/traits/defaults.json @@ -2,7 +2,12 @@ "spawnShip": { "build": { "hull": "01", - "turrets": [0] + "turrets": [0], + "power": { + "forward": 0.0015, + "back": 0, + "rotation": 0.0001 + } } } }