1
0
Fork 0

Added ship hovering system

This commit is contained in:
Michaël Lemaire 2014-12-31 01:00:00 +01:00 committed by Michaël Lemaire
parent 4efaafafd9
commit 37b7bd40d2
10 changed files with 213 additions and 20 deletions

View file

@ -103,10 +103,17 @@ module SpaceTac.Game {
// 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
// Attributes 'play_order' and 'playing_ship' should be defined before calling this
injectInitialEvents(): void {
// TODO Simulate initial ship placement
var log = this.log;
// Simulate initial ship placement
this.play_order.forEach((ship) => {
log.add(new Events.MoveEvent(ship, ship.arena_x, ship.arena_y));
});
// Simulate game turn
this.log.add(new Events.ShipChangeEvent(this.playing_ship, this.playing_ship));
log.add(new Events.ShipChangeEvent(this.playing_ship, this.playing_ship));
}
// Create a quick random battle, for testing purposes

View file

@ -6,14 +6,37 @@ module SpaceTac.Game {
// Full list of battle events
events: Events.BaseLogEvent[];
// List of subscribers
private subscribers: Function[];
// Create an initially empty log
constructor() {
this.events = [];
this.subscribers = [];
}
// Add a battle event to the log
add(event: Events.BaseLogEvent) {
this.events.push(event);
this.subscribers.forEach((subscriber) => {
subscriber(event);
});
}
// Subscribe a callback to receive further events
subscribe(callback: (event: Events.BaseLogEvent) => void): Function {
this.subscribers.push(callback);
return callback;
}
// Unsubscribe a callback
// Pass the value returned by 'subscribe' as argument
unsubscribe(callback: Function): void {
var index = this.subscribers.indexOf(callback);
if (index >= 0) {
this.subscribers.splice(index, 1);
}
}
}
}

View file

@ -0,0 +1,8 @@
module SpaceTac.Game.Events {
// Event logged when a ship moves
export class MoveEvent extends BaseLogEvent {
constructor(ship: Ship, x: number, y: number) {
super("move", ship, Target.newFromLocation(x, y));
}
}
}

View file

@ -1,4 +1,4 @@
/// <reference path="../definitions/jasmine.d.ts"/>
/// <reference path="../../definitions/jasmine.d.ts"/>
module SpaceTac.Specs {
describe("Battle", function () {

View file

@ -1,3 +1,5 @@
/// <reference path="../../definitions/jasmine.d.ts"/>
module SpaceTac.Specs {
// Check a single game log event
@ -27,7 +29,34 @@ module SpaceTac.Specs {
}
}
// Fake event
class FakeEvent extends Game.Events.BaseLogEvent {
constructor() {
super("fake");
}
}
describe("BattleLog", function () {
it("forwards events to subscribers, until unsubscribe", function () {
var log = new Game.BattleLog();
var received = [];
var fake = new FakeEvent();
var sub = log.subscribe(function (event) {
received.push(event);
});
log.add(fake);
expect(received).toEqual([fake]);
log.add(fake);
expect(received).toEqual([fake, fake]);
log.unsubscribe(sub);
log.add(fake);
expect(received).toEqual([fake, fake]);
});
it("logs ship change events", function () {
var battle = Game.Battle.newQuickRandom();
expect(battle.log.events.length).toBe(0);
@ -36,5 +65,19 @@ module SpaceTac.Specs {
expect(battle.log.events.length).toBe(1);
checkEvent(battle.log.events[0], battle.play_order[0], "ship_change", battle.play_order[1]);
});
it("can receive simulated initial state events", function (){
var battle = Game.Battle.newQuickRandom();
expect(battle.log.events.length).toBe(0);
battle.injectInitialEvents();
expect(battle.log.events.length).toBe(9);
for (var i = 0; i < 8; i++) {
checkEvent(battle.log.events[i], battle.play_order[i], "move", null, battle.play_order[i].arena_x, battle.play_order[i].arena_y);
}
checkEvent(battle.log.events[8], battle.playing_ship, "ship_change", battle.playing_ship);
});
});
}

View file

@ -1,4 +1,4 @@
/// <reference path="../definitions/jasmine.d.ts"/>
/// <reference path="../../definitions/jasmine.d.ts"/>
module SpaceTac.Specs {
describe("Ship", function(){

View file

@ -17,15 +17,30 @@ module SpaceTac.View {
// Targetting mode (null if we're not in this mode)
targetting: Targetting;
// Card to display current playing ship
card_playing: Widgets.ShipCard;
// Card to display hovered ship
card_hovered: Widgets.ShipCard;
// Currently hovered ship
ship_hovered: Game.Ship;
// Subscription to the battle log
log_subscription: any;
// Init the view, binding it to a specific battle
init(player, battle) {
this.player = player;
this.battle = battle;
this.targetting = null;
this.ship_hovered = null;
this.log_subscription = null;
}
// Create view graphics
create() {
var battleview = this;
var game = this.game;
var player = this.player;
@ -37,28 +52,83 @@ module SpaceTac.View {
game.add.existing(this.arena);
var arena = this.arena;
this.card_playing = new Widgets.ShipCard(this, 500, 0);
this.card_hovered = new Widgets.ShipCard(this, 500, 300);
game.stage.backgroundColor = 0x000000;
// Add ship buttons to UI
this.battle.play_order.forEach(function(ship: Game.Ship, rank: number){
new Widgets.ShipListItem(ui, 0, rank * 50, ship.getPlayer() === player);
this.battle.play_order.forEach(function (ship: Game.Ship, rank: number) {
new Widgets.ShipListItem(battleview, 0, rank * 50, ship, ship.getPlayer() === player);
});
// Add ship sprites to arena
this.battle.play_order.forEach(function(ship: Game.Ship){
new Arena.ShipArenaSprite(arena, ship);
this.battle.play_order.forEach(function (ship: Game.Ship) {
new Arena.ShipArenaSprite(battleview, ship);
});
// Subscribe to log events
this.battle.log.subscribe((event) => {
battleview.processBattleEvent(event);
});
this.battle.injectInitialEvents();
}
// Leaving the view, we unbind the battle
shutdown() {
if (this.log_subscription) {
this.battle.log.unsubscribe(this.log_subscription);
this.log_subscription = null;
}
if (this.ui) {
this.ui.destroy();
this.ui = null;
}
if (this.arena) {
this.arena.destroy();
this.arena = null;
}
if (this.card_playing) {
this.card_playing.destroy();
this.card_playing = null;
}
if (this.card_hovered) {
this.card_hovered.destroy();
this.card_hovered = null;
}
this.battle = null;
}
this.ui.destroy();
this.ui = null;
// Process a BaseLogEvent
processBattleEvent(event: Game.Events.BaseLogEvent) {
console.log("Battle event", event);
if (event.code == "ship_change") {
// Playing ship changed
this.card_playing.setShip(event.target.ship);
}
}
this.arena.destroy();
this.arena = null;
// Method called when cursor starts hovering over a ship (or its icon)
cursorOnShip(ship: Game.Ship): void {
this.setShipHovered(ship);
}
// Method called when cursor stops hovering over a ship (or its icon)
cursorOffShip(ship: Game.Ship): void {
if (this.ship_hovered === ship) {
this.setShipHovered(null);
}
}
// Set the currently hovered ship
setShipHovered(ship: Game.Ship): void {
this.ship_hovered = ship;
this.card_hovered.setShip(ship);
}
// Enter targetting mode

View file

@ -1,14 +1,21 @@
module SpaceTac.Arena {
module SpaceTac.View.Arena {
// Ship sprite in the arena (BattleView)
export class ShipArenaSprite extends Phaser.Sprite {
constructor(arena: Phaser.Group, ship: Game.Ship) {
super(arena.game, ship.arena_x, ship.arena_y, "arena-ship");
export class ShipArenaSprite extends Phaser.Button {
constructor(battleview: BattleView, ship: Game.Ship) {
super(battleview.game, ship.arena_x, ship.arena_y, "arena-ship");
this.scale.set(0.1, 0.1);
this.rotation = ship.arena_angle;
this.anchor.set(0.5, 0.5);
arena.add(this);
battleview.arena.add(this);
this.onInputOver.add(() => {
battleview.cursorOnShip(ship);
});
this.onInputOut.add(() => {
battleview.cursorOffShip(ship);
});
}
}
}

View file

@ -0,0 +1,23 @@
module SpaceTac.View.Widgets {
// Card to display detailed information about a ship
export class ShipCard extends Phaser.Sprite {
// Displayed ship
private ship: Game.Ship;
// Build an empty ship card
constructor(battleview: BattleView, x: number, y: number) {
super(battleview.game, x, y, "ui-ship-card");
this.ship = null;
this.visible = false;
battleview.ui.add(this);
}
// Set the currently displayed ship (null to hide)
setShip(ship: Game.Ship) {
this.ship = ship;
this.visible = (ship !== null);
}
}
}

View file

@ -1,10 +1,22 @@
module SpaceTac.View.Widgets {
// One item in a ship list (used in BattleView)
export class ShipListItem extends Phaser.Button {
// Reference to the ship game object
private ship: Game.Ship;
// Create a ship button for the battle ship list
constructor(ui: UIGroup, x: number, y: number, owned: boolean) {
super(ui.game, x, y, owned ? 'ui-shiplist-own' : 'ui-shiplist-enemy');
ui.add(this);
constructor(battleview: BattleView, x: number, y: number, ship:Game.Ship, owned: boolean) {
this.ship = ship;
super(battleview.game, x, y, owned ? 'ui-shiplist-own' : 'ui-shiplist-enemy');
battleview.ui.add(this);
this.onInputOver.add(() => {
battleview.cursorOnShip(ship);
});
this.onInputOut.add(() => {
battleview.cursorOffShip(ship);
});
}
}
}