191 lines
4 KiB
JavaScript
191 lines
4 KiB
JavaScript
'use strict';
|
|
|
|
const Physics = require('./physics.js');
|
|
const Ship = require('./body/ship.js');
|
|
const Spawner = require('./spawner.js');
|
|
|
|
const b2Vec2 = require('box2d-html5').b2Vec2;
|
|
|
|
class World {
|
|
constructor(room) {
|
|
this.physics = new Physics();
|
|
this.spawner = new Spawner(this);
|
|
this.bodies = new Set();
|
|
this.asteroids = new Set();
|
|
this.copulae = new Set();
|
|
this.players = new Set();
|
|
this.projectiles = new Set();
|
|
this.ships = new Map();
|
|
this.structures = new Set();
|
|
this.room = room;
|
|
this.tps = 0;
|
|
this.tpsCount = 0;
|
|
this.tpsStart = Date.now();
|
|
|
|
this.scale = 32;
|
|
|
|
this.tickCount = 0;
|
|
|
|
this.bounds = {
|
|
left: 0,
|
|
right: 150,
|
|
top: 0,
|
|
bottom: 30
|
|
}
|
|
}
|
|
|
|
addPlayer(player) {
|
|
this.players.add(player);
|
|
let pos = {
|
|
x: player.team == 'b' ? this.bounds.right - 5 : 5,
|
|
y: this.bounds.bottom / 2
|
|
};
|
|
let ship = new Ship(this, pos, player);
|
|
player.ship = ship;
|
|
this.addShip(ship);
|
|
|
|
//this.test();
|
|
}
|
|
|
|
test() {
|
|
if (this.players.size == 2) {
|
|
let b1 = Array.from(this.players)[0].ship;
|
|
let b2 = Array.from(this.players)[1].ship;
|
|
|
|
let copula = new (require('./copula/rope.js'))(b1, b2);
|
|
if (b1 != b2) {
|
|
this.physics.createCopula(copula);
|
|
}
|
|
}
|
|
}
|
|
|
|
addShip(ship) {
|
|
this.ships.set(ship.player, ship);
|
|
this.addBody(ship);
|
|
}
|
|
|
|
addAsteroid(asteroid) {
|
|
this.addBody(asteroid);
|
|
}
|
|
|
|
addProjectile(projectile) {
|
|
this.addBody(projectile);
|
|
projectile.connect();
|
|
}
|
|
|
|
addBody(body) {
|
|
this.bodies.add(body);
|
|
if (body.type == 'asteroid') this.asteroids.add(body);
|
|
if (body.type == 'structure') this.structures.add(body);
|
|
if (body.class == 'projectile') this.projectiles.add(body);
|
|
this.physics.createBody(body);
|
|
this.room.broadcast('create', body.packFull());
|
|
}
|
|
|
|
addCopula(copula) {
|
|
this.copulae.add(copula);
|
|
this.physics.createCopula(copula);
|
|
this.room.broadcast('effect', copula.packFull());
|
|
}
|
|
|
|
applyDelta(data, bodyPos) {
|
|
data = data.map(v => +(v.toFixed(3)));
|
|
this.players.forEach(player => {
|
|
let dx = player.ship.pos.x - bodyPos.x;
|
|
let dy = player.ship.pos.y - bodyPos.y;
|
|
if (dx * dx + dy * dy < 900)
|
|
player.applyDelta(data)
|
|
});
|
|
}
|
|
|
|
explosion(pos, power) {
|
|
var rays = Array(200).fill().map((_, i) => {
|
|
let a = Math.PI * i / 100;
|
|
let rx = Math.cos(a) * Math.sqrt(power);
|
|
let ry = Math.sin(a) * Math.sqrt(power);
|
|
let x = pos.x + rx;
|
|
let y = pos.y + ry;
|
|
let closest = this.physics.raycast(pos, { x : x, y: y });
|
|
if (!closest)
|
|
return;
|
|
let dis = Math.max(closest.dis, 1);
|
|
let force = power * (1 / dis) * (1 / dis);
|
|
closest.body.debug = (255 * (force / power)) | 0;
|
|
force *= 0.001;
|
|
closest.body.applyImpulse(rx * force, ry * force, closest.point);
|
|
});
|
|
}
|
|
|
|
populate() {
|
|
for (var i = 0; i < 50; i++) {
|
|
let pos = {
|
|
x: Math.random() * this.bounds.right,
|
|
y: Math.random() * this.bounds.bottom
|
|
};
|
|
this.spawner.spawnAsteroid(pos.x, pos.y, Math.random() * 50 + 10);
|
|
}
|
|
}
|
|
|
|
removePlayer(player) {
|
|
this.removeBody(player.ship);
|
|
this.ships.delete(player);
|
|
this.players.delete(player);
|
|
}
|
|
|
|
removeBody(body) {
|
|
body.destruct();
|
|
this.bodies.delete(body);
|
|
this.asteroids.delete(body);
|
|
this.structures.delete(body);
|
|
this.ships.delete(body);
|
|
this.projectiles.delete(body);
|
|
this.room.broadcast('destroy', body.id);
|
|
}
|
|
|
|
removeCopula(copula) {
|
|
this.copulae.delete(body);
|
|
this.room.broadcast('destroy', copula.id);
|
|
}
|
|
|
|
weld(bodyA, bodyB, point) {
|
|
this.physics.weld(bodyA, bodyB, point);
|
|
}
|
|
|
|
start() {
|
|
|
|
}
|
|
|
|
stop() {
|
|
|
|
}
|
|
|
|
tick() {
|
|
this.physics.step();
|
|
|
|
let tickBodies = (set, interval, canSleep) => {
|
|
set.forEach(body => {
|
|
if (this.tickCount % interval == 0 && body.awake)
|
|
body.applyDelta();
|
|
body.tick();
|
|
});
|
|
};
|
|
|
|
tickBodies(this.ships, 1);
|
|
tickBodies(this.asteroids, 1);
|
|
tickBodies(this.projectiles, 1);
|
|
|
|
if (Date.now() - this.tpsStart > 5000) {
|
|
this.tps = this.tpsCount / 5 | 0;
|
|
this.tpsCount = 0;
|
|
this.tpsStart = Date.now();
|
|
if(this.tps < 50) {
|
|
wingbase.warning(`${this.room.name} TPS: ${this.tps}`);
|
|
}
|
|
}
|
|
|
|
this.tpsCount++;
|
|
this.tickCount++;
|
|
}
|
|
}
|
|
|
|
module.exports = World;
|