105 lines
3 KiB
TypeScript
105 lines
3 KiB
TypeScript
module TK.SpaceTac {
|
|
/**
|
|
* Abstract grid for the arena where the battle takes place
|
|
*
|
|
* The grid is used to snap arena coordinates on grid vertices, for ships and targets
|
|
*
|
|
* The default implementation does not enforce any grid or unit (leaves coordinates as they are)
|
|
*/
|
|
export class ArenaGrid {
|
|
/**
|
|
* Get the base unit of measurement between two points
|
|
*/
|
|
getUnit(): number {
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* Check that an arena location is on a grid vertex
|
|
*/
|
|
check(loc: IArenaLocation): boolean {
|
|
return arenaDistance(loc, this.snap(loc)) < 1e-8;
|
|
}
|
|
|
|
/**
|
|
* Snap a floating point arena location to a grid vertex
|
|
*/
|
|
snap(loc: IArenaLocation): IArenaLocation {
|
|
return loc;
|
|
}
|
|
|
|
/**
|
|
* Measure the distance between two points
|
|
*
|
|
* This returns a distance in grid units
|
|
*/
|
|
measure(loc1: IArenaLocation, loc2: IArenaLocation): number {
|
|
return arenaDistance(this.snap(loc1), this.snap(loc2));
|
|
}
|
|
|
|
/**
|
|
* Check that a location is in range of another
|
|
*/
|
|
inRange(loc1: IArenaLocation, loc2: IArenaLocation, range: number): boolean {
|
|
return this.measure(loc1, loc2) - range < 1e-8;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Pixel unbounded grid
|
|
*
|
|
* This will only round the coordinates to the pixels, with an optional unit for distance measurements
|
|
*/
|
|
export class PixelGrid extends ArenaGrid {
|
|
constructor(protected readonly unit = 1) {
|
|
super();
|
|
}
|
|
|
|
getUnit(): number {
|
|
return this.unit;
|
|
}
|
|
|
|
snap(loc: IArenaLocation): IArenaLocation {
|
|
return new ArenaLocation(Math.round(loc.x), Math.round(loc.y));
|
|
}
|
|
|
|
measure(loc1: IArenaLocation, loc2: IArenaLocation): number {
|
|
let d = super.measure(loc1, loc2) / this.unit;
|
|
let r = Math.round(d);
|
|
if (r >= d) {
|
|
return Math.floor(d);
|
|
} else if (r - d < 1e-8) {
|
|
return r;
|
|
} else {
|
|
return Math.ceil(d);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Hexagonal unbounded arena grid
|
|
*
|
|
* This grid is composed of regular hexagons where all vertices are at a same distance "unit" of the hexagon center
|
|
*/
|
|
export class HexagonalArenaGrid extends PixelGrid {
|
|
private readonly yunit: number;
|
|
|
|
constructor(unit: number, yfactor = Math.sqrt(0.75)) {
|
|
super(unit);
|
|
|
|
this.yunit = unit * yfactor;
|
|
}
|
|
|
|
snap(loc: IArenaLocation): IArenaLocation {
|
|
let yr = Math.round(loc.y / this.yunit);
|
|
let xr: number;
|
|
if (yr % 2 == 0) {
|
|
xr = Math.round(loc.x / this.unit);
|
|
} else {
|
|
xr = Math.round((loc.x - 0.5 * this.unit) / this.unit) + 0.5;
|
|
}
|
|
return new ArenaLocation((xr * this.unit) || 0, (yr * this.yunit) || 0);
|
|
}
|
|
}
|
|
}
|