Improved buttons for battle result dialog
|
@ -22,7 +22,7 @@ If you want to build on your computer, clone the repository, then run:
|
|||
|
||||
./spacetac install # Install dependencies
|
||||
./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 start # Start development server, and open game in web browser
|
||||
|
||||
|
|
10
TODO.md
|
@ -19,7 +19,7 @@ Map/story
|
|||
* Allow to cancel secondary missions
|
||||
* 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
|
||||
* 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
|
||||
---------------
|
||||
|
@ -39,13 +39,13 @@ Battle
|
|||
* 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 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)
|
||||
* Add engine trail effect, and sound
|
||||
* Fix targetting not resetting on current cursor location when using keyboard shortcuts
|
||||
* Allow to skip animations, and allow no animation mode
|
||||
* 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
|
||||
* Find incentives to move from starting position (permanent drones or anomalies?)
|
||||
* 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)
|
||||
* Repair drone has its activation effect sometimes displayed as permanent effect on ships in the radius
|
||||
* Merge identical sticky effects
|
||||
|
@ -110,7 +110,7 @@ Postponed
|
|||
* Replays
|
||||
* Multiplayer/co-op
|
||||
* 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
|
||||
* 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
|
||||
|
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
BIN
graphics/exported/translucent.png
Normal file
After Width: | Height: | Size: 169 B |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 5 KiB |
Before Width: | Height: | Size: 94 KiB |
BIN
out/assets/images/common/dialog-textbutton.png
Normal file
After Width: | Height: | Size: 696 B |
|
@ -7,7 +7,7 @@
|
|||
"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",
|
||||
"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 .",
|
||||
"test": "karma start spec/support/karma.conf.js && remap-istanbul -i out/coverage/coverage.json -o out/coverage -t html",
|
||||
"prestart": "tsc -p . || true",
|
||||
|
@ -41,4 +41,4 @@
|
|||
"phaser": "^2.6.2",
|
||||
"phaser-plugin-scene-graph": "^1.0.4"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ module TS.SpaceTac.UI {
|
|||
this.loadImage("common/button-ok.png");
|
||||
this.loadImage("common/button-cancel.png");
|
||||
this.loadImage("common/dialog.png");
|
||||
this.loadSheet("common/dialog-textbutton.png", 316, 59);
|
||||
this.loadSheet("common/dialog-close.png", 92, 82);
|
||||
this.loadImage("menu/title.png");
|
||||
this.loadImage("menu/button.png");
|
||||
|
@ -51,13 +52,6 @@ module TS.SpaceTac.UI {
|
|||
this.loadImage("battle/weapon/hot.png");
|
||||
this.loadImage("battle/weapon/shield-impact.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/current-location.png");
|
||||
this.loadImage("map/name.png");
|
||||
|
|
|
@ -41,9 +41,6 @@ module TS.SpaceTac.UI {
|
|||
// Ship tooltip
|
||||
ship_tooltip: ShipTooltip
|
||||
|
||||
// Outcome dialog layer
|
||||
outcome_layer: Phaser.Group
|
||||
|
||||
// Character sheet
|
||||
character_sheet: CharacterSheet
|
||||
|
||||
|
@ -101,8 +98,6 @@ module TS.SpaceTac.UI {
|
|||
this.action_bar = new ActionBar(this);
|
||||
this.ship_list = new ShipList(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.layer_sheets.add(this.character_sheet);
|
||||
|
||||
|
@ -250,8 +245,7 @@ module TS.SpaceTac.UI {
|
|||
|
||||
this.battle.stats.processLog(this.battle.log, this.player.fleet);
|
||||
|
||||
let dialog = new OutcomeDialog(this, this.player, this.battle.outcome, this.battle.stats);
|
||||
dialog.moveToLayer(this.outcome_layer);
|
||||
new OutcomeDialog(this, this.player, this.battle.outcome, this.battle.stats);
|
||||
} else {
|
||||
console.error("Battle not ended !");
|
||||
}
|
||||
|
|
|
@ -1,45 +1,87 @@
|
|||
/// <reference path="../common/UIComponent.ts" />
|
||||
/// <reference path="../common/UIDialog.ts" />
|
||||
|
||||
module TS.SpaceTac.UI {
|
||||
/**
|
||||
* 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) {
|
||||
super(parent, 1428, 1032, "battle-outcome-dialog");
|
||||
super(parent);
|
||||
|
||||
let victory = outcome.winner && (outcome.winner.player == player);
|
||||
this.addImage(714, 164, victory ? "battle-outcome-title-victory" : "battle-outcome-title-defeat");
|
||||
this.battleview = parent;
|
||||
this.player = player;
|
||||
this.outcome = outcome;
|
||||
this.stats = stats;
|
||||
|
||||
if (victory) {
|
||||
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.refreshContent();
|
||||
}
|
||||
|
||||
this.addButton(924, 871, () => {
|
||||
parent.exitBattle();
|
||||
}, "battle-outcome-button-map", 0, 0, "Exit the battle and go back to the map");
|
||||
} else {
|
||||
this.addButton(502, 871, () => {
|
||||
parent.revertBattle();
|
||||
}, "battle-outcome-button-revert", 0, 0, "Go back to where the fleet was before the battle happened");
|
||||
/**
|
||||
* Shortcut to add a single action button at the bottom of dialog
|
||||
*/
|
||||
addActionButton(x: number, text: string, tooltip: string, action: Function) {
|
||||
let button = this.addButton(x, 885, action, "common-dialog-textbutton", 0, 1, tooltip);
|
||||
button.addChild(this.addText(0, 0, text, "#d9e0e5"));
|
||||
}
|
||||
|
||||
this.addButton(924, 871, () => {
|
||||
// Quit the game, and go back to menu
|
||||
parent.gameui.quitGame();
|
||||
}, "battle-outcome-button-menu", 0, 0, "Quit the game, and go back to main menu");
|
||||
}
|
||||
/**
|
||||
* Refresh the whole dialog
|
||||
*/
|
||||
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.addText(980, 270, "Enemy", "#ffffff", 20);
|
||||
stats.getImportant(10).forEach((stat, index) => {
|
||||
this.addText(500, 314 + 40 * index, stat.name, "#ffffff", 20);
|
||||
this.addText(780, 314 + 40 * index, stat.attacker.toString(), "#8ba883", 20, true);
|
||||
this.addText(980, 314 + 40 * index, stat.defender.toString(), "#cd6767", 20, true);
|
||||
this.clearContent();
|
||||
|
||||
this.addImage(747, 180, victory ? "battle-outcome-title-victory" : "battle-outcome-title-defeat");
|
||||
|
||||
this.addText(815, 320, "You", "#ffffff", 20);
|
||||
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();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ module TS.SpaceTac.UI {
|
|||
// Attributes and skills
|
||||
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");
|
||||
|
||||
this.view = view;
|
||||
|
@ -73,7 +73,10 @@ module TS.SpaceTac.UI {
|
|||
this.xhidden = xhidden;
|
||||
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);
|
||||
UIComponent.setButtonSound(close_button);
|
||||
this.addChild(close_button);
|
||||
|
@ -283,7 +286,7 @@ module TS.SpaceTac.UI {
|
|||
}
|
||||
|
||||
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 {
|
||||
this.x = this.xshown;
|
||||
}
|
||||
|
@ -304,7 +307,7 @@ module TS.SpaceTac.UI {
|
|||
this.view.audio.playOnce("ui-dialog-close");
|
||||
|
||||
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 {
|
||||
this.x = this.xhidden;
|
||||
}
|
||||
|
|
|
@ -212,21 +212,21 @@ module TS.SpaceTac.UI {
|
|||
/**
|
||||
* 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);
|
||||
UIComponent.setButtonSound(button);
|
||||
button.anchor.set(0.5, 0.5);
|
||||
button.angle = angle;
|
||||
if (tooltip) {
|
||||
this.view.tooltip.bindStaticText(button, tooltip);
|
||||
}
|
||||
this.addInternalChild(button);
|
||||
return button;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 text = new Phaser.Text(this.view.game, x, y, content, style);
|
||||
text.anchor.set(center ? 0.5 : 0, vcenter ? 0.5 : 0);
|
||||
|
@ -235,12 +235,15 @@ module TS.SpaceTac.UI {
|
|||
text.wordWrapWidth = width;
|
||||
}
|
||||
this.addInternalChild(text);
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
image.anchor.set(0.5, 0.5);
|
||||
image.scale.set(scale);
|
||||
|
@ -250,12 +253,13 @@ module TS.SpaceTac.UI {
|
|||
/**
|
||||
* 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 image = new Phaser.Image(this.container.game, x, y, info.key, info.frame);
|
||||
image.anchor.set(0.5, 0.5);
|
||||
image.scale.set(scale);
|
||||
this.addInternalChild(image);
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,7 +24,8 @@ module TS.SpaceTac.UI {
|
|||
* Add a control-capturing overlay
|
||||
*/
|
||||
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.scale.set(this.view.getWidth() / overlay.width, this.view.getHeight() / overlay.height);
|
||||
layer.add(overlay);
|
||||
|
|
|
@ -7,7 +7,7 @@ module TS.SpaceTac.UI {
|
|||
super(view);
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -43,7 +43,7 @@ module TS.SpaceTac.UI {
|
|||
width -= offset;
|
||||
|
||||
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) {
|
||||
let text_size = Math.ceil(style.text_size * 0.6);
|
||||
|
|
|
@ -47,7 +47,7 @@ module TS.SpaceTac.UI {
|
|||
let offset = 245 - active.length * spacing;
|
||||
active.forEach((mission, idx) => {
|
||||
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);
|
||||
|
||||
let location = mission.current_part.getLocationHint();
|
||||
|
|
|
@ -16,7 +16,7 @@ module TS.SpaceTac.UI {
|
|||
this.clearContent();
|
||||
|
||||
if (title) {
|
||||
this.addImage(239, 57, "map-subname");
|
||||
this.addImageF(239, 57, "map-subname");
|
||||
this.addText(239, 57, title, "#b8d2f1", 22, false, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ module TS.SpaceTac.UI {
|
|||
let title = mission.title;
|
||||
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) {
|
||||
this.addText(380, yoffset - 15, title, "#d2e1f3", 22, false, false, 620, true);
|
||||
}
|
||||
|
|
|
@ -13,8 +13,9 @@ module TS.SpaceTac.UI {
|
|||
constructor(parent: MainMenu) {
|
||||
super(parent, 1344, 566, "menu-load-bg");
|
||||
|
||||
this.addButton(600, 115, () => this.paginateSave(-1), "common-arrow", 0, 0, "Scroll to newer saves", 180);
|
||||
this.addButton(1038, 115, () => this.paginateSave(1), "common-arrow", 0, 0, "Scroll to older saves", 0);
|
||||
let button = this.addButton(600, 115, () => this.paginateSave(-1), "common-arrow", 0, 0, "Scroll to newer saves");
|
||||
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, 341, () => this.join(), "common-button-ok");
|
||||
|
||||
|
|