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
|
* 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)
|
* Improve arena ships layering (sometimes information is displayed behind other sprites)
|
||||||
* In the ship tooltip, show power cost, toggled and overheat states
|
* In the ship tooltip, show power cost, toggled and overheat states
|
||||||
* Display shield (and its (dis)appearance)
|
* Display shield (and its (dis)appearance)
|
||||||
|
|
|
@ -5,6 +5,18 @@ module TK.SpaceTac.Specs {
|
||||||
}
|
}
|
||||||
|
|
||||||
testing("HexagonalArenaGrid", test => {
|
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 => {
|
test.case("snaps coordinates to the nearest grid point, on a biased grid", check => {
|
||||||
let grid = new HexagonalArenaGrid(4, 0.75);
|
let grid = new HexagonalArenaGrid(4, 0.75);
|
||||||
checkLocation(check, grid.snap({ x: 0, y: 0 }), 0, 0);
|
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
|
* 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 {
|
export class ArenaGrid {
|
||||||
snap(loc: IArenaLocation): IArenaLocation;
|
/**
|
||||||
|
* 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 {
|
snap(loc: IArenaLocation): IArenaLocation {
|
||||||
return new ArenaLocation(Math.round(loc.x), Math.round(loc.y));
|
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
|
* 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 {
|
export class HexagonalArenaGrid extends PixelGrid {
|
||||||
private yunit: number;
|
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;
|
this.yunit = unit * yfactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ module TK.SpaceTac {
|
||||||
*/
|
*/
|
||||||
export class Battle {
|
export class Battle {
|
||||||
// Grid for the arena
|
// Grid for the arena
|
||||||
grid: IArenaGrid
|
grid: ArenaGrid
|
||||||
|
|
||||||
// Battle outcome, if the battle has ended
|
// Battle outcome, if the battle has ended
|
||||||
outcome: BattleOutcome | null = null
|
outcome: BattleOutcome | null = null
|
||||||
|
@ -34,8 +34,6 @@ module TK.SpaceTac {
|
||||||
// Size of the battle area
|
// Size of the battle area
|
||||||
width: number
|
width: number
|
||||||
height: number
|
height: number
|
||||||
border = 50
|
|
||||||
ship_separation = 100
|
|
||||||
|
|
||||||
// Indicator that an AI is playing
|
// Indicator that an AI is playing
|
||||||
ai_playing = false
|
ai_playing = false
|
||||||
|
|
|
@ -115,8 +115,6 @@ module TK.SpaceTac.Specs {
|
||||||
battle.fleets[0].addShip(ship);
|
battle.fleets[0].addShip(ship);
|
||||||
let ship1 = battle.fleets[0].addShip();
|
let ship1 = battle.fleets[0].addShip();
|
||||||
let moveaction = nn(simulator.findEngine());
|
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(350, 200), 100), ApproachSimulationError.NO_MOVE_NEEDED);
|
||||||
check.same(simulator.getApproach(moveaction, Target.newFromLocation(400, 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
|
// Playing ship
|
||||||
private ship: Ship,
|
private ship: Ship,
|
||||||
// Coordinates grid
|
// 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 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
|
* Returns the name of this ship
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -37,7 +37,7 @@ module TK.SpaceTac {
|
||||||
/**
|
/**
|
||||||
* Snap to battle grid
|
* Snap to battle grid
|
||||||
*/
|
*/
|
||||||
snap(grid: IArenaGrid): Target {
|
snap(grid: ArenaGrid): Target {
|
||||||
if (this.ship_id) {
|
if (this.ship_id) {
|
||||||
return this;
|
return this;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -75,7 +75,7 @@ module TK.SpaceTac {
|
||||||
if (this.distance_per_power == 0) {
|
if (this.distance_per_power == 0) {
|
||||||
return Infinity;
|
return Infinity;
|
||||||
} else if (target) {
|
} 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);
|
return Math.ceil(distance / this.distance_per_power);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -83,19 +83,16 @@ module TK.SpaceTac {
|
||||||
}
|
}
|
||||||
|
|
||||||
getRangeRadius(ship: Ship): number {
|
getRangeRadius(ship: Ship): number {
|
||||||
return this.getRangeRadiusForPower(ship);
|
return ship.getValue("power") * this.distance_per_power * ship.grid.getUnit();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the distance reachable with a given power
|
|
||||||
*/
|
|
||||||
getRangeRadiusForPower(ship: Ship, power = ship.getValue("power")): number {
|
|
||||||
return power * this.distance_per_power;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkLocationTarget(ship: Ship, target: Target): boolean {
|
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
|
// TODO Check the space is not occupied
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ module TK.SpaceTac {
|
||||||
|
|
||||||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||||
let engine = new MoveAction("Engine", {
|
let engine = new MoveAction("Engine", {
|
||||||
distance_per_power: 60,
|
distance_per_power: 1,
|
||||||
});
|
});
|
||||||
engine.configureCooldown(1, 1);
|
engine.configureCooldown(1, 1);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
||||||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||||
if (level == 1) {
|
if (level == 1) {
|
||||||
let engine = new MoveAction("Engine", {
|
let engine = new MoveAction("Engine", {
|
||||||
distance_per_power: 460,
|
distance_per_power: 9,
|
||||||
});
|
});
|
||||||
engine.configureCooldown(2, 1);
|
engine.configureCooldown(2, 1);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
||||||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||||
if (level == 1) {
|
if (level == 1) {
|
||||||
let engine = new MoveAction("Engine", {
|
let engine = new MoveAction("Engine", {
|
||||||
distance_per_power: 120,
|
distance_per_power: 3,
|
||||||
});
|
});
|
||||||
|
|
||||||
let laser = new TriggerAction("Wingspan Laser", {
|
let laser = new TriggerAction("Wingspan Laser", {
|
||||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
||||||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||||
if (level == 1) {
|
if (level == 1) {
|
||||||
let engine = new MoveAction("Engine", {
|
let engine = new MoveAction("Engine", {
|
||||||
distance_per_power: 240,
|
distance_per_power: 5,
|
||||||
});
|
});
|
||||||
|
|
||||||
let gatling = new TriggerAction("Gatling Gun", {
|
let gatling = new TriggerAction("Gatling Gun", {
|
||||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
||||||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||||
if (level == 1) {
|
if (level == 1) {
|
||||||
let engine = new MoveAction("Engine", {
|
let engine = new MoveAction("Engine", {
|
||||||
distance_per_power: 130,
|
distance_per_power: 3,
|
||||||
});
|
});
|
||||||
|
|
||||||
let missile = new TriggerAction("SubMunition Missile", {
|
let missile = new TriggerAction("SubMunition Missile", {
|
||||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
||||||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||||
if (level == 1) {
|
if (level == 1) {
|
||||||
let engine = new MoveAction("Main Engine", {
|
let engine = new MoveAction("Main Engine", {
|
||||||
distance_per_power: 420,
|
distance_per_power: 8,
|
||||||
});
|
});
|
||||||
|
|
||||||
let depleter = new TriggerAction("Power Depleter", {
|
let depleter = new TriggerAction("Power Depleter", {
|
||||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
||||||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||||
if (level == 1) {
|
if (level == 1) {
|
||||||
let engine = new MoveAction("Engine", {
|
let engine = new MoveAction("Engine", {
|
||||||
distance_per_power: 310,
|
distance_per_power: 6,
|
||||||
});
|
});
|
||||||
|
|
||||||
let missile = new TriggerAction("SubMunition Missile", {
|
let missile = new TriggerAction("SubMunition Missile", {
|
||||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
||||||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||||
if (level == 1) {
|
if (level == 1) {
|
||||||
let engine = new MoveAction("Engine", {
|
let engine = new MoveAction("Engine", {
|
||||||
distance_per_power: 120,
|
distance_per_power: 2,
|
||||||
});
|
});
|
||||||
|
|
||||||
let gatling = new TriggerAction("Gatling Gun", {
|
let gatling = new TriggerAction("Gatling Gun", {
|
||||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
||||||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||||
if (level == 1) {
|
if (level == 1) {
|
||||||
let engine = new MoveAction("Engine", {
|
let engine = new MoveAction("Engine", {
|
||||||
distance_per_power: 120,
|
distance_per_power: 2,
|
||||||
});
|
});
|
||||||
|
|
||||||
let gatling1 = new TriggerAction("Primary Gatling", {
|
let gatling1 = new TriggerAction("Primary Gatling", {
|
||||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
||||||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||||
if (level == 1) {
|
if (level == 1) {
|
||||||
let engine = new MoveAction("Engine", {
|
let engine = new MoveAction("Engine", {
|
||||||
distance_per_power: 220,
|
distance_per_power: 3,
|
||||||
});
|
});
|
||||||
engine.configureCooldown(1, 1);
|
engine.configureCooldown(1, 1);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ module TK.SpaceTac {
|
||||||
getLevelUpgrades(level: number): ShipUpgrade[] {
|
getLevelUpgrades(level: number): ShipUpgrade[] {
|
||||||
if (level == 1) {
|
if (level == 1) {
|
||||||
let engine = new MoveAction("Engine", {
|
let engine = new MoveAction("Engine", {
|
||||||
distance_per_power: 280,
|
distance_per_power: 5,
|
||||||
});
|
});
|
||||||
|
|
||||||
let laser = new TriggerAction("Prokhorov Laser", {
|
let laser = new TriggerAction("Prokhorov Laser", {
|
||||||
|
@ -29,7 +29,7 @@ module TK.SpaceTac {
|
||||||
hull.configureCooldown(1, 4);
|
hull.configureCooldown(1, 4);
|
||||||
|
|
||||||
let disengage = new MoveAction("Disengage", {
|
let disengage = new MoveAction("Disengage", {
|
||||||
distance_per_power: 1000,
|
distance_per_power: 20,
|
||||||
}, "ionthruster");
|
}, "ionthruster");
|
||||||
disengage.configureCooldown(1, 3);
|
disengage.configureCooldown(1, 3);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue