From 40925d54e11d649292a94f3f3274e07e6d507889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Tue, 24 Mar 2015 01:00:00 +0100 Subject: [PATCH] Added star system map view --- src/app/GameUI.ts | 1 + src/app/game/Fleet.ts | 4 ++ src/app/game/Star.ts | 41 +++++++++++++++++ src/app/game/StarLocation.ts | 35 ++++++++++++++ src/app/game/Universe.ts | 4 ++ src/app/view/Preload.ts | 3 ++ src/app/view/map/StarSystemView.ts | 63 ++++++++++++++++++++++++++ src/app/view/map/UniverseMapView.ts | 21 ++++++--- src/assets/images/map/button-back.png | Bin 0 -> 4772 bytes src/assets/images/map/planet-icon.png | Bin 0 -> 2044 bytes src/assets/images/map/warp-icon.png | Bin 0 -> 3062 bytes 11 files changed, 166 insertions(+), 6 deletions(-) create mode 100644 src/app/game/StarLocation.ts create mode 100644 src/app/view/map/StarSystemView.ts create mode 100644 src/assets/images/map/button-back.png create mode 100644 src/assets/images/map/planet-icon.png create mode 100644 src/assets/images/map/warp-icon.png diff --git a/src/app/GameUI.ts b/src/app/GameUI.ts index 593968f..ad74d1a 100644 --- a/src/app/GameUI.ts +++ b/src/app/GameUI.ts @@ -19,6 +19,7 @@ module SpaceTac { this.state.add('router', View.Router); this.state.add('battle', View.BattleView); this.state.add('universe', View.UniverseMapView); + this.state.add('starsystem', View.StarSystemView); this.state.start('boot'); } diff --git a/src/app/game/Fleet.ts b/src/app/game/Fleet.ts index 8fa686b..0afaeac 100644 --- a/src/app/game/Fleet.ts +++ b/src/app/game/Fleet.ts @@ -11,6 +11,9 @@ module SpaceTac.Game { // List of ships ships: Ship[]; + // Current fleet location + location: StarLocation; + // Current battle in which the fleet is engaged (null if not fighting) battle: Battle; @@ -20,6 +23,7 @@ module SpaceTac.Game { this.player = player || new Player(); this.ships = []; + this.location = null; this.battle = null; } diff --git a/src/app/game/Star.ts b/src/app/game/Star.ts index 896cf63..c630637 100644 --- a/src/app/game/Star.ts +++ b/src/app/game/Star.ts @@ -12,12 +12,20 @@ module SpaceTac.Game { x: number; y: number; + // Radius of the star system + radius: number; + + // List of points of interest + locations: StarLocation[]; + constructor(universe: Universe, x: number, y: number) { super(); this.universe = universe; this.x = x; this.y = y; + this.radius = 0.1; + this.locations = []; } // Get the distance to another star @@ -27,5 +35,38 @@ module SpaceTac.Game { return Math.sqrt(dx * dx + dy * dy); } + + // Generate the contents of this star system + generate(random: RandomGenerator = new RandomGenerator()): void { + var location_count = random.throwInt(2, 10); + this.locations = this.generateLocations(location_count, random); + } + + // Generate points of interest (*count* doesn't include the star and warp locations) + generateLocations(count: number, random: RandomGenerator = new RandomGenerator()): StarLocation[] { + var result: StarLocation[] = []; + + // Add the star + result.push(new StarLocation(this, StarLocationType.STAR, 0, 0)); + + // Add warp locations around the star + var warps = 3; + while (warps--) { + result.push(this.generateOneLocation(StarLocationType.WARP, result, this.radius * 0.3, random)); + } + + // Add random locations + while (count--) { + result.push(this.generateOneLocation(StarLocationType.PLANET, result, this.radius, random)); + } + + return result; + } + + private generateOneLocation(type: StarLocationType, others: StarLocation[], radius: number, random: RandomGenerator): StarLocation { + var x = (random.throw(2) - 1) * radius; + var y = (random.throw(2) - 1) * radius; + return new StarLocation(this, type, x, y); + } } } diff --git a/src/app/game/StarLocation.ts b/src/app/game/StarLocation.ts new file mode 100644 index 0000000..a28149f --- /dev/null +++ b/src/app/game/StarLocation.ts @@ -0,0 +1,35 @@ +/// + +module SpaceTac.Game { + "use strict"; + + export enum StarLocationType { + STAR, + WARP, + PLANET, + ASTEROID, + STATION + } + + // Point of interest in a star system + export class StarLocation extends Serializable { + // Parent star system + star: Star; + + // Type of location + type: StarLocationType; + + // Location in the star system + x: number; + y: number; + + constructor(star: Star, type: StarLocationType, x: number, y: number) { + super(); + + this.star = star; + this.type = type; + this.x = x; + this.y = y; + } + } +} diff --git a/src/app/game/Universe.ts b/src/app/game/Universe.ts index d6722d4..255e838 100644 --- a/src/app/game/Universe.ts +++ b/src/app/game/Universe.ts @@ -60,6 +60,10 @@ module SpaceTac.Game { var links = this.getPotentialLinks(); this.starlinks = this.filterCrossingLinks(links); + + this.stars.forEach((star: Star) => { + star.generate(random); + }); } // Generate a given number of stars, not too crowded diff --git a/src/app/view/Preload.ts b/src/app/view/Preload.ts index ab6c571..b9fefe7 100644 --- a/src/app/view/Preload.ts +++ b/src/app/view/Preload.ts @@ -54,6 +54,9 @@ module SpaceTac.View { this.loadImage("common/standard-bar-background.png"); this.loadImage("common/standard-bar-foreground.png"); this.loadImage("map/star-icon.png"); + this.loadImage("map/planet-icon.png"); + this.loadImage("map/warp-icon.png"); + this.loadImage("map/button-back.png"); // Load sounds this.loadSound("battle/ship-change.wav"); diff --git a/src/app/view/map/StarSystemView.ts b/src/app/view/map/StarSystemView.ts new file mode 100644 index 0000000..6dc78a6 --- /dev/null +++ b/src/app/view/map/StarSystemView.ts @@ -0,0 +1,63 @@ +module SpaceTac.View { + "use strict"; + + // Interactive map of a star system + export class StarSystemView extends Phaser.State { + + // Displayed star system + star: Game.Star; + + // Interacting player + player: Game.Player; + + // Group for the locations diplay + locations: Phaser.Group; + + // Scaling used to transform game coordinates in screen ones + private scaling: number; + + + // Init the view, binding it to a universe + init(star: Game.Star, player: Game.Player) { + this.star = star; + this.player = player; + } + + // Create view graphics + create() { + this.locations = this.add.group(); + + this.scaling = 720 / (this.star.radius * 2); + this.locations.position.set(this.star.radius * this.scaling, this.star.radius * this.scaling); + this.locations.scale.set(this.scaling); + + this.drawLocations(); + + // Back button + this.add.button(0, 0, "map-button-back", this.onBackClicked, this); + } + + // Leaving the view, unbind and destroy + shutdown() { + this.star = null; + this.player = null; + } + + // Redraw the locations map + drawLocations(): void { + console.log(this.star.locations); + this.locations.removeAll(true, true); + this.star.locations.forEach((location: Game.StarLocation) => { + var key = "map-" + Game.StarLocationType[location.type].toLowerCase() + "-icon"; + var sprite = this.add.sprite(location.x, location.y, key, 0, this.locations); + sprite.scale.set(1.0 / this.scaling, 1.0 / this.scaling); + sprite.anchor.set(0.5, 0.5); + }); + } + + // Called when "Back" is clicked, go back to universe map + onBackClicked(): void { + this.game.state.start("universe", true, false, this.star.universe, this.player); + } + } +} diff --git a/src/app/view/map/UniverseMapView.ts b/src/app/view/map/UniverseMapView.ts index 0d34e51..54b8fe5 100644 --- a/src/app/view/map/UniverseMapView.ts +++ b/src/app/view/map/UniverseMapView.ts @@ -11,7 +11,10 @@ module SpaceTac.View { player: Game.Player; // Group for the stars and links - stars: Phaser.Group; + private stars: Phaser.Group; + + // Scaling used to transform game coordinates in screen ones + private scaling: number; // Init the view, binding it to a universe init(universe: Game.Universe, player: Game.Player) { @@ -23,9 +26,9 @@ module SpaceTac.View { create() { this.stars = this.add.group(); - var scale = 720 / (this.universe.radius * 2); - this.stars.position.set(this.universe.radius * scale, this.universe.radius * scale); - this.stars.scale.set(scale); + this.scaling = 720 / (this.universe.radius * 2); + this.stars.position.set(this.universe.radius * this.scaling, this.universe.radius * this.scaling); + this.stars.scale.set(this.scaling); this.drawStars(); @@ -52,9 +55,15 @@ module SpaceTac.View { }); this.universe.stars.forEach((star: Game.Star) => { if (this.player.hasVisited(star)) { - var sprite = this.add.sprite(star.x, star.y, "map-star-icon", 0, this.stars); - sprite.scale.set(0.1, 0.1); + var sprite = new Phaser.Button(this.game, star.x, star.y, "map-star-icon"); + sprite.scale.set(1.0 / this.scaling, 1.0 / this.scaling); sprite.anchor.set(0.5, 0.5); + + sprite.onInputUp.add(() => { + this.game.state.start("starsystem", true, false, star, this.player); + }); + + this.stars.addChild(sprite); } }); } diff --git a/src/assets/images/map/button-back.png b/src/assets/images/map/button-back.png new file mode 100644 index 0000000000000000000000000000000000000000..bfaf7c2978276eac408b8b4a9cc8d2ea40bf539f GIT binary patch literal 4772 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 literal 0 HcmV?d00001 diff --git a/src/assets/images/map/planet-icon.png b/src/assets/images/map/planet-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b000815160797eee08c41606b84f63c2e8ef4fda GIT binary patch literal 2044 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 Ef-JT1%m4rY literal 0 HcmV?d00001