diff --git a/buildout.cfg b/buildout.cfg index 54e2a48..4c7734f 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -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 diff --git a/src/scripts/game/Battle.ts b/src/scripts/game/Battle.ts index 663d2e2..b1c9a43 100644 --- a/src/scripts/game/Battle.ts +++ b/src/scripts/game/Battle.ts @@ -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) => { diff --git a/src/scripts/game/Equipment.ts b/src/scripts/game/Equipment.ts index 5f2e744..43482f4 100644 --- a/src/scripts/game/Equipment.ts +++ b/src/scripts/game/Equipment.ts @@ -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 diff --git a/src/scripts/game/Fleet.ts b/src/scripts/game/Fleet.ts index 60cb25e..1ec363d 100644 --- a/src/scripts/game/Fleet.ts +++ b/src/scripts/game/Fleet.ts @@ -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; } diff --git a/src/scripts/game/Ship.ts b/src/scripts/game/Ship.ts index d516588..cb8b5d4 100644 --- a/src/scripts/game/Ship.ts +++ b/src/scripts/game/Ship.ts @@ -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 diff --git a/src/scripts/game/Target.ts b/src/scripts/game/Target.ts index a7d7674..fa90332 100644 --- a/src/scripts/game/Target.ts +++ b/src/scripts/game/Target.ts @@ -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; diff --git a/src/scripts/game/actions/MoveAction.ts b/src/scripts/game/actions/MoveAction.ts index cfa7493..55fe1e0 100644 --- a/src/scripts/game/actions/MoveAction.ts +++ b/src/scripts/game/actions/MoveAction.ts @@ -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; } } diff --git a/src/scripts/game/equipments/ConventionalEngine.ts b/src/scripts/game/equipments/ConventionalEngine.ts index d83455a..5781ea8 100644 --- a/src/scripts/game/equipments/ConventionalEngine.ts +++ b/src/scripts/game/equipments/ConventionalEngine.ts @@ -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); } diff --git a/src/scripts/game/specs/MoveAction.spec.ts b/src/scripts/game/specs/MoveAction.spec.ts index 5ef3d37..4f9a51b 100644 --- a/src/scripts/game/specs/MoveAction.spec.ts +++ b/src/scripts/game/specs/MoveAction.spec.ts @@ -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((battle.log.events[1]).attribute).toEqual( + new Attribute(AttributeCode.AP, 20, 0)); }); }); } diff --git a/src/scripts/game/specs/Ship.spec.ts b/src/scripts/game/specs/Ship.spec.ts index 180638b..2d64469 100644 --- a/src/scripts/game/specs/Ship.spec.ts +++ b/src/scripts/game/specs/Ship.spec.ts @@ -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);