add start of grappling hook
This commit is contained in:
parent
ff0ac094cf
commit
4753f879e5
14 changed files with 192 additions and 69 deletions
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -54,4 +54,8 @@ class Body {
|
|||
updateType() {
|
||||
|
||||
}
|
||||
|
||||
tick() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,9 +65,15 @@ class Body {
|
|||
}
|
||||
|
||||
packTypeDelta() {
|
||||
return [];
|
||||
}
|
||||
|
||||
packFull() {
|
||||
return {
|
||||
type: 'body',
|
||||
id: this.id,
|
||||
delta: this.packDelta()
|
||||
}
|
||||
}
|
||||
|
||||
get com() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -6,6 +6,10 @@ class Projectile extends Body {
|
|||
constructor(world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
connect() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Projectile;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -7,6 +7,10 @@ class Copula {
|
|||
this.pointA = p1 || b1.com;
|
||||
this.pointB = p2 || b2.com;
|
||||
}
|
||||
|
||||
packFull() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Copula;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 = [];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue