211 lines
7.8 KiB
TypeScript
211 lines
7.8 KiB
TypeScript
/// <reference path="../BaseView.ts"/>
|
|
|
|
module TS.SpaceTac.UI {
|
|
/**
|
|
* Interactive map of the universe
|
|
*/
|
|
export class UniverseMapView extends BaseView {
|
|
// Displayed universe
|
|
universe = new Universe();
|
|
|
|
// Interacting player
|
|
player = new Player();
|
|
|
|
// Layers
|
|
layer_universe: Phaser.Group;
|
|
layer_overlay: Phaser.Group;
|
|
|
|
// Star systems
|
|
starsystems: StarSystemDisplay[] = [];
|
|
starlinks: Phaser.Graphics[] = [];
|
|
|
|
// Fleets
|
|
player_fleet: FleetDisplay;
|
|
|
|
// Frame to highlight current location
|
|
current_location: CurrentLocationMarker;
|
|
|
|
// Button to jump to another system
|
|
button_jump: Phaser.Button;
|
|
|
|
// Character sheet
|
|
character_sheet: CharacterSheet;
|
|
|
|
// Zoom level
|
|
zoom = 0;
|
|
|
|
/**
|
|
* Init the view, binding it to a universe
|
|
*/
|
|
init(universe: Universe, player: Player) {
|
|
super.init();
|
|
|
|
this.universe = universe;
|
|
this.player = player;
|
|
}
|
|
|
|
/**
|
|
* Create view graphics
|
|
*/
|
|
create() {
|
|
super.create();
|
|
|
|
this.layer_universe = this.addLayer("universe");
|
|
this.layer_overlay = this.addLayer("overlay");
|
|
|
|
this.starlinks = this.universe.starlinks.map(starlink => {
|
|
let loc1 = starlink.first.getWarpLocationTo(starlink.second);
|
|
let loc2 = starlink.second.getWarpLocationTo(starlink.first);
|
|
|
|
let result = new Phaser.Graphics(this.game);
|
|
if (loc1 && loc2) {
|
|
result.lineStyle(0.005, 0x8bbeff);
|
|
result.moveTo(starlink.first.x - 0.5 + loc1.x, starlink.first.y - 0.5 + loc1.y);
|
|
result.lineTo(starlink.second.x - 0.5 + loc2.x, starlink.second.y - 0.5 + loc2.y);
|
|
}
|
|
result.data.link = starlink;
|
|
return result;
|
|
});
|
|
this.starlinks.forEach(starlink => this.layer_universe.add(starlink));
|
|
|
|
this.player_fleet = new FleetDisplay(this, this.player.fleet);
|
|
|
|
this.starsystems = this.universe.stars.map(star => new StarSystemDisplay(this, star));
|
|
this.starsystems.forEach(starsystem => this.layer_universe.add(starsystem));
|
|
|
|
this.layer_universe.add(this.player_fleet);
|
|
|
|
this.current_location = new CurrentLocationMarker(this, this.player_fleet);
|
|
this.layer_universe.add(this.current_location);
|
|
|
|
this.button_jump = new Phaser.Button(this.game, 0, 0, "map-button-jump", () => this.doJump());
|
|
this.button_jump.anchor.set(0.5, 0.5);
|
|
this.button_jump.visible = false;
|
|
this.layer_universe.add(this.button_jump);
|
|
this.tooltip.bindStaticText(this.button_jump, "Engage warp drive to jump to another star system");
|
|
|
|
let button = new Phaser.Button(this.game, 1520, 100, "map-zoom-in", () => this.setZoom(this.zoom + 1));
|
|
button.anchor.set(0.5, 0.5);
|
|
this.layer_overlay.add(button);
|
|
this.tooltip.bindStaticText(button, "Zoom in");
|
|
button = new Phaser.Button(this.game, 1520, 980, "map-zoom-out", () => this.setZoom(this.zoom - 1));
|
|
button.anchor.set(0.5, 0.5);
|
|
this.layer_overlay.add(button);
|
|
this.tooltip.bindStaticText(button, "Zoom out");
|
|
|
|
this.character_sheet = new CharacterSheet(this, this.getWidth() - 307);
|
|
this.character_sheet.show(this.player.fleet.ships[0], false);
|
|
this.character_sheet.hide(false);
|
|
this.layer_overlay.add(this.character_sheet);
|
|
|
|
this.gameui.audio.startMusic("spring-thaw");
|
|
|
|
// Inputs
|
|
this.inputs.bindCheat("r", "Reveal whole map", () => this.revealAll());
|
|
|
|
this.setZoom(2);
|
|
|
|
// Trigger an auto-save any time we go back to the map
|
|
this.autoSave();
|
|
}
|
|
|
|
/**
|
|
* Leaving the view, unbind and destroy
|
|
*/
|
|
shutdown() {
|
|
this.universe = new Universe();
|
|
this.player = new Player();
|
|
|
|
super.shutdown();
|
|
}
|
|
|
|
/**
|
|
* Refresh the view
|
|
*/
|
|
refresh() {
|
|
this.setZoom(this.zoom);
|
|
}
|
|
|
|
/**
|
|
* Update info on all star systems (fog of war, available data...)
|
|
*/
|
|
updateInfo(current_star: Star | null) {
|
|
this.current_location.setZoom(this.zoom);
|
|
|
|
this.starlinks.forEach(linkgraphics => {
|
|
let link = <StarLink>linkgraphics.data.link;
|
|
linkgraphics.visible = this.player.hasVisitedSystem(link.first) || this.player.hasVisitedSystem(link.second);
|
|
})
|
|
|
|
this.starsystems.forEach(system => system.updateInfo(this.zoom, system.starsystem == current_star));
|
|
|
|
let location = this.player.fleet.location;
|
|
if (location && location.type == StarLocationType.WARP && this.zoom >= 2) {
|
|
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));
|
|
this.animations.setVisible(this.button_jump, true, 300);
|
|
} else {
|
|
this.animations.setVisible(this.button_jump, false, 300);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reveal the whole map (this is a cheat)
|
|
*/
|
|
revealAll(): void {
|
|
this.universe.stars.forEach(star => {
|
|
star.locations.forEach(location => {
|
|
this.player.setVisited(location);
|
|
});
|
|
});
|
|
this.refresh();
|
|
}
|
|
|
|
/**
|
|
* Set the camera to center on a target, and to display a given span in height
|
|
*/
|
|
setCamera(x: number, y: number, span: number, duration = 500, easing = Phaser.Easing.Cubic.InOut) {
|
|
let scale = 1000 / span;
|
|
this.tweens.create(this.layer_universe.position).to({ x: 800 - x * scale, y: 540 - y * scale }, duration, easing).start();
|
|
this.tweens.create(this.layer_universe.scale).to({ x: scale, y: scale }, duration, easing).start();
|
|
}
|
|
|
|
/**
|
|
* Set the current zoom level (0, 1 or 2)
|
|
*/
|
|
setZoom(level: number) {
|
|
let current_star = this.player.fleet.location ? this.player.fleet.location.star : null;
|
|
if (!current_star || level <= 0) {
|
|
this.setCamera(0, 0, this.universe.radius * 2);
|
|
this.zoom = 0;
|
|
} else if (level == 1) {
|
|
// TODO Zoom to next-jump accessible
|
|
this.setCamera(current_star.x, current_star.y, this.universe.radius * 0.5);
|
|
this.zoom = 1;
|
|
} else {
|
|
this.setCamera(current_star.x, current_star.y, current_star.radius * 2);
|
|
this.zoom = 2;
|
|
}
|
|
|
|
this.updateInfo(current_star);
|
|
}
|
|
|
|
/**
|
|
* Do the jump animation to another system
|
|
*/
|
|
doJump() {
|
|
if (this.player.fleet.location && this.player.fleet.location.type == StarLocationType.WARP && this.player.fleet.location.jump_dest) {
|
|
this.animations.setVisible(this.button_jump, false, 300);
|
|
|
|
let dest_location = this.player.fleet.location.jump_dest;
|
|
let dest_star = dest_location.star;
|
|
this.player_fleet.moveToLocation(dest_location, 3, duration => {
|
|
this.timer.schedule(duration / 2, () => this.updateInfo(dest_star));
|
|
this.setCamera(dest_star.x, dest_star.y, dest_star.radius * 2, duration, Phaser.Easing.Cubic.Out);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|