Creëer een racegame zonder een 3D-engine

Deze zelfstudie biedt u een alternatief voor 3D voor racegames in ActionScript 3. Er is geen extern framework vereist voor dit voorbeeld van de oude school.


Eindresultaat voorbeeld

Laten we eens kijken naar het eindresultaat waar we naartoe zullen werken:


Stap 1: Stel het FLA-document in

Maak een nieuwe Flash-documentenset voor ActionScript 3.0. Ik gebruik dimensies van 480x320 px, een framesnelheid van 30 FPS en een lichtblauwe achtergrond. Sla het bestand op met een naam naar keuze.


Stap 2: Maak een documentklasse

Naast de FLA moeten we ook een documentklasse maken. Maak een nieuw Actionscript-bestand en voeg deze code toe:

 pakket import flash.display.MovieClip; public class Main breidt MovieClip uit public function Main () 

Bewaar dit bestand in dezelfde map als onze FLA. Geef het een naamMain.as.


Stap 3: Koppel het Hoofd Klasse met de FLA

Om de code te compileren van de Hoofd klasse, we moeten het koppelen aan de FLA. Over theяeigenschappen paneel van de FLA, naastKlasse, voer de naam van de documentklasse in, in dit geval, Hoofd.

Sla vervolgens de wijzigingen op de FLA op.


Stap 4: teken een weglijn

We moeten beginnen met een lijn om een ​​deel van de weg te vertegenwoordigen. druk op R om de te selecteren Rechthoekgereedschap. In dit voorbeeld maak ik een grijze rechthoek voor de weg zelf, twee kleine rode rechthoeken aan elke rand van de grijze en groene rechthoeken om de rest van de lijn te vullen. De groene moeten nog breder zijn dan het podium, ik maak ze 1500 pixels breed. De breedte van de weg kan verschillen naar jouw behoeften, ik gebruik een van 245px breed. Het is niet noodzakelijk dat ze erg hoog zijn, omdat we verschillende instanties gebruiken om de hele weg op het scherm te tekenen. Ik zal ze 10px hoog maken.


Stap 5: Maak een MovieClip voor de road lines

Nadat u alle rechthoeken hebt getekend, selecteert u ze allemaal (Ctrl + A) en druk op F8 om een ​​filmclip te maken uit die rechthoeken die u zojuist hebt gemaakt. Noem het "Road", zorg ervoor dat de de Registratiepunt staat in het midden en vinkt het selectievakje "Exporteren voor ActionScript" aan.

Je zult eindigen met een Road MovieClip in de bibliotheek.

Het is aan jou als je elke rechthoek op verschillende lagen wilt tekenen. Ik ga gewoon de grijze op een tweede laag zetten. Als u een Road-instantie in het werkgebied hebt, verwijdert u deze. We voegen de Road MovieClip later door code toe.


Stap 6: Stel het speelveld in

Laten we teruggaan naar de Hoofd klasse. We gaan dat gebruiken Weg MovieClip om de illusie van een racebaan te genereren.

We gaan de diepte van de zichtbare weg bepalen, evenals de afmetingen van het speelterrein. Ook in onze klas, alle Weg exemplaren die we toevoegen aan de fase worden benaderd vanuit een array. We gebruiken een andere array (zMap) om de diepte van elke regel te bepalen.

In dit voorbeeld zal ik een diepte van 150 weglijnen in een 480x320 speelveld instellen (het is niet nodig om dezelfde grootte van het podium te hebben, maar aangezien dat alles is wat er te zien zal zijn, zal ik die nummers gebruiken).

 // Diepte van de zichtbare weg private const roadLines: int = 150; // Afmetingen van het speelveld. private const resX: int = 480; private constYY: int = 320; // Lijn van de auto van de speler. private const noScaleLine: int = 8; // Alle weglijnen worden geopend vanuit een array. private var zMap: Array = []; privé var-regels: Array = []; private var halfWidth: Number; private var lineDepth: int; private const widthStep: Number = 1;

Stap 7: toon de weg op code

We zullen alle voorgaande variabelen en constanten binnen de Hoofd functie. We zullen elke regel aanpassen op basis van de corresponderende diepte.

 public function Main () // vul de zMap in met de diepte van de weglijnen voor (var i: int = 0; i < roadLines; i++)  zMap.push(1 / (i - resY / 2));  //We want the line at the bottom to be in front of the rest, //so we'll add every line at the same position, bottom first. lineDepth = numChildren; for (i = 0; i < roadLines; i++)  var line = new Road(); lines.push(line); addChildAt(line, lineDepth); line.x = resX / 2; line.y = resY - i;  //Scaling the road lines according to their position halfWidth = resX / 2; for (i = 0; i < roadLines; i++)  lines[i].scaleX = halfWidth / 60 - 1.2; halfWidth -= widthStep;  

als jij Publiceren (Ctrl + Enter) het document op dit punt krijgt u een weergave van een rechte weg.

Je kunt spelen met de schaalberekeningen om verschillende resultaten te krijgen. Misschien wilt u een bredere weg of een langere kijkafstand.


Stap 8: Maak een tweede weggrafiek

Op dit moment ziet de weg er zo plat uit dat je niet kunt zien of we vooruit gaan. We hebben ten minste twee verschillende segmentstijlen nodig om te onderscheiden hoe snel of hoe traag we ons verplaatsen.

Ga naar de Bibliotheek paneel en dubbelklik op de Weg MovieClip om terug te gaan naar de rechthoeken die u tekende. Druk nu op F6 om een ​​nieuw keyframe in te voegen (als u meer dan één laag hebt, wilt u mogelijk op elke laag een nieuw keyframe invoegen). Nu kunt u op basis van het eerste frame de kleuren van de rechthoeken wijzigen of hun ontwerp op de een of andere manier wijzigen. Ik zal hun kleur veranderen en een aantal rijstrooklijnen toevoegen aan het tweede frame.


Stap 9: houd de spelerlijn van schalen

We gaan een nieuwe variabele definiëren in de Hoofd klasse om de consistentie op de lijn van de speler te behouden (ervan uitgaande dat er een auto in het spel zal zijn, zullen we de schaal naar 1 op die lijn houden)

 private var playerZ: Number;

Vervolgens zullen we de Hoofd functie.


Stap 10: voeg afwisselende lijnen toe aan de weg

Deze variabele wordt gebruikt in de Hoofd functie. Nu de Weg lijnen worden gesegmenteerd, sommige tonen het tweede frame en de rest toont het eerste frame, wat de illusie van een racebaan verbetert.

 public function Main () for (var i: int = 0; i < roadLines; i++)  zMap.push(1 / (i - resY / 2));  playerZ = 100 / zMap[noScaleLine]; for (i = 0; i < roadLines; i++)  zMap[i] *= playerZ;  lineDepth = numChildren; for (i = 0; i < roadLines; i++)  var line = new Road(); lines.push(line); addChildAt(line, lineDepth); line.x = resX / 2; line.y = resY - i;  halfWidth = resX / 2; for (i = 0; i < roadLines; i++)  if (zMap[i] % 100 > 50) regels [i] .gotoAndStop (1); else lines [i] .gotoAndStop (2); lines [i] .scaleX = halfWidth / 60 - 1,2; halfWidth - = widthStep; 

Het is misschien niet nodig om met 100 te vermenigvuldigen om de segmenten correct te krijgen, maar dit zijn de getallen die ik in dit voorbeeld zal gebruiken, u bent vrij om de getallen naar uw smaak aan te passen (en als u iets verknoeit, hebt u dit als referentie).


Stap 11: Stel een snelheid en een offset in

Laten we beginnen om dingen te laten bewegen. We gaan een variabele instellen voor snelheid. Dit geeft de diepte aan die we per frame vooruit gaan. Ik begin met een snelheid van 20, je mag elk willekeurig nummer gebruiken.

We hebben ook een indicator nodig voor de wegsegmenten, die volgens de snelheid zullen veranderen.

 privé var snelheid: int = 20; private var texOffset: int = 100;

Stap 12: Begin met vooruit te gaan

Voordat we iets met deze variabelen kunnen doen, moeten we een nieuw evenement in deze klasse importeren. We kunnen een timer of een enterframe gebruiken. In dit voorbeeld gebruik ik het EnterFrame-evenement.

 import flash.events.Event;

Vervolgens gaan we de laatste conditionele in de Hoofd() functie en verplaats deze naar een nieuwe functie die we aan het maken zijn. Deze nieuwe functie wordt geactiveerd door het EnterFrame-evenement, dus we krijgen continu beweging op de weg. Laten we het noemen race().

 public function Main () for (var i: int = 0; i < roadLines; i++)  zMap.push(1 / (i - resY / 2));  playerZ = 100 / zMap[noScaleLine]; for (i = 0; i < roadLines; i++)  zMap[i] *= playerZ;  lineDepth = numChildren; for (i = 0; i < roadLines; i++)  var line = new Road(); lines.push(line); addChildAt(line, lineDepth); line.x = resX / 2; line.y = resY - i;  halfWidth = resX / 2; for (i = 0; i < roadLines; i++)  lines[i].scaleX = halfWidth / 60 - 1.2; halfWidth -= widthStep;  addEventListener(Event.ENTER_FRAME, race); 

Stap 13: Definieer een Race-functie

Laten we nu het voorwaardelijke terugbrengen dat was afgesneden naar de nieuwe functie, zodat we beweging krijgen. De texOffset zal de positie van de weg aangeven om een ​​nauwkeurige illusie van beweging te behouden.

 private function race (event: Event): void for (var i: int = 0; i < roadLines; i++)  if ((zMap[i] + texOffset) % 100 > 50) regels [i] .gotoAndStop (1); else lines [i] .gotoAndStop (2);  texOffset = texOffset + speed; while (texOffset> = 100) texOffset - = 100; 

als jij Publiceren dit nu, je zou een geanimeerde weg moeten krijgen.


Stap 14: Sturen

Voortdurende rechte wegen zijn saai en er zijn duizenden manieren om een ​​perspectief alleen vooruit te laten gaan. Laten we nu een paar nieuwe variabelen toevoegen om de bochten in beweging te houden.

In dit voorbeeld zal ik bochten naar rechts afwisselen met rechte stukken. De weg verderop wordt opgeslagen in de nextStretch variabel. Ook zullen we de lijnen verplaatsen ' X positie op de bochten.

 private var rx: Number; // De x-positie van elke regel private var dx: Number; // Curvebedrag per segment private var ddx: Number = 0.02; // Curvebedrag per regel privé var-segmentY: int = roadLines; private var nextStretch = "Straight";

Stap 15: voeg krommen toe aan de weg

De rx variabele zal de X positie van elke lijn, dus we willen dat deze in het midden begint en de bochten neemt vanaf daar. Ook, DDX regelt de scherpte van de curven. In dit voorbeeld heb ik het op 0,02; misschien wilt u de waarde ervan tussen curven variëren. Dit is hoe het nieuwe race() functie ziet eruit:

 private function race (event: Event): void rx = resX / 2; dx = 0; for (var i: int = 0; i < roadLines; i++)  if ((zMap[i] + texOffset) % 100 > 50) regels [i] .gotoAndStop (1); else lines [i] .gotoAndStop (2); lijnen [i] .x = rx; if (nextStretch == "Straight") if (i> = segmentsY) dx + = ddx; anders dx - = ddx / 64; // Keert soepel terug van een curve naar een recht stuk.  else if (nextStretch == "Curved") if (i <= segmentY) dx += ddx; else dx -= ddx / 64;  rx += dx;  texOffset = texOffset + speed; while (texOffset >= 100) texOffset - = 100;  segmentY - = 1; terwijl (segmentY < 0)  segmentY += roadLines; if (nextStretch == "Curved") nextStretch = "Straight"; else nextStretch = "Curved";  

Deze keer zullen we de Hoofd functie. als jij Publiceren nu zou je zoiets als dit moeten krijgen:

Misschien wilt u de Curve-waarde voor Links en Rechts wijzigen en de stuurwaarden wijzigen. Op dit punt zou je al in staat moeten zijn om een ​​auto aan de scène toe te voegen en de snelheid handmatig te regelen.


Stap 16: Heuvels, hellingen

Weet je nog dat de rechthoeken voor de weg meer dan 1 pixel hoog zijn? Dat kan ons helpen het zicht op de weg te vergroten voor het geval we heuvels willen in onze game.

Er is een methode voor het maken van heuvels die sterk lijkt op het maken van bochten. Er zijn veel verschillende methoden, maar dit is degene die ik hier ga gebruiken. Voor de eenvoud zal ik zoveel van de code die we al hebben recyclen en slechts een paar regels toevoegen voor dit nieuwe effect. Zoals gewoonlijk, als je de resultaten niet leuk vindt, kun je de waarden naar believen aanpassen.

We hebben zojuist variabelen gemaakt voor de X posities van de rijbanen, laten we nu die maken voor de Y posities ook.

 private var ry: Number; privévar dy: Number; privé var ddy: Number = 0.01; // Een beetje minder stijl dan de bochten.

Stap 17: Downhill, bergopwaarts

Eenvoudigheidshalve, in dit voorbeeld ga ik dezelfde rechte segmenten gebruiken voor zowel een rechtopgaand als een heuvelopwaarts effect, en de bochten voor zowel een bocht als een afdalingseffect.

 private function race (event: Event): void rx = resX / 2; ry = resY; dx = 0; dy = 0; for (var i: int = 0; i < roadLines; i++)  if ((zMap[i] + texOffset) % 100 > 50) regels [i] .gotoAndStop (1); else lines [i] .gotoAndStop (2); lijnen [i] .x = rx; lijnen [i] .y = ry; if (nextStretch == "Straight") if (i> = segmentsY) dx + = ddx; dy - = ddy;  else dx - = ddx / 64; dy + = ddy;  else if (nextStretch == "Curved") if (i <= segmentY)  dx += ddx; dy -= ddy;  else  dx -= ddx / 64; dy += ddy;   rx += dx; ry += dy - 1;  texOffset = texOffset + speed; while (texOffset >= 100) texOffset - = 100;  segmentY - = 1; terwijl (segmentY < 0)  segmentY += roadLines; if (nextStretch == "Curved") nextStretch = "Straight"; else nextStretch = "Curved";  

In je game moet je de bochten van de heuvels scheiden en twee verschillende algoritmen maken, maar dit voorbeeld laat zien hoe vergelijkbaar ze kunnen zijn.


Stap 18: verbeter de esthetiek van de weg

Old-school games konden geen gebruik maken van Flash, maar we kunnen wel. Iets eenvoudigs als het toevoegen van een verloop aan de rijbaanlijnen zal een groot verschil maken. Als je wilt, kun je alle filters en texturen gebruiken die je leuk vindt, maar in dit voorbeeld voeg ik gewoon enkele gradiënten toe, dus laten we teruggaan naar de Weg Filmclip.

Selecteer in frame 1 de grijze rechthoek en ga vervolgens naar het deelvenster Kleur en kies Lineair verloop in het vervolgkeuzemenu en kies vervolgens Kleur reflecteren als Flow, dus het verloop gaat van de eerste naar de laatste kleur heen en weer. Ik zeg niet dat je dezelfde kleuren moet kiezen als ik, maar ik gebruik hier # 666666 en # 999999. Als u het verloop wilt draaien, drukt u op F om over te schakelen naar het gereedschap Gradiënttransformatie, waarmee u uw verloop kunt verplaatsen, draaien en de grootte van het verloop kunt wijzigen. In dit geval verplaats ik het verloop naar een kwart van de rechthoek en verander ik het naar de helft van de grootte van de rechthoek, zodat het midden lichter wordt en de randen donkerder worden. Ik gebruik een vergelijkbare grootte voor het groene gedeelte, dus het verandert van continu donkergroen (# 006600) naar lichtgroen (# 009900).

Ga nu naar frame 2 en maak nieuwe verlopen met verschillende kleuren. Voor de grijze rechthoek heb ik de lichtere kleur behouden en alleen de donkerdere kleur gewijzigd in # 777777. Op het groene gedeelte heb ik de grootte van het verloop gewijzigd om te proberen een dambordlook te voorkomen, en de kleurverandering was erg subtiel (# 007700 en # 008800).

Misschien wil je nu een mooie achtergrond toevoegen aan de horizon, of een afbeelding voor de lucht.


Conclusie

Of je nu te weinig middelen hebt voor 3D-frameworks of gewoon wilt gaan old-school, nu heb je een eenvoudig voorbeeld van hoe je een illusie van diepte kunt geven voor een racespel. Het is nu aan u of het een Grand Prix-motorfiets is, of een straatrace op een snelweg vol verkeer, of misschien iets dat niets met racen te maken heeft.

Ik hoop dat je deze tutorial nuttig hebt gevonden. Bedankt voor het lezen!