Jeg skal gå deg gjennom etableringen av et Megaman-inspirert skytespill / plattformspill. Vi vil være mer fokusert på skytespillene i spillet i stedet for plattformen. I denne opplæringen bruker jeg Construct 2 som verktøy for å lage spillet, men jeg vil forklare logikken ved hjelp av pseudokode, slik at du kan følge denne opplæringen i hvilket språk som helst.
Relaterte innleggFor å fokusere på implementeringen av spillet, vil jeg ikke forklare hver Construct 2-funksjon; Jeg kommer til å anta at du kjenner grunnleggende, for eksempel lasting av sprite, grunnleggende kollisjon eller spillelyder. Med det sagt, la oss begynne å lage spillet.
Første ting først, vi må ha sprites for vårt spill. Heldigvis har opengameart oss dekket med sin fantastiske samling av lovlig spillkunst. Vi trenger fire sett med sprites; en helt, en fiende og fliser til plattformer.
For å bruke dem i Construct 2, beskjærer jeg heltens sprites i individuelle rammer ved hjelp av GIMP.
Jeg skal bruke Construct 2s plattformsadferd for resten av opplæringen slik at jeg kan fokusere på skyting og AI-delen av spillet, som var hovedfokus for denne opplæringen.
Hvis du jobber på et annet språk, eller vil implementere din egen grunnleggende plattformsbeverkelse i stedet for å bruke den innebygde oppførselen. Du trenger bare å bruke koden i denne delen hvis du ikke skal bruke Construct 2s innebygde oppførsel.
For å begynne, må vi vurdere tre måter vår helt kan flytte; gå rett, gå til venstre eller hoppe. Hver ramme, vi oppdaterer spillsimuleringen.
antall moveSpeed = 50; funksjon oppdatering () moveHero ();
For å oppdatere spillerens karakter, implementerer vi grunnleggende bevegelse slik:
funksjon moveHero () // spiller trykker denne tasten ned hvis (keyDown (KEY_LEFT)) hero.x - = moveSpeed * deltaTime; hero.animate ( "walkLeft"); hvis (keyDown (KEY_RIGHT)) hero.x + = moveSpeed * deltaTime; hero.animate ( "walkRight"); hvis (keyDown (KEY_UP)) hero.jump (); hero.animate ( "hoppe"); // en nøkkel som nettopp ble unpressed hvis (keyReleased (KEY_LEFT)) hero.animate ("standLeft"); hvis (keyReleased (KEY_RIGHT)) hero.animate ("standRight");
Jeg bruker en annen funksjon til å hoppe fordi hopping handler ikke bare om å endre y-verdien, men også å beregne tyngdekraften. Vi vil også ha en funksjon som lytter om en nøkkel har nettopp blitt utgitt, for å returnere vår helt animasjon til en stående animasjon.
La oss snakke om hvordan du får spilleren til å hoppe. Helt vil trenge å vite om han for tiden hopper eller ikke, og også om han for tiden faller eller ikke. Så vi vil erklære to nye variabler: isJumping og isFalling. Som standard er begge falske, noe som betyr at helten står på en plattform.
For å utføre et hopp må vi først sjekke om begge verdiene er falske, og gjør deretter isJump sant.
Funksjon hopp () hvis (! ErJumping &&! IsFalling) isJumping = True
For at helten skal kunne hoppe, trenger vi en variabel som heter JumpPower og gravity. JumpPowers standardverdien er -20 og tyngdekraften er 1. Logikken er å legge til verdien av hoppeffekten til helten Y-posisjon og å legge tyngdekraften til å hoppe kraftens verdi.
Vi gjør dette hvert kryss. Kanskje dette ikke er den mest realistiske gravitetsfysikken det er, men spill trenger ikke å være realistiske, de trenger bare å være troverdige, derfor har noen spill super humans hopp og dobbelt hopp. Koden nedenfor tilhører oppdateringsfunksjonen.
Hvis (erJumping || isFalling) hero.y + = hero.jumpPower; hero.jumpPower + = hero.gravity; // til slutt hoppe kraften vil være større enn null, og det betyr at helten faller hvis (hero.jumpPower> = 0) isJumping = False; isFalling = True; // for å stoppe høsten, gjør noe når helten overlapper plattformen hvis (hero.isOverlapping (plattform1)) // platform1 er plattformen som vår helt kan gå på // tilbakestiller variabelen til standardverdien isJumping = False; isFalling = False; hero.jumpPower = -20; // og så er det det frie fallet når spilleren faller over kanten av en plattform hvis (! hero.isOverlapping (platform1) && hero.jumpPower < 0 && !isJumping) // !hero.isOverlapping(platform1) checks whether or not our hero is standing on a platform // and if jumpPower is less than zero and the player is not currently jumping, then that means // he's falling // setting these two values like this will make the player fall. hero.jumpPower = 0; isFalling = true;
Construct 2s innebygde plattformsadferd replikerer eksemplet ovenfor, som bare er gitt til hjelpen som arbeider på et annet språk.
Nå kommer skytespillet av spillet. I Megaman-serien er det tre typer skudd: vanlige skudd, ladede skudd og sjefens energislag.
Normale skudd er selvforklarende. Ladede skudd er bilder som belastes først før de slippes. Disse ladede skuddene kommer i to typer: halv ladet og fulladet. Disse belastede angrepene er sterkere enn vanlige skudd, med fullt ladet bli den sterkeste.
Boss energi skudd er skudd med makt som spilleren kjøpte etter å ha beseiret hver sjef. Skaden er den samme som vanlig, men de har spesielle egenskaper som vanlige skudd ikke har.
Nå som vi kjenner hvert skudd er type, la oss begynne å lage dem. Først må vi se logikken bak hvordan vi bruker hvert skudd. Her antar vi at Z-knappen på tastaturet brukes til å brenne et skudd. Vi implementerer to forskjellige oppføringer:
Nå, la oss begynne å kode. Fordi vår helt kan skyte til venstre og høyre, må vi vite hvilken retning han står overfor. La oss erklære en ny variabel som kalles mot som lagrer en strengverdi av om helten vender mot venstre eller høyre.
String vendt mot = "høyre"; // hvilken retning helten står overfor for øyeblikket funksjon moveHero () // player trykker denne tasten ned hvis (keyDown (KEY_LEFT)) hero.x - = moveSpeed * deltaTime; hero.animate ( "walkLeft"); vendt = "venstre"; hvis (keyDown (KEY_RIGHT)) hero.x + = moveSpeed * deltaTime; hero.animate ( "walkRight"); vendt mot = "rett"; // fortsettelsen av moveHero () -funksjonen går her funksjon oppdatering () // ... oppdateringskoden vi skrev tidligere går her ... // spiller trykk denne tasten en gang hvis (keyPressed (KEY_Z)) hvis == "høyre") hero.animate ("Shoot"); // vi legger til skytingsfunksjon her senere annet hvis (vender == "venstre") hero.animate ("Shoot"); hero.mirrorSprite (); // denne funksjonen spretter spritet horisontalt hvis (keyReleased (KEY_Z)) hvis (vender == "høyre") hero.animate ("standRight"); annet hvis (vender == "venstre") hero.animate ("standLeft"); hero.mirrorSprite (); // vi trenger å ringe dette igjen fordi sprite ble speilet // hvis vi ikke speiler sprite igjen, vil standLeft se ut som standRight
Før vi skyter en kule, må vi se på egenskapene kulen har:
Disse egenskapene vil variere for hver kulde. Spesielt vil kraftegenskapen være forskjellig. Vinkelegenskapen er normalt bare en av to verdier; om kulen er skutt til høyre eller venstre, med mindre det er en sjefens energikule som kan skutt i en unik vinkel.
Skuddvariasjoner blir diskutert senere, så nå vil jeg bare dekke grunnleggende bilder. Følgende er koden som skaper en kule.
// Først oppretter vi en funksjon som lager en ny kule Funksjonsspor (strengsporToSprite, nummer bulletPower, nummer bulletSpeed, number bulletAngle) myBullet = new Bullet (pathToSprite); myBullet.power = bulletPower; // kuleklassen eller objektet har to private variabler som beveger den i henhold til vinkelen sin // mer forklaring på disse to linjene trenger mer matte, så jeg velger ikke å forklare // Jeg antar at din valgte motor har en måte å flytte en objekt i henhold til sin vinkel ySpeed = Math.sin (bulletAngle) * bulletSpeed; xSpeed = Math.cos (bulletAngle) * bulletSpeed; // dette er Bullet class-funksjonen som kalles hver ramme, dette beveger kulen i henhold til vinkelfunksjonen moveBullet () x + = xSpeed * deltaTime; y + = ySpeed * deltaTime; // og dette er modifiseringen til vår forrige oppdatering () funksjon funksjon oppdatering () // ... oppdateringskoden vi skrev tidligere går her ... // spiller trykk denne tasten en gang hvis (keyPressed (KEY_Z)) if ( vendt mot == "høyre") hero.animate ("Shoot"); hero.shoot ("path / to / sprite.png", 10, 400, 0); annet hvis (vender == "venstre") hero.animate ("Shoot"); hero.mirrorSprite (); // denne funksjonen spretter sprite horisontalt hero.shoot ("path / to / sprite.png", 10, 400, 180); // vinkelen er 180 slik at kulen går til venstre // ... fortsettelsen av oppdateringskoden går her ...
Noen kuler kan være kraftigere enn andre. For å opprette et ladet skudd trenger vi en variabel som heter ladetid, som øker hvert sekund spilleren holder Z nede, og kommer tilbake til null når kulen er sparken. Endringene i oppdateringskoden er som følger:
// spiller bare utgitt z-nøkkel hvis (keyReleased (KEY_Z)) if (chargedTime> 0 && chargedTime <= 5) if (facing == "right") hero.animate("Shoot"); hero.shoot("path/to/halfChargedBullet.png", 20, 400, 0); chargedTime = 0; else if (facing == "left") hero.animate("Shoot"); hero.mirrorSprite(); // this function flips the sprite horizontally hero.shoot("path/to/halfChargedBullet.png", 20, 400, 180); chargedTime = 0; else if (chargedTime > 5) hvis (vender == "høyre") hero.animate ("Shoot"); hero.shoot ("path / to / fullChargedBullet.png", 40, 400, 0); chargedTime = 0; annet hvis (vender == "venstre") hero.animate ("Shoot"); hero.mirrorSprite (); // denne funksjonen spretter sprite horisontalt hero.shoot ("path / to / fullChargedBullet.png", 40, 400, 180); chargedTime = 0; hvis (vender == "høyre") hero.animate ("standRight"); annet hvis (vender == "venstre") hero.animate ("standLeft"); hero.mirrorSprite (); // vi trenger å ringe dette igjen fordi sprite ble speilet // hvis vi ikke speiler sprite igjen, vil standLeft se ut som standRight // spiller trykker denne tasten ned hvis (keyDown (KEY_Z)) // dette er funksjonen som legger verdien til chargedTime hvert sekund // denne keyDown-koden vil bli kjørt hver ramme, som er mindre enn et sekund // din valgte motor skal ha en måte å fortelle om et sekund har gått eller ikke addChargedTime ();
Vår heltegang nye trekk går til venstre, høyre og hopper i henhold til vårt innspill, og skyter også kuler, enten det er normalt, halv ladet eller fulladet.
Vi har nå en kontrollerbar helt. La oss kalle det Xeon for enkelhets skyld. Han kan utføre noen grunnleggende bevegelser som å gå, hoppe og skyte. Det er flott! Men hva god er muligheten til å skyte uten noe å skyte på, ikke sant? Det er derfor denne gangen vi skal lage vår første fiende.
La oss lage fiendens egenskaper før vi begynner å kode det.
Helse: Hvor mange helsemessige fiendene våre har avgjort hvor mange skudd (og hva slags) det er nødvendig for å ødelegge det.
Kraft: Enemys angrepskraft, hvor mye skade er det for vår spiller?.
ShotAngle: I hvilken retning fienden skyter kulen, kan den være igjen eller høyre eller hvor som helst vi vil.
Det er ganske mye det vi trenger for vår fiende, la oss nå gjøre fiendens klasse / objekt.
Enemy-klassen / -objektet er stort sett det samme som spillerklassen / -objektet, bortsett fra at fienden ikke hører på spillerinngang. På grunn av det må vi erstatte delene hvor helten lytter til spillerinngang, til fiendens AI / logikk.
For startere, la oss håndtere fiendens grunnleggende skyting AI. Fienden vil skyte på spilleren når den ser spilleren.
For å avgjøre om fienden "ser" spilleren, må vi definere en variabel for fienden objekt som kalles mot, hvilket er en streng som lagrer en av to verdier, "venstre" eller "høyre".
Fienden trenger også en slags synsfelt, og derfor skal vi lage en annen variabel som heter. Hvis spilleren er innenfor dette området, betyr det at fienden "ser" spilleren. Pseudokoden er som følger:
funksjon boolean checkSees () if (facing == "left" && hero.x> = enemy.x - rekkevidde) return true; hvis (motsatt == "høyre" && hero.x <= enemy.x + range) return true; return false;
checkSees () funksjon
Kanskje du har lagt merke til noe i denne pseudokoden: det tar ikke hensyn til heltenes y-posisjon, så fienden vil fortsatt skyte på helten, selv om de er på plattformer med forskjellige høyder.
For nå vil dette være tilstrekkelig, fordi det er utenfor omfanget av denne opplæringen å lage en synhetsalgoritme. I ditt eget spill vil du kanskje legge til en Y-toleranse i den funksjonen over som vil sjekke om heltens y-posisjon er mellom to punkter som definerer fiendens høyder.
Pseudokoden for fiendeskyting er som følger:
// kan være i oppdatering () eller et annet sted som utføres hver rammefunksjonsoppdatering () if (checkSees ()) shoot ("path / to / bulletSprite.png", enemyPower, 400, shotAngle);
Som du kan se, er fiendeskytingen () -funksjonen lik den som spilleren har. Det tar spriteens sti, angrepskraft, kuldehastighet og skyvvinkel som parametere.
Når bytter fienden fra vender mot venstre til høyre? For vår helt bruker vi spillerinnspillingen til å endre retningen til vår helt. For vår fiende har vi to alternativer: bruk en slags timer for å bytte retning i noen få sekunder mens du har fienden til å stå stille, eller få fienden til å gå til et bestemt sted og deretter bytte retning og deretter gå til et annet sted for å bytte retningen igjen.
Denne andre metoden kan brukes som patruljering AI. Selvfølgelig kan vi bare få fienden til å gå i en retning og aldri vende tilbake.
Pseudokoden for den første metoden er som følger:
funksjon switchingAI () // elapsedTime () er en funksjon som teller hvor mange sekunder har gått siden verdien er tilbakestilt // Jeg antar at din valgte motor har denne typen funksjonalitet hvis (forløptTime ()> 4.0) hvis == "left") facing = "right"; shotAngle = 0; hvis (vender == "høyre") facing = "left"; shotAngle = 180; enemy.mirrorSprite (); // også vri sprite horisontalt resetTime (); // nullstiller tiden som teller i forløpt tid ()
For å lage patruljering AI må vi lage to usynlige objekter som er på slutten av begge veier av fiendens patruljeringsrute, og få fienden til å bevege seg en annen måte hvis den kolliderer med dem.
La oss nå skrive vår pseudokode for fiendens patruljering AI:
funksjon patruleringAI () hvis (vendt == "høyre") walkRight (); // det samme som i spillerobjekt / klasse hvis (collidesWith (rightPatrolBorder)) facing = "left"; enemy.mirrorSprite (); hvis (vender == "venstre") walkLeft (); hvis (collidesWith (leftPatrolBorder)) facing = "right"; enemy.mirrorSprite ();
Etter dette vil fienden patrulje mellom to punkter som vi vil ha det til.
For å sette opp hvilken AI fienden bruker, skal vi legge til en ny variabel med en strengtype for fienden vår: fiende AI. Dette bestemmer hva AI skal bruke hver ramme, slik som:
hvis (fiendeAI == "bytter") switchingAI (); ellers hvis (fiendeAI == "patruljerer") patrollingAI ();
Selvfølgelig kan du legge til flere fiendtlige AI-typer hvis du vil.
La oss fortsette hvordan vi kan skape skuddvarianter for både spilleren og fienden. Vi lager skuddvariasjoner ved å bytte to ting: skytingsvinkelen og antall skuddene skutt.
På denne måten kan vi lage en enkelt en kule, eller en tre retningsskudd. Før vi gjør dette, skal vi lage en annen variabel til fiendens objekt / klasse som heter shotAI, som er en streng. Vi bruker dette i våre sjekkerSe () sjekker om blokk, hvor fienden skyter. Endringene i den kodeblokken vil være slik:
// kan være i oppdatering () eller et annet sted som utføres hver rammefunksjonsoppdatering () if (checkSees ()) if (shotAI == "simple") skyte ("path / to / bulletSprite.png" , 400, shotAngle); hvis (shotAI == "threeBullets") shootThreeBullets ();
Selvfølgelig, navnet på AI og hva slags skudd fienden ville brenne er opp til deg, dette er bare et eksempel.
La oss nå dybere inn i hva som er inne i shootThreeBullets () -funksjonen.
Funksjon shootThreeBullets () hvis (vender == "høyre") shoot ("path / to / bulletSprite.png", enemyPower, 400, 0); // denne kula går rett til høyre skudd ("bane / til / bulletSprite.png", fiendePower, 400, 330); // dette går opp med 30 grader skyte ("bane / til / bulletSprite.png", fiendePower, 400, 30); // dette går ned med 30 grader hvis (vender == "venstre") shoot ("path / to / bulletSprite.png", enemyPower, 400, 180); // denne kula går rett til venstre skudd ("path / to / bulletSprite.png", enemyPower, 400, 210); // dette går opp med 30 grader skyte ("bane / til / bulletSprite.png", fiendePower, 400, 150); // dette går ned med 30 grader
Hvis du er usikker på hvorfor 0 går til høyre og 180 går til venstre, er det fordi retningen på 0 grader går rett til høyre på skjermen, 90 grader går til nedsiden av skjermen, og så videre til den treffer 360 grader. Når du vet hva verdien går der, kan du lage din egen skuddvariasjon.
Vi kan også lage en shotAI-variabel for spilleren, men jeg foretrekker at vi kaller det valgtShot, fordi vår spiller vil velge kulen i stedet for programmert fra begynnelsen. T
han logikk i megaman er hver gang megaman beseirer en sjef, får han den sjefens makt som et nytt skudd. Jeg skal prøve å gjenskape den logikken. For å gjøre dette trenger vi en matrise som inneholder spillerens skudd, inkludert vanlige skudd. Pseudokoden er slik:
var shotArr = ["normalShot", "boss1", "boss2"]; var skuttIndex = 0; var selectedShot = "normalShot"; funksjonsoppdatering () // dette er koden av koden i spillerens oppdateringsfunksjon hvor spilleren skyter en kule // denne funksjonen endrer kule som spilleren skyter changeBullet (); // spiller trykk denne tasten en gang hvis (keyPressed (KEY_Z)) hvis (motsatt == "høyre") hero.animate ("Shoot"); if (selectedShot == "normalShot") hero.shoot ("path / to / sprite.png", 10, 400, 0); ellers hvis (selectedShot == "boss1") // legg til koder for å skyte den typen av skudd som spilleren mottok etter å ha beseiret sjefen 1 funksjonsendringBullet () // endrer skuttIndex basert på knapptrykket hvis (tastetrykk (KEY_E)) shotIndex + = 1; hvis (keyPressed (KEY_Q)) shotIndex - = 1; // fix shotIndex hvis det er utenfor rekkevidde hvis (shotIndex == shotArr.length) shotIndex = 0; hvis (shotIndex < 0) shotIndex = shotArr.length -- 1; selectedShot = shotArr[shotIndex];
Vi må holde styr på to nye variabler:
Vi vil skyve nye elementer til shotArr når spilleren slår en sjef.
Akkurat som fiendens shootThreeBullet (), kan du være kreativ og skape dine egne skuddvariasjoner. Siden dette er heltenes kulde, la oss gi det noe spesielt.
La oss lage en type skudd for å være effektiv mot en bestemt sjef, slik at den gir mer skade. For å gjøre dette, vil vi opprette en variabel for punktobjektet kalt strongAgainst, som er en annen strengtypevariabel som inneholder navnet på sjefen som denne kollen er effektiv mot. Vi vil legge til denne avtalen mer skadefunksjonalitet når vi diskuterer sjefsdelen av spillet.
Det er her alle skuddvariasjonene vi lager virkelig begynner å gjøre noe. Det er her vår skade ødelegger og dreper fienden, og omvendt.
For å begynne med, la oss lage en variabel for både helten og fiendens gjenstand, kalt helse som er en int, og en annen variabel bare for helten som heter liv. La oss ta en titt på pseudokoden:
hvis (bullet.collidesWith (hero)) hero.health - = bullet.power; createExplosion (); // for nå har vi ikke en eksplosjonssprite, så dette vil fungere som en påminnelse // se om helten er død hvis (hero.health <= 0) hero.lives -= 1; // decreases hero's total number of lives. destroyHero();
Vi vil lage den samme pseudokoden for å skade fiender, slik som:
hvis (bullet.collidesWith (fiende)) enemy.health - = bullet.power; createExplosion (); hvis (fiende. sunnhet <= 0) destroyEnemy();
Nå, hvis jeg forlater det da ville det ikke være interessant. Så jeg lager et rektangel-sprite i øverste venstre hjørne av skjermen som fungerer som vår heltes helsestang.
Denne helsenes lengde skal endres avhengig av vår helts nåværende helse. Formelen for endring av barnehøyde er dette:
// dette er i oppdateringsfunksjonen healthBar.width = (hero.health / hero.maxHealth) * 100;
Vi trenger en mer variabel for vår helt som heter maxHealth; vår helt er full helse verdi. For nå kan denne verdien ikke endres, men kanskje i fremtiden kan vi lage et element som øker mengden av heltenes maksimal helse.
Nå som vi har skapt vår helt, fiende og skuddvariasjoner, må vi lage flere nivåer og sjefer.
For å ha flere nivåer betyr at noen gang i spillet skal spilleren nå en eller flere kontrollpunkter som bytter spillet fra nivå 1-1 til nivå 1-2 til nivå 1-3 og så videre til de når sjefen.
Når spilleren dør et sted i nivå 1-2, trenger han eller hun ikke å spille helt tilbake fra begynnelsen av nivå 1-1. Hvordan gjør jeg dette? Først skal vi gjøre nivået, jeg kommer ikke til å forklare mye om nivådesign, men her er eksempelnivået i Construct 2.
Bildet øverst til venstre er HUD-laget. Det vil rulle etter helten når spillet spilles.
En sprite du bør være oppmerksom på, er den grønne sprite i øvre høyre del av nivået. Det er kontrollpunktet på dette nivået når helten kolliderer med det, vi overfører spillet til nivå 1-2.
For å håndtere flere nivåer trenger vi tre variabler: currentLevel, levelName og nextLevel.
CurrentLevel-variabelen er opprettet i helt-objektet / klassen. LevelName er opprettet i spillet scene (nivå) objekt for hvert nivå. NextLevel-variabelen er opprettet i den grønne spriteobjektet.
Logikken er som følger: Når helten kolliderer med den grønne sprite (jeg kaller den greenDoor), vil vi endre nivået til spillscenen i hvilket nivånavn er det samme som nextLevel-variabelen. Etter at vi har endret nivået, vil vi endre verdien av heltens nåværende variabel til det samme som spillescens nivånavn. Her er pseudokoden:
// dette er inne i spillets oppdateringsfunksjon hvis (hero.collidesWith (greenDoor)) changeLevelTo (greenDoor.nextLevel);
Her er pseudokoden for å håndtere når neste nivå er lastet og klar til å spille.
// dette er funksjonen som utløses når det nye nivået er lastet funksjon onStart () hero.currentLevel = scene.LevelName; hero.x = startPos.x; hero.y = startPos.y;
Nå som vi har endret seg til et nytt nivå, vil jeg forklare oransje sprite bak vår helt i nivådesignbildet over. Den oransje sprite er et objekt som jeg kaller startPos. Det brukes til å markere startposisjonen til hvert nivå.
Vi refererer til dette objektet når heltten bare endret nivåer eller døde, slik at vi vet hvor de skal gyte ham.
Her er pseudokoden for håndtering når helten dør:
// funksjonen som utløses når helten er ødelagt Funksjon onDestroyed () // gjenoppretter helt hvis helten fortsatt har liv. Hvis (hero.lives> 0) var newHero = new Hero (); newHero.x = startPos.x; newHero.y = startPos.y;
Nå kan vi ha flere nivåer, og vi kan også respawn helten etter at han dør.
Du kan lage så mange nivåer som du vil, eller kanskje til og med lage to greenDoor-objekter på et nivå som en av dem går tilbake til nivå 1-1 hvis spilleren løser et puslespill på feil måte.
Det er endelig tid til å gjennomføre sjefen selv. Å lage en sjef nivå er like enkelt som å lage et annet nivå som vil gyte en sjef i stedet for vanlige fiender.
Den vanskelige delen er å skape AI for sjefen fordi hver sjef vil ha en unik AI. Så for å gjøre det enkelt å forstå og duplisere for mange sjefer, skal jeg gjøre sjefen AI avhengig av tiden etter at de er oppstått. Hvilket betyr at de skal gjøre A for x sekunder, deretter bytt til B i y sekunder, og gjør C for z sekunder før du vender tilbake til A. Pseudokoden vil se slik ut:
// denne koden er inne i sjefsoppdateringsfunksjonen, slik at den utføres hver ramme hvis (forløptTime ()> 2.0) // dette hvis blokk utføres i 3 sekunder, fordi forskjellen i tid med if-blokken nedenfor // er tre sekunder. BossShot1 (); // shot variasjon som skal utføres denne gangen ellers hvis (forløptTime ()> 5.0) bossShot2 (); ellers hvis (forløptTime ()> 6,0) bossShot3 (); hvis (forløptTime ()> 7.0) // tilbakestille tiden slik at sjefen utfører den første handlingen igjen, resetterTime ();
Definisjonen av sjefsfotograferingsfunksjonene er under. Du er velkommen til å endre den slik at den passer til det du vil ha for en sjefs kamp:
funksjon bossShot1 () // en enkel straight shot bossEnemy.shoot ("bane / til / bullet / sprite.png", bossPower, 400, shotAngle); // shotAngle er 180 funksjon bossShot2 () // en tre retningskuler skutt bossEnemy.shoot ("bane / til / bullet / sprite.png", bossPower, 400, shotAngle); bossEnemy.shoot ("path / to / bullet / sprite.png", bossPower, 400, shotAngle + 30); bossEnemy.shoot ("path / to / bullet / sprite.png", bossPower, 400, shotAngle - 30); funksjon bossShot3 () // for denne, jeg skal lage en sirkelskade, så kulene vil danne en sirkel for (var i = 0; i <= 9; i++) bossEnemy.shoot("path/to/bullet/sprite.png", bossPower, 400, 36 * i); // change the shotAngle
Det er opp til deg å legge til skuddvariasjoner til sjefens rutine. Variablene som brukes av sjefens fiendeobjekt, er de samme som fiendens objekt, bortsett fra at sjefer ikke bruker fiendensAI- og shotAI-variabler, siden begge vil bli håndtert i if-blokket ovenfor, avhengig av den forløpte tiden.
Boss fiender har også en variabel som fiendens gjenstander ikke gjør. Det kalles belønningShot, som er en streng. Denne variabelen innebærer navnet på en sjefsskudd som spilleren vil skaffe etter å ha beseiret sjefen (de som er i shotArr array variabel).
Dette vil tillate spilleren å "lære" sjefsangrepet som forklart tidligere. For å legge til denne skuddtypen i spekteret av spillerskudd, må vi legge til følgende kode etter at fienden dør:
funksjon bossShot1 () // en enkel straight shot bossEnemy.shoot ("bane / til / bullet / sprite.png", bossPower, 400, shotAngle); // shotAngle er 180 funksjon bossShot2 () // en tre retningskuler skutt bossEnemy.shoot ("bane / til / bullet / sprite.png", bossPower, 400, shotAngle); bossEnemy.shoot ("path / to / bullet / sprite.png", bossPower, 400, shotAngle + 30); bossEnemy.shoot ("path / to / bullet / sprite.png", bossPower, 400, shotAngle - 30); funksjon bossShot3 () // for denne, jeg skal lage en sirkelskade, så kulene vil danne en sirkel for (var i = 0; i <= 9; i++) bossEnemy.shoot("path/to/bullet/sprite.png", bossPower, 400, 36 * i); // change the shotAngle
For å implementere flere kuletyper for spillerne å nyte, er alt du trenger å gjøre, å legge til riktig kode for hver belønning. Skape opprettelsen, akkurat som vi gjorde tidligere.
Du har fullført opplæringen min om hvordan du lager et Megaman-lignende Metroidvania-plattformspill i Construct 2. Resten bygger bare opp spillet ditt basert på det du har lært her for å gjøre det til ditt eget. Legg til flere fiendtlige typer, flere nivåer, powerups og mer. Lykke til og ha det moro.