Removed Ship.movement_cost, in favor of engine-defined AP cost
Ship movement and AP consumption is now handled by MoveAction
This commit is contained in:
parent
55615600b8
commit
66f86b4ddb
|
@ -69,8 +69,8 @@ executable = ${js-tools:bin-bower}
|
|||
base-directory = ${buildout:directory}/src/vendor
|
||||
downloads = .
|
||||
packages =
|
||||
phaser-official
|
||||
jasmine
|
||||
phaser-official#2.2.2
|
||||
jasmine#2.1.3
|
||||
|
||||
[mkdir-var]
|
||||
recipe = z3c.recipe.mkdir
|
||||
|
|
|
@ -20,13 +20,17 @@ module SpaceTac.Game {
|
|||
first_turn: boolean;
|
||||
|
||||
// Create a battle between two fleets
|
||||
constructor(fleet1: Fleet, fleet2: Fleet) {
|
||||
constructor(fleet1: Fleet = null, fleet2: Fleet = null) {
|
||||
this.log = new BattleLog();
|
||||
this.fleets = [fleet1, fleet2];
|
||||
this.fleets = [fleet1 || new Fleet(), fleet2 || new Fleet()];
|
||||
this.play_order = [];
|
||||
this.playing_ship_index = null;
|
||||
this.playing_ship = null;
|
||||
this.first_turn = true;
|
||||
|
||||
this.fleets.forEach((fleet: Fleet) => {
|
||||
fleet.setBattle(this);
|
||||
});
|
||||
}
|
||||
|
||||
// Create a quick random battle, for testing purposes
|
||||
|
@ -100,9 +104,6 @@ module SpaceTac.Game {
|
|||
// This will call all necessary initialization steps (initiative, placement...)
|
||||
// This will not add any event to the battle log
|
||||
start(): void {
|
||||
this.fleets.forEach((fleet: Fleet) => {
|
||||
fleet.setBattle(this);
|
||||
});
|
||||
this.placeShips();
|
||||
this.throwInitiative();
|
||||
this.play_order.forEach((ship: Ship) => {
|
||||
|
|
|
@ -9,7 +9,7 @@ module SpaceTac.Game {
|
|||
// Equipment name
|
||||
name: string;
|
||||
|
||||
// Distance to target
|
||||
// Maximal distance allowed to target
|
||||
distance: number;
|
||||
|
||||
// Effect area's radius
|
||||
|
|
|
@ -13,8 +13,8 @@ module SpaceTac.Game {
|
|||
battle: Battle;
|
||||
|
||||
// Create a fleet, bound to a player
|
||||
constructor(player: Player) {
|
||||
this.player = player;
|
||||
constructor(player: Player = null) {
|
||||
this.player = player || new Player();
|
||||
this.ships = [];
|
||||
this.battle = null;
|
||||
}
|
||||
|
|
|
@ -37,9 +37,6 @@ module SpaceTac.Game {
|
|||
// Number of shield points (a shield wan absorb some damage to protect the hull)
|
||||
shield: Attribute;
|
||||
|
||||
// Number of action points used to make a 1.0 move
|
||||
movement_cost: number;
|
||||
|
||||
// List of slots, able to contain equipment
|
||||
slots: Slot[];
|
||||
|
||||
|
@ -49,7 +46,7 @@ module SpaceTac.Game {
|
|||
// Create a new ship inside a fleet
|
||||
constructor(fleet: Fleet = null, name: string = null) {
|
||||
this.attributes = new AttributeCollection();
|
||||
this.fleet = fleet;
|
||||
this.fleet = fleet || new Fleet();
|
||||
this.name = name;
|
||||
this.initiative = this.newAttribute(AttributeCode.Initiative);
|
||||
this.initiative.setMaximal(1);
|
||||
|
@ -58,11 +55,11 @@ module SpaceTac.Game {
|
|||
this.ap_recover = this.newAttribute(AttributeCode.AP_Recovery);
|
||||
this.hull = this.newAttribute(AttributeCode.Hull);
|
||||
this.shield = this.newAttribute(AttributeCode.Shield);
|
||||
this.movement_cost = 0.1;
|
||||
this.slots = [];
|
||||
|
||||
this.arena_x = 0;
|
||||
this.arena_y = 0;
|
||||
this.arena_angle = 0;
|
||||
|
||||
if (fleet) {
|
||||
fleet.addShip(this);
|
||||
|
@ -188,32 +185,17 @@ module SpaceTac.Game {
|
|||
}
|
||||
}
|
||||
|
||||
// Get the maximal position reachable in the arena with current action points
|
||||
getLongestMove(x: number, y: number): number[] {
|
||||
var dx = x - this.arena_x;
|
||||
var dy = y - this.arena_y;
|
||||
var length = Math.sqrt(dx * dx + dy * dy);
|
||||
var max_length = this.ap_current.current / this.movement_cost;
|
||||
if (max_length >= length) {
|
||||
return [x, y];
|
||||
} else {
|
||||
var factor = max_length / length;
|
||||
return [this.arena_x + dx * factor, this.arena_y + dy * factor];
|
||||
}
|
||||
}
|
||||
|
||||
// Move toward a location, consuming action points
|
||||
moveTo(x: number, y: number): void {
|
||||
var dest = this.getLongestMove(x, y);
|
||||
var dx = dest[0] - this.arena_x;
|
||||
var dy = dest[1] - this.arena_y;
|
||||
var distance = Math.sqrt(dx * dx + dy * dy);
|
||||
var cost = distance * this.movement_cost;
|
||||
// Move toward a location
|
||||
// This does not check or consume action points
|
||||
moveTo(x: number, y: number, log: boolean = true): void {
|
||||
var angle = Math.atan2(y - this.arena_y, x - this.arena_x);
|
||||
|
||||
this.setArenaPosition(this.arena_x + dx, this.arena_y + dy);
|
||||
this.setArenaFacingAngle(angle);
|
||||
this.useActionPoints(cost);
|
||||
|
||||
this.setArenaPosition(x, y);
|
||||
|
||||
if (log && this.getBattle()) {
|
||||
this.getBattle().log.add(new MoveEvent(this, x, y));
|
||||
}
|
||||
}
|
||||
|
||||
// Add an empty equipment slot of the given type
|
||||
|
|
|
@ -28,6 +28,13 @@ module SpaceTac.Game {
|
|||
return new Target(x, y, null);
|
||||
}
|
||||
|
||||
// Get distance to another target
|
||||
getDistanceTo(other: Target): number {
|
||||
var dx = other.x - this.x;
|
||||
var dy = other.y - this.y;
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
// Check if a target is in range from a specific point
|
||||
isInRange(x: number, y: number, radius: number): boolean {
|
||||
var dx = this.x - x;
|
||||
|
|
|
@ -13,13 +13,15 @@ module SpaceTac.Game {
|
|||
|
||||
checkLocationTarget(battle: Battle, ship: Ship, target: Target): Target {
|
||||
// TODO Should forbid to move too much near another ship
|
||||
var coords = ship.getLongestMove(target.x, target.y);
|
||||
return Target.newFromLocation(coords[0], coords[1]);
|
||||
var max_distance = this.equipment.distance * ship.ap_current.current / this.equipment.ap_usage;
|
||||
return target.constraintInRange(ship.arena_x, ship.arena_y, max_distance);
|
||||
}
|
||||
|
||||
protected customApply(battle: Battle, ship: Ship, target: Target): boolean {
|
||||
var distance = Target.newFromShip(ship).getDistanceTo(target);
|
||||
ship.moveTo(target.x, target.y);
|
||||
battle.log.add(new MoveEvent(ship, target.x, target.y));
|
||||
var cost = this.equipment.ap_usage * distance / this.equipment.distance;
|
||||
ship.useActionPoints(cost);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,9 @@ module SpaceTac.Game.Equipments {
|
|||
super(SlotType.Engine, "Conventional Engine");
|
||||
|
||||
this.min_level = new IntegerRange(1, 1);
|
||||
this.distance = new Range(50, 50);
|
||||
this.ap_usage = new Range(3);
|
||||
|
||||
this.addPermanentAttributeMaxEffect(AttributeCode.Initiative, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,10 +8,12 @@ module SpaceTac.Game {
|
|||
var ship = new Ship(null, "Test");
|
||||
ship.ap_current.setMaximal(20);
|
||||
ship.ap_current.set(6);
|
||||
ship.movement_cost = 2;
|
||||
ship.arena_x = 0;
|
||||
ship.arena_y = 0;
|
||||
var action = new MoveAction(null);
|
||||
var engine = new Equipment();
|
||||
engine.distance = 1;
|
||||
engine.ap_usage = 2;
|
||||
var action = new MoveAction(engine);
|
||||
|
||||
var result = action.checkTarget(null, ship, Target.newFromLocation(0, 2));
|
||||
expect(result).toEqual(Target.newFromLocation(0, 2));
|
||||
|
@ -37,14 +39,16 @@ module SpaceTac.Game {
|
|||
});
|
||||
|
||||
it("applies to ship location, battle log and AP", function () {
|
||||
var battle = new Battle(null, null);
|
||||
var ship = new Ship(null, "Test");
|
||||
var ship = new Ship();
|
||||
var battle = new Battle(ship.fleet);
|
||||
ship.ap_current.setMaximal(20);
|
||||
ship.ap_current.set(5);
|
||||
ship.movement_cost = 1;
|
||||
ship.arena_x = 0;
|
||||
ship.arena_y = 0;
|
||||
var action = new MoveAction(null);
|
||||
var engine = new Equipment();
|
||||
engine.distance = 1;
|
||||
engine.ap_usage = 1;
|
||||
var action = new MoveAction(engine);
|
||||
|
||||
var result = action.apply(battle, ship, Target.newFromLocation(10, 10));
|
||||
expect(result).toBe(true);
|
||||
|
@ -58,12 +62,18 @@ module SpaceTac.Game {
|
|||
expect(ship.arena_y).toBeCloseTo(3.535533, 0.00001);
|
||||
expect(ship.ap_current.current).toEqual(0);
|
||||
|
||||
expect(battle.log.events.length).toBe(1);
|
||||
expect(battle.log.events.length).toBe(2);
|
||||
|
||||
expect(battle.log.events[0].code).toEqual("move");
|
||||
expect(battle.log.events[0].ship).toBe(ship);
|
||||
expect(battle.log.events[0].target.ship).toBeNull();
|
||||
expect(battle.log.events[0].target.x).toBeCloseTo(3.535533, 0.00001);
|
||||
expect(battle.log.events[0].target.y).toBeCloseTo(3.535533, 0.00001);
|
||||
|
||||
expect(battle.log.events[1].code).toEqual("attr");
|
||||
expect(battle.log.events[1].ship).toBe(ship);
|
||||
expect((<AttributeChangeEvent>battle.log.events[1]).attribute).toEqual(
|
||||
new Attribute(AttributeCode.AP, 20, 0));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,49 +4,22 @@ module SpaceTac.Game {
|
|||
"use strict";
|
||||
|
||||
describe("Ship", function () {
|
||||
it("limits movement range by action points", function () {
|
||||
it("moves and computes facing angle", function () {
|
||||
var ship = new Ship(null, "Test");
|
||||
ship.ap_current.setMaximal(20);
|
||||
ship.ap_current.set(8);
|
||||
ship.movement_cost = 3;
|
||||
ship.setArenaFacingAngle(0);
|
||||
ship.setArenaPosition(50, 50);
|
||||
|
||||
var point = ship.getLongestMove(51, 52);
|
||||
expect(point).toEqual([51, 52]);
|
||||
|
||||
point = ship.getLongestMove(60, 55);
|
||||
expect(point[0]).toBeCloseTo(52.385139, 0.0001);
|
||||
expect(point[1]).toBeCloseTo(51.19256, 0.0001);
|
||||
});
|
||||
|
||||
it("moves and consumes action points", function () {
|
||||
var ship = new Ship(null, "Test");
|
||||
ship.ap_current.setMaximal(20);
|
||||
ship.ap_current.set(8);
|
||||
ship.movement_cost = 3;
|
||||
ship.setArenaPosition(50, 50);
|
||||
expect(ship.arena_x).toEqual(50);
|
||||
expect(ship.arena_y).toEqual(50);
|
||||
expect(ship.arena_angle).toEqual(0);
|
||||
|
||||
ship.moveTo(51, 50);
|
||||
expect(ship.ap_current.current).toEqual(5);
|
||||
expect(ship.arena_x).toEqual(51);
|
||||
expect(ship.arena_y).toEqual(50);
|
||||
|
||||
ship.moveTo(53, 50);
|
||||
expect(ship.ap_current.current).toBe(0);
|
||||
expect(ship.arena_x).toBeCloseTo(52.333333, 0.00001);
|
||||
expect(ship.arena_y).toEqual(50);
|
||||
});
|
||||
|
||||
it("computes facing angle", function () {
|
||||
var ship = new Ship(null, "Test");
|
||||
ship.ap_current.setMaximal(20);
|
||||
ship.ap_current.set(20);
|
||||
ship.movement_cost = 3;
|
||||
ship.arena_angle = 0;
|
||||
ship.setArenaPosition(50, 50);
|
||||
expect(ship.arena_angle).toEqual(0);
|
||||
|
||||
ship.moveTo(50, 50);
|
||||
expect(ship.arena_angle).toEqual(0);
|
||||
expect(ship.arena_angle).toBeCloseTo(3.14159265, 0.00001);
|
||||
|
||||
ship.moveTo(51, 51);
|
||||
expect(ship.arena_angle).toBeCloseTo(0.785398, 0.00001);
|
||||
|
@ -55,6 +28,8 @@ module SpaceTac.Game {
|
|||
expect(ship.arena_angle).toBeCloseTo(1.5707963, 0.00001);
|
||||
|
||||
ship.moveTo(52, 52);
|
||||
expect(ship.arena_x).toEqual(52);
|
||||
expect(ship.arena_y).toEqual(52);
|
||||
expect(ship.arena_angle).toEqual(0);
|
||||
|
||||
ship.moveTo(52, 50);
|
||||
|
|
Loading…
Reference in a new issue