Hei Flash Developers, bine ai venit în a doua parte a tutorialului meu de joc Tower Defense. În prima parte, am dezvoltat mecanismul de bază de creare a turnuletelor și de a le face să tragă spre punctul de clic al mouse-ului. Dar nu pentru asta sunt pușcăriile! În această parte vom extinde jocul pentru a include și dușmani, inteligența artificială de bază (AI) în turreți și alte elemente de joc. Sunteți gata?
Acesta este jocul pe care îl vom crea în acest tutorial:
Faceți clic pe cercurile portocalii pentru a plasa turle. Cercurile roșii sunt dușmani, iar numărul pe fiecare reprezintă punctele sale de lovit.
În tutorialul precedent am dezvoltat un joc care a avut locații pentru turrete. Am putea folosi turnulete făcând clic pe acei locași, iar turnurile au vizat indicatorul mouse-ului și au tras gloanțe spre punctul în care a făcut clic pe utilizator.
Am terminat cu a Principal
clasa care avea loopul jocului și logica jocului. În afară de asta am avut turelă
clasă care nu avea nimic altceva decât Actualizați
funcția care a făcut turnul să se rotească.
Am creat anterior gloanțele în Principal
clasă și atașat un ENTER_FRAME
ascultător pentru ao muta. Glonțul nu avea suficiente proprietăți mai devreme pentru a considera că este o clasă separată. Dar într-un astfel de joc, gloanțele pot avea mai multe soiuri, cum ar fi viteza, deteriorarea și așa mai departe, deci este o idee bună să scoateți codul glonțului și să îl încapsulați într-o Glonţ
clasă. S-o facem.
Creați o nouă clasă numită Glonţ
, extinderea spiriduș
clasă. Codul de bază pentru această clasă ar trebui să fie:
pachet import flash.display.Sprite; clasa publică Bullet extinde Sprite funcția publică Bullet ()
Apoi am plasat codul pentru a desena graficul de glont, luat de la Principal
, în Glonţ
. Așa cum am făcut și cu turelă
class, creăm o funcție numită a desena
în Glonţ
clasă:
funcția privată (): void var g: Graphics = this.graphics; g.beginFill (0xEEEEEE); g.drawCircle (0, 0, 5); g.endFill ();
Și numim această funcție din Glonţ
constructor:
funcția publică Bullet () draw ();
Acum adăugăm câteva proprietăți bulletului. Adăugați patru variabile: viteză
, speed_x
, rapid
și deteriora
, inainte de Glonţ
constructor:
viteză privată var: număr; private var speed_x: Număr; private var speed_y: Număr; public var damage: int;
Care sunt aceste variabile pentru?
viteză
: Această variabilă stochează viteza glonțului.speed_x
și rapid
: Acestea stochează componentele x și y ale vitezei, respectiv, astfel încât calcularea ruperii vitezei în componentele sale nu trebuie făcută din nou și din nou. deteriora
: Aceasta este suma daunelor pe care glonțul o poate face unui inamic. Păstrăm această variabilă publică, așa cum o vom cere în jocul nostru de joc Principal
clasă. Inițializăm aceste variabile în constructor. Actualizați-vă Glonţ
constructor:
funcția publică Bullet (unghi: număr) speed = 5; daune = 1; speed_x = Math.cos (unghi * Math.PI / 180) * viteza; speed_y = Math.sin (unghi * Math.PI / 180) * viteza; a desena();
Observați unghi
variabilă pe care o primim în constructor. Aceasta este direcția (în grade) în care glonțul se va mișca. Vom rupe doar viteză
în componentele x și y și le cache pentru utilizare ulterioară.
Ultimul lucru care rămâne în Glonţ
clasa este de a avea un Actualizați
funcția care va fi apelată din bucla de joc pentru a actualiza (muta) gloanțele. Adăugați următoarea funcție la sfârșitul secțiunii Glonţ
clasă:
funcția publică (): void x + = speed_x; y + = viteza_y;
Bingo! Am terminat cu noi Glonţ
clasă.
Am mutat o mulțime de cod de glonț Principal
clasa proprie Glonţ
clasa, astfel încât o mulțime de cod rămâne neutilizat în Principal
și multe trebuie să fie actualizate.
Mai întâi, ștergeți createBullet ()
și moveBullet ()
funcții. De asemenea, eliminați viteza glontului
variabil.
Apoi, mergeți la trage
funcția și actualizați-l cu următorul cod:
funcția privată (e: MouseEvent): void pentru fiecare (var turret: turret în turreți) var new_bullet: Bullet = Bullet nou (turret.rotation); new_bullet.x = turret.x + Math.cos (turret.ro * Math.PI / 180) * 25; new_bullet.y = turret.y + Math.sin (turret.ro * Math.PI / 180) * 25; addChild (new_bullet);
Nu mai folosim createBullet
funcția de a crea glont mai degrabă utilizați Glonţ
constructorul și să treacă turela rotație
la care este direcția mișcării glonțului și nu avem nevoie să-l depozităm în gloanțe rotație
proprietate așa cum am făcut-o mai devreme. De asemenea, nu atasem nici un ascultător la glonț, deoarece glonțul va fi actualizat din buclele de joc următoare.
Acum că trebuie să actualizăm gloanțele din bucla de joc, avem nevoie de o referință a acestora pentru a fi stocată undeva. Soluția este aceeași ca și pentru turnulete: creați un nou mulțime
numit gloanțe
și împingeți gloanțele pe el în timp ce sunt create.
Mai întâi declarați o matrice imediat sub turnulete
matrice declarație:
privat Var ghost_turret: Turret; private var turrets: Array = []; buletine private var: Array = [];
Acum, pentru a popula această matrice. Facem acest lucru ori de câte ori creăm un nou glonț - deci, în trage
funcţie. Adăugați următoarele înainte de a adăuga un glonț în scenă:
var nou_bullet: Bullet = noul Bullet (turret.rotation); new_bullet.x = turret.x + Math.cos (turret.ro * Math.PI / 180) * 25; new_bullet.y = turret.y + Math.sin (turret.ro * Math.PI / 180) * 25; bullets.push (new_bullet); addChild (new_bullet);
La fel ca modul în care actualizăm turletele cu bucla de joc, vom actualiza și gloanțele. Dar de data aceasta, în loc să folosești a pentru fiecare
buclă, vom folosi o bază pentru
buclă. Înainte de aceasta, trebuie să adăugăm două variabile în partea superioară a buclei de joc, astfel încât să știm care sunt variabilele folosite în cadrul jocului și pot fi libere pentru colectarea gunoiului.
var turret: turret; var bullet: Bullet;
Mergeți mai departe și adăugați următorul cod la sfârșitul jocului:
pentru (var i: int = bullets.length - 1; i> = 0; i -) bullet = ghilimele [i]; dacă (! bullet) continuați; bullet.update ();
Aici traversăm peste toate gloanțele de pe scenă fiecare cadru și îi sunăm Actualizați
funcție care le face să se miște. Rețineți că vom itera gloanțe
array în sens invers. De ce? Vom vedea asta înainte.
Acum că avem a turelă
variabila declarată afară deja, nu este nevoie să o declanșăm din nou înăuntru pentru fiecare
buclă de turle. Modificați-l la:
pentru fiecare (turelă în turle) turret.update ();
În final, adăugăm condiția de verificare a limitei; acest lucru a fost anterior în glonț ENTER_FRAME
dar acum o verificam in bucla de joc:
dacă (bullet.x < 0 || bullet.x > stage.stageWidth || bullet.y < 0 || bullet.y > stage.stageHeight) bullets.splice (i, 1); bullet.parent.removeChild (glonț); continua;
Verificăm dacă glonțul se află în afara limitei scenei și, dacă este cazul, eliminăm mai întâi referința din gloanțe
folosind matricea lipitură
apoi îndepărtați glonțul din scenă și continuați cu următoarea iterație. Acesta este modul în care ar trebui să arate bucla dvs. de joc:
funcția privată gameLoop (e: Eveniment): void var turret: Turret; var bullet: Bullet; pentru fiecare (turelă în turle) turret.update (); pentru (var i: int = bullets.length - 1; i> = 0; i -) bullet = ghilimele [i]; dacă (! bullet) continuați; bullet.update ();
Dacă rulați acum jocul, trebuie să aveți aceeași funcționalitate ca în Partea 1, cu un cod mult mai curat și mai organizat.
Acum adăugăm unul dintre cele mai importante elemente ale jocului: Enemy. Primul lucru este să creați o nouă clasă numită Dusman
extinderea spiriduș
clasă:
pachet import flash.display.Sprite; clasa publică Enemy extinde Sprite funcția publică Enemy ()
Acum adăugăm câteva proprietăți la clasă. Adăugați-le înainte de dvs. Dusman
constructor:
private var speed_x: Număr; private var speed_y: Număr;
Inițializăm aceste variabile în Dusman
constructor:
funcția publică Enemy () speed_x = -1.5; speed_y = 0;
Apoi vom crea a desena
și Actualizați
funcții pentru Dusman
clasă. Acestea sunt foarte asemănătoare cu cele de la Glonţ
. Adăugați următorul cod:
funcția privată (): void var g: Graphics = this.graphics; g.beginFill (0xff3333); g.drawCircle (0, 0, 15); g.endFill (); actualizarea funcției publice (): void x + = speed_x; y + = viteza_y;
În jocul nostru trebuie să avem multe evenimente care au loc în anumite momente sau în mod repetat, la anumite intervale. Astfel de timp poate fi realizat folosind un contor de timp. Contorul este doar o variabilă care crește odată cu trecerea timpului în joc. Lucrul important aici este atunci când și cu câte cantități trebuie să creștem contorul. Există două moduri în care sincronizarea se face, în general, în jocuri: bazată pe timp și bazată pe cadre.
Diferența este că unitatea de pas în joc bazată pe timp se bazează pe timpul real (adică numărul de milisecunde trecut), dar într-un joc bazat pe cadru, unitatea de pas este bazată pe unități de cadru (adică numărul de cadre trecute).
Pentru jocul nostru vom folosi un contor bazat pe cadre. Vom avea un contor pe care îl vom majora cu unul în jocul de joc, care rulează fiecare cadru, și astfel ne va da numărul de cadre care au trecut de la începerea jocului. Mergeți mai departe și declarați o variabilă după celelalte declarații de variabile din Principal
clasă:
privat Var ghost_turret: Turret; private var turrets: Array = []; buletine private var: Array = []; privat var global_time: număr = 0;
Am incrementat această variabilă în bucla de joc din partea de sus:
global_time ++;
Acum, pe baza acestui contor, putem face lucruri cum ar fi crearea de inamici, pe care o vom face în continuare.
Ceea ce vrem să facem acum este să creăm dușmani pe teren după fiecare două secunde. Dar avem de-a face cu cadre aici, îți amintești? Deci, după câte rame trebuie să creăm dușmani? Ei bine, jocul nostru rulează la 30 FPS, crescând astfel global_time
contra 30 de ori pe secundă. Un calcul simplu ne spune că 3 secunde = 90 de cadre.
La sfârșitul jocului adăugați următoarele dacă
bloc:
dacă (global_time% 90 == 0)
Despre ce este această condiție? Folosim operatorul modulo (%), care dă restul unei diviziuni - așa global_time% 90
ne dă restul când global_time
este împărțit prin 90
. Verificăm dacă restul este 0
, deoarece acest lucru se va întâmpla numai atunci când global_time
este un multiplu de 90
- adică, condiția revine Adevărat
cand global_time
este egală 0
, 90
, 180
și așa mai departe ... În acest fel, realizăm un declanșator la fiecare 90 de cadre sau 3 secunde.
Înainte de a crea dușmanul, declarăm o altă matrice numită inamici
chiar sub turnulete
și gloanțe
matrice. Acest lucru va fi folosit pentru a stoca referințe la inamici pe scenă.
privat Var ghost_turret: Turret; private var turrets: Array = []; buletine private var: Array = []; private vrăjmașii var: Array = []; privat var global_time: număr = 0;
De asemenea, declarați un dusman
variabilă în partea de sus a jocului:
global_time ++; var turret: turret; var bullet: Bullet; var inamic: Inamic;
În final, adăugați următorul cod în interiorul dacă
bloc pe care l-am creat mai devreme:
inamic = nou Enemy (); enemy.x = 410; enemy.y = 30 + Math.random () * 370; enemies.push (inamic); addChild (inamic);
Aici creăm un nou inamic, poziționează-l la întâmplare în dreptul scenei, împingeți-l în inamici
și adăugați-o pe scenă.
La fel cum actualizăm gloanțele în jocul de joc, actualizăm dușmanii. Puneți următorul cod sub turelă pentru fiecare
buclă:
pentru (var j: int = enemies.length - 1; j> = 0; j--) enemy = inamici [j]; enemy.update (); dacă (enemy.x < 0) enemies.splice(j, 1); enemy.parent.removeChild(enemy); continue;
Ca și cum am făcut o verificare a granițelor pentru gloanțe, verificăm și dușmanii. Dar pentru dușmani, verificăm doar dacă au ieșit din stânga scenei, deoarece se mișcă de la dreapta la stânga. Ar trebui să vadă dușmani venind din dreapta dacă conduci jocul acum.
Fiecare inamic are o viață / sănătate și așa va fi și al nostru. Vom arăta și sănătatea rămasă pe dușmani. Permite declararea unor variabile în Dusman
clasa pentru sănătate:
privat var health_txt: TextField; private var health: int; private var speed_x: Număr; private var speed_y: Număr;
Inițializăm sănătate
variabilă în constructorul următor. Adăugați următoarele la Dusman
constructor:
sănătate = 2;
Acum inițializăm variabila textului de sănătate pentru a arăta în centrul inamicului. Facem acest lucru în a desena
funcţie:
health_txt = TextField nou (); health_txt.height = 20; health_txt.width = 15; health_txt.textColor = 0xffffff; health_txt.x = -5; health_txt.y = -8; health_txt.text = sănătate + ""; addChild (health_txt);
Tot ce facem este să creați un nou TextField
, setați culoarea, poziționați-o și setați textul acesteia la valoarea curentă de sănătate
În cele din urmă adăugăm o funcție de actualizare a sănătății inamicului:
funcția publică funcția updateHealth (suma: int): int health + = suma; health_txt.text = sănătate + ""; returnează sănătatea;
Funcția acceptă un număr întreg pentru adăugarea la sănătate, actualizează textul de sănătate și returnează sănătatea finală. Vom numi această funcție din bucla de joc pentru a actualiza sănătatea inamicului și pentru a afla dacă este încă în viață.
Mai întâi vă permitem să ne modificăm trage
funcționează puțin. Înlocuiți existența trage
funcția cu următoarele:
funcția privată (turelă: turelă, inamic: inamic): void var unghi: număr = Math.atan2 (inamic.y - turret.y, enemy.x - turret.x) / Math.PI * 180; turret.rotation = unghi; var new_bullet: Bullet = Bullet nou (unghi); new_bullet.x = turret.x + Math.cos (turret.ro * Math.PI / 180) * 25; new_bullet.y = turret.y + Math.sin (turret.ro * Math.PI / 180) * 25; bullets.push (new_bullet); addChild (new_bullet);
trage
funcția acceptă acum doi parametri. Prima este o referire la o turelă care va face focul; a doua este o referire la un dușman spre care va trage.
Noul cod este similar cu cel prezent în turelă
clasa lui Actualizați
funcția, dar în loc de poziția mouse-ului, folosim acum coordonatele dușmanului. Deci, acum puteți să eliminați tot codul din Actualizați
funcția turelă
clasă.
Acum cum să faci turlele să tragă la inamici? Ei bine, logica este simplă pentru jocul nostru. Noi facem toate turnurile să împușcă primul inamic în inamici
matrice. Ce? Să punem niște cod și să încercăm să înțelegem. Adăugați următoarele linii la sfârșitul secțiunii pentru fiecare
buclă pentru a actualiza turletele:
pentru fiecare (turelă în turle) turret.update (); pentru fiecare (dușman în dușmani) trage (turelă, inamic); pauză;
Pentru fiecare turelă actualizăm acum, apoi iterați inamici
array, trage primul dușman în matrice și se rupe din bucla. Deci, în mod esențial, fiecare turelă împușcă cel mai devreme inamic creat așa cum este întotdeauna la începutul matricei. Încercați să rulați jocul și ar trebui să vedeți turnulete care să împuște dușmanii.
Dar așteptați, care este fluxul bullet care curge? Se pare că trag prea repede. Să vedem de ce.
După cum știm, bucla de joc rulează fiecare cadru, adică de 30 de ori pe secundă în cazul nostru, așa că declarația de fotografiere pe care am adăugat-o în pasul anterior este apelată la viteza jocului nostru și, prin urmare, vedem un flux de gloanțe care curge. Se pare că avem nevoie și de un mecanism de sincronizare în interiorul turretului. Treceți la turelă
clasă și adăugați următorul cod:
privat var local_time: Număr = 0; privat var reload_time: int;
ora locala
: Numărătoarele noastre sunt numite ora locala
În contrast cu global_time
în Principal
clasă. Acest lucru este din două motive: în primul rând, deoarece această variabilă este locală la turelă
clasă; în al doilea rând, pentru că nu merge întotdeauna ca și noi global_time
variabilă - se va reseta de mai multe ori pe parcursul jocului. timp de reîncărcare
: Acesta este timpul necesar pentru reîncărcarea turelei după fotografierea unei gloanțe. Practic este diferența de timp dintre două lunete de glonț de o turelă. Amintiți-vă că toate unitățile de timp din jocul nostru sunt în termeni de cadre. Creșteți valoarea ora locala
variabilă în Actualizați
funcționează și inițializează timp de reîncărcare
în constructor:
funcția publică (): void local_time ++;
funcția publică funcția Turret () reload_time = 30; a desena();
Apoi adăugați următoarele două funcții la sfârșitul secțiunii turelă
clasă:
funcția publică esteReady (): Boolean return local_time> reload_time; funcția publică resetată (): void local_time = 0;
este gata
returnează adevărat numai atunci când curentul ora locala
este mai mare decât timp de reîncărcare
, adică când turela a fost reîncărcată. Si restabili
funcția reinițializează pur și simplu ora locala
, pentru a porni din nou încărcarea.
Acum, înapoi în Principal
clasă, modificați codul de înregistrare în bucla de joc pe care am adăugat-o în etapa anterioară la următoarele:
pentru fiecare (turelă în turle) turret.update (); dacă (! turret.isReady ()) continuă; pentru fiecare (dușman în dușmani) trage (turelă, inamic); turret.reset (); pauză;
Deci, dacă acum turnuletul nu este gata (este gata()
se intoarce fals
), vom continua cu următoarea iterație a buclei de turelă. Veți vedea că turnurile se declanșează la un interval de 30 de cadre sau o secundă acum. Rece!
Încă ceva nu este corect. Turnuletele trag la dușmani, indiferent de distanța dintre ele. Ceea ce lipsește aici este gamă de o turelă. Fiecare turelă ar trebui să aibă propria gamă în care să poată împușca un inamic. Adăugați o altă variabilă la turelă
clasa numită gamă
și puneți-o la dispoziție 120
în interiorul constructorului:
privat var reload_time: int; privat var local_time: Număr = 0; gama privată var: int;
funcția publică funcția Turret () reload_time = 30; interval = 120; a desena();
Adăugați, de asemenea, o funcție numită canShoot
la sfârșitul clasei:
funcția publică canShoot (inamic: Enemy): Boolean var dx: Number = enemy.x - x; var dy: Număr = inamic.y - y; dacă (Math.sqrt (dx * dx + dy * dy) <= range) return true; else return false;
Fiecare turelă poate să tragă un dușman numai atunci când îndeplinește anumite criterii - de exemplu, ați putea lăsa turela să tragă doar dușmani roșii cu mai puțin de jumătate din viață și nu mai mult de 30px distanță. Toată această logică pentru a determina dacă turela este capabilă să tragă un dușman sau nu va intra în canShoot
funcție, care se întoarce Adevărat
sau fals
conform logicii.
Logica noastră este simplă. Dacă inamicul se află în intervalul de întoarcere Adevărat
; altfel returnează falsul. Deci, atunci când distanța dintre turelă și inamic (Math.sqrt (dx * dx + dy * dy)
) este mai mică sau egală cu gamă
, se întoarce Adevărat
. Un pic mai multă modificare în secțiunea de film a jocului:
pentru fiecare (turelă în turle) turret.update (); dacă (! turret.isReady ()) continuă; pentru fiecare (inamic in dusmani) if (turret.canShoot (inamic)) trage (turela, inamic); turret.reset (); pauză;
Acum numai dacă dușmanul se află în raza de acțiune a turelei, va trage turela.
O parte foarte importantă a fiecărui joc este detecția coliziunilor. În joc, verificarea coliziunii se face între gloanțe și dușmani. Vom adăuga codul de detectare a coliziunii în interiorul pentru fiecare
buclă care actualizează gloanțele în bucla de joc.
Logica este simplă. Pentru fiecare glonț traversăm inamici
și verificați dacă există o coliziune între ele. Dacă da, eliminăm glontul, actualizăm sănătatea inamicului și ieșim din bucla pentru a verifica alți dușmani. Să adăugăm un cod:
pentru (i = bullets.length - 1; i> = 0; i -) bullet = gloanțe [i]; // dacă nu este definită gluma, continuați cu următoarea iterație dacă (! bullet) continuați; bullet.update (); dacă (bullet.x < 0 || bullet.x > stage.stageWidth || bullet.y < 0 || bullet.y > stage.stageHeight) bullets.splice (i, 1); bullet.parent.removeChild (glonț); continua; pentru (var k: int = enemies.length - 1; k> = 0; k--) enemy = inamici [k]; dacă (bullet.hitTestObject (inamic)) bullets.splice (i, 1); bullet.parent.removeChild (glonț); dacă (inamic.updateHealth (-1) == 0) enemies.splice (k, 1); enemy.parent.removeChild (inamic); pauză;
Folosim ActionScript hitTestObject
pentru a verifica coliziunea dintre glonț și inamic. Dacă se produce ciocnirea, glonțul este îndepărtat în același mod ca atunci când părăsește etapa. Sănătatea inamicului este apoi actualizată folosind updateHealth
metodă, la care glonţ
„s deteriora
proprietatea este trecută. În cazul în care updateHealth
funcția returnează un număr mai mic sau egal cu 0
, aceasta înseamnă că dușmanul este mort și așa îl eliminăm în același mod ca și glonțul.
Și detectarea coliziunilor noastre sa terminat!
Amintiți-vă că traversăm dușmanii și gloanțele înapoi în bucla noastră de joc. Să înțelegem de ce. Să presupunem că am folosit un ascendent pentru
buclă. Suntem pe index i = 3
și eliminăm un glonț din matrice. La îndepărtarea elementului în poziție 3
, spațiul său este umplut de articol apoi în poziție 4
. Deci, acum elementul anterior în poziție 4
este la 3
. După repetare eu
incremente de 1
și devine 4
și așa mai departe la poziție 4
este bifat.
Hopa, vezi ce sa întâmplat acum? Tocmai am pierdut articolul acum în poziție 3
care s-au mutat înapoi ca rezultat al îmbinării. Și așa vom folosi o inversă pentru
care elimină această problemă. Puteți vedea de ce.
Să adăugăm câteva lucruri suplimentare pentru a face jocul să arate bine. Vom adăuga funcționalități pentru a afișa o rază a turelei atunci când mouse-ul este plutind pe el. Treceți la turelă
și adăugați câteva variabile la ea:
gama privată var: int; privat var reload_time: int; privat var local_time: Număr = 0; privat var corp: Sprite; privat var_circle: Sprite;
Actualizați ulterior a desena
funcționează la următoarele:
funcția privată (): void range_circle = Sprite nou (); g = range_circle.graphics; g.beginFill (0x00D700); g.drawCircle (0, 0, interval); g.endFill (); range_circle.alpha = 0.2; range_circle.visible = false; addChild (range_circle); corp = Sprite nou (); var g: Grafica = grafica corporala; g.beginFill (0xD7D700); g.drawCircle (0, 0, 20); g.beginFill (0x800000); g.drawRect (0, -5, 25, 10); g.endFill (); addChild (corp);
Spargem graficele turelei în două părți: corpul și graficul intervalului. Facem acest lucru pentru a da o comandă diferitelor părți ale turelei. Aici avem nevoie de range_circle
pentru a fi în spatele corpului turelei, așa că o adăugăm mai întâi la scenă. În cele din urmă, adăugăm doi ascultători de mouse pentru a comuta graficul de domeniu:
funcția privată onMouseOver (e: MouseEvent): void range_circle.visible = true; funcția privată onMouseOut (e: MouseEvent): void range_circle.visible = false;
Acum atașați ascultătorii la evenimentele respective la sfârșitul constructorului:
corp.addEventListener (MouseEvent.MOUSE_OVER, onMouseOver); corp.addEventListener (MouseEvent.MOUSE_OUT, onMouseOut);
Dacă rulați jocul și încercați să desfășurați o turelă, veți vedea o pâlpâire atunci când se deplasează pe locurile de substituție. De ce este asta?
Amintiți-vă că am setat mouseEnabled
proprietate a turelei fantomă la fals
? Am făcut-o pentru că turela fantomă capta evenimentele mouse-ului venind între mouse și substituent. Aceeași situație a sosit din nou, deoarece turela are acum doi copii - corpul său și sprite - care captează evenimentele mouse-ului între.
Soluția este aceeași. Le putem stabili individul mouseEnabled
proprietăți pentru fals
. Dar o soluție mai bună este de a seta turela ghost mouseChildren
proprietate la fals
. Ceea ce face acest lucru este să restricționăm toți copiii turelei fantomă de la recepția evenimentelor mouse-ului. Neat, nu? Mergeți și puneți-o la dispoziție fals
în Principal
constructor:
ghost_turret = noua turela (); ghost_turret.alpha = 0.5; ghost_turret.mouseEnabled = false; ghost_turret.mouseChildren = false; ghost_turret.visible = false; addChild (ghost_turret);
Problema rezolvata.
Am putea extinde acest demo pentru a include caracteristici mult mai avansate și transforma-l într-un joc care poate fi jucat. Unele dintre acestea ar putea fi:
Să vedem ce puteți face de la acest demo de bază. Voi fi bucuros să aud despre jocurile de apărare din turn și comentariile sau sugestiile dvs. pentru serii.