diff --git a/src/assets/images/battle/waiting.png b/src/assets/images/battle/waiting.png new file mode 100644 index 0000000..5c1b7f0 Binary files /dev/null and b/src/assets/images/battle/waiting.png differ diff --git a/src/scripts/game/Battle.ts b/src/scripts/game/Battle.ts index 5091d9f..10e6803 100644 --- a/src/scripts/game/Battle.ts +++ b/src/scripts/game/Battle.ts @@ -41,15 +41,30 @@ module SpaceTac.Game { } // Create a quick random battle, for testing purposes - static newQuickRandom(): Battle { + static newQuickRandom(with_ai: boolean = false): Battle { var player1 = Player.newQuickRandom("John"); var player2 = Player.newQuickRandom("Carl"); var result = new Battle(player1.fleet, player2.fleet); + if (with_ai) { + player2.ai = new AI.BullyAI(player2.fleet); + } result.start(); return result; } + // Check if a player is able to play + // This can be used by the UI to determine if player interaction is allowed + canPlay(player: Player): boolean { + if (this.ended) { + return false; + } else if (this.playing_ship.getPlayer() === player) { + return this.playing_ship.isAbleToPlay(); + } else { + return false; + } + } + // Create play order, performing an initiative throw throwInitiative(gen: RandomGenerator = new RandomGenerator()): void { var play_order: Ship[] = []; @@ -160,6 +175,18 @@ module SpaceTac.Game { if (this.playing_ship) { this.playing_ship.startTurn(this.first_turn); + + if (!this.playing_ship.isAbleToPlay()) { + // If the ship is not able to play, wait a little, then advance to the next one + setTimeout(() => { + this.advanceToNextShip(log); + }, 2000); + } else if (this.playing_ship.getPlayer().ai) { + // TODO If the ship is managed by an AI, let it get to work + setTimeout(() => { + this.advanceToNextShip(log); + }, 2000); + } } if (log) { @@ -178,7 +205,7 @@ module SpaceTac.Game { ship.updateAttributes(); ship.restoreHealth(); }); - this.advanceToNextShip(false); + this.advanceToNextShip(); } // Force an injection of events in the battle log to simulate the initial state diff --git a/src/scripts/game/Player.ts b/src/scripts/game/Player.ts index 7edf8d3..ed64e04 100644 --- a/src/scripts/game/Player.ts +++ b/src/scripts/game/Player.ts @@ -6,9 +6,13 @@ module SpaceTac.Game { // Current fleet fleet: Fleet; + // AI playing (null for human player) + ai: AI.AbstractAI; + // Create a player, with an empty fleet constructor() { this.fleet = new Fleet(this); + this.ai = null; } // Create a quick random player, with a fleet, for testing purposes diff --git a/src/scripts/game/ai/AbstractAI.ts b/src/scripts/game/ai/AbstractAI.ts new file mode 100644 index 0000000..18433b7 --- /dev/null +++ b/src/scripts/game/ai/AbstractAI.ts @@ -0,0 +1,17 @@ +module SpaceTac.Game.AI { + "use strict"; + + // Base class for all Artificial Intelligence interaction + export class AbstractAI { + // The battle this AI is involved in + battle: Battle; + + // The fleet controlled by this AI + fleet: Fleet; + + constructor(fleet: Fleet) { + this.fleet = fleet; + this.battle = fleet.battle; + } + } +} diff --git a/src/scripts/game/ai/BullyAI.ts b/src/scripts/game/ai/BullyAI.ts new file mode 100644 index 0000000..4662c5b --- /dev/null +++ b/src/scripts/game/ai/BullyAI.ts @@ -0,0 +1,11 @@ +/// +module SpaceTac.Game.AI { + "use strict"; + + // Basic Artificial Intelligence, with a tendency to move forward and shoot the nearest enemy + export class BullyAI extends AbstractAI { + constructor(fleet: Fleet) { + super(fleet); + } + } +} diff --git a/src/scripts/view/Main.ts b/src/scripts/view/Main.ts index 709a6e7..2b3b95b 100644 --- a/src/scripts/view/Main.ts +++ b/src/scripts/view/Main.ts @@ -4,7 +4,7 @@ module SpaceTac.View { export class Main extends Phaser.State { create() { // Switch to a test battle - var battle = Game.Battle.newQuickRandom(); + var battle = Game.Battle.newQuickRandom(true); this.game.state.start("battle", true, false, battle.fleets[0].player, battle); } } diff --git a/src/scripts/view/Preload.ts b/src/scripts/view/Preload.ts index 022a46f..6e130c3 100644 --- a/src/scripts/view/Preload.ts +++ b/src/scripts/view/Preload.ts @@ -11,12 +11,13 @@ module SpaceTac.View { this.load.setPreloadSprite(this.preloadBar); // Load assets - this.loadImage("battle/background.jpg"); + this.loadImage("battle/waiting.png"); this.loadImage("battle/shiplist-base.png"); this.loadImage("battle/shiplist-normal.png"); this.loadImage("battle/shiplist-playing.png"); this.loadImage("battle/shiplist-own.png"); this.loadImage("battle/shiplist-enemy.png"); + this.loadImage("battle/background.jpg"); this.loadImage("battle/arena/background.png"); this.loadImage("battle/actionbar.png"); this.loadImage("battle/action-inactive.png"); diff --git a/src/scripts/view/battle/ActionBar.ts b/src/scripts/view/battle/ActionBar.ts index 1222145..731b4e7 100644 --- a/src/scripts/view/battle/ActionBar.ts +++ b/src/scripts/view/battle/ActionBar.ts @@ -60,12 +60,16 @@ module SpaceTac.View { var action_bar = this; this.clearAll(); - var actions = ship.getAvailableActions(); - actions.forEach((action: Game.BaseAction) => { - action_bar.addAction(ship, action); - }); + if (ship.getPlayer() === this.battleview.player) { + var actions = ship.getAvailableActions(); + actions.forEach((action: Game.BaseAction) => { + action_bar.addAction(ship, action); + }); - this.ship = ship; + this.ship = ship; + } else { + this.ship = null; + } this.updateActionPoints(); } diff --git a/src/scripts/view/battle/BattleView.ts b/src/scripts/view/battle/BattleView.ts index 35cea10..a82f6c1 100644 --- a/src/scripts/view/battle/BattleView.ts +++ b/src/scripts/view/battle/BattleView.ts @@ -40,6 +40,12 @@ module SpaceTac.View { // Subscription to the battle log log_processor: LogProcessor; + // True if player interaction is allowed + interacting: boolean; + + // Indicator of interaction disabled + icon_waiting: Phaser.Image; + // Init the view, binding it to a specific battle init(player: Game.Player, battle: Game.Battle) { this.player = player; @@ -74,6 +80,11 @@ module SpaceTac.View { this.card_playing = new ShipCard(this, 1060, 130); this.card_hovered = new ShipCard(this, 1060, 430); + this.icon_waiting = new Phaser.Image(this.game, 640, 360, "battle-waiting", 0); + this.icon_waiting.anchor.set(0.5, 0.5); + game.add.existing(this.icon_waiting); + game.tweens.create(this.icon_waiting).to({"angle": 360}, 3000).repeat(-1).start(); + // Start processing the battle log this.log_processor = new LogProcessor(this); } @@ -153,9 +164,22 @@ module SpaceTac.View { } } + // Enable or disable the global player interaction + // Disable interaction when it is the AI turn, or when the current ship can't play + setInteractionEnabled(enabled: boolean): void { + this.exitTargettingMode(); + this.interacting = enabled; + + this.icon_waiting.visible = !this.interacting; + } + // Enter targetting mode // While in this mode, the Targetting object will receive hover and click events, and handle them enterTargettingMode(): Targetting { + if (!this.interacting) { + return null; + } + if (this.targetting) { this.exitTargettingMode(); } diff --git a/src/scripts/view/battle/LogProcessor.ts b/src/scripts/view/battle/LogProcessor.ts index 9cc9ab3..1d3dc1a 100644 --- a/src/scripts/view/battle/LogProcessor.ts +++ b/src/scripts/view/battle/LogProcessor.ts @@ -62,6 +62,8 @@ module SpaceTac.View { this.view.ship_list.setPlaying(event.target.ship); this.view.card_playing.setShip(event.target.ship); this.view.action_bar.setShip(event.target.ship); + + this.view.setInteractionEnabled(this.battle.canPlay(this.view.player)); } // Damage to ship diff --git a/src/scripts/view/specs/BattleView.spec.ts b/src/scripts/view/specs/BattleView.spec.ts index 8fe0529..50bfd6d 100644 --- a/src/scripts/view/specs/BattleView.spec.ts +++ b/src/scripts/view/specs/BattleView.spec.ts @@ -8,7 +8,7 @@ module SpaceTac.View.Specs { export function inbattleview_it(desc: string, func: (battleview: BattleView) => void) { var battleview = new BattleView(); var battle = Game.Battle.newQuickRandom(); - var player = battle.fleets[0].player; + var player = battle.playing_ship.getPlayer(); ingame_it(desc, (game: Phaser.Game, state: Phaser.State) => { func(battleview); }, battleview, player, battle);