refactor collision methods, rescaffold server
This commit is contained in:
parent
732fe6f481
commit
1c28e10b86
@ -1,6 +1,6 @@
|
||||
import type { Coord2D, Dimension2D } from "../interfaces";
|
||||
|
||||
interface BoxedEntry {
|
||||
export interface BoxedEntry {
|
||||
id: string;
|
||||
dimension: Dimension2D;
|
||||
center: Coord2D;
|
||||
@ -170,4 +170,12 @@ export class QuadTree {
|
||||
private hasChildren() {
|
||||
return this.children && this.children.size > 0;
|
||||
}
|
||||
|
||||
public setTopLeft(topLeft: Coord2D) {
|
||||
this.topLeft = topLeft;
|
||||
}
|
||||
|
||||
public setDimension(dimension: Dimension2D) {
|
||||
this.dimension = dimension;
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ import {
|
||||
import { Game } from "../Game";
|
||||
import { PhysicsConstants } from "../config";
|
||||
import { Entity } from "../entities";
|
||||
import type { Dimension2D, Velocity2D } from "../interfaces";
|
||||
import { QuadTree } from "../structures";
|
||||
import type { Coord2D, Dimension2D, Velocity2D } from "../interfaces";
|
||||
import { QuadTree, BoxedEntry } from "../structures";
|
||||
|
||||
export class Collision extends System {
|
||||
private static readonly COLLIDABLE_COMPONENT_NAMES = [
|
||||
@ -41,19 +41,26 @@ export class Collision extends System {
|
||||
const entitiesToAddToQuadtree: Entity[] = [];
|
||||
|
||||
Collision.COLLIDABLE_COMPONENT_NAMES.map((componentName) =>
|
||||
game.componentEntities.get(componentName),
|
||||
).forEach(
|
||||
(entityIds?: Set<number>) =>
|
||||
entityIds?.forEach((id) => {
|
||||
const entity = game.entities.get(id);
|
||||
if (!entity || !entity.hasComponent(ComponentNames.BoundingBox)) {
|
||||
return;
|
||||
}
|
||||
entitiesToAddToQuadtree.push(entity);
|
||||
}),
|
||||
game.forEachEntityWithComponent(componentName, (entity) => {
|
||||
if (!entity.hasComponent(ComponentNames.BoundingBox)) {
|
||||
return;
|
||||
}
|
||||
entitiesToAddToQuadtree.push(entity);
|
||||
}),
|
||||
);
|
||||
|
||||
entitiesToAddToQuadtree.forEach((entity) => {
|
||||
this.insertEntitiesInQuadTreeAndUpdateBounds(entitiesToAddToQuadtree);
|
||||
|
||||
this.findCollidingEntitiesAndCollide(entitiesToAddToQuadtree, game);
|
||||
}
|
||||
|
||||
private insertEntitiesInQuadTreeAndUpdateBounds(entities: Entity[]) {
|
||||
const topLeft: Coord2D = { x: Infinity, y: Infinity };
|
||||
const bottomRight: Coord2D = { x: -Infinity, y: -Infinity };
|
||||
|
||||
const quadTreeInsertions: BoxedEntry[] = [];
|
||||
|
||||
entities.forEach((entity) => {
|
||||
const boundingBox = entity.getComponent<BoundingBox>(
|
||||
ComponentNames.BoundingBox,
|
||||
);
|
||||
@ -63,18 +70,45 @@ export class Collision extends System {
|
||||
dimension = boundingBox.getOutscribedBoxDims();
|
||||
}
|
||||
|
||||
this.quadTree.insert({
|
||||
const { center } = boundingBox;
|
||||
const topLeftBoundingBox = {
|
||||
x: center.x - dimension.width / 2,
|
||||
y: center.y - dimension.height / 2,
|
||||
};
|
||||
const bottomRightBoundingBox = {
|
||||
x: center.x + dimension.width / 2,
|
||||
y: center.y + dimension.height / 2,
|
||||
};
|
||||
|
||||
topLeft.x = Math.min(topLeftBoundingBox.x, topLeft.x);
|
||||
topLeft.y = Math.min(topLeftBoundingBox.y, topLeft.y);
|
||||
bottomRight.x = Math.max(bottomRightBoundingBox.x, bottomRight.x);
|
||||
bottomRight.y = Math.min(bottomRightBoundingBox.y, bottomRight.y);
|
||||
|
||||
quadTreeInsertions.push({
|
||||
id: entity.id,
|
||||
dimension,
|
||||
center: boundingBox.center,
|
||||
center,
|
||||
});
|
||||
});
|
||||
|
||||
// find colliding entities and perform collisions
|
||||
const collidingEntities = this.getCollidingEntities(
|
||||
entitiesToAddToQuadtree,
|
||||
game,
|
||||
// set bounds first
|
||||
if (entities.length > 0) {
|
||||
this.quadTree.setTopLeft(topLeft);
|
||||
this.quadTree.setDimension({
|
||||
width: bottomRight.x - topLeft.x,
|
||||
height: bottomRight.y - topLeft.y,
|
||||
});
|
||||
}
|
||||
|
||||
// then, begin insertions
|
||||
quadTreeInsertions.forEach((boxedEntry: BoxedEntry) =>
|
||||
this.quadTree.insert(boxedEntry),
|
||||
);
|
||||
}
|
||||
|
||||
private findCollidingEntitiesAndCollide(entities: Entity[], game: Game) {
|
||||
const collidingEntities = this.getCollidingEntities(entities, game);
|
||||
|
||||
collidingEntities.forEach(([entityAId, entityBId]) => {
|
||||
const [entityA, entityB] = [entityAId, entityBId].map((id) =>
|
||||
@ -139,8 +173,8 @@ export class Collision extends System {
|
||||
private getCollidingEntities(
|
||||
collidableEntities: Entity[],
|
||||
game: Game,
|
||||
): [number, number][] {
|
||||
const collidingEntityIds: [number, number][] = [];
|
||||
): [string, string][] {
|
||||
const collidingEntityIds: [string, string][] = [];
|
||||
|
||||
for (const entity of collidableEntities) {
|
||||
const boundingBox = entity.getComponent<BoundingBox>(
|
||||
|
@ -11,50 +11,38 @@ import { Miscellaneous } from "../../engine/config";
|
||||
|
||||
const TICK_RATE = 60 / 1000;
|
||||
|
||||
class Server {
|
||||
private server: any;
|
||||
private game: Game;
|
||||
const game = new Game();
|
||||
|
||||
constructor() {
|
||||
this.game = new Game();
|
||||
[new Physics(), new Collision(), new WallBounds(Miscellaneous.WIDTH)].forEach(
|
||||
(system) => game.addSystem(system),
|
||||
);
|
||||
|
||||
[
|
||||
new Physics(),
|
||||
new Collision({
|
||||
width: Miscellaneous.WIDTH,
|
||||
height: Miscellaneous.HEIGHT,
|
||||
}),
|
||||
new WallBounds(Miscellaneous.WIDTH),
|
||||
].forEach((system) => this.game.addSystem(system));
|
||||
[new Floor(160), new Player()].forEach((entity) => game.addEntity(entity));
|
||||
|
||||
[new Floor(160), new Player()].forEach((entity) =>
|
||||
this.game.addEntity(entity),
|
||||
);
|
||||
game.start();
|
||||
|
||||
this.game.start();
|
||||
setInterval(() => {
|
||||
this.game.doGameLoop(performance.now());
|
||||
}, TICK_RATE);
|
||||
setInterval(() => {
|
||||
game.doGameLoop(performance.now());
|
||||
}, TICK_RATE);
|
||||
|
||||
this.server = Bun.serve<any>({
|
||||
websocket: {
|
||||
open(ws) {
|
||||
ws.subscribe("the-group-chat");
|
||||
ws.publish("the-group-chat", msg);
|
||||
},
|
||||
message(ws, message) {
|
||||
// this is a group chat
|
||||
// so the server re-broadcasts incoming message to everyone
|
||||
ws.publish("the-group-chat", `${ws.data.username}: ${message}`);
|
||||
},
|
||||
close(ws) {
|
||||
const msg = `${ws.data.username} has left the chat`;
|
||||
ws.unsubscribe("the-group-chat");
|
||||
ws.publish("the-group-chat", msg);
|
||||
},
|
||||
const server = Bun.serve({
|
||||
port: 8080,
|
||||
fetch(req, server) {
|
||||
const sessionId = Math.floor(Math.random() * 1e10).toString();
|
||||
|
||||
server.upgrade(req, {
|
||||
headers: {
|
||||
"Set-Cookie": `SessionId=${sessionId}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
websocket: {
|
||||
open(ws) {},
|
||||
message(ws, message) {
|
||||
console.log(message);
|
||||
},
|
||||
close(ws) {},
|
||||
},
|
||||
});
|
||||
|
||||
new Server();
|
||||
console.log(`Listening on ${server.hostname}:${server.port}`);
|
||||
|
@ -13,8 +13,6 @@
|
||||
"noEmit": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
"moduleDetection": "force",
|
||||
// if TS 4.x or earlier
|
||||
"moduleResolution": "nodenext",
|
||||
|
||||
"jsx": "react-jsx", // support JSX
|
||||
"allowJs": true, // allow importing `.js` from `.ts`
|
||||
|
Loading…
Reference in New Issue
Block a user