1
0
Fork 0

Fixed character sheet layering

This commit is contained in:
Michaël Lemaire 2017-10-11 23:49:56 +02:00
parent 99882829a9
commit 4312dcf893
13 changed files with 95 additions and 103 deletions

View file

@ -34,7 +34,6 @@ Character sheet
* Allow to cancel spent skill points (and confirm when closing the sheet)
* Add filters and sort options for cargo and shop
* Display level and slot type on equipment
* Fix dragged equipment being under attributes (put attributes in a layer)
Battle
------
@ -96,6 +95,7 @@ Common UI
* Split atlases by asset stage
* UIBuilder.button should be able to handle hover and pushed images
* If ProgressiveMessage animation performance is bad, show the text directly
* Add caret/focus to text input
* Mobile: think UI layout so that fingers do not block the view (right and left handed)
* Mobile: display tooltips larger and on the side of screen where the finger is not

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -21,13 +21,13 @@ module TK.SpaceTac.UI.Specs {
sheet.show(ship1);
expect(sheet.portraits.length).toBe(2);
expect(sheet.equipments.length).toBe(3);
expect(sheet.layer_equipments.length).toBe(3);
expect(sheet.ship_cargo.length).toBe(3);
// First item fits in the free slot
let source = <CharacterCargo>sheet.ship_cargo.children[0];
let dest = <CharacterFleetMember>sheet.portraits.children[1];
let equ = <CharacterEquipment>sheet.equipments.children[0];
let equ = <CharacterEquipment>sheet.layer_equipments.children[0];
expect(dest.ship).toBe(ship2);
expect(equ.item).toBe(equ1);
expect(ship1.cargo).toContain(equ1);
@ -39,7 +39,7 @@ module TK.SpaceTac.UI.Specs {
// Second item goes to cargo
source = <CharacterCargo>sheet.ship_cargo.children[0];
dest = <CharacterFleetMember>sheet.portraits.children[1];
equ = <CharacterEquipment>sheet.equipments.children[1];
equ = <CharacterEquipment>sheet.layer_equipments.children[1];
expect(dest.ship).toBe(ship2);
expect(equ.item).toBe(equ2);
expect(ship1.cargo).toContain(equ2);
@ -51,7 +51,7 @@ module TK.SpaceTac.UI.Specs {
// Third item has no more room
source = <CharacterCargo>sheet.ship_cargo.children[0];
dest = <CharacterFleetMember>sheet.portraits.children[1];
equ = <CharacterEquipment>sheet.equipments.children[2];
equ = <CharacterEquipment>sheet.layer_equipments.children[2];
expect(dest.ship).toBe(ship2);
expect(equ.item).toBe(equ3);
expect(ship1.cargo).toContain(equ3);

View file

@ -26,14 +26,14 @@ module TK.SpaceTac.UI.Specs {
expect(loot_slot instanceof CharacterLootSlot).toBe(true);
// loot to cargo
let equ2s = <CharacterEquipment>sheet.equipments.children[1];
let equ2s = <CharacterEquipment>sheet.layer_equipments.children[1];
expect(equ2s.item).toBe(equ2);
equ2s.applyDragDrop(loot_slot, cargo_slot, false);
expect(ship.cargo).toEqual([equ1, equ2]);
expect(loot).toEqual([]);
// discard to cargo
let equ1s = <CharacterEquipment>sheet.equipments.children[0];
let equ1s = <CharacterEquipment>sheet.layer_equipments.children[0];
expect(equ1s.item).toBe(equ1);
equ1s.applyDragDrop(cargo_slot, loot_slot, false);
expect(ship.cargo).toEqual([equ2]);

View file

@ -56,14 +56,14 @@ module TK.SpaceTac.UI.Specs {
sheet.show(ship, false);
expect(sheet.loot_slots.visible).toBe(false);
expect(sheet.equipments.children.length).toBe(2);
expect(sheet.layer_equipments.children.length).toBe(2);
sheet.setLoot(loot);
expect(sheet.loot_slots.visible).toBe(true);
expect(sheet.equipments.children.length).toBe(4);
expect(sheet.layer_equipments.children.length).toBe(4);
let findsprite = (equ: Equipment) => nn(first(<CharacterEquipment[]>sheet.equipments.children, sp => sp.item == equ));
let findsprite = (equ: Equipment) => nn(first(<CharacterEquipment[]>sheet.layer_equipments.children, sp => sp.item == equ));
let draddrop = (sp: CharacterEquipment, dest: CharacterCargo | CharacterSlot) => {
sp.applyDragDrop(sp.container, dest, false);
}

View file

@ -11,6 +11,9 @@ module TK.SpaceTac.UI {
// Parent view
view: BaseView
// UI components builder
builder: UIBuilder
// X positions
xshown: number
xhidden: number
@ -33,7 +36,7 @@ module TK.SpaceTac.UI {
// Ship skill upgrade
ship_upgrade_points: Phaser.Text
ship_upgrades: Phaser.Group
layer_upgrades: Phaser.Group
// Ship slots
ship_slots: Phaser.Group
@ -58,8 +61,9 @@ module TK.SpaceTac.UI {
members: CharacterFleetMember[] = []
portraits: Phaser.Group
// Layer for draggable equipments
equipments: Phaser.Group
// Layers
layer_attibutes: Phaser.Group
layer_equipments: Phaser.Group
// Credits
credits: Phaser.Text
@ -71,6 +75,7 @@ module TK.SpaceTac.UI {
super(view.game, 0, 0, "character-sheet");
this.view = view;
this.builder = new UIBuilder(view, this);
this.x = xhidden;
this.xshown = xshown;
@ -80,65 +85,33 @@ module TK.SpaceTac.UI {
if (!onclose) {
onclose = () => this.hide();
}
this.close_button = view.newButton("character-close", 1920, 0, onclose);
this.close_button = this.builder.button("character-close", 1920, 0, onclose, "Close the character sheet");
this.close_button.anchor.set(1, 0);
this.addChild(this.close_button);
view.tooltip.bindStaticText(this.close_button, "Close the character sheet");
this.addChild(view.newText("Level", 420, 1052, 24));
this.addChild(view.newText("Available points", 894, 1052, 24));
this.builder.text("Level", 420, 1052, { size: 24 });
this.builder.text("Available points", 894, 1052, { size: 24 });
this.ship_name = view.newText("", 758, 48, 30);
this.addChild(this.ship_name);
this.ship_level = view.newText("", 554, 1052, 30);
this.addChild(this.ship_level);
this.ship_name = this.builder.text("", 758, 48, { size: 30 });
this.ship_level = this.builder.text("", 554, 1052, { size: 30 });
this.ship_upgrade_points = this.builder.text("", 1068, 1052, { size: 30 });
this.ship_slots = this.builder.group("slots", 372, 120);
this.ship_cargo = this.builder.group("cargo", 1240, 86);
this.loot_slots = this.builder.group("loot", 1270, 670);
this.loot_slots.visible = false;
this.portraits = this.builder.group("portraits", 152, 0);
this.credits = this.builder.text("", 136, 38, { size: 30 });
this.mode_title = this.builder.text("", 1566, 648, { size: 18 });
this.loot_next = this.builder.button("common-arrow-right", 1890, 850, () => this.paginate(1), "Show next items");
this.loot_next.anchor.set(0.5);
this.loot_prev = this.builder.button("common-arrow-left", 1238, 850, () => this.paginate(-1), "Show previous items");
this.loot_prev.anchor.set(0.5);
this.ship_experience = new ValueBar(this.view, "character-experience", ValueBarOrientation.EAST, 516, 1067);
this.addChild(this.ship_experience.node);
this.ship_upgrade_points = view.newText("", 1068, 1052, 30);
this.addChild(this.ship_upgrade_points);
this.ship_upgrades = new Phaser.Group(this.game);
this.addChild(this.ship_upgrades);
this.ship_slots = new Phaser.Group(this.game);
this.ship_slots.position.set(372, 120);
this.addChild(this.ship_slots);
this.ship_cargo = new Phaser.Group(this.game);
this.ship_cargo.position.set(1240, 86);
this.addChild(this.ship_cargo);
this.loot_slots = new Phaser.Group(this.game);
this.loot_slots.position.set(1270, 670);
this.loot_slots.visible = false;
this.addChild(this.loot_slots);
this.portraits = new Phaser.Group(this.game);
this.portraits.position.set(152, 0);
this.addChild(this.portraits);
this.credits = view.newText("", 136, 38, 30);
this.addChild(this.credits);
this.equipments = new Phaser.Group(this.game);
this.addChild(this.equipments);
this.mode_title = view.newText("", 1566, 648, 18);
this.addChild(this.mode_title);
this.loot_next = new Phaser.Button(this.game, 1890, 850, "common-arrow", () => this.paginate(1));
this.loot_next.anchor.set(0.5, 0.5);
UIComponent.setButtonSound(this.loot_next);
this.addChild(this.loot_next);
this.loot_prev = new Phaser.Button(this.game, 1238, 850, "common-arrow", () => this.paginate(-1));
this.loot_prev.anchor.set(0.5, 0.5);
this.loot_prev.angle = 180;
UIComponent.setButtonSound(this.loot_prev);
this.addChild(this.loot_prev);
this.layer_attibutes = this.builder.group("attributes");
this.layer_upgrades = this.builder.group("upgrades");
this.layer_equipments = this.builder.group("equipments");
let x1 = 402;
let x2 = 802;
@ -161,29 +134,22 @@ module TK.SpaceTac.UI {
* Add an attribute display
*/
private addAttribute(attribute: keyof ShipAttributes, x: number, y: number) {
let button = this.view.newButton("character-attribute", x, y);
this.addChild(button);
this.view.tooltip.bindDynamicText(button, () => this.ship.getAttributeDescription(attribute));
let builder = this.builder.in(this.layer_attibutes);
let button = builder.button("character-attribute", x, y, undefined, () => this.ship.getAttributeDescription(attribute));
let attrname = capitalize(SHIP_ATTRIBUTES[attribute].name);
let name = new Phaser.Text(this.game, 120, 22, attrname,
{ align: "center", font: "20pt SpaceTac", fill: "#c9d8ef", stroke: "#395665", strokeThickness: 1 });
name.anchor.set(0.5);
button.addChild(name);
builder.in(button).text(attrname, 120, 22, { size: 20, color: "#c9d8ef", stroke_width: 1, stroke_color: "#395665" });
let value = this.view.newText("", 264, 24, 18, "#ffffff", true, true);
button.addChild(value);
let value = builder.in(button).text("", 264, 24, { size: 18, bold: true });
this.attributes[attribute] = value;
if (SHIP_SKILLS.hasOwnProperty(attribute)) {
let upgrade_button = this.view.newButton("character-skill-upgrade", x + 292, y, () => {
this.builder.in(this.layer_upgrades).button("character-skill-upgrade", x + 292, y, () => {
this.ship.upgradeSkill(<keyof ShipSkills>attribute);
this.refresh();
});
this.ship_upgrades.add(upgrade_button);
this.view.tooltip.bindStaticText(upgrade_button, `Spend one point to upgrade ${attrname}`);
}, `Spend one point to upgrade ${attrname}`);
}
}
@ -222,7 +188,7 @@ module TK.SpaceTac.UI {
show(ship: Ship, animate = true, sound = true) {
this.ship = ship;
this.equipments.removeAll(true);
this.layer_equipments.removeAll(true);
let upgrade_points = ship.getAvailableUpgradePoints();
@ -230,7 +196,7 @@ module TK.SpaceTac.UI {
this.ship_level.setText(ship.level.get().toString());
this.ship_experience.setValue(ship.level.getExperience(), ship.level.getNextGoal());
this.ship_upgrade_points.setText(upgrade_points.toString());
this.ship_upgrades.visible = !ship.critical && upgrade_points > 0;
this.layer_upgrades.visible = !ship.critical && upgrade_points > 0;
iteritems(<any>ship.attributes, (key, value: ShipAttribute) => {
let text = this.attributes[key];
@ -249,7 +215,7 @@ module TK.SpaceTac.UI {
if (slot.attached) {
let equipment = new CharacterEquipment(this, slot.attached, slot_display);
this.equipments.addChild(equipment);
this.layer_equipments.addChild(equipment);
}
});
@ -263,7 +229,7 @@ module TK.SpaceTac.UI {
if (idx < this.ship.cargo.length) {
let equipment = new CharacterEquipment(this, this.ship.cargo[idx], cargo_slot);
this.equipments.addChild(equipment);
this.layer_equipments.addChild(equipment);
}
});
@ -345,7 +311,7 @@ module TK.SpaceTac.UI {
* Update the price tags on each equipment, for a specific shop
*/
updatePrices(shop: Shop) {
this.equipments.children.forEach((equipement: CharacterEquipment) => {
this.layer_equipments.children.forEach((equipement: CharacterEquipment) => {
equipement.setPrice(shop.getPrice(equipement.item));
});
}
@ -377,7 +343,7 @@ module TK.SpaceTac.UI {
if (idx < items.length) {
let equipment = new CharacterEquipment(this, items[idx], loot_slot);
this.equipments.addChild(equipment);
this.layer_equipments.addChild(equipment);
}
});

View file

@ -29,7 +29,7 @@ module TK.SpaceTac.UI.Specs {
expect(shop_slot instanceof CharacterShopSlot).toBe(true);
// sell
let equ1s = <CharacterEquipment>sheet.equipments.children[0];
let equ1s = <CharacterEquipment>sheet.layer_equipments.children[0];
expect(equ1s.item).toBe(equ1);
equ1s.applyDragDrop(cargo_slot, shop_slot, false);
expect(ship.cargo).toEqual([]);
@ -37,7 +37,7 @@ module TK.SpaceTac.UI.Specs {
expect(fleet.credits).toBe(220);
// buy
let equ2s = <CharacterEquipment>sheet.equipments.children[1];
let equ2s = <CharacterEquipment>sheet.layer_equipments.children[1];
expect(equ2s.item).toBe(equ2);
equ2s.applyDragDrop(shop_slot, cargo_slot, false);
expect(ship.cargo).toEqual([equ2]);
@ -45,7 +45,7 @@ module TK.SpaceTac.UI.Specs {
expect(fleet.credits).toBe(100);
// not enough money
equ1s = <CharacterEquipment>sheet.equipments.children[0];
equ1s = <CharacterEquipment>sheet.layer_equipments.children[0];
expect(equ1s.item).toBe(equ1);
equ1s.applyDragDrop(shop_slot, cargo_slot, false);
expect(ship.cargo).toEqual([equ2]);

View file

@ -50,20 +50,22 @@ module TK.SpaceTac.UI {
}
});
this.input.keyboard.addCallbacks(this, undefined, (event: KeyboardEvent) => {
if (this.debug) {
console.log(event);
}
this.forceLeaveHovered();
if (!contains(["Control", "Shift", "Alt", "Meta"], event.key)) {
this.keyPress(event.key);
if (event.code != event.key) {
this.keyPress(event.code);
if (!this.game.headless) {
this.input.keyboard.addCallbacks(this, undefined, (event: KeyboardEvent) => {
if (this.debug) {
console.log(event);
}
}
});
this.forceLeaveHovered();
if (!contains(["Control", "Shift", "Alt", "Meta"], event.key)) {
this.keyPress(event.key);
if (event.code != event.key) {
this.keyPress(event.code);
}
}
});
}
}
/**

View file

@ -111,6 +111,12 @@ module TK.SpaceTac.UI.Specs {
check(["View layers", "base", 0], Phaser.Text, "", { shadowColor: "rgba(0,0,0,0)" });
check(["View layers", "base", 1], Phaser.Text, "", { shadowColor: "rgba(0,0,0,0.6)", shadowFill: true, shadowOffsetX: 3, shadowOffsetY: 4, shadowBlur: 6, shadowStroke: true });
builder.clear();
builder.text("", 0, 0, {});
builder.text("", 0, 0, { stroke_width: 2, stroke_color: "#ff0000" });
check(["View layers", "base", 0], Phaser.Text, "", { stroke: "black", strokeThickness: 0 });
check(["View layers", "base", 1], Phaser.Text, "", { stroke: "#ff0000", strokeThickness: 2 });
builder.clear();
builder.text("", 0, 0, {});
builder.text("", 0, 0, { bold: true });

View file

@ -5,6 +5,7 @@ module TK.SpaceTac.UI {
export type UIText = Phaser.Text
export type UIImage = Phaser.Image
export type UIButton = Phaser.Button
export type UIGroup = Phaser.Group
export type UIContainer = Phaser.Group | Phaser.Image
/**
@ -14,6 +15,8 @@ module TK.SpaceTac.UI {
size?: number
color?: string
shadow?: boolean
stroke_width?: number
stroke_color?: string
bold?: boolean
center?: boolean
vcenter?: boolean
@ -33,6 +36,10 @@ module TK.SpaceTac.UI {
// Shadow under the text
shadow = false
// Stroke around the letters
stroke_width = 0
stroke_color = "#ffffff"
// Bold text
bold = false
@ -105,7 +112,7 @@ module TK.SpaceTac.UI {
/**
* Add a group of components
*/
group(name: string, x = 0, y = 0): UIContainer {
group(name: string, x = 0, y = 0): UIGroup {
let result = new Phaser.Group(this.game, undefined, name);
result.position.set(x, y);
this.add(result);
@ -132,6 +139,10 @@ module TK.SpaceTac.UI {
if (style.shadow) {
result.setShadow(3, 4, "rgba(0,0,0,0.6)", 6);
}
if (style.stroke_width) {
result.stroke = style.stroke_color;
result.strokeThickness = style.stroke_width;
}
this.add(result);
return result;
}
@ -154,7 +165,7 @@ module TK.SpaceTac.UI {
/**
* Add a clickable button
*/
button(name: string, x = 0, y = 0, onclick?: Function): UIButton {
button(name: string, x = 0, y = 0, onclick?: Function, tooltip?: string | (() => string)): UIButton {
let info = this.view.getImageInfo(name);
let result = new Phaser.Button(this.game, x, y, info.key, onclick || nop, null, info.frame, info.frame);
result.name = name;
@ -163,6 +174,13 @@ module TK.SpaceTac.UI {
if (clickable) {
UIComponent.setButtonSound(result);
}
if (tooltip) {
if (typeof tooltip == "string") {
this.view.tooltip.bindStaticText(result, tooltip);
} else {
this.view.tooltip.bindDynamicText(result, tooltip);
}
}
this.add(result);
return result;
}