add start of grappling hook

This commit is contained in:
Asraelite 2016-03-26 20:23:05 +00:00
parent ff0ac094cf
commit 4753f879e5
14 changed files with 192 additions and 69 deletions

View file

@ -4,7 +4,17 @@ class Input {
x: 0,
y: 0,
held: {},
pressed: {}
pressed: {},
get wx() {
let x = this.x + game.world.center.x;
return (x - game.renderer.canvas.width / 2) / SCALE;
},
get wy() {
let y = this.y + game.world.center.y;
return (y - game.renderer.canvas.height / 2) / SCALE;
}
};
this.keys = {
@ -12,11 +22,15 @@ class Input {
pressed: {}
};
this.mouse
document.addEventListener('mousemove', this.mouseMove.bind(this));
document.addEventListener('mousedown', this.mouseDown.bind(this));
document.addEventListener('mouseup', this.mouseUp.bind(this));
document.addEventListener('keydown', this.keyDown.bind(this));
document.addEventListener('keyup', this.keyUp.bind(this));
document.addEventListener('contextmenu', e => e.preventDefault());
}
mouseMove() {

View file

@ -12,6 +12,10 @@ class Player {
let inputs = [87, 65, 68];
inputs = inputs.map(k => game.input.keys.held[k] || false);
inputs[3] = game.input.keys.pressed[32] || false;
inputs[4] = game.input.mouse.wx;
inputs[5] = game.input.mouse.wy;
inputs[6] = game.input.mouse.held[3];
inputs[7] = game.input.mouse.pressed[1];
let delta = this.lastInputs == inputs ? false : inputs;
this.lastInputs = inputs;
return delta;

View file

@ -8,18 +8,20 @@ Renderer.prototype.renderBody = (pallet, body) => {
pallet.view(x + vx, y + vy, false, pos.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]);
var polys = body.frame;
for (var points of polys) {
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.lineWidth = 0.5;
context.strokeStyle = '#fff';
context.fillStyle = '#200';
context.fill();
context.stroke();
}
context.closePath();
context.lineWidth = 0.5;
context.strokeStyle = '#fff';
context.fillStyle = '#200';
context.fill();
context.stroke();
pallet.restore();
};

View file

@ -54,4 +54,8 @@ class Body {
updateType() {
}
tick() {
}
}

View file

@ -14,21 +14,9 @@ class World {
}
}
// Deprecated
getCenter() {
if (!this.playerShip) return { x: 0, y: 0 };
var x = this.playerShip.getPos().x * SCALE;
var y = this.playerShip.getPos().y * SCALE;
var comx = this.playerShip.com.x * SCALE;
var comy = this.playerShip.com.y * SCALE;
var r = this.playerShip.getPos().r;
var d = Math.sqrt(comx * comx + comy * comy);
var a = Math.atan2(comy, comx);
x += Math.cos(a + r) * d;
y += Math.sin(a + r) * d;
return { x: x, y: y };
return this.center;
};
add(data) {
@ -37,6 +25,7 @@ class World {
if (data.type == 'ship') body = new Ship(data);
if (data.type == 'structure') body = new Structure(data);
if (data.type == 'missile') body = new Missile(data);
if (!body) body = new Body(data);
this.bodies[body.id] = body;
this.physics.createBody(body);
@ -80,4 +69,21 @@ class World {
this.bodies[i].tick();
}
};
get center() {
if (!this.playerShip) return { x: 0, y: 0 };
let x = this.playerShip.getPos().x * SCALE;
let y = this.playerShip.getPos().y * SCALE;
let comx = this.playerShip.com.x * SCALE;
let comy = this.playerShip.com.y * SCALE;
let r = this.playerShip.getPos().r;
let d = Math.sqrt(comx * comx + comy * comy);
let a = Math.atan2(comy, comx);
x += Math.cos(a + r) * d;
y += Math.sin(a + r) * d;
return { x: x, y: y };
}
}

View file

@ -65,9 +65,15 @@ class Body {
}
packTypeDelta() {
return [];
}
packFull() {
return {
type: 'body',
id: this.id,
delta: this.packDelta()
}
}
get com() {

View file

@ -1,7 +1,7 @@
'use strict';
const Projectile = require('./projectile.js');
const Rope = require('../copula/rope.js');
const Rope = require('../../copula/rope.js');
class Grapple extends Projectile {
constructor(world, pos, source) {
@ -12,12 +12,13 @@ class Grapple extends Projectile {
this.xvel = pos.xvel;
this.yvel = pos.yvel;
this.r = pos.r;
this.xvel += Math.cos(this.r) * 0.2;
this.yvel += Math.sin(this.r) * 0.2;
this.xvel += Math.cos(this.r) * 0.4;
this.yvel += Math.sin(this.r) * 0.4;
this.welded = false;
this.source = source;
this.player = source.player;
this.rope = new Rope(this, this);
this.type = 'grapple';
this.frame = [
@ -26,29 +27,36 @@ class Grapple extends Projectile {
];
}
contact(body) {
this.detonate();
}
detonate() {
this.world.explosion(this.center, 10);
this.world.room.broadcast('effect', {
type: 'explosion',
size: 10,
pos: this.center
});
release() {
this.source.grapple = false;
this.world.removeBody(this);
}
tickType() {
let power = 0.004;
let x = Math.cos(this.b2body.GetAngleRadians()) * power;
let y = Math.sin(this.b2body.GetAngleRadians()) * power;
this.applyForce(x, y);
retract() {
if (this.rope.length > 0.05)
this.rope.length = this.rope.length - 0.1;
}
connect() {
let p1 = { x: 0, y: 0.5 };
let p2 = { x: 4, y: 0 };
this.rope = new Rope(this.player.ship, this, p1, p2);
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 angle = Math.atan2(normal.y, normal.x);
this.b2body.SetAngleRadians(angle);
this.world.weld(this, body);
}
tickType() {
if(this.fuel-- <= 0) {
this.detonate();
}
}
packTypeDelta() {
@ -57,7 +65,7 @@ class Grapple extends Projectile {
packFull() {
return {
type: 'missile',
type: 'grapple',
id: this.id,
source: this.source.id,
frame: this.frame,
@ -66,4 +74,4 @@ class Grapple extends Projectile {
}
}
module.exports = Missile;
module.exports = Grapple;

View file

@ -6,6 +6,10 @@ class Projectile extends Body {
constructor(world) {
super(world);
}
connect() {
}
}
module.exports = Projectile;

View file

@ -23,6 +23,7 @@ class Ship extends Body {
this.player = player;
this.type = 'ship';
this.inputs = {};
this.grapple = false;
this.thrust = {
forward: 0,
@ -36,7 +37,11 @@ class Ship extends Body {
forward: data[0],
left: data[1],
right: data[2],
missile: data[3]
missile: data[3],
mx: data[4],
my: data[5],
grapple: data[6],
release: data[7]
};
this.thrust.forward = this.inputs.forward;
@ -44,12 +49,26 @@ class Ship extends Body {
this.thrust.right = this.inputs.right;
if (this.inputs.missile) this.launchMissile();
if (this.inputs.grapple) {
if (this.grapple) {
this.grapple.retract();
} else {
this.launchGrapple(this.inputs.mx, this.inputs.my);
}
}
if (this.inputs.release && this.grapple) {
this.grapple.release();
}
}
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;

View file

@ -7,6 +7,10 @@ class Copula {
this.pointA = p1 || b1.com;
this.pointB = p2 || b2.com;
}
packFull() {
return {};
}
}
module.exports = Copula;

View file

@ -3,19 +3,17 @@
const Copula = require('./copula.js');
class Rope extends Copula {
constructor(b1, b2) {
super(b1, b2);
constructor(b1, b2, p1, p2) {
super(b1, b2, p1, p2);
this.type = 'rope';
this._length = 0;
}
get length() {
return this._length;
return this.b2joint.GetMaxLength();
}
set length(len) {
this.length = len;
this.b2joint.SetLength(len);
this.b2joint.SetMaxLength(len);
}
}

View file

@ -14,7 +14,7 @@ class World {
this.copulae = new Set();
this.structures = new Set();
this.asteroids = new Set();
this.missiles = new Set();
this.projectiles = new Set();
this.ships = new Map();
this.players = new Set();
this.room = room;
@ -67,9 +67,10 @@ class World {
this.addBody(asteroid);
}
addMissile(missile) {
this.missiles.add(missile);
this.addBody(missile);
addProjectile(projectile) {
this.projectiles.add(projectile);
this.addBody(projectile);
projectile.connect();
}
addBody(body) {
@ -128,7 +129,7 @@ class World {
this.ships.delete(body);
this.structures.delete(body);
this.asteroids.delete(body);
this.missiles.delete(body);
this.projectiles.delete(body);
this.room.broadcast('destroy', body.id);
}
@ -137,6 +138,10 @@ class World {
this.room.broadcast('destroy', copula.id);
}
weld(bodyA, bodyB) {
this.physics.weld(bodyA, bodyB);
}
start() {
this.interval = setInterval(_ => this.tick(this), 1000 / 60);
}
@ -158,7 +163,7 @@ class World {
tickBodies(self.ships, 1);
tickBodies(self.asteroids, 4);
tickBodies(self.missiles, 1);
tickBodies(self.projectiles, 1);
if (Date.now() - this.tpsStart > 5000) {
this.tps = this.tpsCount / 5 | 0;

View file

@ -20,6 +20,7 @@ class Physics {
constructor() {
this.world = new Box2D.b2World(new b2Vec2(0, 0), false);
this.toRemove = [];
this.toWeld = [];
let onContact = contact => {
let bodya = contact.GetFixtureA().GetBody().GetUserData();
@ -27,12 +28,12 @@ class Physics {
if (bodya) {
bodya.applyDelta();
bodya.contact(bodyb);
bodya.contact(bodyb. contact);
}
if (bodyb) {
bodyb.applyDelta();
bodyb.contact(bodya);
bodyb.contact(bodya, contact);
}
}
@ -88,9 +89,8 @@ class Physics {
let p1 = copula.pointA;
let p2 = copula.pointB;
// See top of file.
let start = b1.GetWorldPoint(b1.GetLocalCenter(), {});
let start = b1.GetWorldPoint(new b2Vec2(p1.x, p1.y), {});
let end = b2.GetWorldPoint(new b2Vec2(p2.x, p2.y), {});
console.log(start, end);
let dx = start.x - end.x
let dy = start.y - end.y;
let len = Math.sqrt(dx * dx + dy * dy);
@ -109,6 +109,24 @@ class Physics {
}
weld(bodyA, bodyB) {
this.toWeld.push([bodyA, bodyB]);
}
contactData(contact) {
let worldManifold = new Box2D.b2WorldManifold();
contact.GetWorldManifold(worldManifold);
let localManifold = new Box2D.b2WorldManifold();
contact.GetManifold(localManifold);
let worldNormal = worldManifold.normal;
let normal = localManifold.normal;
return {
normal: normal,
worldNormal: worldNormal
};
}
raycast(start, end) {
let p1 = new b2Vec2(start.x, start.y);
let p2 = new b2Vec2(end.x, end.y);
@ -149,7 +167,18 @@ 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 = [];
this.toWeld = [];
}
}

View file

@ -1,6 +1,7 @@
'use strict';
const Asteroid = require('./body/asteroid.js');
const Grapple = require('./body/projectile/grapple.js');
const Missile = require('./body/projectile/missile.js');
class Spawner {
@ -29,7 +30,26 @@ class Spawner {
yvel: ship.vel.y
};
let missile = new Missile(this.world, pos, ship);
this.world.addMissile(missile);
this.world.addProjectile(missile);
return missile;
}
spawnGrapple(ship, x, y) {
let sx = ship.center.x;
let sy = ship.center.y;
let dx = x - sx;
let dy = y - sy;
let a = Math.atan2(dy, dx);
let pos = {
x: sx + Math.cos(a) * 1,
y: sy + Math.sin(a) * 1,
r: a,
xvel: ship.vel.x,
yvel: ship.vel.y
};
let grapple = new Grapple(this.world, pos, ship);
this.world.addProjectile(grapple);
return grapple;
}
}