1
0
Fork 0

Fixed tooltip and fading animation issues

This commit is contained in:
Michaël Lemaire 2017-04-10 19:38:33 +02:00
parent 55cd64e3c7
commit 29303e2688
15 changed files with 135 additions and 52 deletions

2
TODO
View file

@ -1,5 +1,4 @@
* UI: Use a common component class, and a layer abstraction
* UI: Fix tooltip sometimes being enormous
* Character sheet: add tooltips (on values, slots and equipments)
* Character sheet: add initial character creation
* Character sheet: disable interaction during battle (except for loot screen)
@ -16,6 +15,7 @@
* All things displayed in battle should be updated from LogProcess forwarding, not from current game state
* Drones: add tooltip
* Drones: add hull points and take area damage
* Show power usage/recovery in action bar, on action hover
* More sound effects
* Add a battle log display
* Organize arena objects and information in layers

View file

@ -12,6 +12,9 @@ module TS.SpaceTac.UI {
// Input and key bindings
inputs: InputManager;
// Animations
animations: Animations;
// Timing
timer: Timer;
@ -49,6 +52,9 @@ module TS.SpaceTac.UI {
// Notifications
this.messages = new Messages(this);
// Animations
this.animations = new Animations(this.game.tweens);
// Input manager
this.inputs = new InputManager(this);

View file

@ -95,7 +95,7 @@ module TS.SpaceTac.UI {
setInteractive(interactive: boolean) {
this.interactive = interactive;
Animation.setVisibility(this.game, this.icon_waiting, !this.interactive, 100);
this.battleview.animations.setVisible(this.icon_waiting, !this.interactive, 100);
}
/**

View file

@ -162,7 +162,7 @@ module TS.SpaceTac.UI {
// Set the selected state on this icon
setSelected(selected: boolean) {
this.selected = selected;
Animation.setVisibility(this.game, this.layer_selected, this.selected, 300);
this.battleview.animations.setVisible(this.layer_selected, this.selected, 300);
}
// Update the active status, from the action canBeUsed result
@ -170,7 +170,7 @@ module TS.SpaceTac.UI {
var old_active = this.active;
this.active = !this.action.checkCannotBeApplied(this.ship);
if (force || (this.active != old_active)) {
Animation.setVisibility(this.game, this.layer_active, this.active, 500);
this.battleview.animations.setVisible(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;
}
@ -181,7 +181,7 @@ module TS.SpaceTac.UI {
var old_fading = this.fading;
this.fading = this.active && (this.action.checkCannotBeApplied(this.ship, remaining_ap) != null);
if (this.fading != old_fading) {
Animation.setVisibility(this.game, this.layer_active, this.active && !this.fading, 500);
this.battleview.animations.setVisible(this.layer_active, this.active && !this.fading, 500);
}
}
}

View file

@ -70,9 +70,9 @@ module TS.SpaceTac.UI {
this.shortcut.setText("");
}
Animation.fadeIn(this.game, this, 200, 0.9);
this.bar.battleview.animations.show(this, 200, 0.9);
} else {
Animation.fadeOut(this.game, this, 200);
this.bar.battleview.animations.hide(this, 200);
}
}
}

View file

@ -167,7 +167,7 @@ module TS.SpaceTac.UI {
if (animate) {
sprite.position.set(drone.owner.arena_x, drone.owner.arena_y);
sprite.rotation = drone.owner.arena_angle;
let move_duration = Animation.moveInSpace(sprite, drone.x, drone.y, angle);
let move_duration = Animations.moveInSpace(sprite, drone.x, drone.y, angle);
this.game.tweens.create(sprite.radius).from({ alpha: 0 }, 500, Phaser.Easing.Cubic.In, true, move_duration);
return move_duration + 500;

View file

@ -1,6 +1,9 @@
module TS.SpaceTac.UI {
// Ship sprite in the arena (BattleView)
export class ArenaShip extends Phaser.Group {
// Link to the view
battleview: BattleView;
// Link to displayed ship
ship: Ship;
@ -25,10 +28,10 @@ module TS.SpaceTac.UI {
// Create a ship sprite usable in the Arena
constructor(parent: Arena, ship: Ship) {
super(parent.game);
let battleview = parent.battleview;
this.battleview = parent.battleview;
this.ship = ship;
this.enemy = this.ship.getPlayer() != battleview.player;
this.enemy = this.ship.getPlayer() != this.battleview.player;
// Add ship sprite
this.sprite = new Phaser.Button(this.game, 0, 0, "ship-" + ship.model + "-sprite");
@ -58,7 +61,11 @@ module TS.SpaceTac.UI {
this.addChild(this.effects);
// Handle input on ship sprite
Tools.setHoverClick(this.sprite, () => battleview.cursorOnShip(ship), () => battleview.cursorOffShip(ship), () => battleview.cursorClicked());
Tools.setHoverClick(this.sprite,
() => this.battleview.cursorOnShip(ship),
() => this.battleview.cursorOffShip(ship),
() => this.battleview.cursorClicked()
);
// Set location
this.position.set(ship.arena_x, ship.arena_y);
@ -67,7 +74,7 @@ module TS.SpaceTac.UI {
// Set the hovered state on this ship
// This will toggle the hover effect
setHovered(hovered: boolean) {
Animation.setVisibility(this.game, this.hover, hovered, 200);
this.battleview.animations.setVisible(this.hover, hovered, 200);
}
// Set the playing state on this ship
@ -84,7 +91,7 @@ module TS.SpaceTac.UI {
this.displayEffect("stasis", false);
}
this.frame.alpha = dead ? 0.5 : 1.0;
Animation.setVisibility(this.game, this.stasis, dead, 400);
this.battleview.animations.setVisible(this.stasis, dead, 400);
}
/**
@ -94,7 +101,7 @@ module TS.SpaceTac.UI {
*/
moveTo(x: number, y: number, facing_angle: number, animate = true): number {
if (animate) {
return Animation.moveInSpace(this, x, y, facing_angle, this.sprite);
return Animations.moveInSpace(this, x, y, facing_angle, this.sprite);
} else {
this.x = x;
this.y = y;

View file

@ -1,6 +1,9 @@
module TS.SpaceTac.UI {
// One item in a ship list (used in BattleView)
export class ShipListItem extends Phaser.Button {
// Reference to the view
view: BattleView;
// Reference to the ship game object
ship: Ship;
@ -28,6 +31,7 @@ module TS.SpaceTac.UI {
// Create a ship button for the battle ship list
constructor(list: ShipList, x: number, y: number, ship: Ship, owned: boolean) {
super(list.battleview.game, x, y, owned ? "battle-shiplist-own" : "battle-shiplist-enemy");
this.view = list.battleview;
this.ship = ship;
@ -104,7 +108,7 @@ module TS.SpaceTac.UI {
// Set the hovered status
setHovered(hovered: boolean) {
Animation.setVisibility(this.game, this.layer_hover, hovered, 200);
this.view.animations.setVisible(this.layer_hover, hovered, 200);
}
}
}

View file

@ -118,9 +118,9 @@ module TS.SpaceTac.UI {
this.stasis.visible = !ship.alive;
Animation.fadeIn(this.game, this, 200);
this.battleview.animations.show(this, 200);
} else {
Animation.fadeOut(this.game, this, 200);
this.battleview.animations.hide(this, 200);
}
}

View file

@ -33,7 +33,7 @@ module TS.SpaceTac.UI {
*/
setSelected(selected: boolean) {
this.loadTexture(selected ? "character-ship-selected" : "character-ship");
Animation.setVisibility(this.game, this.levelup, this.ship.getAvailableUpgradePoints() > 0, 200);
this.sheet.view.animations.setVisible(this.levelup, this.ship.getAvailableUpgradePoints() > 0, 200);
}
/**

View file

@ -1,17 +0,0 @@
module TS.SpaceTac.UI.Specs {
describe("Animation", () => {
let testgame = setupEmptyView();
it("animates rotation", function () {
let obj = { rotation: -Math.PI * 2.5 };
let tween = testgame.ui.tweens.create(obj);
let result = Animation.rotationTween(tween, Math.PI * 0.25, 1, Phaser.Easing.Linear.None);
expect(result).toEqual(750);
expect(tween.generateData(4)).toEqual([
{ rotation: -Math.PI * 0.25 },
{ rotation: 0 },
{ rotation: Math.PI * 0.25 },
]);
});
});
}

View file

@ -0,0 +1,36 @@
module TS.SpaceTac.UI.Specs {
describe("Animations", () => {
let testgame = setupEmptyView();
it("shows and hides objects", function () {
let obj = { visible: false, alpha: 0.5 };
expect(testgame.baseview.animations.simulate(obj, 'alpha')).toEqual([]);
testgame.baseview.animations.show(obj);
expect(obj.visible).toBe(true);
expect(obj.alpha).toBe(0);
expect(testgame.baseview.animations.simulate(obj, 'alpha')).toEqual([0, 0.25, 0.5, 0.75, 1]);
obj.alpha = 1;
testgame.baseview.animations.hide(obj);
expect(obj.visible).toBe(true);
expect(obj.alpha).toBe(1);
expect(testgame.baseview.animations.simulate(obj, 'alpha')).toEqual([1, 0.75, 0.5, 0.25, 0]);
});
it("animates rotation", function () {
let obj = { rotation: -Math.PI * 2.5 };
let tween = testgame.ui.tweens.create(obj);
let result = Animations.rotationTween(tween, Math.PI * 0.25, 1, Phaser.Easing.Linear.None);
expect(result).toEqual(750);
expect(tween.generateData(4)).toEqual([
{ rotation: -Math.PI * 0.25 },
{ rotation: 0 },
{ rotation: Math.PI * 0.25 },
]);
});
});
}

View file

@ -7,35 +7,82 @@ module TS.SpaceTac.UI {
};
/**
* Utility functions for animation
* Interface of an object that may be shown/hidden, with opacity transition.
*/
export class Animation {
interface IAnimationFadeable {
alpha: number;
visible: boolean;
}
// Display an object, fading in using opacity
static fadeIn(game: Phaser.Game, obj: PIXI.DisplayObject, duration: number = 1000, alpha: number = 1): void {
/**
* Manager of all animations.
*
* This is a wrapper around phaser's tweens.
*/
export class Animations {
private tweens: Phaser.TweenManager;
constructor(tweens: Phaser.TweenManager) {
this.tweens = tweens;
}
/**
* Create a tween on an object.
*
* If a previous tween is running for this object, it will be stopped, and a new one will be created.
*/
private createTween(obj: any): Phaser.Tween {
this.tweens.removeFrom(obj);
let result = this.tweens.create(obj);
return result;
}
/**
* Simulate the tween currently applied to an object's property
*
* This may be heavy work and should only be done in testing code.
*/
simulate(obj: any, property: string, points = 5, duration = 1000): number[] {
let tween = first(this.tweens.getAll().concat((<any>this.tweens)._add), tween => tween.target === obj && !tween.pendingDelete);
if (tween) {
return [obj[property]].concat(tween.generateData(points - 1).map(data => data[property]));
} else {
return [];
}
}
/**
* Display an object, with opacity transition
*/
show(obj: IAnimationFadeable, duration = 1000, alpha = 1): void {
if (!obj.visible) {
obj.alpha = 0;
obj.visible = true;
}
var tween = game.tweens.create(obj);
let tween = this.createTween(obj);
tween.to({ alpha: alpha }, duration);
tween.start();
}
// Hide an object, fading out using opacity
static fadeOut(game: Phaser.Game, obj: PIXI.DisplayObject, duration: number = 1000): void {
var tween = game.tweens.create(obj);
/**
* Hide an object, with opacity transition
*/
hide(obj: IAnimationFadeable, duration = 1000): void {
let tween = this.createTween(obj);
tween.to({ alpha: 0 }, duration);
tween.onComplete.addOnce(() => obj.visible = false);
tween.start();
}
// Set visibility of an object, using either fadeIn or fadeOut
static setVisibility(game: Phaser.Game, obj: PIXI.DisplayObject, visible: boolean, duration: number = 1000): void {
/**
* Set an object visibility, with opacity transition
*/
setVisible(obj: IAnimationFadeable, visible: boolean, duration = 1000): void {
if (visible) {
Animation.fadeIn(game, obj, duration);
this.show(obj, duration);
} else {
Animation.fadeOut(game, obj, duration);
this.hide(obj, duration);
}
}
@ -77,7 +124,7 @@ module TS.SpaceTac.UI {
static moveInSpace(obj: PhaserGraphics, x: number, y: number, angle: number, rotated_obj = obj): number {
if (x == obj.x && y == obj.y) {
let tween = obj.game.tweens.create(rotated_obj);
let duration = Animation.rotationTween(tween, angle, 0.3);
let duration = Animations.rotationTween(tween, angle, 0.3);
tween.start();
return duration;
} else {

View file

@ -116,7 +116,7 @@ module TS.SpaceTac.UI {
// LOD
let detailed = focus && level == 2;
this.children.forEach(child => Animation.setVisibility(this.game, child, detailed, 300));
this.children.forEach(child => this.view.animations.setVisible(child, detailed, 300));
}
}
}

View file

@ -128,9 +128,9 @@ module TS.SpaceTac.UI {
let angle = Math.atan2(location.y, location.x);
this.button_jump.scale.set(location.star.radius * 0.002, location.star.radius * 0.002);
this.button_jump.position.set(location.star.x + location.x + 0.02 * Math.cos(angle), location.star.y + location.y + 0.02 * Math.sin(angle));
Animation.setVisibility(this.game, this.button_jump, true, 300);
this.animations.setVisible(this.button_jump, true, 300);
} else {
Animation.setVisibility(this.game, this.button_jump, false, 300);
this.animations.setVisible(this.button_jump, false, 300);
}
}
@ -180,7 +180,7 @@ module TS.SpaceTac.UI {
*/
doJump() {
if (this.player.fleet.location && this.player.fleet.location.type == StarLocationType.WARP && this.player.fleet.location.jump_dest) {
Animation.setVisibility(this.game, this.button_jump, false, 300);
this.animations.setVisible(this.button_jump, false, 300);
let dest_location = this.player.fleet.location.jump_dest;
let dest_star = dest_location.star;