Added fleet display on map
This commit is contained in:
parent
cacef3cea8
commit
f1ef892c0b
|
@ -1,4 +1,5 @@
|
||||||
/// <reference path="battle/BattleView.ts"/>
|
/// <reference path="battle/BattleView.ts"/>
|
||||||
|
/// <reference path="map/UniverseMapView.ts"/>
|
||||||
|
|
||||||
module TS.SpaceTac.View.Specs {
|
module TS.SpaceTac.View.Specs {
|
||||||
// Test game wrapper (use instead of jasmine 'it')
|
// Test game wrapper (use instead of jasmine 'it')
|
||||||
|
@ -42,4 +43,14 @@ module TS.SpaceTac.View.Specs {
|
||||||
func(battleview);
|
func(battleview);
|
||||||
}, battleview, player, battle);
|
}, battleview, player, battle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test game wrapper, with a map initialized on a random universe
|
||||||
|
export function inmapview_it(desc: string, func: (mapview: UniverseMapView) => void) {
|
||||||
|
var mapview = new UniverseMapView();
|
||||||
|
var session = new Game.GameSession();
|
||||||
|
session.startNewGame();
|
||||||
|
ingame_it(desc, (game: Phaser.Game, state: Phaser.State) => {
|
||||||
|
func(mapview);
|
||||||
|
}, mapview, session.universe, session.player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
18
src/view/map/FleetDisplay.spec.ts
Normal file
18
src/view/map/FleetDisplay.spec.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
module TS.SpaceTac.View.Specs {
|
||||||
|
describe("FleetDisplay", () => {
|
||||||
|
inmapview_it("orbits the fleet around its current location", mapview => {
|
||||||
|
let fleet = mapview.player_fleet;
|
||||||
|
|
||||||
|
fleet.loopOrbit();
|
||||||
|
expect(fleet.rotation).toBe(0);
|
||||||
|
|
||||||
|
mapview.game.tweens.update();
|
||||||
|
let tween = first(mapview.game.tweens.getAll(), tw => tw.target == fleet);
|
||||||
|
let tweendata = tween.generateData(0.1);
|
||||||
|
expect(tweendata.length).toEqual(3);
|
||||||
|
expect(tweendata[0].rotation).toBeCloseTo(-Math.PI * 2 / 3);
|
||||||
|
expect(tweendata[1].rotation).toBeCloseTo(-Math.PI * 4 / 3);
|
||||||
|
expect(tweendata[2].rotation).toBeCloseTo(-Math.PI * 2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
92
src/view/map/FleetDisplay.ts
Normal file
92
src/view/map/FleetDisplay.ts
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
module TS.SpaceTac.View {
|
||||||
|
const SCALING = 0.00005;
|
||||||
|
const LOCATIONS: [number, number][] = [
|
||||||
|
[80, 0],
|
||||||
|
[0, -50],
|
||||||
|
[0, 50],
|
||||||
|
[-80, 0],
|
||||||
|
[0, 0],
|
||||||
|
];
|
||||||
|
const PI2 = Math.PI * 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group to display a fleet
|
||||||
|
*/
|
||||||
|
export class FleetDisplay extends Phaser.Group {
|
||||||
|
private map: UniverseMapView;
|
||||||
|
private fleet: Game.Fleet;
|
||||||
|
private tween: Phaser.Tween;
|
||||||
|
|
||||||
|
constructor(parent: UniverseMapView, fleet: Game.Fleet) {
|
||||||
|
super(parent.game);
|
||||||
|
|
||||||
|
this.map = parent;
|
||||||
|
this.fleet = fleet;
|
||||||
|
|
||||||
|
fleet.ships.forEach((ship, index) => {
|
||||||
|
let offset = LOCATIONS[index];
|
||||||
|
let sprite = this.game.add.image(offset[0], offset[1] + 150, `ship-${ship.model}-sprite`, 0, this);
|
||||||
|
sprite.anchor.set(0.5, 0.5);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.position.set(fleet.location.star.x + fleet.location.x, fleet.location.star.y + fleet.location.y);
|
||||||
|
this.scale.set(SCALING, SCALING);
|
||||||
|
|
||||||
|
this.tween = this.game.tweens.create(this);
|
||||||
|
this.loopOrbit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animate to a given position in orbit of its current star location
|
||||||
|
*/
|
||||||
|
goToOrbitPoint(angle: number, speed = 1, then: Function | null = null, ease = false) {
|
||||||
|
this.tween.stop(false);
|
||||||
|
this.rotation %= PI2;
|
||||||
|
|
||||||
|
let target = -angle;
|
||||||
|
while (target >= this.rotation) {
|
||||||
|
target -= PI2;
|
||||||
|
}
|
||||||
|
let distance = Math.abs(target - this.rotation) / PI2;
|
||||||
|
this.tween = this.game.tweens.create(this).to({ rotation: target }, 30000 * distance / speed, ease ? Phaser.Easing.Cubic.In : Phaser.Easing.Linear.None);
|
||||||
|
if (then) {
|
||||||
|
this.tween.onComplete.addOnce(then);
|
||||||
|
}
|
||||||
|
this.tween.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the fleet loop in orbit
|
||||||
|
*/
|
||||||
|
loopOrbit() {
|
||||||
|
this.goToOrbitPoint(this.rotation + PI2, 1, () => {
|
||||||
|
this.loopOrbit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the fleet move to another location in the same system
|
||||||
|
*/
|
||||||
|
moveToLocation(location: Game.StarLocation) {
|
||||||
|
if (location != this.fleet.location) {
|
||||||
|
let dx = location.x - this.fleet.location.x;
|
||||||
|
let dy = location.y - this.fleet.location.y;
|
||||||
|
let distance = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
let angle = Math.atan2(dx, dy);
|
||||||
|
this.goToOrbitPoint(angle - Math.PI / 2, 20, () => {
|
||||||
|
let tween = this.game.tweens.create(this.position).to({ x: this.x + dx, y: this.y + dy }, 10000 * distance, Phaser.Easing.Cubic.Out);
|
||||||
|
tween.onComplete.addOnce(() => {
|
||||||
|
this.fleet.setLocation(location);
|
||||||
|
if (this.fleet.battle) {
|
||||||
|
this.game.state.start("router");
|
||||||
|
} else {
|
||||||
|
this.map.updateInfo();
|
||||||
|
this.loopOrbit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tween.start();
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,42 +2,52 @@ module TS.SpaceTac.View {
|
||||||
// Group to display a star system
|
// Group to display a star system
|
||||||
export class StarSystemDisplay extends Phaser.Image {
|
export class StarSystemDisplay extends Phaser.Image {
|
||||||
starsystem: Game.Star;
|
starsystem: Game.Star;
|
||||||
|
player: Game.Player;
|
||||||
|
fleet_display: FleetDisplay;
|
||||||
|
locations: [Game.StarLocation, Phaser.Image, Phaser.Image][] = [];
|
||||||
|
|
||||||
constructor(parent: UniverseMapView, starsystem: Game.Star) {
|
constructor(parent: UniverseMapView, starsystem: Game.Star) {
|
||||||
super(parent.game, starsystem.x, starsystem.y, "map-starsystem-background");
|
super(parent.game, starsystem.x, starsystem.y, "map-starsystem-background");
|
||||||
|
|
||||||
this.anchor.set(0.5, 0.5);
|
this.anchor.set(0.5, 0.5);
|
||||||
|
|
||||||
let scale = this.width;
|
let scale = this.width;
|
||||||
this.scale.set(starsystem.radius * 2 / scale);
|
this.scale.set(starsystem.radius * 2 / scale);
|
||||||
|
|
||||||
this.starsystem = starsystem;
|
this.starsystem = starsystem;
|
||||||
|
this.player = parent.player;
|
||||||
|
this.fleet_display = parent.player_fleet;
|
||||||
|
|
||||||
// Show boundary
|
// Show boundary
|
||||||
this.addCircle(starsystem.radius);
|
this.addCircle(starsystem.radius);
|
||||||
|
|
||||||
// Show locations
|
// Show locations
|
||||||
starsystem.locations.forEach(location => {
|
starsystem.locations.map(location => {
|
||||||
let location_sprite: Phaser.Image | null = null;
|
let location_sprite: Phaser.Image | null = null;
|
||||||
|
let fleet_move = () => this.fleet_display.moveToLocation(location);
|
||||||
|
|
||||||
if (location.type == Game.StarLocationType.STAR) {
|
if (location.type == Game.StarLocationType.STAR) {
|
||||||
location_sprite = this.addImage(location.x, location.y, "map-location-star");
|
location_sprite = this.addImage(location.x, location.y, "map-location-star", fleet_move);
|
||||||
} else if (location.type == Game.StarLocationType.PLANET) {
|
} else if (location.type == Game.StarLocationType.PLANET) {
|
||||||
location_sprite = this.addImage(location.x, location.y, "map-location-planet");
|
location_sprite = this.addImage(location.x, location.y, "map-location-planet", fleet_move);
|
||||||
location_sprite.rotation = Math.atan2(location.y, location.x);
|
location_sprite.rotation = Math.atan2(location.y, location.x);
|
||||||
this.addCircle(Math.sqrt(location.x * location.x + location.y * location.y), 1);
|
this.addCircle(Math.sqrt(location.x * location.x + location.y * location.y), 1);
|
||||||
} else if (location.type == Game.StarLocationType.WARP) {
|
} else if (location.type == Game.StarLocationType.WARP) {
|
||||||
location_sprite = this.addImage(location.x, location.y, "map-location-warp");
|
location_sprite = this.addImage(location.x, location.y, "map-location-warp", fleet_move);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (location_sprite) {
|
if (location_sprite) {
|
||||||
let key = parent.player.hasVisitedLocation(location) ? (location.encounter ? "map-state-enemy" : "map-state-clear") : "map-state-unknown";
|
let key = this.getVisitedKey(location);
|
||||||
this.addImage(location.x + 0.005, location.y + 0.005, key);
|
let status_badge = this.addImage(location.x + 0.005, location.y + 0.005, key);
|
||||||
|
this.locations.push([location, location_sprite, status_badge]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addImage(x: number, y: number, key: string): Phaser.Image {
|
addImage(x: number, y: number, key: string, onclick: Function | null = null): Phaser.Image {
|
||||||
let image = this.game.add.image(x / this.scale.x, y / this.scale.y, key);
|
x /= this.scale.x;
|
||||||
|
y /= this.scale.y;
|
||||||
|
let image = onclick ? this.game.add.button(x, y, key, onclick) : this.game.add.image(x, y, key);
|
||||||
image.anchor.set(0.5, 0.5);
|
image.anchor.set(0.5, 0.5);
|
||||||
this.addChild(image);
|
this.addChild(image);
|
||||||
return image;
|
return image;
|
||||||
|
@ -50,5 +60,21 @@ module TS.SpaceTac.View {
|
||||||
this.addChild(circle);
|
this.addChild(circle);
|
||||||
return circle;
|
return circle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the sprite code to use for visited status.
|
||||||
|
*/
|
||||||
|
getVisitedKey(location: Game.StarLocation) {
|
||||||
|
return this.player.hasVisitedLocation(location) ? (location.encounter ? "map-state-enemy" : "map-state-clear") : "map-state-unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update displayed information, and fog of war
|
||||||
|
*/
|
||||||
|
updateInfo() {
|
||||||
|
this.locations.forEach(info => {
|
||||||
|
info[2].loadTexture(this.getVisitedKey(info[0]));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,9 @@ module TS.SpaceTac.View {
|
||||||
starsystems: StarSystemDisplay[] = [];
|
starsystems: StarSystemDisplay[] = [];
|
||||||
starlinks: Phaser.Graphics[] = [];
|
starlinks: Phaser.Graphics[] = [];
|
||||||
|
|
||||||
|
// Fleets
|
||||||
|
player_fleet: FleetDisplay;
|
||||||
|
|
||||||
// Zoom level
|
// Zoom level
|
||||||
zoom = 0;
|
zoom = 0;
|
||||||
|
|
||||||
|
@ -44,9 +47,13 @@ module TS.SpaceTac.View {
|
||||||
});
|
});
|
||||||
this.starlinks.forEach(starlink => this.group.addChild(starlink));
|
this.starlinks.forEach(starlink => this.group.addChild(starlink));
|
||||||
|
|
||||||
|
this.player_fleet = new FleetDisplay(this, this.player.fleet);
|
||||||
|
|
||||||
this.starsystems = this.universe.stars.map(star => new StarSystemDisplay(this, star));
|
this.starsystems = this.universe.stars.map(star => new StarSystemDisplay(this, star));
|
||||||
this.starsystems.forEach(starsystem => this.group.addChild(starsystem));
|
this.starsystems.forEach(starsystem => this.group.addChild(starsystem));
|
||||||
|
|
||||||
|
this.group.addChild(this.player_fleet);
|
||||||
|
|
||||||
this.setZoom(2);
|
this.setZoom(2);
|
||||||
this.add.button(1830, 100, "map-zoom-in", () => this.setZoom(this.zoom + 1)).anchor.set(0.5, 0.5);
|
this.add.button(1830, 100, "map-zoom-in", () => this.setZoom(this.zoom + 1)).anchor.set(0.5, 0.5);
|
||||||
this.add.button(1830, 980, "map-zoom-out", () => this.setZoom(this.zoom - 1)).anchor.set(0.5, 0.5);
|
this.add.button(1830, 980, "map-zoom-out", () => this.setZoom(this.zoom - 1)).anchor.set(0.5, 0.5);
|
||||||
|
@ -65,6 +72,11 @@ module TS.SpaceTac.View {
|
||||||
super.shutdown();
|
super.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update info on all star systems (fog of war, available data...)
|
||||||
|
updateInfo() {
|
||||||
|
this.starsystems.forEach(system => system.updateInfo());
|
||||||
|
}
|
||||||
|
|
||||||
// Reveal the whole map (this is a cheat)
|
// Reveal the whole map (this is a cheat)
|
||||||
revealAll(): void {
|
revealAll(): void {
|
||||||
this.universe.stars.forEach(star => {
|
this.universe.stars.forEach(star => {
|
||||||
|
|
Loading…
Reference in a new issue