From 4efaafafd98deba26461e3fe6ab36aeb077628e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Wed, 31 Dec 2014 01:00:00 +0100 Subject: [PATCH] Added battle log system (WIP) --- src/scripts/game/Battle.ts | 24 +++++++++++-- src/scripts/game/BattleLog.ts | 19 ++++++++++ src/scripts/game/Target.ts | 29 ++++++++++++++++ src/scripts/game/events/BaseLogEvent.ts | 19 ++++++++++ src/scripts/game/events/ShipChangeEvent.ts | 8 +++++ src/scripts/specs/BattleLog.spec.ts | 40 ++++++++++++++++++++++ src/scripts/view/BattleView.ts | 16 +++++++++ src/scripts/view/Targetting.ts | 12 +++++++ src/scripts/view/widgets/CapabilityIcon.ts | 8 +++++ 9 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 src/scripts/game/BattleLog.ts create mode 100644 src/scripts/game/Target.ts create mode 100644 src/scripts/game/events/BaseLogEvent.ts create mode 100644 src/scripts/game/events/ShipChangeEvent.ts create mode 100644 src/scripts/specs/BattleLog.spec.ts create mode 100644 src/scripts/view/Targetting.ts create mode 100644 src/scripts/view/widgets/CapabilityIcon.ts diff --git a/src/scripts/game/Battle.ts b/src/scripts/game/Battle.ts index 4e4d23d..0a7a37a 100644 --- a/src/scripts/game/Battle.ts +++ b/src/scripts/game/Battle.ts @@ -1,6 +1,9 @@ module SpaceTac.Game { // A turn-based battle between fleets export class Battle { + // Log of all battle events + log: BattleLog; + // List of fleets engaged in battle fleets: Fleet[]; @@ -13,6 +16,7 @@ module SpaceTac.Game { // Create a battle between two fleets constructor(fleet1: Fleet, fleet2: Fleet) { + this.log = new BattleLog(); this.fleets = [fleet1, fleet2]; this.play_order = []; this.playing_ship_index = null; @@ -64,7 +68,9 @@ module SpaceTac.Game { // End the current ship turn, passing control to the next one in play order // If at the end of the play order, next turn will start automatically // Member 'play_order' must be defined before calling this function - advanceToNextShip(): void { + advanceToNextShip(log: boolean=true): void { + var previous_ship = this.playing_ship; + if (this.play_order.length == 0) { this.playing_ship_index = null; this.playing_ship = null; @@ -79,14 +85,28 @@ module SpaceTac.Game { } this.playing_ship = this.play_order[this.playing_ship_index]; } + + if (log) { + this.log.add(new Events.ShipChangeEvent(previous_ship, this.playing_ship)); + } } // Start the battle // This will call all necessary initialization steps (initiative, placement...) + // This will not add any event to the battle log start(): void { this.placeShips(); this.throwInitiative(); - this.advanceToNextShip(); + this.advanceToNextShip(false); + } + + // Force an injection of events in the battle log to simulate the initial state + // For instance, this may be called after 'start', to use the log subscription system + // to initialize a battle UI + injectInitialEvents(): void { + // TODO Simulate initial ship placement + // Simulate game turn + this.log.add(new Events.ShipChangeEvent(this.playing_ship, this.playing_ship)); } // Create a quick random battle, for testing purposes diff --git a/src/scripts/game/BattleLog.ts b/src/scripts/game/BattleLog.ts new file mode 100644 index 0000000..3975e48 --- /dev/null +++ b/src/scripts/game/BattleLog.ts @@ -0,0 +1,19 @@ +module SpaceTac.Game { + // Log of a battle + // This keeps track of all events in a battle + // It also allows to register a callback to receive these events + export class BattleLog { + // Full list of battle events + events: Events.BaseLogEvent[]; + + // Create an initially empty log + constructor() { + this.events = []; + } + + // Add a battle event to the log + add(event: Events.BaseLogEvent) { + this.events.push(event); + } + } +} \ No newline at end of file diff --git a/src/scripts/game/Target.ts b/src/scripts/game/Target.ts new file mode 100644 index 0000000..24e9a10 --- /dev/null +++ b/src/scripts/game/Target.ts @@ -0,0 +1,29 @@ +module SpaceTac.Game { + // Target for a capability + // This could be a location in space, or a ship + export class Target { + // Coordinates of the target + x: number; + y: number; + + // If the target is a ship, this attribute will be set + ship: Ship; + + // Standard constructor + constructor(x: number, y: number, ship: Ship) { + this.x = x; + this.y = y; + this.ship = ship; + } + + // Constructor to target a single ship + static newFromShip(ship: Ship): Target { + return new Target(ship.arena_x, ship.arena_y, ship); + } + + // Constructor to target a location in space + static newFromLocation(x: number, y: number): Target { + return new Target(x, y, null); + } + } +} \ No newline at end of file diff --git a/src/scripts/game/events/BaseLogEvent.ts b/src/scripts/game/events/BaseLogEvent.ts new file mode 100644 index 0000000..2b2fefb --- /dev/null +++ b/src/scripts/game/events/BaseLogEvent.ts @@ -0,0 +1,19 @@ +module SpaceTac.Game.Events { + // Base class for a BattleLog event + export class BaseLogEvent { + // Code of the event (its type) + code: string; + + // The ship causing the event (the one whose turn it is to play) + ship: Ship; + + // Target of the event + target: Target; + + constructor(code: string, ship: Ship = null, target: Target = null) { + this.code = code; + this.ship = ship; + this.target = target; + } + } +} \ No newline at end of file diff --git a/src/scripts/game/events/ShipChangeEvent.ts b/src/scripts/game/events/ShipChangeEvent.ts new file mode 100644 index 0000000..b75a84c --- /dev/null +++ b/src/scripts/game/events/ShipChangeEvent.ts @@ -0,0 +1,8 @@ +module SpaceTac.Game.Events { + // Battle event, when a ship turn ended, and advanced to a new one + export class ShipChangeEvent extends BaseLogEvent { + constructor(ship: Ship, new_ship: Ship) { + super("ship_change", ship, new_ship ? Target.newFromShip(new_ship) : null); + } + } +} \ No newline at end of file diff --git a/src/scripts/specs/BattleLog.spec.ts b/src/scripts/specs/BattleLog.spec.ts new file mode 100644 index 0000000..e5f10f5 --- /dev/null +++ b/src/scripts/specs/BattleLog.spec.ts @@ -0,0 +1,40 @@ +module SpaceTac.Specs { + + // Check a single game log event + function checkEvent(got: Game.Events.BaseLogEvent, ship: Game.Ship, code: string, + target_ship: Game.Ship = null, target_x: number = null, target_y: number = null): void { + if (target_ship) { + if (target_x === null) { + target_x = target_ship.arena_x; + } + if (target_y === null) { + target_y = target_ship.arena_y; + } + } + + expect(got.ship).toBe(ship); + expect(got.code).toEqual(code); + expect(got.target.ship).toBe(target_ship); + if (target_x === null) { + expect(got.target.x).toBeNull(); + } else { + expect(got.target.x).toBeCloseTo(target_x, 0.000001); + } + if (target_y === null) { + expect(got.target.y).toBeNull(); + } else { + expect(got.target.y).toBeCloseTo(target_y, 0.000001); + } + } + + describe("BattleLog", function () { + it("logs ship change events", function () { + var battle = Game.Battle.newQuickRandom(); + expect(battle.log.events.length).toBe(0); + + battle.advanceToNextShip(); + expect(battle.log.events.length).toBe(1); + checkEvent(battle.log.events[0], battle.play_order[0], "ship_change", battle.play_order[1]); + }); + }); +} \ No newline at end of file diff --git a/src/scripts/view/BattleView.ts b/src/scripts/view/BattleView.ts index 1bb43dc..6da2ae6 100644 --- a/src/scripts/view/BattleView.ts +++ b/src/scripts/view/BattleView.ts @@ -14,10 +14,14 @@ module SpaceTac.View { // Battleground container arena: Phaser.Group; + // Targetting mode (null if we're not in this mode) + targetting: Targetting; + // Init the view, binding it to a specific battle init(player, battle) { this.player = player; this.battle = battle; + this.targetting = null; } // Create view graphics @@ -56,5 +60,17 @@ module SpaceTac.View { this.arena.destroy(); this.arena = null; } + + // Enter targetting mode + // While in this mode, the Targetting object will receive hover and click events, and handle them + enterTargettingMode(): Targetting { + this.targetting = new Targetting(this); + return this.targetting; + } + + // Exit targetting mode + exitTargettingMode(): void { + this.targetting = null; + } } } diff --git a/src/scripts/view/Targetting.ts b/src/scripts/view/Targetting.ts new file mode 100644 index 0000000..8d27fa4 --- /dev/null +++ b/src/scripts/view/Targetting.ts @@ -0,0 +1,12 @@ +module SpaceTac.View { + // Targetting system + // Allows to pick a target for a capability + export class Targetting { + // Access to the parent battle view + private battleview: BattleView; + + constructor(battleview: BattleView) { + this.battleview = battleview; + } + } +} \ No newline at end of file diff --git a/src/scripts/view/widgets/CapabilityIcon.ts b/src/scripts/view/widgets/CapabilityIcon.ts new file mode 100644 index 0000000..8796cc0 --- /dev/null +++ b/src/scripts/view/widgets/CapabilityIcon.ts @@ -0,0 +1,8 @@ +module SpaceTac.View.Widgets { + // Icon to activate a ship capability (move, fire...) + export class CapabilityIcon extends Phaser.Button { + constructor(battleview: BattleView, x: number, y:number, code: string) { + super(battleview.game, x, y, 'capability-' + code); + } + } +} \ No newline at end of file