diff --git a/src/apis/arena.ts b/src/apis/arena.ts index 99d72b5..b528a0c 100644 --- a/src/apis/arena.ts +++ b/src/apis/arena.ts @@ -13,7 +13,7 @@ class Arena { ratio, scaling.screenToCanvas(new Vector(_window.innerWidth, _window.innerHeight)) ); - const arenaSize = Vector.round(scaling.toArenaUnits(arenaDim)); + const arenaSize = scaling.toArenaUnits(arenaDim); this.#size = arenaSize.x; }, 16); } diff --git a/src/apis/camera.ts b/src/apis/camera.ts index 473a0ac..cd7a1a6 100644 --- a/src/apis/camera.ts +++ b/src/apis/camera.ts @@ -1,14 +1,23 @@ import { Vector } from '../core/vector'; import { arena } from './arena'; +import { game } from './game'; import { minimap } from './minimap'; class Camera { + #position: Vector; + + constructor() { + game.on('frame_end', () => { + const center = Vector.add(minimap.viewportPos, Vector.unscale(2, minimap.viewportDim)); + const cameraPos = Vector.subtract(center, minimap.minimapPos); + const normalized = Vector.divide(cameraPos, minimap.minimapDim); + this.#position = arena.scale(normalized); + }); + } + get position(): Vector { - const center = Vector.add(minimap.viewportPos, Vector.unscale(2, minimap.viewportDim)); - const cameraPos = Vector.subtract(center, minimap.minimapPos); - const normalized = Vector.divide(cameraPos, minimap.minimapDim); - return arena.scale(normalized); + return this.#position; } } diff --git a/src/apis/game.ts b/src/apis/game.ts index fd19a95..f4ff9ad 100644 --- a/src/apis/game.ts +++ b/src/apis/game.ts @@ -1,6 +1,11 @@ import { CanvasKit } from '../core/canvas_kit'; import { EventEmitter } from '../core/event_emitter'; +/** + * Events: + * - frame: Emitted every frame. Can be used for things that should be executed on every frame + * - frame_end: Emitted after `frame` and is mainly used internally to update position variables + */ class Game extends EventEmitter { #ready = false; @@ -17,6 +22,7 @@ class Game extends EventEmitter { } super.emit('frame'); + super.emit('frame_end'); } #onready(): void { diff --git a/src/apis/player_movement.ts b/src/apis/player_movement.ts index 165df63..da44f6b 100644 --- a/src/apis/player_movement.ts +++ b/src/apis/player_movement.ts @@ -11,7 +11,7 @@ class PlayerMovement extends Movement { constructor() { super(); - game.on('frame', () => super.updatePos(arena.scale(minimap.arrowPos))); + game.on('frame_end', () => super.updatePos(arena.scale(minimap.arrowPos))); } } diff --git a/src/apis/scaling.ts b/src/apis/scaling.ts index 070cf34..f9f8f1f 100644 --- a/src/apis/scaling.ts +++ b/src/apis/scaling.ts @@ -52,7 +52,7 @@ class Scaling { * @returns {Vector} The vector in arena units */ toArenaUnits(v: Vector): Vector { - return Vector.unscale(this.#scalingFactor, v); + return Vector.round(Vector.unscale(this.#scalingFactor, v)); } /** @@ -61,7 +61,7 @@ class Scaling { * @returns {Vector} The vector in canvas units */ toCanvasUnits(v: Vector): Vector { - return Vector.scale(this.#scalingFactor, v); + return Vector.round(Vector.scale(this.#scalingFactor, v)); } /** diff --git a/src/extensions/debug_tool.ts b/src/extensions/debug_tool.ts index 7a73339..bb0f07d 100644 --- a/src/extensions/debug_tool.ts +++ b/src/extensions/debug_tool.ts @@ -112,7 +112,7 @@ class DebugTool extends Extension { } #_drawParent(entity: Entity, position: Vector) { - if (entity.parent === null) { + if (entity.parent == null) { return; } diff --git a/src/extensions/entity_manager.ts b/src/extensions/entity_manager.ts index d557640..2707eb0 100644 --- a/src/extensions/entity_manager.ts +++ b/src/extensions/entity_manager.ts @@ -1,11 +1,9 @@ -import { CanvasKit } from '../core/canvas_kit'; +import { CanvasKit, Vector } from '../core'; +import { game, playerMovement, scaling } from '../apis'; import { Entity, EntityType, EntityColor, TeamColors } from '../types/entity'; import { Extension } from './extension'; -import { Vector } from '../core/vector'; -import { game } from '../apis/game'; -import { playerMovement } from '../apis/player_movement'; -import { scaling } from '../apis/scaling'; +const random_id = () => Math.random().toString(36).slice(2, 5); /** * Entity Manager is used to access the information about the entities, that are currently drawn on the screen. @@ -13,13 +11,13 @@ import { scaling } from '../apis/scaling'; */ class EntityManager extends Extension { #entities: Entity[] = []; - #entitiesUpdated: Entity[] = []; + #entitiesLastFrame: Entity[] = this.#entities; constructor() { super(() => { - game.on('frame', () => { - this.#entities = this.#entitiesUpdated; - this.#entitiesUpdated = []; + game.on('frame_end', () => { + this.#entitiesLastFrame = this.#entities; + this.#entities = []; }); this.#triangleHook(); @@ -53,58 +51,60 @@ class EntityManager extends Extension { } /** - * Adds the entity to `#entitiesUpdated`. + * Adds the entity to `#entities`. * - * Will either find the entity in `#entities` or create a new `Entity`. + * Will either find the entity in `#entitiesLastFrame` or create a new `Entity`. */ #add(type: EntityType, position: Vector, extras: object = {}) { - const entityIndex = this.#findEntity(type, position); - - let entity: Entity; - if (entityIndex === -1) { - let parent = null; - if (type == EntityType.Bullet) { - // TODO: we want to change this to EntityType.Barrel in the future? - const parentIndex = this.#findEntity(EntityType.Player, position, 300); - if (parentIndex >= 0) { - parent = this.entities[parentIndex]; - } - } + let entity = this.#findEntity(type, position); + + if (!entity) { + const parent = this.#findParent(type, position); entity = new Entity(type, parent, { - id: Math.random().toString(36).slice(2, 5), + id: random_id(), timestamp: performance.now(), ...extras, }); - } else { - entity = this.#entities[entityIndex]; } + //TODO: remove radius from extras + entity.extras.radius = (extras as any).radius; entity.updatePos(position); - this.#entitiesUpdated.push(entity); + this.#entities.push(entity); + } + + /** + * If an entity is newly created, try to find it's parent entity. + */ + #findParent(type: EntityType, position: Vector): Entity { + if (type == EntityType.Bullet) { + // TODO: do we want to change the parent entity to EntityType.Barrel in the future? + return this.#findEntity(EntityType.Player, position, 300); + } } /** - * Searches `#entities` for the entity that is closest to `position` and - * returns the __index__ of that entity or __-1__ if there is no match. + * Searches `#entitiesLastFrame` for the entity that is closest to `position` + * @returns the entity or null if there is no match. */ - #findEntity(type: EntityType, position: Vector, tolerance: number = 42): number { - let result = -1; + #findEntity(type: EntityType, position: Vector, tolerance: number = 42): Entity { + let result = null; let shortestDistance = Infinity; - this.#entities.forEach((x, i) => { - if (x.type !== type) return; + this.#entitiesLastFrame.forEach((entity, i) => { + if (entity.type !== type) return; - const distance = Vector.distance(x.position, position); + const distance = Vector.distance(entity.position, position); if (distance < shortestDistance) { shortestDistance = distance; - result = i; + result = entity; } }); if (shortestDistance > tolerance) { - return -1; + return null; } return result;