WIP
This commit is contained in:
parent
c608ac2a08
commit
fc0f9210dd
1
TODO.md
1
TODO.md
|
@ -41,6 +41,7 @@ Battle
|
|||
------
|
||||
|
||||
* Fix tactical information being hidden when changing selected action
|
||||
* Right click while targetting switch to edit mode (move target and fire target are then draggable) - this will be the default on mobile
|
||||
* Improve arena ships layering (sometimes information is displayed behind other sprites)
|
||||
* In the ship tooltip, show power cost, toggled and overheat states
|
||||
* Display shield (and its (dis)appearance)
|
||||
|
|
|
@ -5,6 +5,18 @@ module TK.SpaceTac.Specs {
|
|||
}
|
||||
|
||||
testing("HexagonalArenaGrid", test => {
|
||||
test.case("checks coordinates", check => {
|
||||
let grid = new HexagonalArenaGrid(5, 1);
|
||||
check.equals(grid.check({ x: 0, y: 0 }), true, "0,0");
|
||||
check.equals(grid.check({ x: 1, y: 0 }), false, "1,0");
|
||||
check.equals(grid.check({ x: 5, y: 0 }), true, "5,0");
|
||||
check.equals(grid.check({ x: 6, y: 0 }), false, "6,0");
|
||||
check.equals(grid.check({ x: 0, y: 5 }), false, "0,5");
|
||||
check.equals(grid.check({ x: 2.5, y: 5 }), true, "2.5,5");
|
||||
check.equals(grid.check({ x: 5, y: 5 }), false, "5,5");
|
||||
check.equals(grid.check({ x: 7.5, y: 5 }), true, "7.5,5");
|
||||
});
|
||||
|
||||
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);
|
||||
|
|
|
@ -2,21 +2,59 @@ 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
|
||||
* 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 interface IArenaGrid {
|
||||
snap(loc: IArenaLocation): IArenaLocation;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pixel grid
|
||||
* Pixel unbounded grid
|
||||
*
|
||||
* This will only round the coordinates to the pixels
|
||||
* This will only round the coordinates to the pixels, with an optional unit for distance measurements
|
||||
*/
|
||||
export class PixelGrid implements IArenaGrid {
|
||||
export class PixelGrid extends ArenaGrid {
|
||||
constructor(protected readonly unit = 1) {
|
||||
super();
|
||||
}
|
||||
|
||||
snap(loc: IArenaLocation): IArenaLocation {
|
||||
return new ArenaLocation(Math.round(loc.x), Math.round(loc.y));
|
||||
}
|
||||
|
||||
measure(loc1: IArenaLocation, loc2: IArenaLocation): number {
|
||||
return Math.round(super.measure(loc1, loc2) / this.unit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,10 +62,12 @@ module TK.SpaceTac {
|
|||
*
|
||||
* 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;
|
||||
export class HexagonalArenaGrid extends PixelGrid {
|
||||
private readonly yunit: number;
|
||||
|
||||
constructor(unit: number, yfactor = Math.sqrt(0.75)) {
|
||||
super(unit);
|
||||
|
||||
constructor(private unit: number, private yfactor = Math.sqrt(0.75)) {
|
||||
this.yunit = unit * yfactor;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ module TK.SpaceTac {
|
|||
*/
|
||||
export class Battle {
|
||||
// Grid for the arena
|
||||
grid: IArenaGrid
|
||||
grid: ArenaGrid
|
||||
|
||||
// Battle outcome, if the battle has ended
|
||||
outcome: BattleOutcome | null = null
|
||||
|
@ -34,8 +34,6 @@ module TK.SpaceTac {
|
|||
// Size of the battle area
|
||||
width: number
|
||||
height: number
|
||||
border = 50
|
||||
ship_separation = 100
|
||||
|
||||
// Indicator that an AI is playing
|
||||
ai_playing = false
|
||||
|
|
|
@ -115,8 +115,6 @@ module TK.SpaceTac.Specs {
|
|||
battle.fleets[0].addShip(ship);
|
||||
let ship1 = battle.fleets[0].addShip();
|
||||
let moveaction = nn(simulator.findEngine());
|
||||
(<any>moveaction).safety_distance = 30;
|
||||
battle.ship_separation = 30;
|
||||
|
||||
check.same(simulator.getApproach(moveaction, Target.newFromLocation(350, 200), 100), ApproachSimulationError.NO_MOVE_NEEDED);
|
||||
check.same(simulator.getApproach(moveaction, Target.newFromLocation(400, 200), 100), ApproachSimulationError.NO_MOVE_NEEDED);
|
||||
|
|
|
@ -50,7 +50,7 @@ module TK.SpaceTac {
|
|||
// Playing ship
|
||||
private ship: Ship,
|
||||
// Coordinates grid
|
||||
private grid: IArenaGrid
|
||||
private grid: ArenaGrid
|
||||
) { }
|
||||
|
||||
/**
|
||||
|
|
|
@ -78,6 +78,18 @@ module TK.SpaceTac {
|
|||
return new ArenaLocationAngle(this.arena_x, this.arena_y, this.arena_angle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current grid for the ship
|
||||
*/
|
||||
get grid(): ArenaGrid {
|
||||
let battle = this.getBattle();
|
||||
if (battle) {
|
||||
return battle.grid;
|
||||
} else {
|
||||
return new ArenaGrid();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this ship
|
||||
*/
|
||||
|
|
|
@ -37,7 +37,7 @@ module TK.SpaceTac {
|
|||
/**
|
||||
* Snap to battle grid
|
||||
*/
|
||||
snap(grid: IArenaGrid): Target {
|
||||
snap(grid: ArenaGrid): Target {
|
||||
if (this.ship_id) {
|
||||
return this;
|
||||
} else {
|
||||
|
|
|
@ -75,7 +75,7 @@ module TK.SpaceTac {
|
|||
if (this.distance_per_power == 0) {
|
||||
return Infinity;
|
||||
} else if (target) {
|
||||
let distance = Target.newFromShip(ship).getDistanceTo(target);
|
||||
let distance = ship.grid.measure(ship.location, target);
|
||||
return Math.ceil(distance / this.distance_per_power);
|
||||
} else {
|
||||
return 0;
|
||||
|
@ -83,19 +83,16 @@ module TK.SpaceTac {
|
|||
}
|
||||
|
||||
getRangeRadius(ship: Ship): number {
|
||||
return this.getRangeRadiusForPower(ship);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the distance reachable with a given power
|
||||
*/
|
||||
getRangeRadiusForPower(ship: Ship, power = ship.getValue("power")): number {
|
||||
return power * this.distance_per_power;
|
||||
return ship.getValue("power") * this.distance_per_power * ship.grid.getUnit();
|
||||
}
|
||||
|
||||
checkLocationTarget(ship: Ship, target: Target): boolean {
|
||||
// TODO Check it's on the grid
|
||||
if (!ship.grid.check(target)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO Check the space is not occupied
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ module TK.SpaceTac {
|
|||
|
||||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||
let engine = new MoveAction("Engine", {
|
||||
distance_per_power: 60,
|
||||
distance_per_power: 1,
|
||||
});
|
||||
engine.configureCooldown(1, 1);
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
|||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||
if (level == 1) {
|
||||
let engine = new MoveAction("Engine", {
|
||||
distance_per_power: 460,
|
||||
distance_per_power: 9,
|
||||
});
|
||||
engine.configureCooldown(2, 1);
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
|||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||
if (level == 1) {
|
||||
let engine = new MoveAction("Engine", {
|
||||
distance_per_power: 120,
|
||||
distance_per_power: 3,
|
||||
});
|
||||
|
||||
let laser = new TriggerAction("Wingspan Laser", {
|
||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
|||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||
if (level == 1) {
|
||||
let engine = new MoveAction("Engine", {
|
||||
distance_per_power: 240,
|
||||
distance_per_power: 5,
|
||||
});
|
||||
|
||||
let gatling = new TriggerAction("Gatling Gun", {
|
||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
|||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||
if (level == 1) {
|
||||
let engine = new MoveAction("Engine", {
|
||||
distance_per_power: 130,
|
||||
distance_per_power: 3,
|
||||
});
|
||||
|
||||
let missile = new TriggerAction("SubMunition Missile", {
|
||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
|||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||
if (level == 1) {
|
||||
let engine = new MoveAction("Main Engine", {
|
||||
distance_per_power: 420,
|
||||
distance_per_power: 8,
|
||||
});
|
||||
|
||||
let depleter = new TriggerAction("Power Depleter", {
|
||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
|||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||
if (level == 1) {
|
||||
let engine = new MoveAction("Engine", {
|
||||
distance_per_power: 310,
|
||||
distance_per_power: 6,
|
||||
});
|
||||
|
||||
let missile = new TriggerAction("SubMunition Missile", {
|
||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
|||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||
if (level == 1) {
|
||||
let engine = new MoveAction("Engine", {
|
||||
distance_per_power: 120,
|
||||
distance_per_power: 2,
|
||||
});
|
||||
|
||||
let gatling = new TriggerAction("Gatling Gun", {
|
||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
|||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||
if (level == 1) {
|
||||
let engine = new MoveAction("Engine", {
|
||||
distance_per_power: 120,
|
||||
distance_per_power: 2,
|
||||
});
|
||||
|
||||
let gatling1 = new TriggerAction("Primary Gatling", {
|
||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
|||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||
if (level == 1) {
|
||||
let engine = new MoveAction("Engine", {
|
||||
distance_per_power: 220,
|
||||
distance_per_power: 3,
|
||||
});
|
||||
engine.configureCooldown(1, 1);
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
|||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||
if (level == 1) {
|
||||
let engine = new MoveAction("Engine", {
|
||||
distance_per_power: 280,
|
||||
distance_per_power: 5,
|
||||
});
|
||||
|
||||
let laser = new TriggerAction("Prokhorov Laser", {
|
||||
|
@ -29,7 +29,7 @@ module TK.SpaceTac {
|
|||
hull.configureCooldown(1, 4);
|
||||
|
||||
let disengage = new MoveAction("Disengage", {
|
||||
distance_per_power: 1000,
|
||||
distance_per_power: 20,
|
||||
}, "ionthruster");
|
||||
disengage.configureCooldown(1, 3);
|
||||
|
||||
|
|
Loading…
Reference in a new issue