Added fading on actions that will become unavailable (WIP)
This commit is contained in:
parent
7236afe74b
commit
675a7f80c9
|
@ -36,7 +36,7 @@
|
|||
var queryString = new jasmine.QueryString({
|
||||
getWindowLocation: function() { return window.location; }
|
||||
});
|
||||
if (queryString.getParam('onlytests')) {
|
||||
if (queryString.getParam('onlytests') || queryString.getParam('spec')) {
|
||||
document.getElementById("-space-tac").hidden = true;
|
||||
} else {
|
||||
new SpaceTac.GameRouter();
|
||||
|
|
|
@ -21,8 +21,18 @@ module SpaceTac.Game {
|
|||
|
||||
// Check basic conditions to know if the ship can use this action at all
|
||||
// Method to reimplement to set conditions
|
||||
canBeUsed(battle: Battle, ship: Ship): boolean {
|
||||
return true;
|
||||
canBeUsed(battle: Battle, ship: Ship, remaining_ap: number = null): boolean {
|
||||
if (battle && battle.playing_ship !== ship) {
|
||||
// Ship is not playing
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check AP usage
|
||||
if (remaining_ap === null) {
|
||||
remaining_ap = ship.ap_current.current;
|
||||
}
|
||||
var ap_usage = this.equipment ? this.equipment.ap_usage : 0;
|
||||
return remaining_ap >= ap_usage;
|
||||
}
|
||||
|
||||
// Method to check if a target is applicable for this action
|
||||
|
|
|
@ -7,10 +7,6 @@ module SpaceTac.Game {
|
|||
super("endturn", false);
|
||||
}
|
||||
|
||||
canBeUsed(battle: Battle, ship: Ship): boolean {
|
||||
return battle.playing_ship === ship;
|
||||
}
|
||||
|
||||
protected customApply(battle: Battle, ship: Ship, target: Target): boolean {
|
||||
battle.advanceToNextShip();
|
||||
return true;
|
||||
|
|
|
@ -14,10 +14,6 @@ module SpaceTac.Game {
|
|||
this.can_target_space = can_target_space;
|
||||
}
|
||||
|
||||
canBeUsed(battle: Battle, ship: Ship): boolean {
|
||||
return ship.ap_current.current >= this.equipment.ap_usage;
|
||||
}
|
||||
|
||||
checkLocationTarget(battle: Battle, ship: Ship, target: Target): Target {
|
||||
if (this.can_target_space) {
|
||||
target = target.constraintInRange(ship.arena_x, ship.arena_y, this.equipment.distance);
|
||||
|
|
|
@ -7,8 +7,16 @@ module SpaceTac.Game {
|
|||
super("move", true, equipment);
|
||||
}
|
||||
|
||||
canBeUsed(battle: Battle, ship: Ship): boolean {
|
||||
return ship.ap_current.current > 0;
|
||||
canBeUsed(battle: Battle, ship: Ship, remaining_ap: number = null): boolean {
|
||||
if (battle && battle.playing_ship !== ship) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check AP usage
|
||||
if (remaining_ap === null) {
|
||||
remaining_ap = ship.ap_current.current;
|
||||
}
|
||||
return remaining_ap > 0.0001;
|
||||
}
|
||||
|
||||
checkLocationTarget(battle: Battle, ship: Ship, target: Target): Target {
|
||||
|
|
|
@ -199,6 +199,7 @@ module SpaceTac.Game.AI.Specs {
|
|||
var move = ai.checkBullyMove(ship2, weapon);
|
||||
expect(move).not.toBeNull();
|
||||
|
||||
battle.playing_ship = ai.ship;
|
||||
battle.log.clear();
|
||||
ai.applyMove(move);
|
||||
|
||||
|
|
33
src/scripts/game/specs/BaseAction.spec.ts
Normal file
33
src/scripts/game/specs/BaseAction.spec.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
/// <reference path="../../definitions/jasmine.d.ts"/>
|
||||
|
||||
module SpaceTac.Game {
|
||||
"use strict";
|
||||
|
||||
describe("BaseAction", function () {
|
||||
it("check if equipment can be used with remaining AP", function () {
|
||||
var equipment = new Equipment(SlotType.Armor);
|
||||
equipment.ap_usage = 3;
|
||||
var action = new BaseAction("test", false, equipment);
|
||||
var ship = new Ship();
|
||||
ship.addSlot(SlotType.Armor).attach(equipment);
|
||||
ship.ap_current.setMaximal(10);
|
||||
|
||||
expect(action.canBeUsed(null, ship)).toBe(false);
|
||||
|
||||
ship.ap_current.set(5);
|
||||
|
||||
expect(action.canBeUsed(null, ship)).toBe(true);
|
||||
expect(action.canBeUsed(null, ship, 4)).toBe(true);
|
||||
expect(action.canBeUsed(null, ship, 3)).toBe(true);
|
||||
expect(action.canBeUsed(null, ship, 2)).toBe(false);
|
||||
|
||||
ship.ap_current.set(3);
|
||||
|
||||
expect(action.canBeUsed(null, ship)).toBe(true);
|
||||
|
||||
ship.ap_current.set(2);
|
||||
|
||||
expect(action.canBeUsed(null, ship)).toBe(false);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -49,6 +49,7 @@ module SpaceTac.Game {
|
|||
engine.distance = 1;
|
||||
engine.ap_usage = 1;
|
||||
var action = new MoveAction(engine);
|
||||
battle.playing_ship = ship;
|
||||
|
||||
var result = action.apply(battle, ship, Target.newFromLocation(10, 10));
|
||||
expect(result).toBe(true);
|
||||
|
|
|
@ -22,6 +22,7 @@ module SpaceTac.View {
|
|||
this.loadImage("battle/actionbar.png");
|
||||
this.loadImage("battle/action-inactive.png");
|
||||
this.loadImage("battle/action-active.png");
|
||||
this.loadImage("battle/action-fading.png");
|
||||
this.loadImage("battle/actionpointsempty.png");
|
||||
this.loadImage("battle/actionpointsfull.png");
|
||||
this.loadImage("battle/arena/shipspritehover.png");
|
||||
|
|
|
@ -60,6 +60,19 @@ module SpaceTac.View {
|
|||
}
|
||||
}
|
||||
|
||||
// Update fading flags
|
||||
// ap_usage is the consumption of currently selected action
|
||||
updateFadings(ap_usage: number): void {
|
||||
var remaining_ap = this.ship.ap_current.current - ap_usage;
|
||||
if (remaining_ap < 0) {
|
||||
remaining_ap = 0;
|
||||
}
|
||||
|
||||
this.actions.forEach((icon: ActionIcon) => {
|
||||
icon.updateFadingStatus(remaining_ap);
|
||||
});
|
||||
}
|
||||
|
||||
// Set action icons from selected ship
|
||||
setShip(ship: Game.Ship): void {
|
||||
var action_bar = this;
|
||||
|
|
|
@ -15,6 +15,12 @@ module SpaceTac.View {
|
|||
// Related game action
|
||||
action: Game.BaseAction;
|
||||
|
||||
// True if the action can be used
|
||||
active: boolean;
|
||||
|
||||
// True if an action is currently selected, and this one won't be available after its use
|
||||
fading: boolean;
|
||||
|
||||
// Current targetting
|
||||
private targetting: Targetting;
|
||||
|
||||
|
@ -24,6 +30,9 @@ module SpaceTac.View {
|
|||
// Layer applied when the action is active
|
||||
private layer_active: Phaser.Image;
|
||||
|
||||
// Layer applied when the action will become unavailable if another action is played
|
||||
private layer_fading: Phaser.Image;
|
||||
|
||||
// Create an icon for a single ship action
|
||||
constructor(bar: ActionBar, x: number, y: number, ship: Game.Ship, action: Game.BaseAction) {
|
||||
this.bar = bar;
|
||||
|
@ -35,13 +44,21 @@ module SpaceTac.View {
|
|||
bar.addChild(this);
|
||||
|
||||
// Active layer
|
||||
this.active = false;
|
||||
this.layer_active = new Phaser.Image(this.game, 0, 0, "battle-action-active", 0);
|
||||
this.layer_active.visible = false;
|
||||
this.addChild(this.layer_active);
|
||||
|
||||
// Icon layer
|
||||
this.layer_icon = new Phaser.Image(this.game, 15, 18, "battle-actions-" + action.code, 0);
|
||||
this.addChild(this.layer_icon);
|
||||
|
||||
// Fading layer
|
||||
this.fading = false;
|
||||
this.layer_fading = new Phaser.Image(this.game, 0, 0, "battle-action-fading", 0);
|
||||
this.layer_fading.visible = false;
|
||||
this.addChild(this.layer_fading);
|
||||
|
||||
// Click process
|
||||
this.onInputUp.add(() => {
|
||||
this.processClick();
|
||||
|
@ -62,8 +79,14 @@ module SpaceTac.View {
|
|||
// End any previously selected action
|
||||
this.bar.actionEnded();
|
||||
|
||||
// Update fading statuses
|
||||
this.bar.updateFadings(this.action.equipment.ap_usage);
|
||||
|
||||
// Set the lighting color to highlight
|
||||
this.layer_active.tint = 0xFFD060;
|
||||
if (this.game.renderType !== Phaser.HEADLESS) {
|
||||
// Tint doesn't work in headless renderer
|
||||
this.layer_active.tint = 0xFFD060;
|
||||
}
|
||||
|
||||
if (this.action.needs_target) {
|
||||
// Switch to targetting mode (will apply action when a target is selected)
|
||||
|
@ -104,10 +127,16 @@ module SpaceTac.View {
|
|||
|
||||
// Update the active status, from the action canBeUsed result
|
||||
updateActiveStatus(): void {
|
||||
var active = this.action.canBeUsed(this.battleview.battle, this.ship);
|
||||
Animation.setVisibility(this.game, this.layer_active, active, 500);
|
||||
this.game.tweens.create(this.layer_icon).to({alpha: active ? 1 : 0.3}, 500).start();
|
||||
this.input.useHandCursor = active;
|
||||
this.active = this.action.canBeUsed(this.battleview.battle, this.ship);
|
||||
Animation.setVisibility(this.game, this.layer_active, this.active, 500);
|
||||
this.game.tweens.create(this.layer_icon).to({alpha: this.active ? 1 : 0.3}, 500).start();
|
||||
this.input.useHandCursor = this.active;
|
||||
}
|
||||
|
||||
// Update the fading status, given an hypothetical remaining AP
|
||||
updateFadingStatus(remaining_ap: number): void {
|
||||
this.fading = !this.action.canBeUsed(this.battleview.battle, this.ship, remaining_ap);
|
||||
Animation.setVisibility(this.game, this.layer_fading, this.fading, 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
87
src/scripts/view/specs/ActionBar.spec.ts
Normal file
87
src/scripts/view/specs/ActionBar.spec.ts
Normal file
|
@ -0,0 +1,87 @@
|
|||
/// <reference path="../../definitions/jasmine.d.ts"/>
|
||||
/// <reference path="TestGame.ts"/>
|
||||
|
||||
module SpaceTac.View.Specs {
|
||||
"use strict";
|
||||
|
||||
describe("ActionBar", () => {
|
||||
inbattleview_it("lists available actions for selected ship", (battleview: BattleView) => {
|
||||
var bar = battleview.action_bar;
|
||||
|
||||
// Ship not owned by current battleview player
|
||||
var ship = new Game.Ship();
|
||||
bar.setShip(ship);
|
||||
expect(bar.actions.length).toBe(0);
|
||||
|
||||
// Ship with no equipment (only endturn action)
|
||||
battleview.player = ship.getPlayer();
|
||||
bar.setShip(ship);
|
||||
expect(bar.actions.length).toBe(1);
|
||||
expect(bar.actions[0].action.code).toEqual("endturn");
|
||||
|
||||
// Add an engine, with move action
|
||||
ship.addSlot(Game.SlotType.Engine).attach((new Game.Equipments.ConventionalEngine()).generate());
|
||||
bar.setShip(ship);
|
||||
expect(bar.actions.length).toBe(2);
|
||||
expect(bar.actions[0].action.code).toEqual("move");
|
||||
|
||||
// Add a weapon, with fire action
|
||||
ship.addSlot(Game.SlotType.Weapon).attach((new Game.Equipments.GatlingGun()).generate());
|
||||
bar.setShip(ship);
|
||||
expect(bar.actions.length).toBe(3);
|
||||
expect(bar.actions[1].action.code).toEqual("fire-gatlinggun");
|
||||
});
|
||||
|
||||
inbattleview_it("mark actions that would become unavailable after use", (battleview: BattleView) => {
|
||||
var bar = battleview.action_bar;
|
||||
var ship = new Game.Ship();
|
||||
var engine = (new Game.Equipments.ConventionalEngine()).generate();
|
||||
engine.ap_usage = 8;
|
||||
engine.distance = 4;
|
||||
ship.addSlot(Game.SlotType.Engine).attach(engine);
|
||||
var weapon1 = (new Game.Equipments.GatlingGun()).generate();
|
||||
weapon1.ap_usage = 3;
|
||||
ship.addSlot(Game.SlotType.Weapon).attach(weapon1);
|
||||
var weapon2 = (new Game.Equipments.GatlingGun()).generate();
|
||||
weapon2.ap_usage = 5;
|
||||
ship.addSlot(Game.SlotType.Weapon).attach(weapon2);
|
||||
battleview.battle.playing_ship = ship;
|
||||
battleview.player = ship.getPlayer();
|
||||
|
||||
ship.ap_current.setMaximal(10);
|
||||
ship.ap_current.set(9);
|
||||
bar.setShip(ship);
|
||||
|
||||
expect(bar.actions.length).toBe(4);
|
||||
|
||||
var checkFading = (fading: number[], available: number[]) => {
|
||||
fading.forEach((index: number) => {
|
||||
var icon = bar.actions[index];
|
||||
expect(icon.fading).toBe(true);
|
||||
});
|
||||
available.forEach((index: number) => {
|
||||
var icon = bar.actions[index];
|
||||
expect(icon.fading).toBe(false);
|
||||
});
|
||||
};
|
||||
|
||||
// Weapon 1 leaves all choices open
|
||||
bar.actions[1].processClick();
|
||||
checkFading([], [0, 1, 2, 3]);
|
||||
|
||||
// Weapon 2 can't be fired twice
|
||||
bar.actions[2].processClick();
|
||||
checkFading([2], [0, 1, 3]);
|
||||
|
||||
// Not enough AP for both weapons
|
||||
ship.ap_current.set(7);
|
||||
bar.actions[2].processClick();
|
||||
checkFading([1, 2], [0, 3]);
|
||||
|
||||
// Not enough AP to move
|
||||
ship.ap_current.set(3);
|
||||
bar.actions[1].processClick();
|
||||
checkFading([0, 1, 2], [3]);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -5,15 +5,6 @@
|
|||
module SpaceTac.View.Specs {
|
||||
"use strict";
|
||||
|
||||
export function inbattleview_it(desc: string, func: (battleview: BattleView) => void) {
|
||||
var battleview = new BattleView();
|
||||
var battle = Game.Battle.newQuickRandom();
|
||||
var player = battle.playing_ship.getPlayer();
|
||||
ingame_it(desc, (game: Phaser.Game, state: Phaser.State) => {
|
||||
func(battleview);
|
||||
}, battleview, player, battle);
|
||||
}
|
||||
|
||||
describe("BattleView", () => {
|
||||
inbattleview_it("forwards events in targetting mode", (battleview: BattleView) => {
|
||||
expect(battleview.targetting).toBeNull();
|
||||
|
|
|
@ -7,6 +7,9 @@ module SpaceTac.View.Specs {
|
|||
export function ingame_it(desc: string, func: (game: Phaser.Game, state: Phaser.State) => void,
|
||||
state: Phaser.State = null, ...stateargs: any[]) {
|
||||
it(desc, (done: () => void) => {
|
||||
spyOn(console, "log").and.stub();
|
||||
spyOn(console, "warn").and.stub();
|
||||
|
||||
var game = new Phaser.Game(500, 500, Phaser.HEADLESS);
|
||||
|
||||
if (!state) {
|
||||
|
@ -31,4 +34,14 @@ module SpaceTac.View.Specs {
|
|||
game.state.start.apply(game.state, args);
|
||||
});
|
||||
}
|
||||
|
||||
// Test game wrapper, with a battleview initialized on a random battle
|
||||
export function inbattleview_it(desc: string, func: (battleview: BattleView) => void) {
|
||||
var battleview = new BattleView();
|
||||
var battle = Game.Battle.newQuickRandom();
|
||||
var player = battle.playing_ship.getPlayer();
|
||||
ingame_it(desc, (game: Phaser.Game, state: Phaser.State) => {
|
||||
func(battleview);
|
||||
}, battleview, player, battle);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue