1
0
Fork 0

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:
Michaël Lemaire 2015-01-29 01:00:00 +01:00 committed by Michaël Lemaire
parent 55615600b8
commit 66f86b4ddb
10 changed files with 63 additions and 83 deletions

View file

@ -69,8 +69,8 @@ executable = ${js-tools:bin-bower}
base-directory = ${buildout:directory}/src/vendor base-directory = ${buildout:directory}/src/vendor
downloads = . downloads = .
packages = packages =
phaser-official phaser-official#2.2.2
jasmine jasmine#2.1.3
[mkdir-var] [mkdir-var]
recipe = z3c.recipe.mkdir recipe = z3c.recipe.mkdir

View file

@ -20,13 +20,17 @@ module SpaceTac.Game {
first_turn: boolean; first_turn: boolean;
// Create a battle between two fleets // Create a battle between two fleets
constructor(fleet1: Fleet, fleet2: Fleet) { constructor(fleet1: Fleet = null, fleet2: Fleet = null) {
this.log = new BattleLog(); this.log = new BattleLog();
this.fleets = [fleet1, fleet2]; this.fleets = [fleet1 || new Fleet(), fleet2 || new Fleet()];
this.play_order = []; this.play_order = [];
this.playing_ship_index = null; this.playing_ship_index = null;
this.playing_ship = null; this.playing_ship = null;
this.first_turn = true; this.first_turn = true;
this.fleets.forEach((fleet: Fleet) => {
fleet.setBattle(this);
});
} }
// Create a quick random battle, for testing purposes // 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 call all necessary initialization steps (initiative, placement...)
// This will not add any event to the battle log // This will not add any event to the battle log
start(): void { start(): void {
this.fleets.forEach((fleet: Fleet) => {
fleet.setBattle(this);
});
this.placeShips(); this.placeShips();
this.throwInitiative(); this.throwInitiative();
this.play_order.forEach((ship: Ship) => { this.play_order.forEach((ship: Ship) => {

View file

@ -9,7 +9,7 @@ module SpaceTac.Game {
// Equipment name // Equipment name
name: string; name: string;
// Distance to target // Maximal distance allowed to target
distance: number; distance: number;
// Effect area's radius // Effect area's radius

View file

@ -13,8 +13,8 @@ module SpaceTac.Game {
battle: Battle; battle: Battle;
// Create a fleet, bound to a player // Create a fleet, bound to a player
constructor(player: Player) { constructor(player: Player = null) {
this.player = player; this.player = player || new Player();
this.ships = []; this.ships = [];
this.battle = null; this.battle = null;
} }

View file

@ -37,9 +37,6 @@ module SpaceTac.Game {
// Number of shield points (a shield wan absorb some damage to protect the hull) // Number of shield points (a shield wan absorb some damage to protect the hull)
shield: Attribute; shield: Attribute;
// Number of action points used to make a 1.0 move
movement_cost: number;
// List of slots, able to contain equipment // List of slots, able to contain equipment
slots: Slot[]; slots: Slot[];
@ -49,7 +46,7 @@ module SpaceTac.Game {
// Create a new ship inside a fleet // Create a new ship inside a fleet
constructor(fleet: Fleet = null, name: string = null) { constructor(fleet: Fleet = null, name: string = null) {
this.attributes = new AttributeCollection(); this.attributes = new AttributeCollection();
this.fleet = fleet; this.fleet = fleet || new Fleet();
this.name = name; this.name = name;
this.initiative = this.newAttribute(AttributeCode.Initiative); this.initiative = this.newAttribute(AttributeCode.Initiative);
this.initiative.setMaximal(1); this.initiative.setMaximal(1);
@ -58,11 +55,11 @@ module SpaceTac.Game {
this.ap_recover = this.newAttribute(AttributeCode.AP_Recovery); this.ap_recover = this.newAttribute(AttributeCode.AP_Recovery);
this.hull = this.newAttribute(AttributeCode.Hull); this.hull = this.newAttribute(AttributeCode.Hull);
this.shield = this.newAttribute(AttributeCode.Shield); this.shield = this.newAttribute(AttributeCode.Shield);
this.movement_cost = 0.1;
this.slots = []; this.slots = [];
this.arena_x = 0; this.arena_x = 0;
this.arena_y = 0; this.arena_y = 0;
this.arena_angle = 0;
if (fleet) { if (fleet) {
fleet.addShip(this); fleet.addShip(this);
@ -188,32 +185,17 @@ module SpaceTac.Game {
} }
} }
// Get the maximal position reachable in the arena with current action points // Move toward a location
getLongestMove(x: number, y: number): number[] { // This does not check or consume action points
var dx = x - this.arena_x; moveTo(x: number, y: number, log: boolean = true): void {
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;
var angle = Math.atan2(y - this.arena_y, x - this.arena_x); 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.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 // Add an empty equipment slot of the given type

View file

@ -28,6 +28,13 @@ module SpaceTac.Game {
return new Target(x, y, null); 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 // Check if a target is in range from a specific point
isInRange(x: number, y: number, radius: number): boolean { isInRange(x: number, y: number, radius: number): boolean {
var dx = this.x - x; var dx = this.x - x;

View file

@ -13,13 +13,15 @@ module SpaceTac.Game {
checkLocationTarget(battle: Battle, ship: Ship, target: Target): Target { checkLocationTarget(battle: Battle, ship: Ship, target: Target): Target {
// TODO Should forbid to move too much near another ship // TODO Should forbid to move too much near another ship
var coords = ship.getLongestMove(target.x, target.y); var max_distance = this.equipment.distance * ship.ap_current.current / this.equipment.ap_usage;
return Target.newFromLocation(coords[0], coords[1]); return target.constraintInRange(ship.arena_x, ship.arena_y, max_distance);
} }
protected customApply(battle: Battle, ship: Ship, target: Target): boolean { protected customApply(battle: Battle, ship: Ship, target: Target): boolean {
var distance = Target.newFromShip(ship).getDistanceTo(target);
ship.moveTo(target.x, target.y); 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; return true;
} }
} }

View file

@ -9,6 +9,9 @@ module SpaceTac.Game.Equipments {
super(SlotType.Engine, "Conventional Engine"); super(SlotType.Engine, "Conventional Engine");
this.min_level = new IntegerRange(1, 1); this.min_level = new IntegerRange(1, 1);
this.distance = new Range(50, 50);
this.ap_usage = new Range(3);
this.addPermanentAttributeMaxEffect(AttributeCode.Initiative, 1); this.addPermanentAttributeMaxEffect(AttributeCode.Initiative, 1);
} }

View file

@ -8,10 +8,12 @@ module SpaceTac.Game {
var ship = new Ship(null, "Test"); var ship = new Ship(null, "Test");
ship.ap_current.setMaximal(20); ship.ap_current.setMaximal(20);
ship.ap_current.set(6); ship.ap_current.set(6);
ship.movement_cost = 2;
ship.arena_x = 0; ship.arena_x = 0;
ship.arena_y = 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)); var result = action.checkTarget(null, ship, Target.newFromLocation(0, 2));
expect(result).toEqual(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 () { it("applies to ship location, battle log and AP", function () {
var battle = new Battle(null, null); var ship = new Ship();
var ship = new Ship(null, "Test"); var battle = new Battle(ship.fleet);
ship.ap_current.setMaximal(20); ship.ap_current.setMaximal(20);
ship.ap_current.set(5); ship.ap_current.set(5);
ship.movement_cost = 1;
ship.arena_x = 0; ship.arena_x = 0;
ship.arena_y = 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)); var result = action.apply(battle, ship, Target.newFromLocation(10, 10));
expect(result).toBe(true); expect(result).toBe(true);
@ -58,12 +62,18 @@ module SpaceTac.Game {
expect(ship.arena_y).toBeCloseTo(3.535533, 0.00001); expect(ship.arena_y).toBeCloseTo(3.535533, 0.00001);
expect(ship.ap_current.current).toEqual(0); 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].code).toEqual("move");
expect(battle.log.events[0].ship).toBe(ship); expect(battle.log.events[0].ship).toBe(ship);
expect(battle.log.events[0].target.ship).toBeNull(); 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.x).toBeCloseTo(3.535533, 0.00001);
expect(battle.log.events[0].target.y).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));
}); });
}); });
} }

View file

@ -4,49 +4,22 @@ module SpaceTac.Game {
"use strict"; "use strict";
describe("Ship", function () { describe("Ship", function () {
it("limits movement range by action points", function () { it("moves and computes facing angle", function () {
var ship = new Ship(null, "Test"); var ship = new Ship(null, "Test");
ship.ap_current.setMaximal(20); ship.setArenaFacingAngle(0);
ship.ap_current.set(8);
ship.movement_cost = 3;
ship.setArenaPosition(50, 50); ship.setArenaPosition(50, 50);
var point = ship.getLongestMove(51, 52); expect(ship.arena_x).toEqual(50);
expect(point).toEqual([51, 52]); expect(ship.arena_y).toEqual(50);
expect(ship.arena_angle).toEqual(0);
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);
ship.moveTo(51, 50); ship.moveTo(51, 50);
expect(ship.ap_current.current).toEqual(5);
expect(ship.arena_x).toEqual(51); expect(ship.arena_x).toEqual(51);
expect(ship.arena_y).toEqual(50); expect(ship.arena_y).toEqual(50);
expect(ship.arena_angle).toEqual(0);
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);
ship.moveTo(50, 50); ship.moveTo(50, 50);
expect(ship.arena_angle).toEqual(0); expect(ship.arena_angle).toBeCloseTo(3.14159265, 0.00001);
ship.moveTo(51, 51); ship.moveTo(51, 51);
expect(ship.arena_angle).toBeCloseTo(0.785398, 0.00001); 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); expect(ship.arena_angle).toBeCloseTo(1.5707963, 0.00001);
ship.moveTo(52, 52); ship.moveTo(52, 52);
expect(ship.arena_x).toEqual(52);
expect(ship.arena_y).toEqual(52);
expect(ship.arena_angle).toEqual(0); expect(ship.arena_angle).toEqual(0);
ship.moveTo(52, 50); ship.moveTo(52, 50);