Hallo Flash-ontwikkelaars, welkom bij het tweede deel van mijn Tower Defense Game-zelfstudie. In het eerste deel ontwikkelden we het basismechanisme om torentjes te maken en ze te laten schieten met het oog op muisklikken. Maar dat is niet waar torentjes voor zijn! In dit deel breiden we het spel uit met vijanden, basale kunstmatige intelligentie (AI) in torentjes en nog wat spelelementen. Ben je klaar?
Dit is de game die we gaan maken in deze tutorial:
Klik op de oranje cirkels om torentjes te plaatsen. De rode cirkels zijn vijanden en het aantal op elk vertegenwoordigt de hitpunten.
In de vorige tutorial hebben we een game ontwikkeld met plaatshouders voor de torentjes. We zouden torentjes kunnen inzetten door op die tijdelijke aanduidingen te klikken, en de torentjes gericht op de muisaanwijzer en geschoten kogels naar het punt waar de gebruiker klikte.
We zijn klaar met een Hoofd
klasse die de spelloop en spellogica had. Afgezien daarvan hadden we de Torentje
klas die niets anders had dan de bijwerken
functie waardoor de toren draaide.
We hebben eerder de kogels gemaakt Hoofd
klasse en bijgevoegd een ENTER_FRAME
luisteraar om het te verplaatsen. De kogel had niet genoeg eigenschappen eerder om het als een afzonderlijke klasse te beschouwen. Maar in een dergelijk spel kunnen kogels allerlei soorten hebben, zoals snelheid, schade, enzovoort. Het is dus een goed idee om de opsommingscode op te halen en deze in een afzonderlijke kapsule te plaatsen. Kogel
klasse. Laten we het doen.
Maak een nieuwe klasse genaamd Kogel
, uitbreiding van de sprite
klasse. De basiscode voor deze klasse moet zijn:
pakket import flash.display.Sprite; public class Bullet breidt uit public function Bullet ()
Vervolgens plaatsen we de code om de bullet-afbeelding te tekenen Hoofd
, in Kogel
. Zoals we deden met de Torentje
klasse maken we een functie genaamd trek
in de Kogel
klasse:
private function draw (): void var g: Graphics = this.graphics; g.beginFill (0xEEEEEE); g.drawCircle (0, 0, 5); g.endFill ();
En we noemen deze functie van de Kogel
constructor:
public function Bullet () draw ();
Nu voegen we wat eigenschappen toe aan de kogel. Voeg vier variabelen toe: snelheid
, speed_x
, speed_y
en schade
, voor de Kogel
constructor:
privé var snelheid: Number; privé var speed_x: Number; private var speed_y: Number; public var damage: int;
Waar zijn deze variabelen voor?
snelheid
: Deze variabele slaat de snelheid van de kogel op.speed_x
en speed_y
: Deze slaan de x- en y-componenten van de snelheid op, zodat de berekening van het breken van de snelheid in de componenten niet steeds opnieuw hoeft te worden uitgevoerd. schade
: Dit is de hoeveelheid schade die de kogel kan aanrichten aan een vijand. We houden deze variabele openbaar omdat we dit nodig hebben in onze gamelus in de Hoofd
klasse. We initialiseren deze variabelen in de constructor. Update uw Kogel
constructor:
publieke functie Bullet (hoek: Number) speed = 5; schade = 1; speed_x = Math.cos (hoek * Math.PI / 180) * snelheid; speed_y = Math.sin (angle * Math.PI / 180) * snelheid; trek();
Let op de hoek
variabele die we ontvangen in de constructor. Dit is de richting (in graden) waarin de kogel zal bewegen. We breken gewoon de snelheid
in de x- en y-componenten en cacheer ze voor toekomstig gebruik.
Het laatste wat overblijft in de Kogel
klasse is om een te hebben bijwerken
functie die wordt aangeroepen vanuit de spellus om de opsomming bij te werken (te verplaatsen). Voeg de volgende functie toe aan het einde van de Kogel
klasse:
public function update (): void x + = speed_x; y + = speed_y;
Bingo! We zijn klaar met onze Kogel
klasse.
We hebben veel bullet code verplaatst Hoofd
klasse op zichzelf Kogel
klasse, dus veel code blijft ongebruikt in Hoofd
en er moet nog veel worden bijgewerkt.
Wis eerst de createBullet ()
en moveBullet ()
functies. Verwijder ook de kogel snelheid
veranderlijk.
Ga vervolgens naar de schieten
functie en update deze met de volgende code:
privéfunctie shoot (e: MouseEvent): void voor elk (var torentje: torentje in torentjes) var new_bullet: Bullet = new Bullet (revolver.rotatie); new_bullet.x = turret.x + Math.cos (turret.rotation * Math.PI / 180) * 25; new_bullet.y = turret.y + Math.sin (turret.rotation * Math.PI / 180) * 25; addChild (new_bullet);
We gebruiken niet langer het createBullet
functie om kogel te maken, gebruik liever de Kogel
bouwer en passeer de toren omwenteling
erop, wat de richting is van de beweging van de kogel en dus hoeven we hem niet op te slaan in de kogels omwenteling
eigendom zoals we eerder deden. We voegen ook geen luisteraars aan de opsomming toe, omdat de opsommingsteken wordt bijgewerkt vanuit de volgende lus van de game.
Nu we de opsommingstekens van de gamelus moeten bijwerken, moeten we ergens een referentie van deze opsommen. De oplossing is hetzelfde als voor de torentjes: maak een nieuwe reeks
genaamd bullets
en duw de kogels erop zoals ze zijn gemaakt.
Verklaar eerst een array net onder de torentjes
matrixverklaring:
private var ghost_turret: Turret; private var torentjes: Array = []; private var bullets: Array = [];
Nu om deze array te vullen. We doen dit telkens wanneer we een nieuwe bullet creëren - dus in de schieten
functie. Voeg het volgende toe vlak voor het toevoegen van de kogel aan het podium:
var new_bullet: Bullet = new Bullet (revolver.rotatie); new_bullet.x = turret.x + Math.cos (turret.rotation * Math.PI / 180) * 25; new_bullet.y = turret.y + Math.sin (turret.rotation * Math.PI / 180) * 25; bullets.push (new_bullet); addChild (new_bullet);
Net als hoe we de loop van de turrets bijwerken, zullen we ook de kogels bijwerken. Maar deze keer in plaats van een voor ... elk
loop, we zullen een basis gebruiken voor
lus. Hiervoor moeten we twee variabelen aan de bovenkant van de gamelus toevoegen, zodat we weten welke variabelen binnen de gamelus worden gebruikt en deze gratis kunnen instellen voor garbagecollection.
var torentje: torentje; var bullet: Bullet;
Ga je gang en voeg de volgende code toe aan het einde van de game-lus:
for (var i: int = bullets.length - 1; i> = 0; i--) bullet = bullets [i]; als (! opsommingsteken) doorgaan; bullet.update ();
Hier doorkruisen we alle frames op het podium elk beeld en noemen ze hun bijwerken
functie waardoor ze bewegen. Merk op dat we de bullets
array in omgekeerde volgorde. Waarom? We zullen dit vooruit zien.
Nu dat we een hebben torentje
variabele die al buiten is gedeclareerd, hoeven we niet opnieuw te declareren binnen de voor ... elk
loop van torentjes. Pas het aan:
voor elk (torentje in torentjes) torentje.update ();
Als laatste voegen we de grenscontrole toe; dit was eerder in de kogel ENTER_FRAME
maar nu controleren we het in de game-loop:
if (bullet.x < 0 || bullet.x > stage.stageWidth || bullet.y < 0 || bullet.y > stage.stageHeight) bullets.splice (i, 1); bullet.parent.removeChild (kogel); doorgaan met;
We controleren of de kogel buiten de grens van het toneel is en als dat zo is, verwijderen we eerst zijn referentie van de bullets
array met behulp van de verbinding
functie en verwijder vervolgens de kogel uit het werkgebied en ga verder met de volgende iteratie. Dit is hoe je game-loop eruit zou moeten zien:
privéfunctiegameLoop (e: Event): void var torentje: torentje; var bullet: Bullet; voor elk (torentje in torentjes) torentje.update (); for (var i: int = bullets.length - 1; i> = 0; i--) bullet = bullets [i]; als (! opsommingsteken) doorgaan; bullet.update ();
Als je nu het spel uitvoert, zou je dezelfde functionaliteit moeten hebben als in deel 1, met code die veel zuiverder en overzichtelijker is.
Nu voegen we een van de belangrijkste elementen van het spel toe: de vijand. Het eerste is om een nieuwe klasse genaamd te maken Vijand
uitbreiding van de sprite
klasse:
pakket import flash.display.Sprite; openbare klasse Enemy breidt Sprite uit openbare functie Enemy ()
Nu voegen we wat eigenschappen toe aan de klas. Voeg ze toe vóór je Vijand
constructor:
privé var speed_x: Number; private var speed_y: Number;
We initialiseren deze variabelen in de Vijand
constructor:
openbare functie Enemy () speed_x = -1.5; speed_y = 0;
Vervolgens maken we de trek
en bijwerken
functies voor de Vijand
klasse. Deze lijken erg op die uit Kogel
. Voeg de volgende code toe:
private function draw (): void var g: Graphics = this.graphics; g.beginFill (0xff3333); g.drawCircle (0, 0, 15); g.endFill (); public function update (): void x + = speed_x; y + = speed_y;
In ons spel moeten we veel evenementen hebben die plaatsvinden op bepaalde tijden of herhaaldelijk met bepaalde tussenpozen. Een dergelijke timing kan worden bereikt met behulp van een tijdteller. De teller is slechts een variabele die wordt opgehoogd naarmate de tijd verstrijkt in het spel. Het belangrijkste is hier wanneer en met hoeveel bedrag de teller moet worden verhoogd. Er zijn twee manieren waarop timing in het algemeen in games wordt gedaan: tijdgebaseerd en frame-gebaseerd.
Het verschil is dat de eenheid van stap in tijdgebaseerd spel gebaseerd is op realtime (dat wil zeggen, het aantal milliseconden gepasseerd), maar in een op frames gebaseerd spel is de eenheid van stap gebaseerd op frame-eenheden (dat wil zeggen het aantal frames dat is gepasseerd).
Voor onze game gaan we een frame-gebaseerde teller gebruiken. We hebben een teller die we met één verhogen in de spellus, die elk frame uitvoert, en dus in feite ons het aantal frames geven dat is verstreken sinds de game is gestart. Ga je gang en declareer een variabele na de andere variabele declaraties in de Hoofd
klasse:
private var ghost_turret: Turret; private var torentjes: Array = []; private var bullets: Array = []; private var global_time: Number = 0;
We verhogen deze variabele in de spellus bovenaan:
global_time ++;
Nu gebaseerd op deze teller kunnen we dingen doen als vijanden maken, wat we vervolgens zullen doen.
Wat we nu willen doen is vijanden om de twee seconden op het veld maken. Maar we hebben hier te maken met frames, weet je nog? Dus na hoeveel frames moeten we vijanden maken? Welnu, onze game draait op 30 FPS, waardoor de global_time
tel 30 keer per seconde. Een eenvoudige berekening vertelt ons dat 3 seconden = 90 frames.
Voeg aan het einde van de spellus het volgende toe als
blok:
if (global_time% 90 == 0)
Waar gaat die toestand over? We gebruiken de modulo (%) -operator, die de rest van een divisie geeft - dus global_time% 90
geeft ons de rest wanneer global_time
is gedeeld door 90
. We controleren of de rest is 0
, omdat dit alleen het geval zal zijn wanneer global_time
is een veelvoud van 90
- dat wil zeggen dat de toestand terugkeert waar
wanneer global_time
is gelijk aan 0
, 90
, 180
en zo verder ... Op deze manier bereiken we een trigger op elke 90 frames of 3 seconden.
Voordat we de vijand creëren, verklaar een andere array genaamd vijanden
net onder de torentjes
en bullets
matrix. Dit wordt gebruikt om verwijzingen naar vijanden op het podium op te slaan.
private var ghost_turret: Turret; private var torentjes: Array = []; private var bullets: Array = []; privé var vijanden: Array = []; private var global_time: Number = 0;
Verklaar ook een vijand
variabele aan de bovenkant van de spellus:
global_time ++; var torentje: torentje; var bullet: Bullet; var vijand: vijand;
Voeg ten slotte de volgende code toe in de als
blok dat we eerder hebben gemaakt:
vijand = nieuwe vijand (); vijand.x = 410; enemy.y = 30 + Math.random () * 370; enemies.push (vijand); addChild (vijand);
Hier creëren we een nieuwe vijand, positioneer het willekeurig aan de rechterkant van het podium, druk het in de vijanden
array en voeg het toe aan het podium.
Net zoals we de kogels in de loop van het spel updaten, werken we de vijanden bij. Plaats de volgende code onder het torentje voor ... elk
lus:
for (var j: int = vijemies.length - 1; j> = 0; j--) enemy = vijanden [j]; enemy.update (); als (vijand.x < 0) enemies.splice(j, 1); enemy.parent.removeChild(enemy); continue;
Net zoals we een grenscontrole voor kogels uitvoerden, controleren we ook op vijanden. Maar voor vijanden controleren we gewoon of ze van de linkerkant van het podium zijn gegaan, omdat ze alleen van rechts naar links bewegen. Je zou vijanden van rechts moeten zien komen als je het spel nu uitvoert.
Elke vijand heeft wat leven / gezondheid en dat geldt ook voor ons. We zullen ook de resterende gezondheid van de vijanden laten zien. Laten we enkele variabelen verklaren in de Vijand
klasse voor het gezondheidsmateriaal:
private var health_txt: TextField; privé var gezondheid: int; privé var speed_x: Number; private var speed_y: Number;
We initialiseren de Gezondheid
variabele in de volgende constructor. Voeg het volgende toe aan de Vijand
constructor:
gezondheid = 2;
Nu initialiseren we de gezondheidstekstvariabele die in het midden van de vijand wordt weergegeven. We doen dit in de trek
functie:
health_txt = nieuw TextField (); health_txt.height = 20; health_txt.width = 15; health_txt.textColor = 0xffffff; health_txt.x = -5; health_txt.y = -8; health_txt.text = health + ""; addChild (health_txt);
Alles wat we doen is een nieuw maken TextField
, stel de kleur in, positioneer het en stel de tekst in op de huidige waarde van Gezondheid
Als laatste voegen we een functie toe om de gezondheid van de vijand bij te werken:
public function updateHealth (amount: int): int health + = amount; health_txt.text = health + ""; gezondheid teruggeven;
De functie accepteert een geheel getal om aan de status toe te voegen, werkt de gezondheidstekst bij en retourneert de uiteindelijke status. We zullen deze functie uit onze spellus halen om de gezondheid van elke vijand bij te werken en te detecteren of hij nog leeft.
Laten we eerst onze wijzigen schieten
functioneer een beetje. Vervang de bestaande schieten
functie met het volgende:
privéfunctie shoot (torentje: torentje, vijand: vijand): void var angle: Number = Math.atan2 (vijand.y - torentje.y, vijand.x - torentje.x) / Math.PI * 180; torentje.rotatie = hoek; var new_bullet: Bullet = new Bullet (angle); new_bullet.x = turret.x + Math.cos (turret.rotation * Math.PI / 180) * 25; new_bullet.y = turret.y + Math.sin (turret.rotation * Math.PI / 180) * 25; bullets.push (new_bullet); addChild (new_bullet);
De schieten
functie accepteert nu twee parameters. De eerste is een verwijzing naar een torentje dat de schietpartij zal doen; de tweede is een verwijzing naar een vijand waarnaar hij zal schieten.
De nieuwe code is hier vergelijkbaar met de code in de Torentje
klasse bijwerken
functie, maar in plaats van de positie van de muis gebruiken we nu de cordinaten van de vijand. Dus nu kun je alle code verwijderen uit de bijwerken
functie van de Torentje
klasse.
Hoe kunnen de torentjes op vijanden schieten? Nou, de logica is eenvoudig voor onze game. We laten alle torens schieten op de eerste vijand in de vijanden
matrix. Wat? Laten we wat code zetten en dan proberen te begrijpen. Tel de volgende regels op aan het eind van de voor ... elk
lus gebruikt om de torentjes bij te werken:
voor elk (torentje in torentjes) torentje.update (); voor elke (vijand in vijanden) shoot (torentje, vijand); breken;
Voor elk torentje werken we het nu bij, en dan herhalen we het vijanden
array, schiet de eerste vijand in de array en breek uit de lus. Dus in wezen schiet elk torentje naar de vroegst gecreëerde vijand omdat het altijd aan het begin van de reeks staat. Probeer het spel uit te voeren en je moet zien dat torens de vijanden neerschieten.
Maar wacht, wat is die kogelstroom? Het lijkt erop dat ze te snel schieten. Laten we zien waarom.
Zoals we weten draait de gamelus elk frame, dus 30 keer per seconde in ons geval, dus de schietverklaring die we in de vorige stap hebben toegevoegd, wordt gebeld met de snelheid van onze gamelus en daarom zien we een stroom kogels stroomt. Het lijkt erop dat we ook een timingmechanisme nodig hebben in de torentjes. Schakel over naar de Torentje
klasse en voeg de volgende code toe:
private var local_time: Number = 0; private var reload_time: int;
lokale tijd
: Onze teller wordt gebeld lokale tijd
in tegenstelling tot global_time
in de Hoofd
klasse. Dit is om twee redenen: ten eerste omdat deze variabele lokaal is voor de Torentje
klasse; ten tweede omdat het niet altijd naar voren komt zoals het onze global_time
variabele - deze wordt tijdens de game vaak opnieuw ingesteld. herlaad tijd
: Dit is de tijd die het torentje nodig heeft om te herladen na het maken van een kogel. Eigenlijk is het het tijdsverschil tussen twee kogelspruiten door een torentje. Onthoud dat alle tijdseenheden in onze game qua frames zijn. Verhoog de lokale tijd
variabele in de bijwerken
functie en initialiseer de herlaad tijd
in de constructor:
public function update (): void local_time ++;
public function Turret () reload_time = 30; trek();
Voeg vervolgens de volgende twee functies toe aan het einde van de Torentje
klasse:
public function isReady (): Boolean return local_time> reload_time; public function reset (): void local_time = 0;
is gereed
geeft alleen true als de huidige lokale tijd
is groter dan de herlaad tijd
, d.w.z. wanneer het torentje is herladen. En de reset
functie reset gewoon de lokale tijd
variabele, om te beginnen met opnieuw laden.
Nu terug in de Hoofd
klasse, wijzig de shoot-code in de gamelus die we in de vorige stap hebben toegevoegd aan het volgende:
voor elk (torentje in torentjes) torentje.update (); als (! turret.isReady ()) doorgaat; voor elke (vijand in vijanden) shoot (torentje, vijand); turret.reset (); breken;
Dus als nu het torentje niet klaar is (is gereed()
komt terug vals
), gaan we verder met de volgende iteratie van de revolverlijn. Je zult zien dat de torentjes schieten met een interval van 30 frames of 1 seconde nu. Stoer!
Nog steeds iets niet goed. De torentjes schieten op vijanden, ongeacht de afstand tussen hen. Wat hier ontbreekt, is de reeks van een torentje. Elk torentje zou een eigen bereik moeten hebben waarbinnen het een vijand kan neerschieten. Voeg een andere variabele toe aan de Torentje
klas genoemd reeks
en zet het op 120
in de constructor:
private var reload_time: int; private var local_time: Number = 0; privé var-bereik: int;
public function Turret () reload_time = 30; bereik = 120; trek();
Voeg ook een functie toe met de naam canShoot
aan het einde van de les:
openbare functie kanShoot (vijand: vijand): Boolean var dx: Number = enemy.x - x; var dy: Number = enemy.y - y; if (Math.sqrt (dx * dx + dy * dy) <= range) return true; else return false;
Elk torentje kan een vijand alleen neerschieten als het aan bepaalde criteria voldoet - je kunt bijvoorbeeld het torentje alleen rode vijanden laten schieten met minder dan de helft van hun leven en niet meer dan 30px weg. Al deze logica om te bepalen of het torentje in staat is om een vijand te verslaan of niet, gaat in de canShoot
functie, die terugkeert waar
of vals
volgens de logica.
Onze logica is eenvoudig. Als de vijand binnen het bereik is, ga terug waar
; anders wordt false geretourneerd. Dus wanneer de afstand tussen het torentje en de vijand (Math.sqrt (dx * dx + dy * dy)
) is kleiner dan of gelijk aan reeks
, het komt terug waar
. Een beetje meer modificatie in de shoot-sectie van de game-loop:
voor elk (torentje in torentjes) torentje.update (); als (! turret.isReady ()) doorgaat; voor elke (vijand in vijanden) if (turret.canShoot (vijand)) shoot (torentje, vijand); turret.reset (); breken;
Alleen als de vijand zich binnen het bereik van het torentje bevindt, schiet het torentje dan.
Een zeer belangrijk onderdeel van elke game is de botsingsdetectie. In onze game wordt botsing gecontroleerd tussen kogels en vijanden. We zullen de botsingsdetectiecode toevoegen in de voor ... elk
lus die de kogels in de spellus bijwerkt.
De logica is eenvoudig. Voor elke kogel doorkruisen we de vijanden
array en controleer of er een botsing tussen is. Als dat zo is, verwijderen we de kogel, werken we de vijandelijke gezondheid bij en breken we uit de kring om andere vijanden te controleren. Laten we wat code toevoegen:
for (i = bullets.length - 1; i> = 0; i--) bullet = bullets [i]; // als de kogel niet is gedefinieerd, gaat u verder met de volgende iteratie als (! opsommingsteken) wordt voortgezet; bullet.update (); if (bullet.x < 0 || bullet.x > stage.stageWidth || bullet.y < 0 || bullet.y > stage.stageHeight) bullets.splice (i, 1); bullet.parent.removeChild (kogel); doorgaan met; for (var k: int = vijemies.length - 1; k> = 0; k--) enemy = vijanden [k]; if (bullet.hitTestObject (vijand)) bullets.splice (i, 1); bullet.parent.removeChild (kogel); if (enemy.updateHealth (-1) == 0) vijanden.splice (k, 1); enemy.parent.removeChild (vijand); pauze;
We gebruiken ActionScript's hitTestObject
functie om te controleren op een botsing tussen de kogel en de vijand. Als de collie optreedt, wordt de kogel op dezelfde manier verwijderd als wanneer deze de etappe verlaat. De gezondheid van de vijand wordt dan bijgewerkt met behulp van de updateHealth
methode, waarnaar kogel
's schade
eigendom is doorgegeven. Als het updateHealth
functie retourneert een geheel getal kleiner dan of gelijk aan 0
, dit betekent dat de vijand dood is en dus verwijderen we het op dezelfde manier als de kogel.
En onze botsingsdetectie is voltooid!
Vergeet niet dat we de vijanden en kogels in omgekeerde volgorde doorkruisen in onze gamelus. Laten we begrijpen waarom. Laten we veronderstellen dat we een oplopende lijn gebruikten voor
lus. We zijn op index i = 3
en we verwijderen een kogel uit de array. Bij verwijdering van het artikel op positie 3
, de ruimte wordt gevuld door het item en vervolgens op positie 4
. Dus nu het item eerder op positie 4
is om 3
. Na de iteratie ik
verhogingen door 1
en wordt 4
en dus item op positie 4
is nagekeken.
Oeps, zie je wat er net is gebeurd? We hebben het item net op positie gemist 3
die terugging als resultaat van de splitsing. En dus gebruiken we een tegengestelde voor
lus die dit probleem oplost. Je kunt zien waarom.
Laten we wat extra dingen toevoegen om het spel er goed uit te laten zien. We voegen functionaliteit toe om het bereik van een revolver weer te geven wanneer de muis erop zweeft. Schakel over naar de Torentje
class en voeg wat variabelen toe:
privé var-bereik: int; private var reload_time: int; private var local_time: Number = 0; privaat var-lichaam: Sprite; privé var bereik_circle: Sprite;
Volgende update het trek
functioneren als volgt:
private function draw (): void range_circle = new Sprite (); g = range_circle.graphics; g.beginFill (0x00D700); g.drawCircle (0, 0, bereik); g.endFill (); bereik_cirkel.alpha = 0,2; range_circle.visible = false; addChild (range_circle); body = nieuwe Sprite (); var g: Graphics = body.graphics; g.beginFill (0xD7D700); g.drawCircle (0, 0, 20); g.beginFill (0x800000); g.drawRect (0, -5, 25, 10); g.endFill (); addChild (body);
We breken de grafische weergave van het torentje in twee delen: het lichaam en de reeksafbeelding. We doen dit om een bestelling te plaatsen voor de verschillende delen van het torentje. Hier hebben we de range_circle
om achter het lichaam van de toren te zijn, en dus voegen we het eerst aan het podium toe. Ten slotte voegen we twee muisluisteraars toe om de bereikafbeelding in te schakelen:
private function onMouseOver (e: MouseEvent): void range_circle.visible = true; private function onMouseOut (e: MouseEvent): void range_circle.visible = false;
Bevestig nu de luisteraars aan de respectievelijke gebeurtenissen aan het einde van de constructor:
body.addEventListener (MouseEvent.MOUSE_OVER, onMouseOver); body.addEventListener (MouseEvent.MOUSE_OUT, onMouseOut);
Als je het spel uitvoert en een turret probeert te gebruiken, zie je een flikkering wanneer je de plaatsaanduidingen gebruikt. Waarom is dat?
Denk eraan dat we de mouseEnabled
eigendom van de geestentoren aan vals
? We deden dat omdat het ghost torentje muisgebeurtenissen ving door tussen de muis en de tijdelijke aanduiding te komen. Dezelfde situatie is weer aangebroken, aangezien het torentje zelf nu twee kinderen heeft - het lichaam en de range sprite - die de muisgebeurtenissen vastleggen tussenin.
De oplossing is hetzelfde. We kunnen hun persoon instellen mouseEnabled
eigenschappen voor vals
. Maar een betere oplossing is om de spookrevolver's te plaatsen mouseChildren
eigendom aan vals
. Wat dit doet is het beperken van alle kinderen van ghost torentje van het ontvangen van muisgebeurtenissen. Nette, huh? Ga je gang en zet het op vals
in de Hoofd
constructor:
ghost_turret = new Turret (); ghost_turret.alpha = 0,5; ghost_turret.mouseEnabled = false; ghost_turret.mouseChildren = false; ghost_turret.visible = false; addChild (ghost_turret);
Probleem opgelost.
We kunnen deze demo uitbreiden met veel geavanceerdere functies en er een speelbare game van maken. Sommige daarvan kunnen zijn:
Laten we eens kijken wat u kunt bedenken uit deze eenvoudige demo. Ik ben blij om te horen over jullie torenverdedigingsspellen en jullie opmerkingen of suggesties voor de serie.