1
0
Fork 0

Improved buttons for battle result dialog

This commit is contained in:
Michaël Lemaire 2017-08-22 00:01:11 +02:00
parent a2f783d5fc
commit b8a792a300
24 changed files with 107 additions and 68 deletions

View file

@ -22,7 +22,7 @@ If you want to build on your computer, clone the repository, then run:
./spacetac install # Install dependencies ./spacetac install # Install dependencies
./spacetac run build # Build the final JS ./spacetac run build # Build the final JS
./spacetac run pack # Pack the images and sounds ./spacetac run atlas # Pack the images and sounds
./spacetac test # Run unit tests ./spacetac test # Run unit tests
./spacetac start # Start development server, and open game in web browser ./spacetac start # Start development server, and open game in web browser

10
TODO.md
View file

@ -19,7 +19,7 @@ Map/story
* Allow to cancel secondary missions * Allow to cancel secondary missions
* Forbid to end up with more than 5 ships in the fleet because of escorts * Forbid to end up with more than 5 ships in the fleet because of escorts
* Fix problems when several dialogs are active at the same time * Fix problems when several dialogs are active at the same time
* Handle case where cargo is full to give a reward (give money ?) * Handle case where cargo is full to give a reward (give money?)
Character sheet Character sheet
--------------- ---------------
@ -39,13 +39,13 @@ Battle
* Add quick animation of playing ship indicator, on ship change * Add quick animation of playing ship indicator, on ship change
* Display a hint when a move-fire simulation failed (cannot enter exclusion area for example) * Display a hint when a move-fire simulation failed (cannot enter exclusion area for example)
* Display effects description instead of attribute changes * Display effects description instead of attribute changes
* Display radius and power usage hints for area effects on action icon hover + add confirmation ? * Display radius and power usage hints for area effects on action icon hover + add confirmation?
* Any displayed info should be based on a ship copy stored in ArenaShip, and in sync with current log index (not the game state ship) * Any displayed info should be based on a ship copy stored in ArenaShip, and in sync with current log index (not the game state ship)
* Add engine trail effect, and sound * Add engine trail effect, and sound
* Fix targetting not resetting on current cursor location when using keyboard shortcuts * Fix targetting not resetting on current cursor location when using keyboard shortcuts
* Allow to skip animations, and allow no animation mode * Allow to skip animations, and allow no animation mode
* Find incentives to move from starting position (permanent drones or anomalies ?) * Find incentives to move from starting position (permanent drones or anomalies?)
* Add a "loot all" button, disable the loot button if there is no loot * Add a "loot all" button (on the character sheet or outcome dialog?)
* Do not focus on ship while targetting for area effects (dissociate hover and target) * Do not focus on ship while targetting for area effects (dissociate hover and target)
* Repair drone has its activation effect sometimes displayed as permanent effect on ships in the radius * Repair drone has its activation effect sometimes displayed as permanent effect on ships in the radius
* Merge identical sticky effects * Merge identical sticky effects
@ -110,7 +110,7 @@ Postponed
* Replays * Replays
* Multiplayer/co-op * Multiplayer/co-op
* Formation or deployment phase * Formation or deployment phase
* Add ship personality (with icons to identify ?), with reaction dialogs * Add ship personality (with icons to identify?), with reaction dialogs
* New battle internal flow: any game state change should be done through revertable events * New battle internal flow: any game state change should be done through revertable events
* Animated arena background, instead of big picture * Animated arena background, instead of big picture
* Hide enemy information (shield, hull, weapons), until they are in play, or until a "spy" effect is used * Hide enemy information (shield, hull, weapons), until they are in play, or until a "spy" effect is used

View file

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View file

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

View file

@ -7,7 +7,7 @@
"shell": "${SHELL} || true", "shell": "${SHELL} || true",
"postinstall": "rm -rf out/vendor && mkdir -p out/vendor && cp -r node_modules/phaser/build out/vendor/phaser && cp -r node_modules/phaser-plugin-scene-graph/dist out/vendor/phaser-plugin-scene-graph && cp -r node_modules/parse/dist out/vendor/parse && cp -r node_modules/jasmine-core/lib/jasmine-core out/vendor/jasmine", "postinstall": "rm -rf out/vendor && mkdir -p out/vendor && cp -r node_modules/phaser/build out/vendor/phaser && cp -r node_modules/phaser-plugin-scene-graph/dist out/vendor/phaser-plugin-scene-graph && cp -r node_modules/parse/dist out/vendor/parse && cp -r node_modules/jasmine-core/lib/jasmine-core out/vendor/jasmine",
"build": "tsc -p .", "build": "tsc -p .",
"pack": "rm -f out/assets/atlas* && find graphics/exported -name '*.png' -print0 | xargs -0 gf-pack --name out/assets/atlas --fullpath --width 1024 --height 1024 --square --powerOfTwo --trim --padding 2", "atlas": "rm -f out/assets/atlas* && find graphics/exported -name '*.png' -print0 | xargs -0 gf-pack --name out/assets/atlas --fullpath --width 1024 --height 1024 --square --powerOfTwo --trim --padding 2",
"pretest": "tsc -p .", "pretest": "tsc -p .",
"test": "karma start spec/support/karma.conf.js && remap-istanbul -i out/coverage/coverage.json -o out/coverage -t html", "test": "karma start spec/support/karma.conf.js && remap-istanbul -i out/coverage/coverage.json -o out/coverage -t html",
"prestart": "tsc -p . || true", "prestart": "tsc -p . || true",
@ -41,4 +41,4 @@
"phaser": "^2.6.2", "phaser": "^2.6.2",
"phaser-plugin-scene-graph": "^1.0.4" "phaser-plugin-scene-graph": "^1.0.4"
} }
} }

View file

@ -19,6 +19,7 @@ module TS.SpaceTac.UI {
this.loadImage("common/button-ok.png"); this.loadImage("common/button-ok.png");
this.loadImage("common/button-cancel.png"); this.loadImage("common/button-cancel.png");
this.loadImage("common/dialog.png"); this.loadImage("common/dialog.png");
this.loadSheet("common/dialog-textbutton.png", 316, 59);
this.loadSheet("common/dialog-close.png", 92, 82); this.loadSheet("common/dialog-close.png", 92, 82);
this.loadImage("menu/title.png"); this.loadImage("menu/title.png");
this.loadImage("menu/button.png"); this.loadImage("menu/button.png");
@ -51,13 +52,6 @@ module TS.SpaceTac.UI {
this.loadImage("battle/weapon/hot.png"); this.loadImage("battle/weapon/hot.png");
this.loadImage("battle/weapon/shield-impact.png"); this.loadImage("battle/weapon/shield-impact.png");
this.loadImage("battle/weapon/blast.png"); this.loadImage("battle/weapon/blast.png");
this.loadImage("battle/outcome/dialog.png");
this.loadImage("battle/outcome/title-victory.png");
this.loadImage("battle/outcome/title-defeat.png");
this.loadImage("battle/outcome/button-menu.png");
this.loadImage("battle/outcome/button-map.png");
this.loadImage("battle/outcome/button-revert.png");
this.loadImage("battle/outcome/button-loot.png");
this.loadImage("map/starsystem-background.png"); this.loadImage("map/starsystem-background.png");
this.loadImage("map/current-location.png"); this.loadImage("map/current-location.png");
this.loadImage("map/name.png"); this.loadImage("map/name.png");

View file

@ -41,9 +41,6 @@ module TS.SpaceTac.UI {
// Ship tooltip // Ship tooltip
ship_tooltip: ShipTooltip ship_tooltip: ShipTooltip
// Outcome dialog layer
outcome_layer: Phaser.Group
// Character sheet // Character sheet
character_sheet: CharacterSheet character_sheet: CharacterSheet
@ -101,8 +98,6 @@ module TS.SpaceTac.UI {
this.action_bar = new ActionBar(this); this.action_bar = new ActionBar(this);
this.ship_list = new ShipList(this); this.ship_list = new ShipList(this);
this.ship_tooltip = new ShipTooltip(this); this.ship_tooltip = new ShipTooltip(this);
this.outcome_layer = new Phaser.Group(this.game);
this.layer_dialogs.add(this.outcome_layer);
this.character_sheet = new CharacterSheet(this, -this.getWidth()); this.character_sheet = new CharacterSheet(this, -this.getWidth());
this.layer_sheets.add(this.character_sheet); this.layer_sheets.add(this.character_sheet);
@ -250,8 +245,7 @@ module TS.SpaceTac.UI {
this.battle.stats.processLog(this.battle.log, this.player.fleet); this.battle.stats.processLog(this.battle.log, this.player.fleet);
let dialog = new OutcomeDialog(this, this.player, this.battle.outcome, this.battle.stats); new OutcomeDialog(this, this.player, this.battle.outcome, this.battle.stats);
dialog.moveToLayer(this.outcome_layer);
} else { } else {
console.error("Battle not ended !"); console.error("Battle not ended !");
} }

View file

@ -1,45 +1,87 @@
/// <reference path="../common/UIComponent.ts" /> /// <reference path="../common/UIDialog.ts" />
module TS.SpaceTac.UI { module TS.SpaceTac.UI {
/** /**
* Dialog to display battle outcome * Dialog to display battle outcome
*/ */
export class OutcomeDialog extends UIComponent { export class OutcomeDialog extends UIDialog {
battleview: BattleView
player: Player
outcome: BattleOutcome
stats: BattleStats
constructor(parent: BattleView, player: Player, outcome: BattleOutcome, stats: BattleStats) { constructor(parent: BattleView, player: Player, outcome: BattleOutcome, stats: BattleStats) {
super(parent, 1428, 1032, "battle-outcome-dialog"); super(parent);
let victory = outcome.winner && (outcome.winner.player == player); this.battleview = parent;
this.addImage(714, 164, victory ? "battle-outcome-title-victory" : "battle-outcome-title-defeat"); this.player = player;
this.outcome = outcome;
this.stats = stats;
if (victory) { this.refreshContent();
this.addButton(502, 871, () => { }
parent.character_sheet.show(nn(outcome.winner).ships[0]);
parent.character_sheet.setLoot(outcome.loot);
}, "battle-outcome-button-loot", 0, 0, "Open character sheet to loot equipment from defeated fleet");
this.addButton(924, 871, () => { /**
parent.exitBattle(); * Shortcut to add a single action button at the bottom of dialog
}, "battle-outcome-button-map", 0, 0, "Exit the battle and go back to the map"); */
} else { addActionButton(x: number, text: string, tooltip: string, action: Function) {
this.addButton(502, 871, () => { let button = this.addButton(x, 885, action, "common-dialog-textbutton", 0, 1, tooltip);
parent.revertBattle(); button.addChild(this.addText(0, 0, text, "#d9e0e5"));
}, "battle-outcome-button-revert", 0, 0, "Go back to where the fleet was before the battle happened"); }
this.addButton(924, 871, () => { /**
// Quit the game, and go back to menu * Refresh the whole dialog
parent.gameui.quitGame(); */
}, "battle-outcome-button-menu", 0, 0, "Quit the game, and go back to main menu"); refreshContent(): void {
} let parent = this.battleview;
let outcome = this.outcome;
let victory = outcome.winner && (outcome.winner.player == this.player);
this.addText(780, 270, "You", "#ffffff", 20); this.clearContent();
this.addText(980, 270, "Enemy", "#ffffff", 20);
stats.getImportant(10).forEach((stat, index) => { this.addImage(747, 180, victory ? "battle-outcome-title-victory" : "battle-outcome-title-defeat");
this.addText(500, 314 + 40 * index, stat.name, "#ffffff", 20);
this.addText(780, 314 + 40 * index, stat.attacker.toString(), "#8ba883", 20, true); this.addText(815, 320, "You", "#ffffff", 20);
this.addText(980, 314 + 40 * index, stat.defender.toString(), "#cd6767", 20, true); this.addText(1015, 320, "Enemy", "#ffffff", 20);
this.stats.getImportant(10).forEach((stat, index) => {
this.addText(530, 364 + 40 * index, stat.name, "#ffffff", 20);
this.addText(815, 364 + 40 * index, stat.attacker.toString(), "#8ba883", 20, true);
this.addText(1015, 364 + 40 * index, stat.defender.toString(), "#cd6767", 20, true);
}); });
this.setPositionInsideParent(0.5, 0.5); if (!this.battleview.session.hasUniverse()) {
this.addActionButton(747, "Main menu", "Exit the battle and go back to the main menu", () => {
parent.exitBattle();
});
} else if (victory) {
if (this.outcome.loot.length) {
this.addActionButton(535, "Loot equipment", "Open character sheet to loot equipment from defeated fleet", () => {
let sheet = new CharacterSheet(this.view, undefined, undefined, () => {
sheet.destroy(true);
this.refreshContent();
});
sheet.show(this.player.fleet.ships[0], false);
sheet.setLoot(outcome.loot);
this.view.add.existing(sheet);
});
this.addActionButton(957, "Back to map", "Exit the battle and go back to the map", () => {
parent.exitBattle();
});
} else {
this.addActionButton(747, "Back to map", "Exit the battle and go back to the map", () => {
parent.exitBattle();
});
}
} else {
this.addActionButton(535, "Revert battle", "Go back to where the fleet was before the battle happened", () => {
parent.revertBattle();
});
this.addActionButton(957, "Main menu", "Quit the game, and go back to main menu", () => {
parent.gameui.quitGame();
});
}
} }
} }
} }

View file

@ -63,7 +63,7 @@ module TS.SpaceTac.UI {
// Attributes and skills // Attributes and skills
attributes: { [key: string]: Phaser.Text } = {}; attributes: { [key: string]: Phaser.Text } = {};
constructor(view: BaseView, xhidden = -2000, xshown = 0) { constructor(view: BaseView, xhidden = -2000, xshown = 0, onclose?: Function) {
super(view.game, 0, 0, "character-sheet"); super(view.game, 0, 0, "character-sheet");
this.view = view; this.view = view;
@ -73,7 +73,10 @@ module TS.SpaceTac.UI {
this.xhidden = xhidden; this.xhidden = xhidden;
this.inputEnabled = true; this.inputEnabled = true;
let close_button = new Phaser.Button(this.game, view.getWidth(), 0, "character-close", () => this.hide()); if (!onclose) {
onclose = () => this.hide();
}
let close_button = new Phaser.Button(this.game, view.getWidth(), 0, "character-close", onclose);
close_button.anchor.set(1, 0); close_button.anchor.set(1, 0);
UIComponent.setButtonSound(close_button); UIComponent.setButtonSound(close_button);
this.addChild(close_button); this.addChild(close_button);
@ -283,7 +286,7 @@ module TS.SpaceTac.UI {
} }
if (animate) { if (animate) {
this.game.tweens.create(this).to({ x: this.xshown }, 800, Phaser.Easing.Circular.InOut, true); this.game.tweens.create(this).to({ x: this.xshown }, 400, Phaser.Easing.Circular.InOut, true);
} else { } else {
this.x = this.xshown; this.x = this.xshown;
} }
@ -304,7 +307,7 @@ module TS.SpaceTac.UI {
this.view.audio.playOnce("ui-dialog-close"); this.view.audio.playOnce("ui-dialog-close");
if (animate) { if (animate) {
this.game.tweens.create(this).to({ x: this.xhidden }, 800, Phaser.Easing.Circular.InOut, true); this.game.tweens.create(this).to({ x: this.xhidden }, 400, Phaser.Easing.Circular.InOut, true);
} else { } else {
this.x = this.xhidden; this.x = this.xhidden;
} }

View file

@ -212,21 +212,21 @@ module TS.SpaceTac.UI {
/** /**
* Add a button in the component, positioning its center. * Add a button in the component, positioning its center.
*/ */
addButton(x: number, y: number, on_click: Function, background: string, frame_normal = 0, frame_hover = 1, tooltip = "", angle = 0) { addButton(x: number, y: number, on_click: Function, background: string, frame_normal = 0, frame_hover = 1, tooltip = ""): Phaser.Button {
let button = new Phaser.Button(this.view.game, x, y, background, on_click, undefined, frame_hover, frame_normal); let button = new Phaser.Button(this.view.game, x, y, background, on_click, undefined, frame_hover, frame_normal);
UIComponent.setButtonSound(button); UIComponent.setButtonSound(button);
button.anchor.set(0.5, 0.5); button.anchor.set(0.5, 0.5);
button.angle = angle;
if (tooltip) { if (tooltip) {
this.view.tooltip.bindStaticText(button, tooltip); this.view.tooltip.bindStaticText(button, tooltip);
} }
this.addInternalChild(button); this.addInternalChild(button);
return button;
} }
/** /**
* Add a static text. * Add a static text.
*/ */
addText(x: number, y: number, content: string, color = "#ffffff", size = 16, bold = false, center = true, width = 0, vcenter = center): void { addText(x: number, y: number, content: string, color = "#ffffff", size = 16, bold = false, center = true, width = 0, vcenter = center): Phaser.Text {
let style = { font: `${bold ? "bold " : ""}${size}pt SpaceTac`, fill: color, align: center ? "center" : "left" }; let style = { font: `${bold ? "bold " : ""}${size}pt SpaceTac`, fill: color, align: center ? "center" : "left" };
let text = new Phaser.Text(this.view.game, x, y, content, style); let text = new Phaser.Text(this.view.game, x, y, content, style);
text.anchor.set(center ? 0.5 : 0, vcenter ? 0.5 : 0); text.anchor.set(center ? 0.5 : 0, vcenter ? 0.5 : 0);
@ -235,12 +235,15 @@ module TS.SpaceTac.UI {
text.wordWrapWidth = width; text.wordWrapWidth = width;
} }
this.addInternalChild(text); this.addInternalChild(text);
return text;
} }
/** /**
* Add a static image, positioning its center. * Add a static image, positioning its center.
*
* DEPRECATED - Use addImage instead
*/ */
addImage(x: number, y: number, key: string, frame = 0, scale = 1): void { addImageF(x: number, y: number, key: string, frame = 0, scale = 1): void {
let image = new Phaser.Image(this.container.game, x, y, key, frame); let image = new Phaser.Image(this.container.game, x, y, key, frame);
image.anchor.set(0.5, 0.5); image.anchor.set(0.5, 0.5);
image.scale.set(scale); image.scale.set(scale);
@ -250,12 +253,13 @@ module TS.SpaceTac.UI {
/** /**
* Add a static image, from atlases, positioning its center. * Add a static image, from atlases, positioning its center.
*/ */
addImageA(x: number, y: number, name: string, scale = 1): void { addImage(x: number, y: number, name: string, scale = 1): Phaser.Image {
let info = this.view.getImageInfo(name); let info = this.view.getImageInfo(name);
let image = new Phaser.Image(this.container.game, x, y, info.key, info.frame); let image = new Phaser.Image(this.container.game, x, y, info.key, info.frame);
image.anchor.set(0.5, 0.5); image.anchor.set(0.5, 0.5);
image.scale.set(scale); image.scale.set(scale);
this.addInternalChild(image); this.addInternalChild(image);
return image;
} }
/** /**

View file

@ -24,7 +24,8 @@ module TS.SpaceTac.UI {
* Add a control-capturing overlay * Add a control-capturing overlay
*/ */
addOverlay(layer: Phaser.Group): void { addOverlay(layer: Phaser.Group): void {
let overlay = layer.game.add.button(0, 0, "common-transparent", () => null); let info = this.view.getImageInfo("translucent");
let overlay = layer.game.add.button(0, 0, info.key, () => null, undefined, info.frame, info.frame);
overlay.input.useHandCursor = false; overlay.input.useHandCursor = false;
overlay.scale.set(this.view.getWidth() / overlay.width, this.view.getHeight() / overlay.height); overlay.scale.set(this.view.getWidth() / overlay.width, this.view.getHeight() / overlay.height);
layer.add(overlay); layer.add(overlay);

View file

@ -7,7 +7,7 @@ module TS.SpaceTac.UI {
super(view); super(view);
this.addText(this.width * 0.5, this.height * 0.3, message, "#90FEE3", 32); this.addText(this.width * 0.5, this.height * 0.3, message, "#90FEE3", 32);
this.addImage(this.width * 0.5, this.height * 0.6, "common-waiting"); this.addImageF(this.width * 0.5, this.height * 0.6, "common-waiting");
} }
/** /**

View file

@ -43,7 +43,7 @@ module TS.SpaceTac.UI {
width -= offset; width -= offset;
let ioffset = style.padding + Math.floor(style.image_size / 2); let ioffset = style.padding + Math.floor(style.image_size / 2);
this.addImageA(ioffset, ioffset, style.image); this.addImage(ioffset, ioffset, style.image);
if (style.image_caption) { if (style.image_caption) {
let text_size = Math.ceil(style.text_size * 0.6); let text_size = Math.ceil(style.text_size * 0.6);

View file

@ -47,7 +47,7 @@ module TS.SpaceTac.UI {
let offset = 245 - active.length * spacing; let offset = 245 - active.length * spacing;
active.forEach((mission, idx) => { active.forEach((mission, idx) => {
let frame = mission.main ? 0 : 1; let frame = mission.main ? 0 : 1;
this.addImage(35, offset + spacing * idx, "map-missions", frame); this.addImageF(35, offset + spacing * idx, "map-missions", frame);
this.addText(90, offset + spacing * idx, mission.current_part.title, "#d2e1f3", 20, false, false, 430, true); this.addText(90, offset + spacing * idx, mission.current_part.title, "#d2e1f3", 20, false, false, 430, true);
let location = mission.current_part.getLocationHint(); let location = mission.current_part.getLocationHint();

View file

@ -16,7 +16,7 @@ module TS.SpaceTac.UI {
this.clearContent(); this.clearContent();
if (title) { if (title) {
this.addImage(239, 57, "map-subname"); this.addImageF(239, 57, "map-subname");
this.addText(239, 57, title, "#b8d2f1", 22, false, true); this.addText(239, 57, title, "#b8d2f1", 22, false, true);
} }

View file

@ -62,7 +62,7 @@ module TS.SpaceTac.UI {
let title = mission.title; let title = mission.title;
let subtitle = `${capitalize(MissionDifficulty[mission.difficulty])} - Reward: ${mission.getRewardText()}`; let subtitle = `${capitalize(MissionDifficulty[mission.difficulty])} - Reward: ${mission.getRewardText()}`;
this.addImage(320, yoffset, "map-missions", 1); this.addImageF(320, yoffset, "map-missions", 1);
if (title) { if (title) {
this.addText(380, yoffset - 15, title, "#d2e1f3", 22, false, false, 620, true); this.addText(380, yoffset - 15, title, "#d2e1f3", 22, false, false, 620, true);
} }

View file

@ -13,8 +13,9 @@ module TS.SpaceTac.UI {
constructor(parent: MainMenu) { constructor(parent: MainMenu) {
super(parent, 1344, 566, "menu-load-bg"); super(parent, 1344, 566, "menu-load-bg");
this.addButton(600, 115, () => this.paginateSave(-1), "common-arrow", 0, 0, "Scroll to newer saves", 180); let button = this.addButton(600, 115, () => this.paginateSave(-1), "common-arrow", 0, 0, "Scroll to newer saves");
this.addButton(1038, 115, () => this.paginateSave(1), "common-arrow", 0, 0, "Scroll to older saves", 0); button.angle = 180;
this.addButton(1038, 115, () => this.paginateSave(1), "common-arrow", 0, 0, "Scroll to older saves");
this.addButton(1224, 115, () => this.load(), "common-button-ok"); this.addButton(1224, 115, () => this.load(), "common-button-ok");
this.addButton(1224, 341, () => this.join(), "common-button-ok"); this.addButton(1224, 341, () => this.join(), "common-button-ok");