a bit of refactoring; importing engine into bun for server
This commit is contained in:
parent
0fd9fb0975
commit
72c6c7de12
169
.gitignore
vendored
Normal file
169
.gitignore
vendored
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
|
||||||
|
logs
|
||||||
|
_.log
|
||||||
|
npm-debug.log_
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
|
||||||
|
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
|
||||||
|
pids
|
||||||
|
_.pid
|
||||||
|
_.seed
|
||||||
|
\*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
|
||||||
|
coverage
|
||||||
|
\*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
|
||||||
|
\*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
|
||||||
|
.stylelintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
|
||||||
|
\*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
|
||||||
|
.env
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
|
||||||
|
.cache/
|
||||||
|
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# vuepress v2.x temp and cache directory
|
||||||
|
|
||||||
|
.temp
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Docusaurus cache and generated files
|
||||||
|
|
||||||
|
.docusaurus
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.\*
|
@ -1,35 +0,0 @@
|
|||||||
import { System, SystemNames } from ".";
|
|
||||||
import { BoundingBox, ComponentNames } from "../components";
|
|
||||||
import type { Entity } from "../entities";
|
|
||||||
|
|
||||||
export class WallBounds extends System {
|
|
||||||
private screenWidth: number;
|
|
||||||
|
|
||||||
constructor(screenWidth: number) {
|
|
||||||
super(SystemNames.WallBounds);
|
|
||||||
|
|
||||||
this.screenWidth = screenWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
public update(
|
|
||||||
_dt: number,
|
|
||||||
entityMap: Map<number, Entity>,
|
|
||||||
componentEntities: Map<string, Set<number>>
|
|
||||||
) {
|
|
||||||
componentEntities.get(ComponentNames.WallBounded)?.forEach((entityId) => {
|
|
||||||
const entity = entityMap.get(entityId);
|
|
||||||
if (!entity.hasComponent(ComponentNames.BoundingBox)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const boundingBox = entity.getComponent<BoundingBox>(
|
|
||||||
ComponentNames.BoundingBox
|
|
||||||
);
|
|
||||||
|
|
||||||
boundingBox.center.x = Math.min(
|
|
||||||
this.screenWidth - boundingBox.dimension.width / 2,
|
|
||||||
Math.max(boundingBox.dimension.width / 2, boundingBox.center.x)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
8
client/package-lock.json
generated
8
client/package-lock.json
generated
@ -7,6 +7,9 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "client",
|
"name": "client",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"module-alias": "^2.2.3"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/vite-plugin-svelte": "^2.0.4",
|
"@sveltejs/vite-plugin-svelte": "^2.0.4",
|
||||||
"@tsconfig/svelte": "^4.0.1",
|
"@tsconfig/svelte": "^4.0.1",
|
||||||
@ -1585,6 +1588,11 @@
|
|||||||
"mkdirp": "bin/cmd.js"
|
"mkdirp": "bin/cmd.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/module-alias": {
|
||||||
|
"version": "2.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.3.tgz",
|
||||||
|
"integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q=="
|
||||||
|
},
|
||||||
"node_modules/mri": {
|
"node_modules/mri": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
||||||
|
@ -20,5 +20,8 @@
|
|||||||
"tslib": "^2.5.0",
|
"tslib": "^2.5.0",
|
||||||
"typescript": "^5.0.2",
|
"typescript": "^5.0.2",
|
||||||
"vite": "^4.3.9"
|
"vite": "^4.3.9"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"module-alias": "^2.2.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Floor, Player } from "./entities";
|
import { Floor, Player } from "@engine/entities";
|
||||||
import { Game } from "./Game";
|
import { Game } from "@engine/Game";
|
||||||
import {
|
import {
|
||||||
WallBounds,
|
WallBounds,
|
||||||
FacingDirection,
|
FacingDirection,
|
||||||
@ -7,7 +7,7 @@ import {
|
|||||||
Physics,
|
Physics,
|
||||||
Input,
|
Input,
|
||||||
Collision,
|
Collision,
|
||||||
} from "./systems";
|
} from "@engine/systems";
|
||||||
|
|
||||||
export class JumpStorm {
|
export class JumpStorm {
|
||||||
private game: Game;
|
private game: Game;
|
@ -1,10 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import { Game } from "../../lib/Game";
|
import { loadAssets } from "@engine/config";
|
||||||
import { Render } from "../../lib/systems";
|
import { JumpStorm} from "../Jumpstorm";
|
||||||
import { Floor } from "../../lib/entities";
|
|
||||||
import { loadAssets } from "../../lib/config";
|
|
||||||
import { JumpStorm } from "../../lib/JumpStorm";
|
|
||||||
|
|
||||||
let canvas: HTMLCanvasElement;
|
let canvas: HTMLCanvasElement;
|
||||||
let ctx: CanvasRenderingContext2D;
|
let ctx: CanvasRenderingContext2D;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type LeaderBoardEntry } from "../../lib/interfaces";
|
import { type LeaderBoardEntry } from "@engine/interfaces";
|
||||||
import LeaderBoardCard from "./LeaderBoardCard.svelte";
|
import LeaderBoardCard from "./LeaderBoardCard.svelte";
|
||||||
|
|
||||||
const MAX_ENTRIES = 8;
|
const MAX_ENTRIES = 8;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type LeaderBoardEntry } from "../../lib/interfaces";
|
import { type LeaderBoardEntry } from "@engine/interfaces";
|
||||||
|
|
||||||
export let entry: LeaderBoardEntry = {
|
export let entry: LeaderBoardEntry = {
|
||||||
name: "simponic",
|
name: "simponic",
|
||||||
|
@ -24,5 +24,8 @@
|
|||||||
"src/**/*.js",
|
"src/**/*.js",
|
||||||
"src/**/*.svelte"
|
"src/**/*.svelte"
|
||||||
],
|
],
|
||||||
|
"paths": {
|
||||||
|
"@engine/*": ["../engine/*"]
|
||||||
|
},
|
||||||
"references": [{ "path": "./tsconfig.node.json" }]
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from "vite";
|
||||||
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
||||||
|
import { fileURLToPath, URL } from "node:url";
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [svelte()],
|
plugins: [svelte()],
|
||||||
})
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@engine": fileURLToPath(new URL("../engine", import.meta.url)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
@ -2,18 +2,21 @@ import { Entity } from "./entities";
|
|||||||
import { System } from "./systems";
|
import { System } from "./systems";
|
||||||
|
|
||||||
export class Game {
|
export class Game {
|
||||||
private entities: Map<number, Entity>;
|
|
||||||
private systems: Map<string, System>;
|
|
||||||
private systemOrder: string[];
|
private systemOrder: string[];
|
||||||
|
|
||||||
private running: boolean;
|
private running: boolean;
|
||||||
private lastTimeStamp: number;
|
private lastTimeStamp: number;
|
||||||
|
|
||||||
|
public entities: Map<number, Entity>;
|
||||||
|
public systems: Map<string, System>;
|
||||||
|
public componentEntities: Map<string, Set<number>>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.running = false;
|
this.running = false;
|
||||||
this.systemOrder = [];
|
this.systemOrder = [];
|
||||||
this.systems = new Map();
|
this.systems = new Map();
|
||||||
this.entities = new Map();
|
this.entities = new Map();
|
||||||
|
this.componentEntities = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
public start() {
|
public start() {
|
||||||
@ -52,19 +55,22 @@ export class Game {
|
|||||||
const dt = timeStamp - this.lastTimeStamp;
|
const dt = timeStamp - this.lastTimeStamp;
|
||||||
this.lastTimeStamp = timeStamp;
|
this.lastTimeStamp = timeStamp;
|
||||||
|
|
||||||
const componentEntities = new Map<string, Set<number>>();
|
this.componentEntities.clear();
|
||||||
this.entities.forEach((entity) =>
|
this.entities.forEach((entity) =>
|
||||||
entity.getComponents().forEach((component) => {
|
entity.getComponents().forEach((component) => {
|
||||||
if (!componentEntities.has(component.name)) {
|
if (!this.componentEntities.has(component.name)) {
|
||||||
componentEntities.set(component.name, new Set<number>([entity.id]));
|
this.componentEntities.set(
|
||||||
|
component.name,
|
||||||
|
new Set<number>([entity.id])
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
componentEntities.get(component.name).add(entity.id);
|
this.componentEntities.get(component.name).add(entity.id);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.systemOrder.forEach((systemName) => {
|
this.systemOrder.forEach((systemName) => {
|
||||||
this.systems.get(systemName).update(dt, this.entities, componentEntities);
|
this.systems.get(systemName).update(dt, this);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -7,13 +7,14 @@ import {
|
|||||||
Velocity,
|
Velocity,
|
||||||
Moment,
|
Moment,
|
||||||
} from "../components";
|
} from "../components";
|
||||||
|
import { Game } from "../Game";
|
||||||
import { PhysicsConstants } from "../config";
|
import { PhysicsConstants } from "../config";
|
||||||
import { Entity } from "../entities";
|
import { Entity } from "../entities";
|
||||||
import type { Dimension2D } from "../interfaces";
|
import type { Dimension2D } from "../interfaces";
|
||||||
import { QuadTree } from "../structures";
|
import { QuadTree } from "../structures";
|
||||||
|
|
||||||
export class Collision extends System {
|
export class Collision extends System {
|
||||||
private static readonly COLLIDABLE_COMPONENTS = [
|
private static readonly COLLIDABLE_COMPONENT_NAMES = [
|
||||||
ComponentNames.Collide,
|
ComponentNames.Collide,
|
||||||
ComponentNames.TopCollidable,
|
ComponentNames.TopCollidable,
|
||||||
];
|
];
|
||||||
@ -33,19 +34,17 @@ export class Collision extends System {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(
|
public update(dt: number, game: Game) {
|
||||||
dt: number,
|
// rebuild the quadtree
|
||||||
entityMap: Map<number, Entity>,
|
|
||||||
entityComponents: Map<string, Set<number>>
|
|
||||||
) {
|
|
||||||
this.quadTree.clear();
|
this.quadTree.clear();
|
||||||
|
|
||||||
const entitiesToAddToQuadtree: Entity[] = [];
|
const entitiesToAddToQuadtree: Entity[] = [];
|
||||||
Collision.COLLIDABLE_COMPONENTS.map((componentName) =>
|
|
||||||
entityComponents.get(componentName)
|
Collision.COLLIDABLE_COMPONENT_NAMES.map((componentName) =>
|
||||||
|
game.componentEntities.get(componentName)
|
||||||
).forEach((entityIds: Set<number>) =>
|
).forEach((entityIds: Set<number>) =>
|
||||||
entityIds.forEach((id) => {
|
entityIds.forEach((id) => {
|
||||||
const entity = entityMap.get(id);
|
const entity = game.entities.get(id);
|
||||||
if (!entity.hasComponent(ComponentNames.BoundingBox)) {
|
if (!entity.hasComponent(ComponentNames.BoundingBox)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -65,13 +64,15 @@ export class Collision extends System {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// find colliding entities and perform collisions
|
||||||
const collidingEntities = this.getCollidingEntities(
|
const collidingEntities = this.getCollidingEntities(
|
||||||
entitiesToAddToQuadtree,
|
entitiesToAddToQuadtree,
|
||||||
entityMap
|
game.entities
|
||||||
);
|
);
|
||||||
|
|
||||||
collidingEntities.forEach(([entityAId, entityBId]) => {
|
collidingEntities.forEach(([entityAId, entityBId]) => {
|
||||||
const [entityA, entityB] = [entityAId, entityBId].map((id) =>
|
const [entityA, entityB] = [entityAId, entityBId].map((id) =>
|
||||||
entityMap.get(id)
|
game.entities.get(id)
|
||||||
);
|
);
|
||||||
this.performCollision(entityA, entityB);
|
this.performCollision(entityA, entityB);
|
||||||
});
|
});
|
||||||
@ -92,7 +93,7 @@ export class Collision extends System {
|
|||||||
entityB.hasComponent(ComponentNames.TopCollidable) &&
|
entityB.hasComponent(ComponentNames.TopCollidable) &&
|
||||||
entityABoundingBox.center.y <= entityBBoundingBox.center.y &&
|
entityABoundingBox.center.y <= entityBBoundingBox.center.y &&
|
||||||
velocity &&
|
velocity &&
|
||||||
velocity.dCartesian.dy >= 0 // don't apply floor logic when coming through the bottom
|
velocity.dCartesian.dy >= 0 // don't apply "floor" logic when coming through the bottom
|
||||||
) {
|
) {
|
||||||
if (entityBBoundingBox.rotation != 0) {
|
if (entityBBoundingBox.rotation != 0) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@ -157,11 +158,11 @@ export class Collision extends System {
|
|||||||
return collidingEntityIds;
|
return collidingEntityIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ramblings: https://excalidraw.com/#json=z-xD86Za4a3duZuV2Oky0,KaGe-5iHJu1Si8inEo4GLQ
|
||||||
private getDyToPushOutOfFloor(
|
private getDyToPushOutOfFloor(
|
||||||
entityBoundingBox: BoundingBox,
|
entityBoundingBox: BoundingBox,
|
||||||
floorBoundingBox: BoundingBox
|
floorBoundingBox: BoundingBox
|
||||||
): number {
|
): number {
|
||||||
// ramblings: https://excalidraw.com/#json=z-xD86Za4a3duZuV2Oky0,KaGe-5iHJu1Si8inEo4GLQ
|
|
||||||
const {
|
const {
|
||||||
rotation,
|
rotation,
|
||||||
center: { x, y },
|
center: { x, y },
|
@ -3,6 +3,7 @@ import {
|
|||||||
Velocity,
|
Velocity,
|
||||||
FacingDirection as FacingDirectionComponent,
|
FacingDirection as FacingDirectionComponent,
|
||||||
} from "../components";
|
} from "../components";
|
||||||
|
import { Game } from "../Game";
|
||||||
import type { Entity } from "../entities";
|
import type { Entity } from "../entities";
|
||||||
import { System, SystemNames } from "./";
|
import { System, SystemNames } from "./";
|
||||||
|
|
||||||
@ -11,15 +12,11 @@ export class FacingDirection extends System {
|
|||||||
super(SystemNames.FacingDirection);
|
super(SystemNames.FacingDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(
|
public update(_dt: number, game: Game) {
|
||||||
_dt: number,
|
game.componentEntities
|
||||||
entityMap: Map<number, Entity>,
|
|
||||||
componentEntities: Map<string, Set<number>>
|
|
||||||
) {
|
|
||||||
componentEntities
|
|
||||||
.get(ComponentNames.FacingDirection)
|
.get(ComponentNames.FacingDirection)
|
||||||
?.forEach((entityId) => {
|
?.forEach((entityId) => {
|
||||||
const entity = entityMap.get(entityId);
|
const entity = game.entities.get(entityId);
|
||||||
if (!entity.hasComponent(ComponentNames.Velocity)) {
|
if (!entity.hasComponent(ComponentNames.Velocity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
@ -6,6 +6,7 @@ import {
|
|||||||
Velocity,
|
Velocity,
|
||||||
Mass,
|
Mass,
|
||||||
} from "../components";
|
} from "../components";
|
||||||
|
import { Game } from "../Game";
|
||||||
import { KeyConstants, PhysicsConstants } from "../config";
|
import { KeyConstants, PhysicsConstants } from "../config";
|
||||||
import type { Entity } from "../entities";
|
import type { Entity } from "../entities";
|
||||||
import { Action } from "../interfaces";
|
import { Action } from "../interfaces";
|
||||||
@ -34,13 +35,9 @@ export class Input extends System {
|
|||||||
return keys.some((key) => this.keys.has(key));
|
return keys.some((key) => this.keys.has(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(
|
public update(dt: number, game: Game) {
|
||||||
dt: number,
|
game.componentEntities.get(ComponentNames.Control)?.forEach((entityId) => {
|
||||||
entityMap: Map<number, Entity>,
|
const entity = game.entities.get(entityId);
|
||||||
componentEntities: Map<string, Set<number>>
|
|
||||||
) {
|
|
||||||
componentEntities.get(ComponentNames.Control)?.forEach((entityId) => {
|
|
||||||
const entity = entityMap.get(entityId);
|
|
||||||
if (!entity.hasComponent(ComponentNames.Velocity)) {
|
if (!entity.hasComponent(ComponentNames.Velocity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -58,8 +55,8 @@ export class Input extends System {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
componentEntities.get(ComponentNames.Jump)?.forEach((entityId) => {
|
game.componentEntities.get(ComponentNames.Jump)?.forEach((entityId) => {
|
||||||
const entity = entityMap.get(entityId);
|
const entity = game.entities.get(entityId);
|
||||||
const jump = entity.getComponent<Jump>(ComponentNames.Jump);
|
const jump = entity.getComponent<Jump>(ComponentNames.Jump);
|
||||||
const velocity = entity.getComponent<Velocity>(ComponentNames.Velocity);
|
const velocity = entity.getComponent<Velocity>(ComponentNames.Velocity);
|
||||||
|
|
@ -12,19 +12,16 @@ import {
|
|||||||
import { PhysicsConstants } from "../config";
|
import { PhysicsConstants } from "../config";
|
||||||
import type { Entity } from "../entities";
|
import type { Entity } from "../entities";
|
||||||
import type { Force2D } from "../interfaces";
|
import type { Force2D } from "../interfaces";
|
||||||
|
import { Game } from "../Game";
|
||||||
|
|
||||||
export class Physics extends System {
|
export class Physics extends System {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(SystemNames.Physics);
|
super(SystemNames.Physics);
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(
|
public update(dt: number, game: Game): void {
|
||||||
dt: number,
|
game.componentEntities.get(ComponentNames.Forces)?.forEach((entityId) => {
|
||||||
entityMap: Map<number, Entity>,
|
const entity = game.entities.get(entityId);
|
||||||
componentEntities: Map<string, Set<number>>
|
|
||||||
): void {
|
|
||||||
componentEntities.get(ComponentNames.Forces)?.forEach((entityId) => {
|
|
||||||
const entity = entityMap.get(entityId);
|
|
||||||
|
|
||||||
const mass = entity.getComponent<Mass>(ComponentNames.Mass).mass;
|
const mass = entity.getComponent<Mass>(ComponentNames.Mass).mass;
|
||||||
const forces = entity.getComponent<Forces>(ComponentNames.Forces).forces;
|
const forces = entity.getComponent<Forces>(ComponentNames.Forces).forces;
|
||||||
@ -74,8 +71,8 @@ export class Physics extends System {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
componentEntities.get(ComponentNames.Velocity)?.forEach((entityId) => {
|
game.componentEntities.get(ComponentNames.Velocity)?.forEach((entityId) => {
|
||||||
const entity = entityMap.get(entityId);
|
const entity = game.entities.get(entityId);
|
||||||
const velocity = entity.getComponent<Velocity>(ComponentNames.Velocity);
|
const velocity = entity.getComponent<Velocity>(ComponentNames.Velocity);
|
||||||
const boundingBox = entity.getComponent<BoundingBox>(
|
const boundingBox = entity.getComponent<BoundingBox>(
|
||||||
ComponentNames.BoundingBox
|
ComponentNames.BoundingBox
|
@ -1,7 +1,9 @@
|
|||||||
import { System, SystemNames } from ".";
|
import { System, SystemNames } from ".";
|
||||||
import { BoundingBox, ComponentNames, Sprite } from "../components";
|
import { BoundingBox, ComponentNames, Sprite } from "../components";
|
||||||
import type { Entity } from "../entities";
|
import type { Entity } from "../entities";
|
||||||
|
import { Game } from "../Game";
|
||||||
import type { DrawArgs } from "../interfaces";
|
import type { DrawArgs } from "../interfaces";
|
||||||
|
import { clamp } from "../utils";
|
||||||
|
|
||||||
export class Render extends System {
|
export class Render extends System {
|
||||||
private ctx: CanvasRenderingContext2D;
|
private ctx: CanvasRenderingContext2D;
|
||||||
@ -11,15 +13,11 @@ export class Render extends System {
|
|||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(
|
public update(dt: number, game: Game) {
|
||||||
dt: number,
|
|
||||||
entityMap: Map<number, Entity>,
|
|
||||||
componentEntities: Map<string, Set<number>>
|
|
||||||
) {
|
|
||||||
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
|
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
|
||||||
|
|
||||||
componentEntities.get(ComponentNames.Sprite)?.forEach((entityId) => {
|
game.componentEntities.get(ComponentNames.Sprite)?.forEach((entityId) => {
|
||||||
const entity = entityMap.get(entityId);
|
const entity = game.entities.get(entityId);
|
||||||
const sprite = entity.getComponent<Sprite>(ComponentNames.Sprite);
|
const sprite = entity.getComponent<Sprite>(ComponentNames.Sprite);
|
||||||
sprite.update(dt);
|
sprite.update(dt);
|
||||||
|
|
||||||
@ -29,6 +27,22 @@ export class Render extends System {
|
|||||||
ComponentNames.BoundingBox
|
ComponentNames.BoundingBox
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// don't render if we're outside the screen
|
||||||
|
if (
|
||||||
|
clamp(
|
||||||
|
boundingBox.center.y,
|
||||||
|
-boundingBox.dimension.height / 2,
|
||||||
|
this.ctx.canvas.height + boundingBox.dimension.height / 2
|
||||||
|
) != boundingBox.center.y ||
|
||||||
|
clamp(
|
||||||
|
boundingBox.center.x,
|
||||||
|
-boundingBox.dimension.width / 2,
|
||||||
|
this.ctx.canvas.width + boundingBox.dimension.width / 2
|
||||||
|
) != boundingBox.center.x
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
drawArgs = {
|
drawArgs = {
|
||||||
center: boundingBox.center,
|
center: boundingBox.center,
|
||||||
dimension: boundingBox.dimension,
|
dimension: boundingBox.dimension,
|
@ -1,4 +1,5 @@
|
|||||||
import { Entity } from "../entities";
|
import { Entity } from "../entities";
|
||||||
|
import { Game } from "../Game";
|
||||||
|
|
||||||
export abstract class System {
|
export abstract class System {
|
||||||
public readonly name: string;
|
public readonly name: string;
|
||||||
@ -7,9 +8,5 @@ export abstract class System {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract update(
|
abstract update(dt: number, game: Game): void;
|
||||||
dt: number,
|
|
||||||
entityMap: Map<number, Entity>,
|
|
||||||
componentEntities: Map<string, Set<number>>
|
|
||||||
): void;
|
|
||||||
}
|
}
|
36
engine/systems/WallBounds.ts
Normal file
36
engine/systems/WallBounds.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { System, SystemNames } from ".";
|
||||||
|
import { BoundingBox, ComponentNames } from "../components";
|
||||||
|
import { Game } from "../Game";
|
||||||
|
import type { Entity } from "../entities";
|
||||||
|
import { clamp } from "../utils";
|
||||||
|
|
||||||
|
export class WallBounds extends System {
|
||||||
|
private screenWidth: number;
|
||||||
|
|
||||||
|
constructor(screenWidth: number) {
|
||||||
|
super(SystemNames.WallBounds);
|
||||||
|
|
||||||
|
this.screenWidth = screenWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(_dt: number, game: Game) {
|
||||||
|
game.componentEntities
|
||||||
|
.get(ComponentNames.WallBounded)
|
||||||
|
?.forEach((entityId) => {
|
||||||
|
const entity = game.entities.get(entityId);
|
||||||
|
if (!entity.hasComponent(ComponentNames.BoundingBox)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const boundingBox = entity.getComponent<BoundingBox>(
|
||||||
|
ComponentNames.BoundingBox
|
||||||
|
);
|
||||||
|
|
||||||
|
boundingBox.center.x = clamp(
|
||||||
|
boundingBox.center.x,
|
||||||
|
boundingBox.dimension.width / 2,
|
||||||
|
this.screenWidth - boundingBox.dimension.width / 2
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
2
engine/utils/clamp.ts
Normal file
2
engine/utils/clamp.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const clamp = (num: number, min: number, max: number) =>
|
||||||
|
Math.min(Math.max(num, min), max);
|
@ -1,3 +1,4 @@
|
|||||||
export * from "./rotateVector";
|
export * from "./rotateVector";
|
||||||
export * from "./normalizeVector";
|
export * from "./normalizeVector";
|
||||||
export * from "./dotProduct";
|
export * from "./dotProduct";
|
||||||
|
export * from "./clamp";
|
15
server/README.md
Normal file
15
server/README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# server
|
||||||
|
|
||||||
|
To install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
To run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun run index.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
This project was created using `bun init` in bun v0.6.14. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
|
BIN
server/bun.lockb
Executable file
BIN
server/bun.lockb
Executable file
Binary file not shown.
0
server/index.ts
Normal file
0
server/index.ts
Normal file
13
server/package.json
Normal file
13
server/package.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "server",
|
||||||
|
"module": "src/index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"devDependencies": {
|
||||||
|
"bun-types": "^0.6.14"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
}
|
||||||
|
}
|
3
server/src/index.ts
Normal file
3
server/src/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { Game } from "../../engine/Game";
|
||||||
|
|
||||||
|
console.log(Game);
|
21
server/tsconfig.json
Normal file
21
server/tsconfig.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["ESNext"],
|
||||||
|
"module": "esnext",
|
||||||
|
"target": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"strict": true,
|
||||||
|
"downlevelIteration": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"allowJs": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"types": [
|
||||||
|
"bun-types" // add Bun global
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user