Bruk Citrus til å bygge en enkel Flash Platformer

Har noen gang ønsket å lage en plattformspiller, men ikke så opptatt av å skrive hele koden fra bunnen av? Citrusmotoren eliminerer ikke koden helt, men det gjør det mye enklere, med mange nyttige 2D-spillfunksjoner bygget rett inn. I denne opplæringen bruker vi den til å bygge et enkelt plattformspill.


Trinn 1: Kort oversikt

I denne opplæringen bruker vi en populær Flash Game Engine, kalt Citrus, og en serie ActionScript-klasser for å skape et plattformspill.


Trinn 2: Flash-dokumentinnstillinger

Åpne Flash og opprett et 420x280px-dokument. Still inn bildefrekvensen til 30fps.


Trinn 3: Grensesnitt

Vi bruker disse flotte pikselgrafikkene fra Guillaume Moreau. Du kan laste dem ned fra opengameart.org.


Trinn 4: Bakgrunn

For bakgrunnen, endre scenefarge til # 99D9EA, eller bruk Rectangle Tool (R) til å tegne et rektangel av den fargen.


Trinn 5: Alert

Et varsel vises når spilleren fullfører nivået eller dør; det vil vise et spill over meldingen og poengsummen. Bruke Rektangelverktøy å opprette den og sette sin forekomst navn til AlertView. Merk av Eksporter for ActionScript boks og gi den samme klassenavn.

Det er mange andre objekter i spillet (for eksempel: et tittelskjermbilde, de forskjellige symbolene for hver sprite, terrenget). I stedet for å forklare hvordan du lager dem her, foreslår jeg at du laster ned kildefilene og ser på hvilke objekter som er i FLAs bibliotek. Du kan enten bruke de samme symbolene i ditt eget spill, eller opprette nye!


Trinn 6: Legge inn skrifttype

Vi bruker en bitmap skrift i spillet; siden vi skal bruke fonten dynamisk, må vi legge det inn i applikasjonen. Jeg bruker skrifter 04b11 og Arcade Classic.

Velg et dynamisk tekstfelt med skrifttypen din, og klikk på Bygg inn ... knappen i Egenskaper Panel.

Velg / legg til alle nødvendige tegn og klikk OK.


Trinn 7: Lyder

Vi bruker lydeffekter for å forbedre følelsen av spillet. Lyder brukt i dette eksemplet ble generert ved bruk av as3sfxr og er inkludert i kildefilene.


Trinn 8: TweenNano

Vi bruker en annen tween-motor fra standard som er inkludert i Flash. Dette vil øke ytelsen og være enklere å bruke.

Du kan laste ned TweenNano fra sitt offisielle nettsted.


Trinn 9: Citrusmotor

Vi bruker Citrus Engine til å drive spillet vårt.

Hva er Citrus Engine? Lær mer fra sitt nettsted:

Citrusmotoren er en profesjonell, skalerbar Flash-spillmotor bygget for industrikvalitets spill. Det er bygget på moderne Flash programmeringspraksis, slik at du kan fokusere på å gjøre spillet ditt fantastisk! Den leveres innebygd med en "platformer" startpakke, som du kan bruke til å enkelt lage fantastiske 2D sidescrolling spill.


Trinn 10: Sett opp Citrus Engine

Gå til nedlastingssiden og få de nødvendige filene. Åpne Flash-innstillinger, velg Action fra listen til venstre og klikk på ActionScript 3.0-innstillinger ... , Legg deretter banen til kildene som vist i bildet ovenfor.


Trinn 11: Sett dokumentklasse

Vi gjør interaktiv applikasjon ved å bruke en ekstern klasse. Legg til navnet sitt (Hoved) til Klasse felt i publisere delen av Eiendommer panel for å knytte FLA til hoveddokumentklassen.


Trinn 12: Opprett en ny ActionScript-klasse

Opprett en ny (Cmd + N) ActionScript 3.0-klasse og lagre den som Main.as i klassemappen din.


Trinn 13: Klassestruktur

Lag din grunnklassestruktur for å begynne å skrive koden din.

 pakke offentlig klasse Hoved offentlig funksjon Main (): void // constructor code

Trinn 14: Main.as

De Hoved klassen vil forberede sitrusmotoren til å håndtere første nivå.

 pakke import com.citrusengine.core.CitrusEngine; offentlig siste klasse Main utvider CitrusEngine offentlig sluttfunksjon Main (): void super (); state = new level (); 

Denne klassen utvider CitrusEngine-klassen og setter spillets "state" til Nivå, som er navnet på klassen som vil inneholde alle våre spillets oppførsel.


Trinn 15: Level.as

Statsklassen er en av kjerneklassene til Citrus Engine, og du bør utvide denne klassen for å lage spilllogikken på nivåene eller statene dine. I dette eksemplet Nivå klassen strekker seg Stat å skape spillets første nivå.

Opprett en ny (Cmd + N) ActionScript 3.0-klasse og lagre den som Level.as i klassemappen din.


Trinn 16: Påkrevde klasser

Dette er klassene vi må importere for våre Nivå klasse til jobb. De importere Direktivet gir eksternt definerte klasser og pakker tilgjengelig for koden din.

 importer flash.display.MovieClip; importer flash.display.Sprite; importer flash.events.MouseEvent; importer com.citrusengine.core.CitrusEngine; importer com.citrusengine.core.State; importer com.citrusengine.physics.Box2D; importer com.citrusengine.objects.platformer. *; importer com.citrusengine.objects. *; importer com.citrusengine.math.MathVector; importere flash.events.Event; importer flash.geom.Rectangle; importere flash.ui.Keyboard; importer flash.events.KeyboardEvent; importer flash.text.TextField; importer flash.text.TextFormat; importer com.greensock.TweenNano; importer com.greensock.easing.Expo; importer flash.net.navigateToURL; importere flash.net.URLRequest; importer flash.filters.GlowFilter; importer flash.filters.BitmapFilter;

Trinn 17: Variabler

Dette er variablene vi skal bruke; les kommentarene i koden for å få vite mer om dem. (Noen av navnene deres er selvforklarende, så det er ingen kommentar.)

 private var levelView: LevelView = new LevelView (); // Sprite fra biblioteket Private var helt: Hero; private var hjerter: Vector. = Ny Vector.(); privat var tf: TextFormat = ny TextFormat ('ArcadeClassic', 17, 0xFFFFFF, null, null, null, null, null, 'høyre'); privat var scoreTF: TextField = nytt TextField (); private var gemSnd: GemSnd = ny GemSnd (); // Snd = Sound private var goalSnd: GoalSnd = nytt GoalSnd (); private var hitSnd: HitSnd = ny HitSnd (); private var jumpSnd: JumpSnd = new JumpSnd (); private var loseSnd: LoseSnd = new LoseSnd (); privat var baddySnd: BaddySnd = ny BaddySnd ();

Trinn 18: Konstruktør

Konstruktøren er en funksjon som kjører når et objekt er opprettet fra en klasse, denne koden er den første som skal utføres når du lager en forekomst av et objekt, laster når spillet starter hvis en del av dokumentet klassen.

Det kaller de nødvendige funksjonene for å starte spillet. Kontroller disse funksjonene i de neste trinnene.

 offentlig sluttfunksjon Nivå (): void // Code

Trinn 19: Pausespill

Vi starter med å stoppe spillet; Dette forhindrer at motoren legger til grafikken mens nivåvisningssprittet er på scenen.

 offentlig sluttfunksjon Nivå (): void super (); // standard oppsettkode CitrusEngine.getInstance (). spiller = false; / / pause spillet faktisk

Trinn 20: Legg til nivåvisning

Dette vil legge til Level View-sprite til scenen, så vel som en muselytter for å fjerne den.

 overstyr offentlig funksjon initialiser (): void / * Nivå Start Vis * / addChild (levelView); levelView.addEventListener (MouseEvent.MOUSE_UP, startLevel); 

Trinn 21: Start Nivå

Den neste funksjonen går når nivåvisningen klikkes, og håndterer logikken for å starte spillet.

 privat sluttfunksjon startLevel (e: MouseEvent): void 

Trinn 22: Fjern nivåvisning

Denne koden ødelegger forekomsten av nivåvisning.

 levelView.removeEventListener (MouseEvent.MOUSE_UP, startLevel); removeChild (levelView); levelView = null;

Trinn 23: Start GameState (Unpause)

Nå pause spillet og initierer nivået.

 super.initialize (); CitrusEngine.getInstance (). Spiller = true;

Trinn 24: Start Box2D

Følgende kode starter Box2D-motoren som håndterer fysikken til Citrus Engine.

 var box2D: Box2D = ny Box2D ('Box2d'); legg (box2D); //box2D.visible = true; // uncomment for å se feilsøkingsgrafikkene i Box2D

Trinn 25: Legg til grafiske objekter

Disse linjene vil skape hele nivået, lese gjennom koden for å forstå Citrus Engine instantiation systemet (som er veldig enkelt!).

(Alle utsikt Egenskaper er klassenavnene på symbolene fra FLA-biblioteket: Bg, TerrainPart1, WaterX3, etc.)

 var leftWall: Platform = ny plattform ('LeftWall', bredde: 1, høyde: 280, x: 0, y: 110); legg (leftWall); var rightWall: Platform = ny plattform ('RightWall', bredde: 1, høyde: 280, x: 726, y: 100); legg (rightWall); var bg: CitrusSprite = ny CitrusSprite ('Bg', visning: Bg, x: 0, y: 20); legg (bg); var terreng1: Platform = ny plattform ('Terreng1', bredde: 422, høyde: 32, x: 211, y: 264, visning: TerrainPart1); legg (terrain1); var oneWay1: Platform = ny plattform ('OneWay1', bredde: 92, høyde: 32, x: 184, y: 232, en vei: sann, visning: OneWay1); legg (oneWay1); Var perle: Mynt = Ny mynt ('Gem', bredde: 11, høyde: 10, x: 186, y: 136, visning: Perle); legg (gem); var vann: Sensor = ny Sensor ('Vann', bredde: 92, høyde: 32, x: 468, y: 264, visning: WaterX3); legg (vann); var terrain2: Platform = ny plattform ('Terrain2', bredde: 214, høyde: 32, x: 621, y: 264, visning: TerrainPart2); legg (terrain2); var dårlig: Baddy = ny Baddy ('Baddy', x: 300, y: 200, leftBound: 250, rightBound: 350, visning: Enemy); legg (baddy); var movingPlatform: MovingPlatform = new MovingPlatform ('MP', bredde: 32, høyde: 8, x: 436, y: 232, startX: 436, startY: 232, endX: 500, endy: 232, visning: PlatformClip, hastighet : 0,9); legg (movingPlatform); var oneWay2: Platform = ny plattform ('OneWay2', bredde: 127, høyde: 32, x: 663, y: 232, oneWay: true, view: OneWay2); legg (oneWay2); var oneWay3: Platform = ny plattform ('OneWay3', bredde: 64, høyde: 32, x: 695, y: 200, en vei: sann, visning: OneWay3); legg (oneWay3); vardør: Sensor = ny sensor ('Dør', bredde: 20, høyde: 28, x: 695, y: 202, visning: Dør); legg (dør); helten = nyhelten, x: 30, y: 234, bredde: 19, høyde: 26, visning: HeroClip, jumpHeight: 9, maxVelocity: 2, hurtVelocityX: 2); legg (helt);

Som du ser, lager du i hvert tilfelle en forekomst av typen objekt du vil ha, og bruker parameterne til å spesifisere posisjon, størrelse, grafikk eller hud (dette er utsikt parameter) og andre nyttige elementer. Så legger vi det til Citrus-scenen ved hjelp av Legg til() metode.

La oss stoppe her for å gjøre en rask test og sørge for at vår spillkode fungerer:

Husk at milepæler er inkludert i kildefilene, så hvis filmen din av en eller annen grunn ikke etterligner denne, ta en titt på kilden for å se hva som kan forårsake det. (Og vær oppmerksom på at noen linjer må kommenteres, ettersom noen funksjoner ikke er opprettet ennå.)


Trinn 26: Legg til signaler

Citrus Engine bruker signaler til å håndtere hendelsestypeinteraksjon. Du kan lære mer om signaler på denne Activetuts + opplæringen.

 gem.onBeginContact.addOnce (funksjon (e: *) gemSnd.play (); scoreTF.text = String (int (scoreTF.text) + 50);); door.onBeginContact.addOnce (levelComplete); hero.onTakeDamage.add (hurtHero); hero.onGiveDamage.addOnce (killBaddy); hero.onJump.add (funksjon () jumpSnd.play ()); hero.onGiveDamage.addOnce (funksjon () baddySnd.play ());

Trinn 27: Stopp helten Animasjon

Vår helt MovieClip vil spille som standard med mindre vi hindrer det. Denne koden håndterer det, og du vil også lære hvordan du får tilgang til MovieClip som fungerer som kunsten til Citrus Object.

 this.view.getArt (helt) .content.stop (); //State(Level).SpriteView.SpriteArt.MovieClip.stop gameListeners (); addIndicators ();

Trinn 28: Spillelyttere

Denne koden legger til EnterFrame og Keyboard-lyttere som vil bli brukt i vårt spill. Du kan lese om de tilsvarende håndteringsfunksjonene i de neste trinnene.

 private endelige funksjon gameListeners (action: String = 'add'): void if (action == 'add') stage.addEventListener (Event.ENTER_FRAME, gameLogic); stage.addEventListener (KeyboardEvent.KEY_DOWN, animateWalk); stage.addEventListener (KeyboardEvent.KEY_UP, stopWalk);  else stage.removeEventListener (Event.ENTER_FRAME, gameLogic); stage.removeEventListener (KeyboardEvent.KEY_DOWN, animateWalk); stage.removeEventListener (KeyboardEvent.KEY_UP, stopWalk); 

Trinn 29: Legg til hjerter

Hjerter vil representere heltenes helse. Den neste koden legger til tre hjerter til scenen og lagrer dem i en vektor for å bruke dem senere utenfor denne funksjonen.

 privat endelig funksjon addIndicators (): void / * Hearts * / for (var jeg: int = 0; i < 3; i++)  var heart:Heart = new Heart(); heart.y = 5; heart.x = 5 + (i * heart.width); addChild(heart); hearts.push(heart); 

Trinn 30: Legg til poeng

Resultatet TextField er opprettet av denne koden. Vi bruker filtre for å legge til det svarte slaget rundt bokstavene.

 / * Score * / scoreTF.x = 320; scoreTF.defaultTextFormat = tf; scoreTF.text = '0'; var filter: BitmapFilter = ny GlowFilter (0, 1, 2, 2); var filter2: BitmapFilter = ny GlowFilter (0, 1, 1, 1); scoreTF.filters = [filter, filter2]; addChild (scoreTF); 

Trinn 31: Håndter kamera

Her setter vi opp kameraet, som vil følge vår helt, hvis posisjonen er forbi midten av scenen.

 privat endelig funksjon gameLogic (e: Event): void / * Håndter kamera * / hvis (hero.x> = stage.stageWidth * 0.5) view.setupCamera (helt, ny MathVector (stage.stageWidth * 0.5, 234) nytt rektangel (0, 0, 726, 228), null); 

Trinn 32: Sjekk etter høst

Denne koden sjekker om vår helt har falt i vannet, og i så fall spiller den tapende lyden og kaller et varsel.

 / * Sjekk om helten falt * / hvis (hero.y> scene.stageHeight) loseSnd.play (); alert ( 'miste'); 

Trinn 33: Animer Hero Walk

Våre helte-animasjoner startes når du trykker på venstre eller høyre piltast.

 privat endelig funksjon animateWalk (e: KeyboardEvent): void if (e.keyCode == 37 || e.keyCode == 39) this.view.getArt (hero) .contentplay (); 

Trinn 34: Stopp Walk Animation

Når tastene slippes, stopper animasjonen.

 privat endelig funksjon stopWalk (e: KeyboardEvent): void if (e.keyCode == 37 || e.keyCode == 39) this.view.getArt (hero) .content.gotoAndStop (1); 

La oss stoppe her for å gjøre en ny test og sjekke at vår spillkode fungerer:

Vær oppmerksom på at noen linjer har blitt kommentert, ettersom ikke alle funksjonene er opprettet ennå.

Husk at milepæler er inkludert i kildefilene, så hvis filmen din ikke av en eller annen grunn etterligner denne, ta en titt på kilden for å se hva som kan forårsake at.


Trinn 35: Hurt Hero

Helten skal ta skade hvis baddy berører ham; De neste linjene fjerner ett hjerte og spiller vondt. Et varsel kalles når helten er ute av helse.

 privat endelig funksjon hurtHero (): void removeChild (hjerter [hearts.length-1]); hearts.splice (hearts.length-1, 1); hitSnd.play (); if (hearts.length <= 0)  loseSnd.play(); alert('lose');  

Trinn 36: Drep Baddy

Du kan drepe en baddy ved å hoppe på den. Når dette skjer, øker poengsummen.

 privat endelig funksjon killBaddy (): void scoreTF.text = String (int (scoreTF.text) + 100); 

Trinn 37: Nivå Komplett

Nivået slutter når helten når døren. En lyd vil bli spilt og et varsel vil bli kalt; Du kan se advarselskoden i neste trinn.

 privat endelig funksjonsnivå Komplett (e: *): void goalSnd.play (); varsling(); 

Trinn 38: Alert

Denne funksjonen stopper spillet og viser spillet over meldingen, og legger også til en muselytter for å tilbakestille spillet når det klikkes.

 privat endelig funksjonalarm (gameState: String = 'win'): void gameListeners ('rmv'); CitrusEngine.getInstance (). Spiller = false; this.view.getArt (helt) .content.gotoAndStop (1); var varsel: AlertView = ny AlertView (); alert.x = scene.stageWidth * 0,5; alert.y = scene.stageHeight * 0,5; alert.scoreTF.text = scoreTF.text; alert.addEventListener (MouseEvent.MOUSE_UP, start på nytt); hvis (gameState == 'lose') alert.titleTF.text = 'Nivå mislyktes!';  addChild (advarsel); TweenNano.from (varsel, 0,6, scaleX: 0.2, scaleY: 0.2, ease: Expo.easeOut); 

Trinn 39: Start på nytt

Denne koden vil laste om SWF når spill over meldingen er klikket, gjenoppretter alle innledende verdier og vender tilbake til startskjermbildet.

 privat endelig funksjonstart (e: MouseEvent): void navigateToURL (ny URLRequest (stage.loaderInfo.url), '_level0'); 

Trinn 40: Endelig test

Vi er nå klare til å gjøre en endelig test på spillet vårt og kontroller at alt fungerer som forventet.


Konklusjon

Eksperimenter med denne kraftige spillmotoren og lag dine egne spill!

Jeg håper du likte denne opplæringen, takk for å lese!