manus4oHER's picture
Upload folder using huggingface_hub
eee16fe verified
Raw
History Blame Contribute Delete
5.26 kB
import GameEntity from '../domain/entities/game/GameEntity';
class Rectangle {
private readonly x: number;
private readonly y: number;
private readonly width: number;
private readonly height: number;
constructor(x: number, y: number, width: number, height: number) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
contains(x: number, y: number) {
return x >= this.x && x < this.x + this.width && y >= this.y && y < this.y + this.height;
}
}
export default class QuadTree {
private x: number;
private y: number;
private width: number;
private height: number;
private capacity: number;
private bounds: Rectangle;
private subdivided: boolean;
private entities: Map<number, GameEntity>;
private _nw: QuadTree | null;
private _ne: QuadTree | null;
private _sw: QuadTree | null;
private _se: QuadTree | null;
constructor(x: number, y: number, width: number, height: number, capacity: number) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.capacity = capacity;
this.bounds = new Rectangle(x, y, width, height);
this.subdivided = false;
this.entities = new Map();
this._nw = null;
this._ne = null;
this._sw = null;
this._se = null;
}
getEntities() {
return this.entities;
}
isSubdivided() {
return this.subdivided;
}
insert(entity: GameEntity): boolean {
if (!this.bounds.contains(entity.getPositionX(), entity.getPositionY())) {
return false;
}
if (this.entities.size < this.capacity && !this.subdivided) {
this.entities.set(entity.getVirtualId(), entity);
return true;
}
if (!this.subdivided) {
this.subdivide();
}
return (this._nw?.insert(entity) ||
this._ne?.insert(entity) ||
this._sw?.insert(entity) ||
this._se?.insert(entity))!;
}
remove(entity: GameEntity): boolean {
if (this.subdivided) {
return (this._nw?.remove(entity) ||
this._ne?.remove(entity) ||
this._sw?.remove(entity) ||
this._se?.remove(entity))!;
}
return this.entities.delete(entity.getVirtualId());
}
queryAround(x: number, y: number, radius: number, filter: number | null = null) {
const entities = new Map<number, GameEntity>();
this.queryAroundInternal(entities, x, y, radius, filter);
return entities;
}
queryAroundInternal(
entities: Map<number, GameEntity>,
x: number,
y: number,
radius: number,
filter: number | null = null,
) {
if (!this.circleIntersects(x, y, radius)) {
return;
}
if (this.subdivided) {
this._ne?.queryAroundInternal(entities, x, y, radius, filter);
this._nw?.queryAroundInternal(entities, x, y, radius, filter);
this._se?.queryAroundInternal(entities, x, y, radius, filter);
this._sw?.queryAroundInternal(entities, x, y, radius, filter);
} else {
for (const entity of this.entities.values()) {
if (filter !== null && entity.getEntityType() !== filter) {
continue;
}
const dx = entity.getPositionX() - x;
const dy = entity.getPositionY() - y;
if (dx * dx + dy * dy <= radius * radius) {
entities.set(entity.getVirtualId(), entity);
}
}
}
}
circleIntersects(x: number, y: number, radius: number) {
const halfWidth = this.width / 2;
const halfHeight = this.height / 2;
const centerX = this.x + halfWidth;
const centerY = this.y + halfHeight;
const xDist = Math.abs(centerX - x);
const yDist = Math.abs(centerY - y);
const edges = (xDist - halfWidth) ** 2 + (yDist - halfHeight) ** 2;
if (xDist > radius + halfWidth || yDist > radius + halfHeight) {
return false;
}
if (xDist <= halfWidth || yDist <= halfHeight) {
return true;
}
return edges <= radius * radius;
}
subdivide() {
const halfWidth = this.width / 2;
const halfHeight = this.height / 2;
this._nw = new QuadTree(this.x, this.y, halfWidth, halfHeight, this.capacity);
this._ne = new QuadTree(this.x, this.y + halfHeight, halfWidth, halfHeight, this.capacity);
this._sw = new QuadTree(this.x + halfWidth, this.y, halfWidth, halfHeight, this.capacity);
this._se = new QuadTree(this.x + halfWidth, this.y + halfHeight, halfWidth, halfHeight, this.capacity);
this.subdivided = true;
for (const entity of this.entities.values()) {
this._nw.insert(entity) || this._ne.insert(entity) || this._sw.insert(entity) || this._se.insert(entity);
}
this.entities.clear();
}
updatePosition(entity: GameEntity) {
this.remove(entity);
this.insert(entity);
}
}