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.
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.
Öppna Flash och skapa ett 420x280px-dokument. Ställ in bildfrekvensen till 30fps.
Vi använder dessa stora pixelgrafik av Guillaume Moreau. Du kan hämta dem från opengameart.org.
För bakgrunden, ändra scenfärgen till # 99D9EA, eller använd Rektangelverktyget (R) för att rita en rektangel av den färgen.
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!
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.
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.
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.
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.
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.
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.
Skapa en ny (Cmd + N) ActionScript 3.0-klass och spara den som Main.as i din klassmapp.
Skapa din grundläggande klassstruktur för att börja skriva din kod.
paket public class Main public function Main (): void // constructor code
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.
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.
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;
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 ();
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
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
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);
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
Den här koden förstör Nivåvyn-förekomsten.
levelView.removeEventListener (MouseEvent.MOUSE_UP, startLevel); removeChild (levelView); levelView = null;
Nu plockar vi upp spelet och initierar nivån.
super.initialize (); CitrusEngine.getInstance (). Playing = true;
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
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.)
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 ());
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 ();
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);
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);
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);
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);
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');
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 ();
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.
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');
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);
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();
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);
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');
Vi är nu redo att göra ett slutprov på vårt spel och kontrollera att allt fungerar som förväntat.
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!