1
0
Fork 0

Started work on arena grid

This commit is contained in:
Michaël Lemaire 2018-03-21 23:09:26 +01:00
parent d4635683e3
commit c28d7ba8eb
4 changed files with 80 additions and 0 deletions

View file

@ -0,0 +1,29 @@
module TK.SpaceTac.Specs {
function checkLocation(check: TestContext, got: IArenaLocation, expected_x: number, expected_y: number) {
check.equals(got.x, expected_x, `x differs (${got.x},${got.y}) (${expected_x},${expected_y})`);
check.equals(got.y, expected_y, `y differs (${got.x},${got.y}) (${expected_x},${expected_y})`);
}
testing("HexagonalArenaGrid", test => {
test.case("snaps coordinates to the nearest grid point, on a biased grid", check => {
let grid = new HexagonalArenaGrid(4, 0.75);
checkLocation(check, grid.snap({ x: 0, y: 0 }), 0, 0);
checkLocation(check, grid.snap({ x: 1, y: 0 }), 0, 0);
checkLocation(check, grid.snap({ x: 1.9, y: 0 }), 0, 0);
checkLocation(check, grid.snap({ x: 2.1, y: 0 }), 4, 0);
checkLocation(check, grid.snap({ x: 1, y: 1 }), 0, 0);
checkLocation(check, grid.snap({ x: 1, y: 2 }), 2, 3);
checkLocation(check, grid.snap({ x: -1, y: -1 }), 0, 0);
checkLocation(check, grid.snap({ x: -2, y: -2 }), -2, -3);
checkLocation(check, grid.snap({ x: -3, y: -1 }), -4, 0);
checkLocation(check, grid.snap({ x: 6, y: -5 }), 8, -6);
});
test.case("snaps coordinates to the nearest grid point, on a regular grid", check => {
let grid = new HexagonalArenaGrid(10);
checkLocation(check, grid.snap({ x: 0, y: 0 }), 0, 0);
checkLocation(check, grid.snap({ x: 8, y: 0 }), 10, 0);
checkLocation(check, grid.snap({ x: 1, y: 6 }), 5, 10 * Math.sqrt(0.75));
});
});
}

34
src/core/ArenaGrid.ts Normal file
View file

@ -0,0 +1,34 @@
module TK.SpaceTac {
/**
* Abstract grid for the arena where the battle takes place
*
* The grid is used to snap arena coordinates for ships and targets
*/
export interface IArenaGrid {
snap(loc: IArenaLocation): IArenaLocation;
}
/**
* 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 implements IArenaGrid {
private yunit: number;
constructor(private unit: number, private yfactor = Math.sqrt(0.75)) {
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);
}
}
}

View file

@ -3,6 +3,9 @@ module TK.SpaceTac {
* A turn-based battle between fleets
*/
export class Battle {
// Grid for the arena
grid?: IArenaGrid
// Battle outcome, if the battle has ended
outcome: BattleOutcome | null = null
@ -38,6 +41,8 @@ module TK.SpaceTac {
ai_playing = false
constructor(fleet1 = new Fleet(new Player("Attacker")), fleet2 = new Fleet(new Player("Defender")), width = 1808, height = 948) {
this.grid = new HexagonalArenaGrid(50);
this.fleets = [fleet1, fleet2];
this.ships = new RObjectContainer(fleet1.ships.concat(fleet2.ships));
this.play_order = [];

View file

@ -64,6 +64,18 @@ module TK.SpaceTac {
return new Target(x, y, null);
}
/**
* Snap to battle grid
*/
snap(grid: IArenaGrid): Target {
if (this.ship_id) {
return this;
} else {
let location = grid.snap(this);
return Target.newFromLocation(location.x, location.y);
}
}
// Get distance to another target
getDistanceTo(other: { x: number, y: number }): number {
var dx = other.x - this.x;