Gebruik Citrus om een ​​Simple Flash Platformer te bouwen

Ooit een platformgame willen maken, maar niet al te graag alle code helemaal opnieuw willen schrijven? De Citrus Engine elimineert code niet volledig, maar het maakt het veel eenvoudiger, met veel nuttige 2D-gamefuncties ingebouwd. In deze tutorial gebruiken we het om een ​​eenvoudig platformspel te bouwen.


Stap 1: Kort overzicht

In deze tutorial gebruiken we een populaire Flash Game Engine, Citrus genaamd, en een reeks ActionScript-klassen om een ​​platformgame te maken.


Stap 2: Instellingen voor Flash-document

Open Flash en maak een 420x280px-document. Stel de beeldsnelheid in op 30 fps.


Stap 3: Interface

We gebruiken deze geweldige pixelafbeeldingen van Guillaume Moreau. Je kunt ze downloaden van opengameart.org.


Stap 4: Achtergrond

Verander voor de achtergrond de kleur van het werkgebied naar # 99D9EA, of gebruik het gereedschap Rechthoek (R) om een ​​rechthoek van die kleur te tekenen.


Stap 5: Alert

Een waarschuwing wordt getoond wanneer de speler het level voltooit of sterft; het toont een game over het bericht en de score. Gebruik de Rechthoekgereedschap om het te maken en de naam van het exemplaar in te stellen AlertView. Markeer de Exporteren voor ActionScript vak en geef het dezelfde klassenaam.

Er zijn veel andere objecten in het spel (bijvoorbeeld: een titelscherm, de verschillende symbolen voor elke sprite, het terrein). In plaats van uit te leggen hoe ik ze hier moet maken, raad ik aan de bronbestanden te downloaden en te kijken welke objecten zich in de FLA-bibliotheek bevinden. Je kunt dezelfde symbolen gebruiken in je eigen spel, of nieuwe maken!


Stap 6: sluit lettertype in

We gebruiken een bitmap-lettertype in het spel; omdat we het lettertype dynamisch gaan gebruiken, moeten we het in de applicatie insluiten. Ik gebruik de lettertypen 04b11 en Arcade Classic.

Selecteer een dynamisch tekstveld met het lettertype van uw voorkeur en klik op de Insluiten ... knop in de Eigenschappen paneel.

Selecteer / voeg alle benodigde tekens toe en klik op OK.


Stap 7: Geluiden

We gebruiken Geluidseffecten om het spelgevoel te verbeteren. De geluiden die in dit voorbeeld worden gebruikt, zijn gegenereerd met as3sfxr en zijn opgenomen in de bronbestanden.


Stap 8: TweenNano

We gebruiken een andere tween-engine dan de standaard in Flash. Dit verhoogt de prestaties en is gemakkelijker te gebruiken.

Je kunt TweenNano downloaden van de officiële website.


Stap 9: Citrus Engine

We zullen de Citrus Engine gebruiken om onze game van stroom te voorzien.

Wat is de Citrus Engine? Meer informatie op haar website:

De Citrus Engine is een professionele, schaalbare Flash-game-engine die is gebouwd voor spellen van industriekwaliteit. Het is gebaseerd op moderne Flash-programmeermethoden, zodat u zich kunt concentreren op het geweldig maken van uw spel! Het wordt ingebouwd met een "platformer" starterskit, waarmee je gemakkelijk fantastische 2D sidescrolling-spellen kunt maken.


Stap 10: Stel Citrus Engine in

Ga naar de downloadpagina en ontvang de benodigde bestanden. Open Flash-voorkeuren, selecteer ActionScript uit de lijst aan de linkerkant en klik op ActionScript 3.0-instellingen ... , voeg vervolgens het pad naar de bronnen toe zoals in de bovenstaande afbeelding.


Stap 11: Stel de documentklasse in

We zullen onze applicatie interactief maken door een externe klasse te gebruiken. Voeg de naam toe (Hoofd) naar de Klasse veld in de Publiceren deel van de eigenschappen panel om de FLA te koppelen aan de hoofddocumentklasse.


Stap 12: Maak een nieuwe ActionScript-klasse

Maak een nieuwe ActionScript 3.0-klasse (Cmd + N) en sla deze op als Main.as in je klasmap.


Stap 13: klassestructuur

Maak uw standaard klassenstructuur om te beginnen met het schrijven van uw code.

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

Stap 14: Main.as

De Hoofd klasse bereidt de Citrus Engine voor op het eerste niveau.

 pakket import com.citrusengine.core.CitrusEngine; publieke slotklasse Main verlengt CitrusEngine public final function Main (): void super (); state = nieuw niveau (); 

Deze klasse breidt de CitrusEngine-klasse uit en stelt de "status" van het spel in Niveau, dat is de naam van de klas die het gedrag van al onze spellen bevat.


Stap 15: Level.as

De klasse State is een van de kernklassen van Citrus Engine en u moet deze klasse uitbreiden om de spellogica van uw niveaus of staten te maken. In dit voorbeeld de Niveau klasse breidt zich uit Staat om het eerste niveau van het spel te creëren.

Maak een nieuwe ActionScript 3.0-klasse (Cmd + N) en sla deze op als Level.as in je klasmap.


Stap 16: Vereiste klassen

Dit zijn de klassen die we moeten importeren voor onze Niveau klasse om te werken. De importeren richtlijn maakt extern gedefinieerde klassen en pakketten beschikbaar voor uw code.

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

Stap 17: Variabelen

Dit zijn de variabelen die we zullen gebruiken; lees de opmerkingen in de code om meer over hen te weten. (Sommige van hun namen spreken voor zich, dus er is geen commentaar.)

 privé var-niveauBeeld: LevelView = nieuwe LevelView (); // sprite uit de bibliotheek private var hero: Hero; private var hearts: Vector. = nieuwe Vector.(); private var tf: TextFormat = new TextFormat ('ArcadeClassic', 17, 0xFFFFFF, null, null, null, null, null, 'right'); private var scoreTF: TextField = new TextField (); private var gemSnd: GemSnd = new GemSnd (); // Snd = Geluid private var goalSnd: GoalSnd = new GoalSnd (); private var hitSnd: HitSnd = new HitSnd (); private var jumpSnd: JumpSnd = new JumpSnd (); private var loseSnd: LoseSnd = new LoseSnd (); private var baddySnd: BaddySnd = new BaddySnd ();

Stap 18: Constructor

De constructor is een functie die wordt uitgevoerd wanneer een object wordt gemaakt op basis van een klasse, deze code is de eerste die wordt uitgevoerd wanneer u een exemplaar van een object maakt, wordt geladen zodra het spel start als onderdeel van de documentklasse.

Het roept de nodige functies op om het spel te starten. Controleer die functies in de volgende stappen.

 public final function Level (): void // Code

Stap 19: Game pauzeren

We beginnen met het pauzeren van het spel; dit voorkomt dat de engine de grafische weergave toevoegt terwijl de levelview-sprite zich op het podium bevindt.

 public final function Level (): void super (); // standaard setup-code CitrusEngine.getInstance (). spelen = false; // game eigenlijk pauzeren

Stap 20: Niveauweergave toevoegen

Hiermee wordt de sprit voor niveauweergave aan het podium toegevoegd, evenals een muisluisteraar om het te verwijderen.

 override public function initialize (): void / * Level Start View * / addChild (levelView); levelView.addEventListener (MouseEvent.MOUSE_UP, startLevel); 

Stap 21: Startniveau

De volgende functie wordt uitgevoerd wanneer op de niveauweergave wordt geklikt en de logica wordt verwerkt om het spel te starten.

 private finale functie startLevel (e: MouseEvent): void 

Stap 22: Levelweergave verwijderen

Deze code vernietigt de instantie Level View.

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

Stap 23: Start GameState (Unpause)

Nu pauzeren we het spel en initialiseren we het level.

 super.initialize (); CitrusEngine.getInstance (). Spelen = waar;

Stap 24: Start Box2D

De volgende code start de Box2D-engine die de physics van Citrus Engine verwerkt.

 var box2D: Box2D = nieuwe Box2D ('Box2d'); toe te voegen (Box2D); //box2D.visible = true; // uncomment om de foutopsporingsgrafiek van Box2D te zien

Stap 25: Grafische objecten toevoegen

Deze regels zullen het volledige niveau creëren, lees de code door om het Citrus Engine-instantiatiestelsel te begrijpen (wat heel gemakkelijk is!).

(Allemaal uitzicht eigenschappen zijn de klassenamen van symbolen uit de FLA-bibliotheek: bg, TerrainPart1, WaterX3, enz.)

 var leftWall: Platform = nieuw platform ('LeftWall', width: 1, height: 280, x: 0, y: 110); toe te voegen (leftWall); var rightWall: Platform = nieuw platform ('RightWall', width: 1, height: 280, x: 726, y: 100); toe te voegen (rightWall); var bg: CitrusSprite = nieuwe CitrusSprite ('Bg', view: Bg, x: 0, y: 20); toe te voegen (bg); var terrain1: Platform = nieuw platform ('Terrain1', width: 422, height: 32, x: 211, y: 264, view: TerrainPart1); toe te voegen (terrain1); var oneWay1: Platform = nieuw platform ('OneWay1', width: 92, height: 32, x: 184, y: 232, oneWay: true, view: OneWay1); toe te voegen (oneWay1); var gem: Coin = new Coin ('Gem', width: 11, height: 10, x: 186, y: 136, view: Gem); toe te voegen (gem); var water: Sensor = nieuwe sensor ('Water', breedte: 92, hoogte: 32, x: 468, y: 264, weergave: WaterX3); Voeg water toe); var terrain2: Platform = nieuw Platform ('Terrain2', width: 214, height: 32, x: 621, y: 264, view: TerrainPart2); toe te voegen (terrain2); var baddy: Baddy = nieuwe Baddy ('Baddy', x: 300, y: 200, leftBound: 250, rightBound: 350, view: Enemy); toe te voegen (Baddy); var movingPlatform: MovingPlatform = nieuw MovingPlatform ('MP', width: 32, height: 8, x: 436, y: 232, startX: 436, startY: 232, endX: 500, endY: 232, view: PlatformClip, speed : 0,9); toe te voegen (movingPlatform); var oneWay2: Platform = nieuw platform ('OneWay2', width: 127, height: 32, x: 663, y: 232, oneWay: true, view: OneWay2); toe te voegen (oneWay2); var oneWay3: Platform = nieuw platform ('OneWay3', width: 64, height: 32, x: 695, y: 200, oneWay: true, view: OneWay3); toe te voegen (oneWay3); var deur: Sensor = nieuwe sensor ('Deur', breedte: 20, hoogte: 28, x: 695, y: 202, weergave: Deur); toe te voegen (deur); hero = new Hero ('Hero', x: 30, y: 234, width: 19, height: 26, view: HeroClip, jumpHeight: 9, maxVelocity: 2, hurtVelocityX: 2); toe te voegen (held);

Zoals u kunt zien, maakt u in elk geval een instantie van het type object dat u wilt en gebruikt u de parameters om de positie, grootte, afbeelding of skin (dit is de uitzicht parameter) en andere nuttige elementen. Dan voegen we het toe aan de Citrusfase met behulp van de toevoegen() methode.

Laten we hier stoppen om een ​​snelle test uit te voeren en ervoor te zorgen dat onze spelcode werkt:

Vergeet niet dat de mijlpalen zijn opgenomen in de bronbestanden, dus als dit om een ​​of andere reden niet in dit bestand voorkomt, kijk dan eens naar de bron om te zien wat dat kan veroorzaken. (Houd er rekening mee dat sommige regels moeten worden becommentarieerd omdat sommige functies nog niet zijn gemaakt.)


Stap 26: Signalen toevoegen

Citrus Engine gebruikt signalen om interactie met het gebeurtenistype aan te kunnen. Je kunt meer leren over signalen op deze Activetuts + tutorial.

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

Stap 27: Stop Hero Animation

Onze Hero MovieClip wordt standaard afgespeeld, tenzij we dit voorkomen. Deze code verwerkt dat en u leert ook hoe u toegang krijgt tot de MovieClip die dient als de kunst voor uw Citrus-object.

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

Stap 28: Spelluisteraars

Deze code voegt de luisteraars van het EnterFrame en het toetsenbord toe die in onze game zullen worden gebruikt. U kunt in de volgende stappen over de bijbehorende afhandelingsfuncties lezen.

 private slotfunctie gameListeners (actie: 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); 

Stap 29: Harten toevoegen

Harten vertegenwoordigen de gezondheid van onze held. De volgende code voegt drie harten toe aan het podium en slaat ze op in een Vector om ze later buiten deze functie te gebruiken.

 private laatste functie addIndicators (): void / * Hearts * / for (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); 

Stap 30: Score toevoegen

Het Score TextField wordt gemaakt door deze code. We gebruiken filters om de zwarte streek rond de letters toe te voegen.

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

Stap 31: Behandel Camera

Hier zetten we de camera op, die onze held zal volgen als zijn positie voorbij het midden X van het podium is.

 privé-eindfunctie gameLogic (e: Event): void / * Camera verwerken * / if (hero.x> = stage.stageWidth * 0.5) view.setupCamera (hero, nieuwe MathVector (stage.stageWidth * 0.5, 234), nieuwe Rectangle (0, 0, 726, 228), null); 

Stap 32: Controleer op herfst

Deze code controleert of onze held in het water is gevallen en zo ja, speelt hij het verlossende geluid af en roept hij een waarschuwing.

 / * Controleer of de held viel * / if (hero.y> stage.stageHeight) loseSnd.play (); alert ( 'verliezen'); 

Stap 33: Animate Hero Walk

Onze heldenloopanimatie wordt gestart wanneer de linker- of rechterpijltoetsen worden ingedrukt.

 private finale functie animateWalk (e: KeyboardEvent): void if (e.keyCode == 37 || e.keyCode == 39) this.view.getArt (hero) .content.play (); 

Stap 34: Stop Walk-animatie

Wanneer de toetsen worden losgelaten, stopt de animatie.

 private finale functie stopWalk (e: KeyboardEvent): void if (e.keyCode == 37 || e.keyCode == 39) this.view.getArt (hero) .content.gotoAndStop (1); 

Laten we hier stoppen om nog een test uit te voeren en controleren of onze spelcode werkt:

Houd er nogmaals rekening mee dat sommige regels zijn becommentarieerd omdat nog niet alle functies zijn gemaakt.

Vergeet niet dat de mijlpalen zijn opgenomen in de bronbestanden, dus als dit om een ​​of andere reden niet in dit bestand wordt nagebootst, kijk dan eens naar de bron om te zien wat dat zou kunnen veroorzaken.


Stap 35: Held Held

De held moet schade oplopen als de slechterik hem raakt; de volgende regels verwijderen één hart en spelen het gewonde geluid. Er wordt een melding gegeven wanneer de held zijn gezondheid verliest.

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

Stap 36: Dood Baddy

Je kunt een slechterik doden door erop te springen. Wanneer dit gebeurt, neemt de score toe.

 private final-functie killBaddy (): void scoreTF.text = String (int (scoreTF.text) + 100); 

Stap 37: Level voltooid

Het level eindigt wanneer de held de deur bereikt. Er wordt een geluid afgespeeld en er wordt een melding gegeven; je kunt de waarschuwingscode zien in de volgende stap.

 private final function levelComplete (e: *): void goalSnd.play (); alert (); 

Stap 38: Alert

Deze functie stopt het spel en toont het game-overbericht en voegt ook een muisluisteraar toe om het spel opnieuw in te stellen wanneer erop wordt geklikt.

 private laatste functie alert (gameState: String = 'win'): void gameListeners ('rmv'); CitrusEngine.getInstance (). Spelen = false; this.view.getArt (held) .content.gotoAndStop (1); var alert: AlertView = nieuwe AlertView (); alert.x = stage.stageWidth * 0.5; alert.y = stage.stageHeight * 0.5; alert.scoreTF.text = score TF.text; alert.addEventListener (MouseEvent.MOUSE_UP, restart); if (gameState == 'lose') alert.titleTF.text = 'Level Failed!';  addChild (waarschuwing); TweenNano.from (alert, 0.6, scaleX: 0.2, scaleY: 0.2, ease: Expo.easeOut); 

Stap 39: start opnieuw op

Met deze code wordt de SWF opnieuw geladen wanneer op het bericht wordt geklikt, waarbij alle oorspronkelijke waarden worden hersteld en het oorspronkelijke scherm wordt weergegeven.

 privé laatste functie opnieuw opstarten (e: MouseEvent): void navigateToURL (nieuwe URLRequest (stage.loaderInfo.url), '_level0'); 

Stap 40: Laatste test

We zijn nu klaar om een ​​laatste test voor onze game uit te voeren en te controleren of alles werkt zoals verwacht.


Conclusie

Experimenteer met deze krachtige game-engine en maak je eigen games!

Ik hoop dat je deze tutorial leuk vond, bedankt voor het lezen!