From d82f89aeb5338f67017516c9c2c9dac3dde87b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Fri, 27 Jan 2017 00:01:04 +0100 Subject: [PATCH] More work on new map screen --- graphics/ui/map.svg | 69 +++++++++------ .../map/{planet.png => location-planet.png} | Bin .../map/{star.png => location-star.png} | Bin out/assets/images/map/location-warp.png | Bin 0 -> 4019 bytes out/assets/images/map/state-clear.png | Bin 0 -> 631 bytes out/assets/images/map/state-enemy.png | Bin 0 -> 1387 bytes out/assets/images/map/state-unknown.png | Bin 0 -> 1356 bytes src/game/Star.spec.ts | 59 +++---------- src/game/Star.ts | 83 +++++++++++------- src/game/Universe.spec.ts | 39 ++++++++ src/game/Universe.ts | 20 ++++- src/view/Preload.ts | 8 +- src/view/map/StarSystemDisplay.ts | 24 +++-- src/view/map/UniverseMapView.ts | 18 +++- 14 files changed, 199 insertions(+), 121 deletions(-) rename out/assets/images/map/{planet.png => location-planet.png} (100%) rename out/assets/images/map/{star.png => location-star.png} (100%) create mode 100644 out/assets/images/map/location-warp.png create mode 100644 out/assets/images/map/state-clear.png create mode 100644 out/assets/images/map/state-enemy.png create mode 100644 out/assets/images/map/state-unknown.png diff --git a/graphics/ui/map.svg b/graphics/ui/map.svg index ac1326d..21c7329 100644 --- a/graphics/ui/map.svg +++ b/graphics/ui/map.svg @@ -226,10 +226,10 @@ inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:zoom="2.1771152" - inkscape:cx="1247.613" - inkscape:cy="542.95678" + inkscape:cx="1424.0698" + inkscape:cy="540.88968" inkscape:document-units="mm" - inkscape:current-layer="layer5" + inkscape:current-layer="g7289" showgrid="false" units="px" inkscape:snap-bbox="false" @@ -293,12 +293,6 @@ inkscape:groupmode="layer" id="layer5" inkscape:label="Zoom 3"> - + - - + + + + + id="g7284" + inkscape:export-filename="/home/michael/workspace/perso/spacetac/out/assets/images/map/state-unknown.png" + inkscape:export-xdpi="96" + inkscape:export-ydpi="96"> + sodipodi:nodetypes="ccc" + inkscape:export-filename="/home/michael/workspace/perso/spacetac/out/assets/images/map/state-clear.png" + inkscape:export-xdpi="96" + inkscape:export-ydpi="96" /> + id="g7323" + inkscape:export-filename="/home/michael/workspace/perso/spacetac/out/assets/images/map/state-enemy.png" + inkscape:export-xdpi="96" + inkscape:export-ydpi="96"> 002t}1^@s6I8J)%00004b3#c}2nYxW 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 RnRfsH002ovPDHLkV1irO7}5X$ literal 0 HcmV?d00001 diff --git a/out/assets/images/map/state-enemy.png b/out/assets/images/map/state-enemy.png new file mode 100644 index 0000000000000000000000000000000000000000..ba17aa202f80242d7aabe6076998667684e707d4 GIT binary patch literal 1387 zcmV-x1(f=UP)3-Hckk|I+ooHa#E3?GEf#`B-~4zh z*kVEZ0mW1V!Ln@{AEcmlYoJ7sKz9k^Q(81JKg$snCh4{EK?07rn{F7-YHE;)`faq85m#m5pbH8o|Kruhjl2800& z!yp_EV_6nGJv~S%0Z>X&tyU?ON)!qO9LI5&DQK;yVzJn{W5pxKqwSq z+qP|3mbIbVE^ON-o6S-#m))V8hGD#Q{P^)qM**o+>O~>M4_fP|rIhU0v4cn?(iL$l z^7%Z=%gZRG0R9$2>`f#Rch?m#Jw4s;IL`0DkZGFq_xBSB1RjgrMXgpNlgUu2Q~(xg zwc4KX@$rA$dFg&kO-)&j<6HxV0)YTSLqktY4q%!l0|Nu}^z;A>nx=VWW@aYj6VM2_ zJyJ?`?%cT+U@o-XHip`w)z&Z!@0u^?a=Ft@0@CU9AoXY`9*?_f*HE3m&q{KV@~t}^ z$t!p6vXY#n_UC-lcpwlU9*?^}$ET;K`_}|C@;n?0g@{I@KJxrmGibX+VfONdA}V+8 zQn)yWwoBx`zTguPjYbIug8)&-an1mUR4Nq&{snpm1_qi^P1_|_&VGR|+K*O|lIZAR z0=swl$nzJzgL=dRAi@?~Kl>PAtsObGZL_$z2(X&XW}lK;>ok*3i+*C3A`JxE|=ciT0?;V`*e4yDvSv+=NOc+0IT;+r`T(&za`z*p#i-)axa(GdRPK6z?b*yiHN*=2+_{AOY#=3EuC50K(`&#=(ZCb#87{` z-3Mbsw2gL;s!sQW3lG<-1m*#%)oNGdt(a|GK z(e8?%>mMDGWqi24K4@cbR$JK&0l zdX7T`1N6Rs)OQtoIA)W{WJLlvjxzxi%H=Zoe7@-q=J2!he)t|DY<0}@wc}_AH(z+Z zX+D?BxpiV*DK!C}lI;BX^PdYLK9y23I5_C5hO}Msd9xnc*;XnQ78VvzN+EDw#~i z&HV)-#7l`pVxg@7fOI;&OKbfjFeIfU9*_H~q;Antmj9)--h1-o$v?a{Z5xxuPFw|E z0SE?z^!4>UNn>(DDRp3MY;393cHP!2l}ZJ*)~AIK9|2KlZp}>7bSoPi$DvlMVcRyv zV$mBvc_GA?TI^cAd002ovPDHLkV1k^#hv5JK literal 0 HcmV?d00001 diff --git a/out/assets/images/map/state-unknown.png b/out/assets/images/map/state-unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..fc719d4b9b5337d2039115f5fbc2bc7af479e31c GIT binary patch literal 1356 zcmV-S1+)5zP)&|RNi2mS&UwAQy@zI^#p zDwV1RIajn=FgG_hptZgNd;!D)>U{;=@;q;5dU`s$F9EZ&vtiRTzXqm&2!LT2L?RKw z;V>N?9Y`qwP)gytE}NU1lu9K$&-0HdX{~4D@%YvA=g)5j7ErhPJ75&RvMdfBJV-bk z-qUO!j^j`$6sS}x{?L8HFg}}@n8>vhkWQyZgb+Vyt>2PTa`^CJy1Kdo5${B?SR|j% zqm%+z7DAkzoSgjaKLy;laiib!ykCL0P1B^mzn{*|&V7;lsMTuZayhEiDnO=ItBqc| zbm^a60_r}$3ygMlb}}$9uN+ zU4Z+sSZv&n3DaLx54ce&C5c307rAMgjEs!X-`~HBptrY|!NEZ?nGBB}Jwj{!+Pq;H zBoYZSnG8y)v5k$5%fL6=H&73{KY&PIUmwwEw5jFe;!9UY~ss|(k4dGO!? zwrvO6+rV|8J=O*sJ9dm%EQZ#ag@uK{_OpMqnfo31BPe3WY*jdmFfH2|Ne( zOr2)%KdB%---!mU=Ms3hpMx5Uk#^C*^-yZ9Zv&Le<+cu4US4KtX^Hjq^|l50TvE#K zO(De3z$?%5;*R44eh(HG7uzO=E$izKm7UM$e~}k1T&MuIfVP5ZczBrM;bHpv`q~oE zz;QE`N>wF*=XoEEWSDbo}^nPMkPFGMNlazOk|4*NH`?)C_E;A=A^-S*`Uf zKt7-M%cnPrYPHIX7cT%1LR_Dknp)Ww01%JIuLAd#Qmm}3wER$P+s3x-K-r^|BA3hg z8FNo-ea)Y1R+P>IgKw%RbzPTSF6ZZdMhNl#Y=+K^3 z(q7n6mjA7_K6~-v#ors(G;K`kH}Ng-0YE4eqNk_l|1>7|lv1Djes3uNwwh6`^<^Q% zS3neAZ_P~8+^&K=&!bkW;W!TEa=9^nib9C%TI*}|bl-)R&1wBM{O0sPtMzr*z)hvp zOf#$765u11N_F=1^n9qb{!~hNN^3ntLwhcS_)}}W0NgGV3U`CH=l=q))vl O0000 { - var universe = new Universe(); - universe.stars.push(new Star(universe, 0, 0)); - universe.stars.push(new Star(universe, 1, 0)); - universe.stars.push(new Star(universe, 1, 1)); - universe.addLink(universe.stars[0], universe.stars[1]); - universe.addLink(universe.stars[0], universe.stars[2]); - - var getWarps = (star: Star): StarLocation[] => { - var result: StarLocation[] = []; - star.locations.forEach((location: StarLocation) => { - if (location.type === StarLocationType.WARP) { - result.push(location); - } - }); - return result; - }; - - expect(getWarps(universe.stars[0]).length).toBe(0); - expect(getWarps(universe.stars[1]).length).toBe(0); - expect(getWarps(universe.stars[2]).length).toBe(0); - - universe.stars[0].generate(); - - expect(getWarps(universe.stars[0]).length).toBe(2); - expect(getWarps(universe.stars[1]).length).toBe(0); - expect(getWarps(universe.stars[2]).length).toBe(0); - - universe.stars[1].generate(); - - expect(getWarps(universe.stars[0]).length).toBe(2); - expect(getWarps(universe.stars[1]).length).toBe(1); - expect(getWarps(universe.stars[2]).length).toBe(0); - - universe.stars[2].generate(); - - var warps = getWarps(universe.stars[0]); - expect(warps.length).toBe(2); - expect(warps[0].jump_dest).toBe(universe.stars[2].locations[1]); - expect(warps[1].jump_dest).toBe(universe.stars[1].locations[1]); - warps = getWarps(universe.stars[1]); - expect(warps.length).toBe(1); - expect(warps[0].jump_dest).toBe(universe.stars[0].locations[2]); - warps = getWarps(universe.stars[2]); - expect(warps.length).toBe(1); - expect(warps[0].jump_dest).toBe(universe.stars[0].locations[1]); + expect(universe.stars[0].getLinkTo(universe.stars[1])).toEqual(universe.starlinks[0]); + expect(universe.stars[0].getLinkTo(universe.stars[2])).toBeNull(); + expect(universe.stars[0].getLinkTo(universe.stars[3])).toEqual(universe.starlinks[1]); + expect(universe.stars[1].getLinkTo(universe.stars[0])).toEqual(universe.starlinks[0]); + expect(universe.stars[1].getLinkTo(universe.stars[2])).toBeNull(); + expect(universe.stars[1].getLinkTo(universe.stars[3])).toBeNull(); + expect(universe.stars[2].getLinkTo(universe.stars[0])).toBeNull(); + expect(universe.stars[2].getLinkTo(universe.stars[1])).toBeNull(); + expect(universe.stars[2].getLinkTo(universe.stars[3])).toBeNull(); + expect(universe.stars[3].getLinkTo(universe.stars[0])).toEqual(universe.starlinks[1]); + expect(universe.stars[3].getLinkTo(universe.stars[1])).toBeNull(); + expect(universe.stars[3].getLinkTo(universe.stars[2])).toBeNull(); }); }); } diff --git a/src/game/Star.ts b/src/game/Star.ts index a8c30c4..1dbe862 100644 --- a/src/game/Star.ts +++ b/src/game/Star.ts @@ -77,15 +77,20 @@ module SpaceTac.Game { // Base level for encounters in this system level: number; - constructor(universe: Universe = null, x: number = 0, y: number = 0) { + constructor(universe: Universe = null, x = 0, y = 0, name = "") { super(); this.universe = universe || new Universe(); this.x = x; this.y = y; this.radius = 0.1; - this.locations = []; + this.locations = [new StarLocation(this, StarLocationType.STAR, 0, 0)]; this.level = 1; + this.name = name; + } + + jasmineToString(): string { + return `Star ${this.name}`; } // Get the distance to another star @@ -99,38 +104,22 @@ module SpaceTac.Game { // 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); + this.name = random.choice(Star.NAMES_POOL); + 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 links = this.getLinks(); - links.forEach((link: StarLink) => { - var warp = this.generateOneLocation(StarLocationType.WARP, result, this.radius * 0.3, random); - - // If there is an unbound warp location on destination sector, bind with it - var peer_star = link.getPeer(this); - var peer_location = peer_star.findUnboundWarp(); - if (peer_location) { - peer_location.setJumpDestination(warp); - warp.setJumpDestination(peer_location); - } - - result.push(warp); - }); - - // Add random locations + generateLocations(count: number, random = new RandomGenerator()): void { while (count--) { - result.push(this.generateOneLocation(StarLocationType.PLANET, result, this.radius, random)); + this.generateOneLocation(StarLocationType.PLANET, this.locations, this.radius * 0.2, this.radius * 0.7, random); } + } - return result; + // Generate a warp location to another star (to be bound later) + generateWarpLocationTo(other: Star, random = new RandomGenerator()): StarLocation { + let fav_phi = Math.atan2(other.y - this.y, other.x - this.x); + var warp = this.generateOneLocation(StarLocationType.WARP, this.locations, this.radius * 0.8, this.radius * 1, random, fav_phi); + return warp; } // Get the number of links to other stars @@ -146,6 +135,32 @@ module SpaceTac.Game { return result; } + // Get the link to another star, null of not found + getLinkTo(other: Star): StarLink | null { + var result: StarLink | null = null; + + this.universe.starlinks.forEach(link => { + if (link.isLinking(this, other)) { + result = link; + } + }); + + return result; + } + + // Get the warp location to another star, null if not found + getWarpLocationTo(other: Star): StarLocation | null { + var result: StarLocation | null = null; + + this.locations.forEach(location => { + if (location.type == StarLocationType.WARP && location.jump_dest && location.jump_dest.star == other) { + result = location; + } + }); + + return result; + } + // Find an unbound warp location to bind, null if none found findUnboundWarp(): StarLocation { var result: StarLocation = null; @@ -160,18 +175,20 @@ module SpaceTac.Game { // Check if a location is far enough from all other ones private checkMinDistance(loc: StarLocation, others: StarLocation[]): boolean { return others.every((iloc: StarLocation): boolean => { - return iloc.getDistanceTo(loc) > this.radius * 0.1; + return iloc.getDistanceTo(loc) > this.radius * 0.15; }); } // Generate a single location - private generateOneLocation(type: StarLocationType, others: StarLocation[], radius: number, random: RandomGenerator): StarLocation { + private generateOneLocation(type: StarLocationType, others: StarLocation[], radius_min: number, radius_max: number, random: RandomGenerator, fav_phi: number | null = null): StarLocation { do { - var x = (random.throw(2) - 1) * radius; - var y = (random.throw(2) - 1) * radius; - var result = new StarLocation(this, type, x, y); + var phi = fav_phi ? (fav_phi + random.throw(0.4) - 0.2) : random.throw(Math.PI * 2); + var r = random.throw(radius_max - radius_min) + radius_min; + var result = new StarLocation(this, type, r * Math.cos(phi), r * Math.sin(phi)); } while (!this.checkMinDistance(result, others)); + this.locations.push(result); + return result; } } diff --git a/src/game/Universe.spec.ts b/src/game/Universe.spec.ts index 5ebab5d..2c8eb0c 100644 --- a/src/game/Universe.spec.ts +++ b/src/game/Universe.spec.ts @@ -33,5 +33,44 @@ module SpaceTac.Game.Specs { var filtered = universe.filterCrossingLinks(result); expect(filtered.length).toBe(5); }); + + it("generates warp locations", () => { + var universe = new Universe(); + universe.stars.push(new Star(universe, 0, 0, "0")); + universe.stars.push(new Star(universe, 1, 0, "1")); + universe.stars.push(new Star(universe, 1, 1, "2")); + universe.addLink(universe.stars[0], universe.stars[1]); + universe.addLink(universe.stars[0], universe.stars[2]); + + var getWarps = (star: Star): StarLocation[] => { + var result: StarLocation[] = []; + star.locations.forEach((location: StarLocation) => { + if (location.type === StarLocationType.WARP) { + result.push(location); + } + }); + return result; + }; + + expect(getWarps(universe.stars[0]).length).toBe(0); + expect(getWarps(universe.stars[1]).length).toBe(0); + expect(getWarps(universe.stars[2]).length).toBe(0); + + universe.generateWarpLocations(); + + var warps = getWarps(universe.stars[0]); + expect(warps.length).toBe(2); + expect(warps[0].jump_dest.star).toBe(universe.stars[1]); + expect(warps[1].jump_dest.star).toBe(universe.stars[2]); + expect(universe.stars[0].getWarpLocationTo(universe.stars[1])).toBe(warps[0]); + expect(universe.stars[0].getWarpLocationTo(universe.stars[2])).toBe(warps[1]); + warps = getWarps(universe.stars[1]); + expect(warps.length).toBe(1); + expect(warps[0].jump_dest.star).toBe(universe.stars[0]); + expect(universe.stars[1].getWarpLocationTo(universe.stars[2])).toBeNull(); + warps = getWarps(universe.stars[2]); + expect(warps.length).toBe(1); + expect(warps[0].jump_dest.star).toBe(universe.stars[0]); + }); }); } diff --git a/src/game/Universe.ts b/src/game/Universe.ts index 8ece908..8d08d28 100644 --- a/src/game/Universe.ts +++ b/src/game/Universe.ts @@ -17,7 +17,7 @@ module SpaceTac.Game { this.stars = []; this.starlinks = []; - this.radius = 50; + this.radius = 5; } // Generates a universe, with star systems and such @@ -27,6 +27,8 @@ module SpaceTac.Game { var links = this.getPotentialLinks(); this.starlinks = this.filterCrossingLinks(links); + this.generateWarpLocations(random); + this.stars.forEach((star: Star) => { star.generate(random); }); @@ -76,7 +78,7 @@ module SpaceTac.Game { // Filter a list of potential links to avoid crossing ones filterCrossingLinks(links: StarLink[]): StarLink[] { - var result : StarLink[] = []; + var result: StarLink[] = []; links.forEach((link1: StarLink) => { var crossed = false; @@ -93,6 +95,18 @@ module SpaceTac.Game { return result; } + // Generate warp locations for the links between stars + generateWarpLocations(random = new RandomGenerator()) { + this.starlinks.forEach(link => { + let warp1 = link.first.generateWarpLocationTo(link.second, random); + let warp2 = link.second.generateWarpLocationTo(link.first, random); + + warp1.setJumpDestination(warp2); + warp2.setJumpDestination(warp1); + }); + + } + // Get the star nearest to another getNearestTo(star: Star, others: Star[] = null): Star { if (others === null) { @@ -105,7 +119,7 @@ module SpaceTac.Game { var nearest: Star = null; others.forEach((istar: Star) => { if (istar !== star) { - var dist = star.getDistanceTo(istar); + var dist = star.getDistanceTo(istar); if (dist < mindist) { nearest = istar; mindist = dist; diff --git a/src/view/Preload.ts b/src/view/Preload.ts index 2e6d491..cceca04 100644 --- a/src/view/Preload.ts +++ b/src/view/Preload.ts @@ -59,8 +59,12 @@ module SpaceTac.View { this.loadImage("map/starsystem-background.png"); this.loadImage("map/zoom-in.png"); this.loadImage("map/zoom-out.png"); - this.loadImage("map/star.png"); - this.loadImage("map/planet.png"); + this.loadImage("map/location-star.png"); + this.loadImage("map/location-planet.png"); + this.loadImage("map/location-warp.png"); + this.loadImage("map/state-unknown.png"); + this.loadImage("map/state-enemy.png"); + this.loadImage("map/state-clear.png"); // Load ships this.loadShip("scout"); diff --git a/src/view/map/StarSystemDisplay.ts b/src/view/map/StarSystemDisplay.ts index 268e165..c47407f 100644 --- a/src/view/map/StarSystemDisplay.ts +++ b/src/view/map/StarSystemDisplay.ts @@ -12,26 +12,36 @@ module SpaceTac.View { this.starsystem = starsystem; - let boundary = this.game.add.graphics(0, 0); - boundary.lineStyle(3, 0x424242); - boundary.drawCircle(0, 0, scale); - this.addChild(boundary); + // Show boundary + this.addCircle(starsystem.radius); + // Show locations starsystem.locations.forEach(location => { if (location.type == Game.StarLocationType.STAR) { - this.addImage(location.x, location.y, "map-star"); + this.addImage(location.x, location.y, "map-location-star"); } else if (location.type == Game.StarLocationType.PLANET) { - let planet = this.addImage(location.x, location.y, "map-planet"); + let planet = this.addImage(location.x, location.y, "map-location-planet"); planet.rotation = Math.atan2(location.y, location.x); + this.addCircle(Math.sqrt(location.x * location.x + location.y * location.y), 1); + } else if (location.type == Game.StarLocationType.WARP) { + let warp = this.addImage(location.x, location.y, "map-location-warp"); } }); } addImage(x: number, y: number, key: string): Phaser.Image { - let image = this.game.add.image(x * 0.5 / this.scale.x, y * 0.5 / this.scale.y, key); + let image = this.game.add.image(x / this.scale.x, y / this.scale.y, key); image.anchor.set(0.5, 0.5); this.addChild(image); return image; } + + addCircle(radius, width = 3, color = 0x424242): Phaser.Graphics { + let circle = this.game.add.graphics(0, 0); + circle.lineStyle(width, color); + circle.drawCircle(0, 0, radius * 2 / this.scale.x); + this.addChild(circle); + return circle; + } } } diff --git a/src/view/map/UniverseMapView.ts b/src/view/map/UniverseMapView.ts index 26250c6..db7241f 100644 --- a/src/view/map/UniverseMapView.ts +++ b/src/view/map/UniverseMapView.ts @@ -12,6 +12,7 @@ module SpaceTac.View { // Star systems group: Phaser.Group; starsystems: StarSystemDisplay[] = []; + starlinks: Phaser.Graphics[] = []; // Zoom level zoom = 0; @@ -31,6 +32,18 @@ module SpaceTac.View { this.group = new Phaser.Group(this.game); this.add.existing(this.group); + 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); + 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); + return result; + }); + this.starlinks.forEach(starlink => this.group.addChild(starlink)); + this.starsystems = this.universe.stars.map(star => new StarSystemDisplay(this, star)); this.starsystems.forEach(starsystem => this.group.addChild(starsystem)); @@ -63,8 +76,8 @@ module SpaceTac.View { // Set the camera to center on a target, and to display a given span in height setCamera(x: number, y: number, span: number) { let scale = 1000 / span; - this.tweens.create(this.group.position).to({ x: 960 - x * scale, y: 540 - y * scale }).start(); - this.tweens.create(this.group.scale).to({ x: scale, y: scale }).start(); + this.tweens.create(this.group.position).to({ x: 960 - x * scale, y: 540 - y * scale }, 500, Phaser.Easing.Cubic.InOut).start(); + this.tweens.create(this.group.scale).to({ x: scale, y: scale }, 500, Phaser.Easing.Cubic.InOut).start(); } setZoom(level: number) { @@ -73,6 +86,7 @@ module SpaceTac.View { 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 {