From 663305bd23ea8da07fc91fa9a85f0a970283f9e3 Mon Sep 17 00:00:00 2001 From: Asraelite Date: Sun, 27 Mar 2016 02:22:49 +0100 Subject: [PATCH] improve grappling hook physics and rendering --- public/js/wingbase/render/effect.js | 38 ++++++++- public/js/wingbase/render/ships.js | 4 + public/js/wingbase/world/physics.js | 3 +- public/js/wingbase/world/ship.js | 2 + server/game/room/world/body/body.js | 8 ++ .../room/world/body/projectile/grapple.js | 23 +++--- server/game/room/world/body/ship.js | 2 +- server/game/room/world/copula/rope.js | 16 +++- server/game/room/world/index.js | 6 +- server/game/room/world/physics.js | 80 +++++++++++-------- server/game/room/world/traits/ships.json | 2 +- 11 files changed, 129 insertions(+), 55 deletions(-) diff --git a/public/js/wingbase/render/effect.js b/public/js/wingbase/render/effect.js index fc2fc05..b1d68d6 100644 --- a/public/js/wingbase/render/effect.js +++ b/public/js/wingbase/render/effect.js @@ -4,14 +4,17 @@ class Effect { this[i] = data[i]; } - this.pos.x; - this.pos.y; - this.particles = new Set(); this.pallet = game.renderer.pallet; if (this.type == 'explosion') { this.createExplosion(); + } else if (this.type == 'rope') { + this.createRope(); + this.pos = { + x: 0, + y: 0 + }; } else { } @@ -44,10 +47,29 @@ class Effect { p.tick(); }); - if (this.particles.size == 0) { + if (this.particles.size == 0 && !this.keepAlive) { game.renderer.effects.delete(this); } + rope: if (this.type == 'rope') { + let bd = game.world.bodies; + if (!bd[this.bodyA.id] || !bd[this.bodyB.id]) { + this.keepAlive = false; + break rope; + } + let p1 = this.posA; + let p2 = this.posB; + let posA = this.bodyA.b2body.GetWorldPoint(new b2Vec2(p1.x, p1.y)); + let posB = this.bodyB.b2body.GetWorldPoint(new b2Vec2(p2.x, p2.y)); + let context = this.pallet.context; + context.beginPath(); + context.moveTo(posA.x * SCALE, posA.y * SCALE); + context.lineTo(posB.x * SCALE, posB.y * SCALE); + context.strokeStyle = '#555'; + context.stroke(); + + } + this.pallet.restore(); } @@ -59,4 +81,12 @@ class Effect { let b = 'sizzle'; this.generateParticles(0, 0, 1, num, colors, [1, 2], b, 50, 3); } + + createRope() { + this.bodyA = game.world.bodies[this.bodyA]; + this.bodyB = game.world.bodies[this.bodyB]; + if (!this.bodyA || !this.bodyB) return; + this.keepAlive = true; + + } } diff --git a/public/js/wingbase/render/ships.js b/public/js/wingbase/render/ships.js index c4115c1..8b9bb61 100644 --- a/public/js/wingbase/render/ships.js +++ b/public/js/wingbase/render/ships.js @@ -25,6 +25,10 @@ Renderer.prototype.renderShip = (pallet, ship) => { pallet.image(img, 0, 0, 0); pallet.image(ship.thrust.forward ? thr8 : thr0, 0, 0, 0); + if (ship.debug) { + pallet.square('#f00', ship.debug.x * SCALE, ship.debug.y * SCALE, 2); + } + pallet.restore(); //pallet.text(ship.name, x + vx | 0, y + vy | 0, '#fff', 'FreePixel', 16, 'center', 'bottom'); diff --git a/public/js/wingbase/world/physics.js b/public/js/wingbase/world/physics.js index 42a3fce..001f7ef 100644 --- a/public/js/wingbase/world/physics.js +++ b/public/js/wingbase/world/physics.js @@ -28,7 +28,7 @@ class Physics { bodyDef.angularVelocity = 0; bodyDef.bullet = body.type == 'missile'; bodyDef.linearDamping = body.bodyType == 'asteroid' ? 0.003 : 0.01; - bodyDef.angularDamping = body.bodyType == 'asteroid' ? 0.003 : 0.01; + bodyDef.angularDamping = body.bodyType == 'asteroid' ? 0.003 : 0.04; bodyDef.type = body.bodyType == 'structure' ? b2Body.b2_staticBody : b2Body.b2_dynamicBody; bodyDef.allowSleep = false; @@ -76,6 +76,7 @@ class Physics { var r = 0.1; var body = game.world.bodies[i]; var pos = body.getPos(); + if (Math.abs(body.r - pos.r) > 0.3) pos.r = body.r; var x = (body.x * r + pos.x) / (r + 1); var y = (body.y * r + pos.y) / (r + 1); var r = (body.r * r + pos.r) / (r + 1); diff --git a/public/js/wingbase/world/ship.js b/public/js/wingbase/world/ship.js index aad32bf..3600073 100644 --- a/public/js/wingbase/world/ship.js +++ b/public/js/wingbase/world/ship.js @@ -22,6 +22,8 @@ class Ship extends Body { this.thrust = { forward: data[6] } + + this.debug = data[9]; } tick() { diff --git a/server/game/room/world/body/body.js b/server/game/room/world/body/body.js index a57f3bf..8300d30 100644 --- a/server/game/room/world/body/body.js +++ b/server/game/room/world/body/body.js @@ -36,6 +36,14 @@ class Body { this.b2body.ApplyTorque(f); } + setRotation(r) { + this.b2body.SetAngleRadians(r); + } + + setVelocity(x, y) { + this.b2body.SetLinearVelocity(new b2Vec2(x, y)); + } + contact() { } diff --git a/server/game/room/world/body/projectile/grapple.js b/server/game/room/world/body/projectile/grapple.js index 2f38ea0..e05ee88 100644 --- a/server/game/room/world/body/projectile/grapple.js +++ b/server/game/room/world/body/projectile/grapple.js @@ -12,8 +12,8 @@ class Grapple extends Projectile { this.xvel = pos.xvel; this.yvel = pos.yvel; this.r = pos.r; - this.xvel += Math.cos(this.r) * 0.4; - this.yvel += Math.sin(this.r) * 0.4; + this.xvel += Math.cos(this.r) * 0.25; + this.yvel += Math.sin(this.r) * 0.25; this.welded = false; @@ -22,8 +22,8 @@ class Grapple extends Projectile { this.type = 'grapple'; this.frame = [ - [[0, -8], [5, -12], [4, 0], [0, 0]], - [[0, 0], [4, 0], [5, 12], [0, 8]] + [[0, -8], [5, -12], [2, 0], [0, 0]], + [[0, 0], [2, 0], [5, 12], [0, 8]] ]; } @@ -39,24 +39,25 @@ class Grapple extends Projectile { connect() { let p1 = { x: 0, y: 0.5 }; - let p2 = { x: 4, y: 0 }; + let p2 = { x: 0.0625, y: 0 }; this.rope = new Rope(this.player.ship, this, p1, p2); + this.rope.initLength = 6; this.world.addCopula(this.rope); - this.rope.length = 5; } contact(body, contact) { if (this.welded || body == this.source) return; - this.welded = true; - let normal = this.world.physics.contactData(contact).normal; + let normal = this.world.physics.contactData(contact).worldNormal; let angle = Math.atan2(normal.y, normal.x); - this.b2body.SetAngleRadians(angle); - this.world.weld(this, body); + this.setRotation(angle + Math.PI); + this.b2body.SetAngularVelocity(0); + this.setVelocity(0, 0); + this.world.weld(this, body, { x: 0.15625, y: 0 }); + this.welded = true; } tickType() { - } packTypeDelta() { diff --git a/server/game/room/world/body/ship.js b/server/game/room/world/body/ship.js index 1782810..19b8789 100644 --- a/server/game/room/world/body/ship.js +++ b/server/game/room/world/body/ship.js @@ -89,7 +89,7 @@ class Ship extends Body { packTypeDelta() { let t = this.thrust; - return [t.forward, t.left, t.right]; + return [t.forward, t.left, t.right, this.debug || false]; } packFull() { diff --git a/server/game/room/world/copula/rope.js b/server/game/room/world/copula/rope.js index 79a3ca6..a884150 100644 --- a/server/game/room/world/copula/rope.js +++ b/server/game/room/world/copula/rope.js @@ -9,11 +9,23 @@ class Rope extends Copula { } get length() { - return this.b2joint.GetMaxLength(); + //return this.b2joint.GetMaxLength(); + return 8; } set length(len) { - this.b2joint.SetMaxLength(len); + //this.b2joint.SetMaxLength(len); + } + + packFull() { + return { + type: 'rope', + length: this.length, + bodyA: this.bodyA.id, + bodyB: this.bodyB.id, + posA: this.pointA, + posB: this.pointB + }; } } diff --git a/server/game/room/world/index.js b/server/game/room/world/index.js index c473dca..06a02af 100644 --- a/server/game/room/world/index.js +++ b/server/game/room/world/index.js @@ -82,7 +82,7 @@ class World { addCopula(copula) { this.copulae.add(copula); this.physics.createCopula(copula); - this.room.broadcast('create', copula.packFull()); + this.room.broadcast('effect', copula.packFull()); } applyDelta(body, data) { @@ -138,8 +138,8 @@ class World { this.room.broadcast('destroy', copula.id); } - weld(bodyA, bodyB) { - this.physics.weld(bodyA, bodyB); + weld(bodyA, bodyB, point) { + this.physics.weld(bodyA, bodyB, point); } start() { diff --git a/server/game/room/world/physics.js b/server/game/room/world/physics.js index 76b13b3..b2e2113 100644 --- a/server/game/room/world/physics.js +++ b/server/game/room/world/physics.js @@ -21,20 +21,14 @@ class Physics { this.world = new Box2D.b2World(new b2Vec2(0, 0), false); this.toRemove = []; this.toWeld = []; + this.contacts = []; + this.idk = false; let onContact = contact => { let bodya = contact.GetFixtureA().GetBody().GetUserData(); let bodyb = contact.GetFixtureB().GetBody().GetUserData(); - if (bodya) { - bodya.applyDelta(); - bodya.contact(bodyb. contact); - } - - if (bodyb) { - bodyb.applyDelta(); - bodyb.contact(bodya, contact); - } + this.contacts.push([bodya, bodyb, contact]); } let listener = new Box2D.b2ContactListener(); @@ -58,7 +52,7 @@ class Physics { bodyDef.angularVelocity = body.rvel || 0; bodyDef.bullet = body.type == 'missile'; bodyDef.linearDamping = body.type == 'asteroid' ? 0.003 : 0.01; - bodyDef.angularDamping = body.type == 'asteroid' ? 0.003 : 0.01; + bodyDef.angularDamping = body.type == 'asteroid' ? 0.003 : 0.04; bodyDef.type = body.type == 'structure' ? Box2D.b2BodyType.b2_staticBody : Box2D.b2BodyType.b2_dynamicBody; if (body.player || true) bodyDef.allowSleep = false; @@ -83,14 +77,18 @@ class Physics { // TODO: Make this shorter somehow. createCopula(copula) { + let s = SCALE; + if (copula.type == 'rope') { let b1 = copula.bodyA.b2body; let b2 = copula.bodyB.b2body; - let p1 = copula.pointA; - let p2 = copula.pointB; + let p1 = new b2Vec2(copula.pointA.x, copula.pointA.y); + let p2 = new b2Vec2(copula.pointB.x, copula.pointB.y); // See top of file. - let start = b1.GetWorldPoint(new b2Vec2(p1.x, p1.y), {}); - let end = b2.GetWorldPoint(new b2Vec2(p2.x, p2.y), {}); + let start = b1.GetWorldPoint(p1, {}); + let end = b2.GetWorldPoint(p2, {}); + copula.bodyA.debug = p1; + //copula.bodyB.debug = end; let dx = start.x - end.x let dy = start.y - end.y; let len = Math.sqrt(dx * dx + dy * dy); @@ -98,10 +96,10 @@ class Physics { let ropeDef = new Box2D.b2RopeJointDef(); ropeDef.bodyA = b1; ropeDef.bodyB = b2; - ropeDef.maxLength = len; + ropeDef.maxLength = copula.initLength || len; ropeDef.collideConnected = true; - ropeDef.worldAnchorA = new b2Vec2(start); - ropeDef.worldAnchorB = new b2Vec2(end); + ropeDef.localAnchorA = p1; + ropeDef.localAnchorB = p2; let b2joint = this.world.CreateJoint(ropeDef); copula.b2joint = b2joint; @@ -109,17 +107,28 @@ class Physics { } - weld(bodyA, bodyB) { - this.toWeld.push([bodyA, bodyB]); + weld(bodyA, bodyB, point) { + let b1 = bodyA.b2body; + let b2 = bodyB.b2body; + let jointDef = new Box2D.b2WeldJointDef(); + let anchor = b1.GetWorldPoint(new b2Vec2(point.x, point.y), {}); + jointDef.bodyA = b1; + jointDef.bodyB = b2; + jointDef.collideConnected = true; + jointDef.localAnchorA = b1.GetLocalPoint(anchor, {}); + jointDef.localAnchorB = b2.GetLocalPoint(anchor, {}); + jointDef.localAnchorA = new b2Vec2(jointDef.localAnchorA.x, jointDef.localAnchorA.y); + jointDef.localAnchorB = new b2Vec2(jointDef.localAnchorB.x, jointDef.localAnchorB.y); + jointDef.referenceAngle = b2.GetAngleRadians() - b1.GetAngleRadians(); + this.world.CreateJoint(jointDef); } contactData(contact) { let worldManifold = new Box2D.b2WorldManifold(); contact.GetWorldManifold(worldManifold); - let localManifold = new Box2D.b2WorldManifold(); - contact.GetManifold(localManifold); + let localManifold = contact.GetManifold(); let worldNormal = worldManifold.normal; - let normal = localManifold.normal; + let normal = localManifold.localNormal; return { normal: normal, @@ -167,18 +176,25 @@ class Physics { this.world.DestroyBody(this.toRemove[i].b2body); } - for (var i = 0; i < this.toWeld.length; i++) { - let b1 = this.toWeld[i][0].b2body; - let b2 = this.toWeld[i][1].b2body; - let jointDef = new Box2D.b2WeldJointDef(); - jointDef.bodyA = b1; - jointDef.bodyB = b2; - //jointDef.referenceAngle = b1.GetAngleRadians() - b2.GetAngleRadians(); - this.world.CreateJoint(jointDef); + this.toRemove = []; + + for (var i = 0; i < this.contacts.length; i++) { + let contact = this.contacts[i][2]; + let bodya = this.contacts[i][0]; + let bodyb = this.contacts[i][1]; + + if (bodya) { + bodya.applyDelta(); + bodya.contact(bodyb, contact); + } + + if (bodyb) { + bodyb.applyDelta(); + bodyb.contact(bodya, contact); + } } - this.toRemove = []; - this.toWeld = []; + this.contacts = []; } } diff --git a/server/game/room/world/traits/ships.json b/server/game/room/world/traits/ships.json index 88a005a..bbb5093 100644 --- a/server/game/room/world/traits/ships.json +++ b/server/game/room/world/traits/ships.json @@ -5,7 +5,7 @@ "power": { "forward": 0.015, "back": 0, - "rotation": 0.001 + "rotation": 0.003 }, "hull": [ [