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({
|
var queryString = new jasmine.QueryString({
|
||||||
getWindowLocation: function() { return window.location; }
|
getWindowLocation: function() { return window.location; }
|
||||||
});
|
});
|
||||||
if (queryString.getParam('onlytests')) {
|
if (queryString.getParam('onlytests') || queryString.getParam('spec')) {
|
||||||
document.getElementById("-space-tac").hidden = true;
|
document.getElementById("-space-tac").hidden = true;
|
||||||
} else {
|
} else {
|
||||||
new SpaceTac.GameRouter();
|
new SpaceTac.GameRouter();
|
||||||
|
|
|
@ -21,8 +21,18 @@ module SpaceTac.Game {
|
||||||
|
|
||||||
// Check basic conditions to know if the ship can use this action at all
|
// Check basic conditions to know if the ship can use this action at all
|
||||||
// Method to reimplement to set conditions
|
// Method to reimplement to set conditions
|
||||||
canBeUsed(battle: Battle, ship: Ship): boolean {
|
canBeUsed(battle: Battle, ship: Ship, remaining_ap: number = null): boolean {
|
||||||
return true;
|
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
|
// Method to check if a target is applicable for this action
|
||||||
|
|
|
@ -7,10 +7,6 @@ module SpaceTac.Game {
|
||||||
super("endturn", false);
|
super("endturn", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
canBeUsed(battle: Battle, ship: Ship): boolean {
|
|
||||||
return battle.playing_ship === ship;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected customApply(battle: Battle, ship: Ship, target: Target): boolean {
|
protected customApply(battle: Battle, ship: Ship, target: Target): boolean {
|
||||||
battle.advanceToNextShip();
|
battle.advanceToNextShip();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -14,10 +14,6 @@ module SpaceTac.Game {
|
||||||
this.can_target_space = can_target_space;
|
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 {
|
checkLocationTarget(battle: Battle, ship: Ship, target: Target): Target {
|
||||||
if (this.can_target_space) {
|
if (this.can_target_space) {
|
||||||
target = target.constraintInRange(ship.arena_x, ship.arena_y, this.equipment.distance);
|
target = target.constraintInRange(ship.arena_x, ship.arena_y, this.equipment.distance);
|
||||||
|
|
|
@ -7,8 +7,16 @@ module SpaceTac.Game {
|
||||||
super("move", true, equipment);
|
super("move", true, equipment);
|
||||||
}
|
}
|
||||||
|
|
||||||
canBeUsed(battle: Battle, ship: Ship): boolean {
|
canBeUsed(battle: Battle, ship: Ship, remaining_ap: number = null): boolean {
|
||||||
return ship.ap_current.current > 0;
|
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 {
|
checkLocationTarget(battle: Battle, ship: Ship, target: Target): Target {
|
||||||
|
|
|
@ -199,6 +199,7 @@ module SpaceTac.Game.AI.Specs {
|
||||||
var move = ai.checkBullyMove(ship2, weapon);
|
var move = ai.checkBullyMove(ship2, weapon);
|
||||||
expect(move).not.toBeNull();
|
expect(move).not.toBeNull();
|
||||||
|
|
||||||
|
battle.playing_ship = ai.ship;
|
||||||
battle.log.clear();
|
battle.log.clear();
|
||||||
ai.applyMove(move);
|
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.distance = 1;
|
||||||
engine.ap_usage = 1;
|
engine.ap_usage = 1;
|
||||||
var action = new MoveAction(engine);
|
var action = new MoveAction(engine);
|
||||||
|
battle.playing_ship = ship;
|
||||||
|
|
||||||
var result = action.apply(battle, ship, Target.newFromLocation(10, 10));
|
var result = action.apply(battle, ship, Target.newFromLocation(10, 10));
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
|
|
|
@ -22,6 +22,7 @@ module SpaceTac.View {
|
||||||
this.loadImage("battle/actionbar.png");
|
this.loadImage("battle/actionbar.png");
|
||||||
this.loadImage("battle/action-inactive.png");
|
this.loadImage("battle/action-inactive.png");
|
||||||
this.loadImage("battle/action-active.png");
|
this.loadImage("battle/action-active.png");
|
||||||
|
this.loadImage("battle/action-fading.png");
|
||||||
this.loadImage("battle/actionpointsempty.png");
|
this.loadImage("battle/actionpointsempty.png");
|
||||||
this.loadImage("battle/actionpointsfull.png");
|
this.loadImage("battle/actionpointsfull.png");
|
||||||
this.loadImage("battle/arena/shipspritehover.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
|
// Set action icons from selected ship
|
||||||
setShip(ship: Game.Ship): void {
|
setShip(ship: Game.Ship): void {
|
||||||
var action_bar = this;
|
var action_bar = this;
|
||||||
|
|
|
@ -15,6 +15,12 @@ module SpaceTac.View {
|
||||||
// Related game action
|
// Related game action
|
||||||
action: Game.BaseAction;
|
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
|
// Current targetting
|
||||||
private targetting: Targetting;
|
private targetting: Targetting;
|
||||||
|
|
||||||
|
@ -24,6 +30,9 @@ module SpaceTac.View {
|
||||||
// Layer applied when the action is active
|
// Layer applied when the action is active
|
||||||
private layer_active: Phaser.Image;
|
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
|
// Create an icon for a single ship action
|
||||||
constructor(bar: ActionBar, x: number, y: number, ship: Game.Ship, action: Game.BaseAction) {
|
constructor(bar: ActionBar, x: number, y: number, ship: Game.Ship, action: Game.BaseAction) {
|
||||||
this.bar = bar;
|
this.bar = bar;
|
||||||
|
@ -35,13 +44,21 @@ module SpaceTac.View {
|
||||||
bar.addChild(this);
|
bar.addChild(this);
|
||||||
|
|
||||||
// Active layer
|
// Active layer
|
||||||
|
this.active = false;
|
||||||
this.layer_active = new Phaser.Image(this.game, 0, 0, "battle-action-active", 0);
|
this.layer_active = new Phaser.Image(this.game, 0, 0, "battle-action-active", 0);
|
||||||
|
this.layer_active.visible = false;
|
||||||
this.addChild(this.layer_active);
|
this.addChild(this.layer_active);
|
||||||
|
|
||||||
// Icon layer
|
// Icon layer
|
||||||
this.layer_icon = new Phaser.Image(this.game, 15, 18, "battle-actions-" + action.code, 0);
|
this.layer_icon = new Phaser.Image(this.game, 15, 18, "battle-actions-" + action.code, 0);
|
||||||
this.addChild(this.layer_icon);
|
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
|
// Click process
|
||||||
this.onInputUp.add(() => {
|
this.onInputUp.add(() => {
|
||||||
this.processClick();
|
this.processClick();
|
||||||
|
@ -62,8 +79,14 @@ module SpaceTac.View {
|
||||||
// End any previously selected action
|
// End any previously selected action
|
||||||
this.bar.actionEnded();
|
this.bar.actionEnded();
|
||||||
|
|
||||||
|
// Update fading statuses
|
||||||
|
this.bar.updateFadings(this.action.equipment.ap_usage);
|
||||||
|
|
||||||
// Set the lighting color to highlight
|
// Set the lighting color to highlight
|
||||||
|
if (this.game.renderType !== Phaser.HEADLESS) {
|
||||||
|
// Tint doesn't work in headless renderer
|
||||||
this.layer_active.tint = 0xFFD060;
|
this.layer_active.tint = 0xFFD060;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.action.needs_target) {
|
if (this.action.needs_target) {
|
||||||
// Switch to targetting mode (will apply action when a target is selected)
|
// 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
|
// Update the active status, from the action canBeUsed result
|
||||||
updateActiveStatus(): void {
|
updateActiveStatus(): void {
|
||||||
var active = this.action.canBeUsed(this.battleview.battle, this.ship);
|
this.active = this.action.canBeUsed(this.battleview.battle, this.ship);
|
||||||
Animation.setVisibility(this.game, this.layer_active, active, 500);
|
Animation.setVisibility(this.game, this.layer_active, this.active, 500);
|
||||||
this.game.tweens.create(this.layer_icon).to({alpha: active ? 1 : 0.3}, 500).start();
|
this.game.tweens.create(this.layer_icon).to({alpha: this.active ? 1 : 0.3}, 500).start();
|
||||||
this.input.useHandCursor = active;
|
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 {
|
module SpaceTac.View.Specs {
|
||||||
"use strict";
|
"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", () => {
|
describe("BattleView", () => {
|
||||||
inbattleview_it("forwards events in targetting mode", (battleview: BattleView) => {
|
inbattleview_it("forwards events in targetting mode", (battleview: BattleView) => {
|
||||||
expect(battleview.targetting).toBeNull();
|
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,
|
export function ingame_it(desc: string, func: (game: Phaser.Game, state: Phaser.State) => void,
|
||||||
state: Phaser.State = null, ...stateargs: any[]) {
|
state: Phaser.State = null, ...stateargs: any[]) {
|
||||||
it(desc, (done: () => void) => {
|
it(desc, (done: () => void) => {
|
||||||
|
spyOn(console, "log").and.stub();
|
||||||
|
spyOn(console, "warn").and.stub();
|
||||||
|
|
||||||
var game = new Phaser.Game(500, 500, Phaser.HEADLESS);
|
var game = new Phaser.Game(500, 500, Phaser.HEADLESS);
|
||||||
|
|
||||||
if (!state) {
|
if (!state) {
|
||||||
|
@ -31,4 +34,14 @@ module SpaceTac.View.Specs {
|
||||||
game.state.start.apply(game.state, args);
|
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