Använd Citrus för att bygga en enkel Flash Platform

Har du någonsin velat göra en plattformsspelare, men inte så angelägen om att skriva hela koden från början? Citrusmotorn eliminerar inte koden helt, men det gör det mycket enklare, med massor av användbara 2D-spelfunktioner byggda in i. I den här handledningen använder vi den för att bygga ett enkelt plattformsspel.


Steg 1: Kortfattad översikt

I denna handledning använder vi en populär Flash Game Engine, kallad Citrus, och en serie ActionScript-klasser för att skapa ett plattformspelspel.


Steg 2: Flash-dokumentinställningar

Öppna Flash och skapa ett 420x280px-dokument. Ställ in bildfrekvensen till 30fps.


Steg 3: Gränssnitt

Vi använder dessa stora pixelgrafik av Guillaume Moreau. Du kan hämta dem från opengameart.org.


Steg 4: Bakgrund

För bakgrunden, ändra scenfärgen till # 99D9EA, eller använd Rektangelverktyget (R) för att rita en rektangel av den färgen.


Steg 5: Alert

En varning visas när spelaren fullbordar nivån eller dör. det kommer att visa ett spel över meddelandet och poängen. Använd Rektangelverktyg att skapa den och ange dess förekomstnamn till AlertView. Markera Exportera till ActionScript lådan och ge det samma klassnamn.

Det finns många andra objekt i spelet (till exempel: en titelskärm, de olika symbolerna för varje sprite, terrängen). Istället för att förklara hur man skapar dem här föreslår jag att du laddar ned källfilerna och tittar på vilka objekt som finns i FLA: s bibliotek. Du kan antingen använda samma symboler i ditt eget spel eller skapa nya!


Steg 6: Bädda in teckensnitt

Vi använder en bitmap-typsnitt i spelet. Eftersom vi ska använda teckensnittet dynamiskt måste vi bädda in det i applikationen. Jag använder teckensnitt 04b11 och Arcade Classic.

Välj ett dynamiskt textfält med typsnittet för din inställning och klicka på Bädda in… knapp i Egenskaper Panel.

Välj / lägg till alla nödvändiga tecken och klicka ok.


Steg 7: Ljud

Vi använder Sound Effects för att förbättra känslan av spelet. Ljuden som användes i detta exempel genererades med as3sfxr och ingår i källfilerna.


Steg 8: TweenNano

Vi använder en annan tween-motor från standard som ingår i Flash. Detta kommer att öka performance samt vara lättare att använda.

Du kan ladda ner TweenNano från sin officiella hemsida.


Steg 9: Citrusmotor

Vi använder Citrus Engine för att driva vårt spel.

Vad är Citrus Engine? Läs mer från sin hemsida:

Citrusmotorn är en professionell, skalbar Flash-spelmotor som är byggd för industrikvalitetsspel. Den bygger på moderna Flash-programmeringspraxis, så att du kan fokusera på att göra ditt spel fantastiskt! Den kommer inbyggd med ett "platformer" startpaket, som du kan använda för att enkelt skapa fantastiska 2D-sidorulle-spel.


Steg 10: Ställ in Citrusmotorn

Gå till hämtningssidan och få de nödvändiga filerna. Öppna Flash-inställningar, välj Action från listan till vänster och klicka på ActionScript 3.0-inställningar ... , Lägg sedan till sökvägen till källorna enligt bilden ovan.


Steg 11: Ange dokumentklass

Vi gör vår applikationsinteraktiv genom att använda en extern klass. Lägg till sitt namn (Huvudsaklig) till Klass fält i Publicera del av Egenskaper panel för att associera FLA med huvuddokumentklassen.


Steg 12: Skapa en ny ActionScript-klass

Skapa en ny (Cmd + N) ActionScript 3.0-klass och spara den som Main.as i din klassmapp.


Steg 13: Klassstruktur

Skapa din grundläggande klassstruktur för att börja skriva din kod.

 paket public class Main public function Main (): void // constructor code

Steg 14: Main.as

De Huvudsaklig klassen kommer att förbereda Citrus Engine för att hantera första nivån.

 paket import com.citrusengine.core.CitrusEngine; offentliga slutklassen Main utökar CitrusEngine public final function Main (): void super (); state = new Level (); 

Denna klass utökar CitrusEngine-klassen och sätter spelets "tillstånd" till Nivå, vilket är namnet på den klass som kommer att innehålla alla våra spelets beteende.


Steg 15: Level.as

Statsklassen är en av kärnklasserna i Citrus Engine, och du bör förlänga den här klassen för att skapa spellogiken på dina nivåer eller stater. I det här exemplet är Nivå klassen sträcker sig stat för att skapa spelets första nivå.

Skapa en ny (Cmd + N) ActionScript 3.0-klass och spara den som Level.as i din klassmapp.


Steg 16: Obligatoriska klasser

Det här är de klasser som vi behöver importera till vårt Nivå klass till jobbet. De importera Direktivet gör externt definierade klasser och paket tillgängliga för din kod.

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

Steg 17: Variabler

Dessa är de variabler vi ska använda; Läs kommentarerna i koden för att få veta mer om dem. (Några av deras namn är självförklarande, så det finns ingen kommentar.)

 privat var levelView: LevelView = ny LevelView (); // Sprite från biblioteket Private var hjälte: Hero; Private Var Hjärtan: Vector. = ny vektor.(); privat var tf: TextFormat = ny TextFormat ('ArcadeClassic', 17, 0xFFFFFF, null, null, null, null, null, 'right'); privat var poängTF: TextField = nytt TextField (); privat var gemSnd: GemSnd = ny GemSnd (); // Snd = Ljud privat var målSnd: GoalSnd = nytt GoalSnd (); privat var hitSnd: HitSnd = new HitSnd (); privat var jumpSnd: JumpSnd = new JumpSnd (); privat var loseSnd: LoseSnd = new LoseSnd (); privat var baddySnd: BaddySnd = ny BaddySnd ();

Steg 18: Konstruktör

Konstruktorn är en funktion som körs när ett objekt skapas från en klass, den här koden är den första som ska utföras när du gör en förekomst av ett objekt, laddas när spelet börjar om en del av dokumentklassen.

Det kallar de nödvändiga funktionerna för att starta spelet. Kontrollera de funktionerna i nästa steg.

 offentlig slutlig funktion Nivå (): void // Code

Steg 19: Pausspel

Vi börjar med att pausa spelet. Detta förhindrar att motorn lägger till grafiken medan Level View-sprite är på scenen.

 Offentlig slutfunktionsnivå (): void super (); // standardinställningskod CitrusEngine.getInstance () .play = false; // pausa spel egentligen

Steg 20: Lägg till nivåvy

Detta lägger till nivån Visa sprite till scenen, såväl som en muslyttare för att ta bort den.

 åsidosätta allmän funktion starta (): void / * Level Start View * / addChild (levelView); levelView.addEventListener (MouseEvent.MOUSE_UP, startLevel); 

Steg 21: Startnivå

Nästa funktion körs när nivåvyn klickas och hanterar logiken för att starta spelet.

 privat slutlig funktion startLevel (e: MouseEvent): void 

Steg 22: Ta bort nivåvisning

Den här koden förstör Nivåvyn-förekomsten.

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

Steg 23: Starta GameState (Unpause)

Nu plockar vi upp spelet och initierar nivån.

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

Steg 24: Starta Box2D

Följande kod startar Box2D-motorn som hanterar Citrus Engine-fysiken.

 var box2D: Box2D = ny Box2D ('Box2d'); lägg (Box2D); //box2D.visible = true; // uncomment att se felsökningsgraden för Box2D

Steg 25: Lägg till grafiska objekt

Dessa linjer kommer att skapa hela nivån, läs igenom koden för att förstå Citrus Engine instantiation-systemet (vilket är väldigt enkelt!).

(Allt se egenskaper är klassnamnen på symboler från FLA-biblioteket: Bg, TerrainPart1, WaterX3, etc.)

 var leftWall: Platform = ny plattform ('LeftWall', bredd: 1, höjd: 280, x: 0, y: 110); lägg (leftWall); var rightWall: Platform = ny plattform ('RightWall', bredd: 1, höjd: 280, x: 726, y: 100); lägg (rightWall); var bg: CitrusSprite = ny CitrusSprite ('Bg', visa: Bg, x: 0, y: 20); lägg (bg); var terrain1: Platform = ny plattform ('Terrain1', bredd: 422, höjd: 32, x: 211, y: 264, vy: TerrainPart1); lägg (terrain1); var oneWay1: Platform = ny plattform ('OneWay1', bredd: 92, höjd: 32, x: 184, y: 232, oneWay: true, view: OneWay1); lägg (oneWay1); Var Gem: Mynt = Ny Mynt ("Gem", Bredd: 11, Höjd: 10, X: 186, Y: 136, Visa: Gem); lägg (pärla); var vatten: Sensor = ny sensor ("Vatten", bredd: 92, höjd: 32, x: 468, y: 264, vy: WaterX3); Lägg till vatten); var terrain2: Platform = ny plattform ('Terrain2', bredd: 214, höjd: 32, x: 621, y: 264, vy: TerrainPart2); lägg (terrain2); var dålig: Baddy = ny Baddy ("Baddy", x: 300, y: 200, vänsterBound: 250, rightBound: 350, view: Enemy); lägg (baddy); var movingPlatform: MovingPlatform = new MovingPlatform ("MP", bredd: 32, höjd: 8, x: 436, y: 232, startX: 436, startY: 232, endX: 500, endY: 232, visa: PlatformClip, hastighet : 0,9); lägg (movingPlatform); var oneWay2: Platform = ny plattform ('OneWay2', bredd: 127, höjd: 32, x: 663, y: 232, oneWay: true, view: OneWay2); lägg (oneWay2); var oneWay3: Platform = ny plattform ('OneWay3', bredd: 64, höjd: 32, x: 695, y: 200, enväg: sant, visa: OneWay3); lägg (oneWay3); var dörr: Sensor = ny sensor ("dörr", bredd: 20, höjd: 28, x: 695, y: 202, visa: dörr); lägg (dörr); hjälte = ny hjälte, x: 30, y: 234, bredd: 19, höjd: 26, visa: HeroClip, jumpHeight: 9, maxVelocity: 2, hurtVelocityX: 2); lägg (hjälte);

Som du kan se skapar du i varje fall en instans av den typ av objekt du vill ha och använder parametrarna för att ange position, storlek, grafik eller hud (det här är se parameter) och andra användbara element. Sedan lägger vi till citrusfasen med hjälp av Lägg till() metod.

Låt oss stanna här för att göra ett snabbtest och se till att vår spelkod fungerar:

Kom ihåg att milstolparna ingår i källfilerna, så om din fil inte av någon anledning efterliknar den här tittar du på källan för att se vad som kan orsaka det. (Och kom ihåg att vissa rader måste kommenteras eftersom vissa funktioner inte har skapats än.)


Steg 26: Lägg till signaler

Citrus Engine använder signaler för hantering av händelsestypsinteraktion. Du kan lära dig mer om signaler på denna Activetuts + handledning.

 gem.onBeginContact.addOnce (funktion (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 (function () jumpSnd.play ()); hero.onGiveDamage.addOnce (function () baddySnd.play ());

Steg 27: Stoppa hjälteanimering

Vår hjälte MovieClip spelar som standard om vi inte förhindrar det. Denna kod hanterar det, och du kommer också att lära dig hur du får tillgång till MovieClip som fungerar som konsten för ditt Citrus Object.

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

Steg 28: Spelare

Denna kod lägger till EnterFrame och Keyboard-lyssnare som kommer att användas i vårt spel. Du kan läsa om motsvarande hanterarfunktioner i nästa steg.

 privata slutliga funktionen spellistor (åtgärd: String = 'add'): void if (action == 'add') stage.addEventListener (Event.ENTER_FRAME, gameLogic); stage.addEventListener (KeyboardEvent.KEY_DOWN, animateWalk); stage.addEventListener (KeyboardEvent.KEY_UP, stopWalk);  annars stage.removeEventListener (Event.ENTER_FRAME, gameLogic); stage.removeEventListener (KeyboardEvent.KEY_DOWN, animateWalk); stage.removeEventListener (KeyboardEvent.KEY_UP, stopWalk); 

Steg 29: Lägg till hjärtan

Hjärtan kommer att representera vår hjältes hälsa. Nästa kod lägger till tre hjärtan till scenen och lagrar dem i en vektor för att använda dem senare utanför denna funktion.

 privat slutlig funktion addIndicators (): void / * Hearts * / för (var i: int = 0; i < 3; i++)  var heart:Heart = new Heart(); heart.y = 5; heart.x = 5 + (i * heart.width); addChild(heart); hearts.push(heart); 

Steg 30: Lägg till poäng

Resultatet TextField skapas av denna kod. Vi använder filter för att lägga till den svarta stroke runt bokstäverna.

 / * Poäng * / poängTF.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); 

Steg 31: Hantera kameran

Här ställer vi upp kameran, som kommer att följa vår hjälte om dess position är förbi stadens mitt X.

 privat slutlig funktion gameLogic (e: Event): void / * Hantera kamera * / om (hero.x> = stage.stageWidth * 0.5) view.setupCamera (hjälte, ny MathVector (stage.stageWidth * 0.5, 234) ny rektangel (0, 0, 726, 228), null); 

Steg 32: Kontrollera efter fall

Denna kod kontrollerar om vår hjälte har fallit i vattnet, och i så fall spelar det förlorat ljud och kallar en varning.

 / * Kontrollera om hjälten föll * / om (hero.y> stage.stageHeight) loseSnd.play (); alert ( 'förlora'); 

Steg 33: Animera hjältevandring

Vår hjältevandringsanimering startas när vänster eller höger piltangentryck trycks in.

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

Steg 34: Stoppa Walk Animation

När tangenterna släpps stannar animeringen.

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

Låt oss stanna här för att göra ett annat test och kontrollera att vår spelkod fungerar:

Tänk på att vissa rader har kommenterats eftersom inte alla funktioner har skapats än.

Kom ihåg att milstolparna ingår i källfilerna, så om din fil inte av någon anledning efterliknar den här tittar du på källan för att se vad som kan orsaka det.


Steg 35: Skynda hjälten

Hjälte ska ta skada om baddyen berör honom; Nästa rader tar bort ett hjärta och spelar sårad ljud. En varning heter när hjälten är ute av hälsa.

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

Steg 36: Döda Baddy

Du kan döda en baddy genom att hoppa på den. När detta händer stiger poängen.

 privat slutlig funktion killBaddy (): void scoreTF.text = String (int (scoreTF.text) + 100); 

Steg 37: Nivå Komplett

Nivån slutar när hjälten når dörren. Ett ljud kommer att spelas upp och en varning kommer att ringas; Du kan se varningskoden i nästa steg.

 privat slutlig funktionsnivå Komplettera (e: *): void goalSnd.play (); varna(); 

Steg 38: Alert

Denna funktion kommer att stoppa spelet och visa spelet över meddelandet, och lägger också till en muslistor för att återställa spelet när det klickas.

 privat slutfunktionsvarning (gameState: String = 'win'): void gameListeners ('rmv'); CitrusEngine.getInstance () .spelar = false; this.view.getArt (hjälte) .content.gotoAndStop (1); var alert: AlertView = ny AlertView (); alert.x = stage.stageWidth * 0,5; alert.y = stage.stageHeight * 0.5; alert.scoreTF.text = scoreTF.text; alert.addEventListener (MouseEvent.MOUSE_UP, starta om); om (gameState == 'förlora') alert.titleTF.text = 'Nivå misslyckades!';  addChild (alert); TweenNano.from (alert, 0.6, scaleX: 0.2, scaleY: 0.2, lätthet: Expo.easeOut); 

Steg 39: Starta om

Den här koden kommer att ladda om SWF när spelet över meddelandet klickas, återställer alla initialvärden och återgår till startskärmen.

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

Steg 40: Slutprov

Vi är nu redo att göra ett slutprov på vårt spel och kontrollera att allt fungerar som förväntat.


Slutsats

Experimentera med denna kraftfulla spelmotor och skapa dina egna spel!

Jag hoppas att du gillade den här handledningen, tack för att du läste!