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
downloads = .
packages =
phaser-official
jasmine
phaser-official#2.2.2
jasmine#2.1.3
[mkdir-var]
recipe = z3c.recipe.mkdir

View file

@ -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) => {

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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));
});
});
}

View file

@ -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);