Twee keer per maand bekijken we enkele van onze favoriete lezers uit de geschiedenis van Activetuts +. Deze tutorial is lang geleden in mei 2009 voor het eerst gepubliceerd.
In deze tut zal ik beschrijven hoe je een standaard 3D-scène kunt maken met behulp van de standaard 3D-opties van Flash Player 10. Vervolgens zal ik uitleggen hoe je interactiviteit toevoegt aan de elementen en een basispong-spel opzet. Laten we gaan?
Laten we het podium opzetten en de 3D-scène creëren. In een gewoon pongspel botst de bal van de boven- en onderkant van het scherm, maar aangezien we wat perspectief aan de mix toevoegen, moeten we ook deze randen opgeven. Er zijn vijf filmclips nodig: de vloer en de vier muren (waarvan er twee daadwerkelijk paddles zijn). De registratiepunten van de muren moeten allemaal tegen de vloer liggen. U kunt al deze eenvoudig maken met het gereedschap Rechthoek of een geïmporteerde bitmapafbeelding gebruiken (denk eraan om "Sta smoothing" in de eigenschappen in te schakelen). Maak een filmclip uit elke muur en geef ze een instantienaam (ik noemde ze "wallTop", "wallBottom", "wallLeft" en "wallRight" en zal daar later naar verwijzen). Noem de achtergrond "verdieping".
Selecteer alle muren en de vloer, maak er een grote filmclip van en noem deze "bg".
Om de score later weer te geven, hebben we ook twee dynamische tekstvelden nodig. Als je deze in de filmclip "bg" plaatst, hebben ze ook het 3D-perspectief. Noem deze "scoreLeft" en "scoreRight" en embed vervolgens de fonts.
Maak de bal met het ovale en verloopgereedschap op het podium. Plaats de bal niet in de filmclip "bg" of deze wordt door het perspectief vervormd. We geven de bal geen echte 3D-eigenschappen, maar laten het doen alsof het 3D was. Plaats de bal in het midden van het scherm en geef het een instantienaam zoals "bal".
Nu gaan we de 3D-scène instellen met behulp van de nieuwe eigenschappen rotationX, Y en Z die zijn toegevoegd in Flash Player 10. Voordat we een ActionScript-code kunnen uitvoeren, moeten we echter de documentklasse maken. Maak een lege Main.as en vul deze met de onderstaande code.
pakket import flash.display.MovieClip; public class Main breidt MovieClip uit public function Main (): void // Vervang deze opmerking door code later
Om dit als de hoofdklasse te gebruiken, kunnen we "Hoofd" in het invoervak "Class:" van de documenteigenschappen invullen.
Laten we de rotatie uitproberen. Voeg deze regel toe aan de functie Main () om alles een beetje perspectief te geven:
bg.rotationX = -30;
Zoals u kunt zien, worden alle filmclips nu 30 × rond de x-as gedraaid.
Elk van de wanden heeft een draaiing nodig om op te staan. Zoals u kunt zien, heb ik ook de overvloeimodus van de wanden gewijzigd in "scherm", zodat de hellingen er beter uitzien. De volgende code is alleen bedoeld als voorbeeld, omdat we deze in de volgende stap vervangen door tweens (dus haal hem na testen).
bg.wallTop.rotationX = 90; bg.wallBottom.rotationX = -90; bg.wallRight.rotationY = 90; bg.wallLeft.rotationY = -90;
Om een effect aan de muren toe te voegen, moeten we eerst een startknop maken. Maak een filmclip met de tekst "Klik hier om te starten". Nogmaals, je kunt dit in "bg" plaatsen als je wilt dat het ook perspectief heeft. Geef het een instantienaam zoals "startText". We kunnen er nu in de code naar verwijzen en er een eventlistener aan toevoegen. Stel ook buttonMode in op true, wat een handcursor oplevert als de muis over de knop zweeft. Wanneer erop wordt geklikt, wordt de startfunctie aangeroepen en is de knop verborgen. We verbergen ook de muisaanwijzer omdat de gebruiker de rechterwand met de muis bedient.
public function Main (): void bg.rotationX = -30; startText.addEventListener (MouseEvent.MOUSE_UP, start); startText.buttonMode = true; start privéfunctie (_e: Event): void startText.buttonMode = false; startText.visible = false; Mouse.hide (); // Dit bevat de tweens
We kunnen TweenLite gebruiken om de wanden van 0 tot 90 maal te roteren. Natuurlijk zal elke tweening-engine het doen, maar ik geef de voorkeur aan deze. De volgende code tweent de muren binnen 2 seconden en gebruikt de versnellingsfunctie "Bounce.easeOut". Om de alfawaarde van de wanden ook tween te geven, moeten we deze eerst op 0 zetten. U kunt dit in Flash doen door de alpha in te stellen op 0 in de kleurinstellingen. Nadat deze tweens zijn voltooid, moet het spel beginnen, dus voeg een eigenschap "onComplete" toe aan een van de tweens en voeg er een functienaam aan toe (u kunt dit laten staan voor testen omdat de functie nog niet bestaat).
persoonlijke functie start (_e: Event): void startText.buttonMode = false; startText.visible = false; Mouse.hide (); nieuwe TweenLite (bg.wallRight, 2, rotationY: 90, alpha: 1, ease: Bounce.easeOut); nieuwe TweenLite (bg.wallLeft, 2, rotationY: -90, alpha: 1, ease: Bounce.easeOut); nieuwe TweenLite (bg.wallTop, 2, rotationX: 90, alpha: 1, ease: Bounce.easeOut); nieuwe TweenLite (bg.wallBottom, 2, rotationX: -90, alpha: 1, ease: Bounce.easeOut, onComplete: goBall);
Voordat we het spel daadwerkelijk kunnen starten, moeten we interactiviteit aan de linker- en rechtermuren en de bal toevoegen. Laten we beginnen met de paddle van de speler. Maak een nieuwe klasse "Player.as" en voeg de volgende code toe.
pakket import flash.display.MovieClip; import flash.events.MouseEvent; openbare klasse Player breidt MovieClip uit public function Player (): void stage.addEventListener (MouseEvent.MOUSE_MOVE, moveAlong); private function moveAlong (_e: MouseEvent): void var mousePos: Number = stage.mouseY - parent.y; if (mousePos < 0 ) y = 0; else if ( mousePos > 340) y = 340; anders y = mousePos;
In de constructor (de Player-functie) voegen we een eventlistener toe aan het podium om te controleren wanneer de muis beweegt en de functie "moveAlong" te bellen wanneer dat het geval is. In de functie moveAlong berekenen we de lokale positie van de muis (alleen de y-positie omdat we alleen verticaal bewegen). Vervolgens controleren we of de muis buiten de grenzen raakt en de positie opnieuw instellen als dat het geval is. Ik vond de 340-waarde met vallen en opstaan omdat "bovenliggende hoogte - hoogte" de verwachte waarde niet retourneert wanneer we 3D-perspectief gebruiken.
Wijzig vervolgens de eigenschappen van de wallRight filmclip; vink "Exporteren voor ActionScript" aan en stel de klasse in op "Speler". Laat "Base Class" leeg.
Het maken van de AI lijkt veel op het maken van de speler. Alleen deze keer laten we hem naar de y-waarde van de bal bewegen, maar met een iets lagere snelheid dan de bal. Maak een andere klasse "AI.as":
pakket import flash.display.MovieClip; import flash.events.Event; public class AI breidt MovieClip public function AI () uit: void addEventListener (Event.ENTER_FRAME, followBall); private functie followBall (_e: Event): void var ball: MovieClip = MovieClip (parent.parent) .ball; if (ball.xspeed || ball.yspeed) var newy: Number = ball.y - height; if (nieuw> 345) newy = 345; als (y <= newy ) y += 9; else y -= 9;
Eerst moeten we naar de bal kunnen verwijzen. Omdat de wallLeft-filmclip zich in de filmclip "bg" bevindt, verwijst "parent" naar "bg". Om deze reden moeten we "parent.parent" gebruiken. De eerste "als" -verklaring controleert of de bal een x- of y-snelheid heeft. Dit zijn openbare variabelen van de bal die we later zullen instellen. De controle voorkomt dat de AI beweegt voordat het spel start. De "newy" -waarde houdt de y-waarde van de bal minus de hoogte van wallLeft vast. Dit is de waarde waarnaar het moet bewegen om de bal te raken. Zoals eerder, verander de klasse van wallLeft in "AI".
De bal heeft de meeste functionaliteit nodig: deze moet rondbewegen, van muren afketsen, een hit met de paddles controleren en zijn eigen diepte bijwerken, omdat het geen 3D-object is.
pakket import flash.display.MovieClip; import flash.events.Event; public class Ball breidt MovieClip uit public var xspeed: Number = 0; public var yspeed: Number = 0; public function Ball (): void public function start (): void xspeed = -12; yspeed = 12; addEventListener (Event.ENTER_FRAME, moveBall); private functie moveBall (_e: Event): void depth (); botsing(); x + = xspeed; y + = yspeed; diepte privéfunctie (): void // schaal de bal op basis van de y-positie botsing met persoonlijke functie (): void // Laat de bal stuiteren
Eerst geven we de bal een x en yspeed. Deze zijn ingesteld op openbaar, zodat we van andere objecten kunnen controleren of de bal beweegt. Voeg vervolgens een "onenterframe" -event toe aan de startfunctie. Wanneer de startfunctie wordt genoemd, zal de bal elk frame gaan bewegen. Ik gaf de bal een beginsnelheid van 12 pixels per frame. Je kunt dit veranderen om het spel te versnellen, maar je zou ook de framerate kunnen verhogen. De functie moveBall maakt de x- en y-waarden van de bal feitelijk hoger op basis van de x- en yspeed. Het roept ook de diepte- en botsfuncties op elk frame aan.
Omdat de bal geen 3D-object is en geen z-waarde heeft, zal deze niet kleiner lijken als de y-waarde verandert. Hoe hoger de bal op het scherm komt (lage y-waarde), hoe kleiner deze moet zijn. We kunnen dit veranderen door eenvoudigweg te schalen op basis van zijn positie:
private function depth (): void var smaller: Number = ((y / stage.stageHeight) * 0.6) + 0.6; scaleX = scaleY = kleiner;
De "botsing" -functie bepaalt hoe en wanneer de bal andere objecten weerkaatst. In de eerste "als" -instructie controleren we eenvoudig de y-waarde om te achterhalen of de bal de boven- of onderwand raakt. Opnieuw vond ik deze waarden met vallen en opstaan omdat de bal op een plausibele manier moet stuiteren. Als de controle waar is, resulteert dit in het veranderen van de yspeed, zodat de bal van verticale richting verandert.
persoonlijke functie botsing (): void if (y> = 463 || y <= 105 ) yspeed *= -1;
Het controleren van de x-grenzen is niet zo eenvoudig vanwege het perspectief en de paddles die bewegen. We kunnen een "hitTest" uitvoeren met de muren en de bal terugsturen als dat waar is. HitTests zijn een beetje cpu zwaar, dus het is het beste om ze niet te veel te gebruiken. Omdat we echter te maken hebben met een eenvoudig pong-spel, vertraagt dit het spel niet merkbaar. Ik heb wel een extra controle toegevoegd; om te zien of de x-waarde van de bal zich aan de linker- of rechterkant van het podium bevindt en controleer de muur dienovereenkomstig. Dit zorgt ervoor dat er slechts één hitTest per frame nodig is in plaats van twee.
if ((x> stage.stageWidth / 2 && hitTestObject (MovieClip (bovenliggende) .bg.wallRight)) || (x < stage.stageWidth / 2 && hitTestObject( MovieClip(parent).bg.wallLeft)) ) xspeed *= -1;
Ten slotte moeten we uitzoeken of de bal nog steeds op het platform staat. We kunnen dit achterhalen door te controleren of een punt op de bodem van de bal zich nog steeds op de "vloer" bevindt. Het exacte punt heeft de x-waarde van de bal en de waarde voor y plus straal. Als dit waar is, komen we erachter of de bal links of rechts is gegaan (opnieuw door de x-waarde te vergelijken met het midden van het scherm) en de score gelijklopend bij te werken. Aan het einde zet je de x- en y-waarden van de bal terug naar het midden, zodat het spel kan doorgaan.
if (! MovieClip (bovenliggende) .bg.floor.hitTestPoint (x, y + (height / 2 * scaleY), true)) if (x < stage.stageWidth / 2 ) MovieClip(parent).bg.scoreRight.text = Number(MovieClip(parent).bg.scoreRight.text) + 1; else MovieClip(parent).bg.scoreLeft.text = Number(MovieClip(parent).bg.scoreLeft.text) + 1; y = stage.stageHeight / 2; x = stage.stageWidth / 2;
Verander de klasse van de bal in "Ball".
Nu we zowel de paddles als de bal hebben gemaakt, is alles wat nodig is om het spel in actie te zetten. Voeg deze functie toe aan de hoofdklasse en zorg ervoor dat de onComplete die we in stap 6 hebben gebruikt, naar deze functie verwijst.
private functie goBall (): void ball.start ();
Nadat de score is bijgewerkt, keert de bal terug naar het midden en begint opnieuw te rollen. We moeten de bal een beetje animeren als hij terugkomt voordat het spel opnieuw begint.
Vervang deze code in de botsfunctie van de bal:
y = stage.stageHeight / 2; x = stage.stageWidth / 2;
Door:
xspeed = yspeed = 0; removeEventListener (Event.ENTER_FRAME, moveBall); y = -hoogte; x = stage.stageWidth / 2; var schaal: Number = (0.5 * 0.6) + 0.6; nieuwe TweenLite (dit, 1.5, y: stage.stageHeight / 2, scaleX: scale, scaleY: scale, ease: Bounce.easeOut, onComplete: start);
Dit voorkomt dat de bal het eerst beweegt. Vervolgens wordt de positie van de bal net boven het scherm ingesteld, maar horizontaal gecentreerd. Als we dan de Bounce easing-functie gebruiken, zal het lijken alsof de bal van bovenaf valt net voordat het spel opnieuw wordt gestart.
Ik hoop dat je zonder al te veel problemen hebt kunnen volgen. De game zoals die nu is, is erg basic en kan enkele verbeteringen gebruiken. De bal bijvoorbeeld kaatst altijd 90 hoekjes af, wat de beweging zeer voorspelbaar maakt.
Als je verder wilt gaan, kun je proberen de x en yspeed te variëren op basis van de plaats waar de bal de peddel raakt (vergelijk de y-waarden). De botsingsdetectie met de paddles is lang niet perfect, maar laat wel een eenvoudige manier zien om een hit te controleren. Ten slotte, als je geen hellingen voor de muren hebt gebruikt, zul je merken dat de bal over de bodemwand lijkt te rollen in plaats van eronder te verdwijnen. Om dit te verhelpen, kun je gemakkelijk objecten scheiden die over de bal moeten verschijnen en die in een nieuwe filmclip plaatsen die je evenveel vervormt als de "bg" filmclip en hoger rangschikken dan de bal in Flash.