Maak een RPG-stijl tekstsysteem voor je volgende spel

In deze zelfstudie maken we een tekstsysteem dat lijkt op wat je in veel rollenspellen ziet. Onze klas zal tijdens het praten dynamisch een pictogram voor de personages weergeven en zal elk blok tekst per letter typen.

Eindresultaat voorbeeld

Hier is een voorbeeld van het tekstsysteem dat we gaan maken:

Stap 1: Stel uw Flash-bestand in

Maak een nieuw Flash-bestand (Actionscript 3). Je filminstellingen zijn afhankelijk van je game. Voor deze demo installeer ik mijn film als 500x300, met een zwarte achtergrond en 30 fps.

Stap 2: voeg een achtergrondafbeelding toe

Je zult waarschijnlijk de tekstmodule over een afbeelding of animatie uit je game laten zien. Voor deze demo gebruik ik alleen een afbeelding die ik heb samengegooid met een paar personages uit mijn games die in een sneeuwveld staan.

Zet je achtergrondafbeelding op een laag genaamd "achtergrond".

Stap 3: Maak het RPGText Filmclip

Maak een nieuwe MovieClip op het podium (Invoegen> MovieClip) met de naam "RPGText."

Controleer in de Symbooleigenschappen "Exporteren voor Actionscript" en stel de klassenaam in op "RPGText". We zullen deze klassennaam later gebruiken om de code aan deze MovieClip te koppelen.

Klik OK. Als u hier een waarschuwing ziet dat de klassendefinitie niet kon worden gevonden, is dat OK. Het betekent alleen dat er nog geen code is om naar dit symbool te linken.

Geef uw MovieClip de instantienaam "rpgText." Onthoud, wanneer ik het heb over "RPGText" (hoofdletters), verwijs ik naar de klasse (of MovieClip); "rpgText" (kleine letters) is de naam van een aanleg van die klasse.

Stap 4: voeg een tekstpaneelachtergrond toe

Teken een rechthoek in je nieuwe RPGText Filmclip. Dit is de achtergrond voor de personagepictogrammen en de tekstballon. Ontwerp het zoals je het wilt, maar het moet de hele breedte van je film overspannen en kort genoeg zijn zodat het niet te veel van je spel bedekt.

Ik heb de mijn 500px breed gemaakt (om bij mijn film te passen) en 100px hoog. Ik heb het gevuld met een verloop van # 666666 tot # 999999 (donkergrijs tot lichtgrijs).

Snelle tip: om een ​​rechthoek van een specifieke grootte te tekenen, selecteer het rechthoekgereedschap en klik met Alt op het werkgebied. U krijgt een dialoogvenster waarin u de afmetingen van uw rechthoek kunt invoeren.

Stap 5: Het personagepictogram MovieClip

Maak een nieuwe laag in de RPGText MovieClip heet "icon". Maak een nieuwe MovieClip op deze laag met de naam "characterIcon" en geef deze de instantienaam "characterIcon".

Binnen in de characterIcon MovieClip maakt twee nieuwe lagen: "pictogrammen" en "labels". De pictogrammenlaag bevat al uw tekenpictogrammen (elk op een eigen hoofdframe) en de laag met labels bevat framelabels die we gebruiken om de tekens op het juiste moment weer te geven.

Importeer (of teken in Flash) een pictogram voor elk personage in uw spel dat zal spreken. Voor deze demo heb ik een 75x75px JPG gemaakt voor elk van mijn personages. Voeg de pictogrammen toe aan de pictogrammen laag, waarmee een nieuw hoofdframe voor elk teken wordt gemaakt. De volgorde waarin ze verschijnen is niet belangrijk, maar zorg ervoor dat elk pictogram op x: 0, y: 0 staat, zodat ze niet rondspringen als je van personage wisselt.

Stap 6: voeg framelabels toe

Maak nu een nieuw keyframe op elk frame van uw labels laag. Een snelle manier om dit te doen is door alle frames te selecteren en op F6 te drukken.

Selecteer één voor één elk keyframe van een label en voeg een framelabel toe dat overeenkomt met de naam van het teken dat in dat frame wordt weergegeven. Als u een paar lege frames (F5) tussen uw hoofdframes plaatst, kunt u gemakkelijker de framelabels lezen. labels hoofdframes blijven in lijn met uw pictogrammen keyframes.

Zorg ervoor dat elk van uw labels een unieke naam heeft. Als je twee tekens met dezelfde naam hebt, moet je ze op de een of andere manier onderscheiden ('John_L' en 'John_K' bijvoorbeeld).

Stap 7: Teken de tekstballon

Ga terug naar de RPGText MovieClip en maak een nieuwe laag met de naam "textBackground."

Teken een tekstballon. Ik tekende een eenvoudige bubbel met vierkante hoeken, maar je kunt ervoor zorgen dat de jouwe eruitziet zoals jij dat wilt. Maak het groot genoeg om het grootste deel van de achtergrondrechthoek te vullen en zit netjes naast je personagepictogrammen.

Selecteer uw tekstballon en converteer deze naar een MovieClip (Wijzigen> Converteren naar symbool). Nu het een MovieClip is, kunnen we er een slagschaduwfilter aan toevoegen. Ik stel de mijne in op zwart, 50% sterkte, 5px vervaging en 1px afstand.

Stap 8: voeg het dynamische tekstveld toe

Maak een nieuwe laag in de RPGText MovieClip genaamd "tekst." Gebruik de teksttool om een ​​tekstvak te tekenen. Zorg dat deze precies binnen de randen van de afbeelding van de spraakballon past.

Maak er een dynamisch tekstveld met meerdere regels van met de instantienaam "txt." Vergeet niet om het lettertype in te sluiten als u geen systeemtekst gebruikt. Ik gebruik 13pt Courier.

Stap 9: voeg de volgende Knop

We hebben een manier nodig waarop de speler naar het volgende tekstblok kan gaan wanneer de speler klaar is met lezen. Laten we een kleine "volgende" knop in de hoek toevoegen.

Maak een nieuwe laag in de RPGText MovieClip heet 'knop'. Voeg een nieuw knopsymbool toe met de naam "b_next." Ontwerp de vier standen van je knop zoals jij dat wilt. Ik gebruikte een kleine pijl naar beneden als het knopsymbool, omdat ik dat in veel spellen zie en neem ik aan dat spelers ermee vertrouwd zijn.

Zet je knop in de rechter benedenhoek op je tekstballon. Maak je geen zorgen over het geven van een instantienaam. Ik zal later uitleggen waarom.

Stap 10: Maak de documentklasse

Maak een nieuw Actionscript-bestand met de naam "Main.as" en voeg deze code toe om de lege shell voor de klasse te maken:

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

Stel hoofd in als de documentklasse in uw Flash-bestand. Als je snel wilt opfrissen over het gebruik van een klasse Document, is deze Quick Tip van Michael Williams een van de beste uitleg die ik heb gezien.

Stap 11: voeg de tekstblokken toe

Als je dit in een game gebruikt, kies je deze waarschijnlijk ergens anders, maar voorlopig voegen we deze toe aan de documentklasse. Voeg deze code toe aan de constructorfunctie in de Hoofd klasse:

var textBlocks: Array = new Array (["Kid", "Look, a robot!"], ["Abe", "BLEEP-BLOOP." Ik ben een Autonomous Botanical Engineer. Je kunt me ABE noemen. "], [" Kid "," Hallo Abe, ontmoet Frosty the Snowman. "], [" Frosty "," Happy Birthday! "], [" Abe "," BEEP-BIP. Hallo, Frosty. "], [" Abe "," Is deze kikker van jou? "], [" Frog "," Ribbit ... "], [" Kid "," Nee, ik heb hem nog nooit gezien. "Heb je geen koude kikker?], [" Frog " , "Ribbit ..."]); rpgText.textBlocks = textBlocks; 

Hier maken we een tweedimensionale array (een array die andere arrays bevat) om het script voor onze scène vast te houden. Voordat u iets verandert, bekijkt u hoe het is gestructureerd. Elke array is een afzonderlijk tekstblok dat twee elementen bevat. De eerste is de naam van het personage en de tweede is de tekst die hij zal spreken. De tekstblokken worden weergegeven in de volgorde waarin ze in de scène worden weergegeven.

De laatste regel verzendt alleen de TextBlocks array naar de rpgText MovieClip (onthoud "rpgText" is de instantienaam van de RPGText MovieClip op het werkgebied). Hierover later meer.

Ga je gang en bewerk dit gedeelte om bij je scene te passen. Wees extra voorzichtig dat de tekennamen exact overeenkomen met de namen die u hebt gebruikt voor de framelabels in het characterIcon MovieClip.

Stap 12: Maak de RPGText-klasse

We zijn eindelijk klaar om te beginnen met het schrijven van de code voor de klasse RPGText.

Maak een nieuw Actionscript-bestand met de naam "RPGText.as" en voeg deze code toe:

pakket import flash.events.Event; import flash.events.MouseEvent; import flash.display.MovieClip; import flash.media.Sound; public class RPGText breidt MovieClip uit private const SPEAKER: int = 0; private const TEXT: int = 1; private var _currentTextBlockIndex: int = 0; private var _currentTextBlock: String; private var _textBlocks: Array; // CONSTRUCTOR publieke functie RPGText () 

Dit is slechts een basishell voor de klas. Het doet nog niets, maar laten we eens kijken wat er is:

  • De eerste paar regels importeren slechts enkele van de klassen die we nodig zullen hebben.
  • In de klassenverklaring breiden we de klasse MovieClip uit. We moeten dit doen omdat deze klasse is gekoppeld aan de RPGText MovieClip in de bibliotheek (zie stap 3).
  • Vervolgens hebben we twee constanten, SPEAKER en TEKST die we zullen gebruiken om de naam en de tekst van de spreker te krijgen uit de array textBlocks die we in de vorige stap hebben ingesteld.
  • De variabele _currentTextBlockIndex zal bijhouden welk blok tekst we momenteel weergeven.
  • _currentTextBlock zal de eigenlijke tekst bevatten.
  • _textBlocks zal de hele reeks tekstblokken bevatten.
  • Ten slotte is er de lege klassenbouwer.

(Opmerking: ik gebruik het onderstrepingsteken in mijn variabelenamen om privévariabelen aan te geven.)

Stap 13: De TextBlocks Setter-functie

Sinds onze _textBlocks variabele is privé, we hebben een manier nodig om toegang te krijgen tot die variabele vanuit de Hoofd klas waar we de tekstblokken instellen. We doen dat door een "setter" -functie te maken. Voeg dit toe aan de klasse RPGText net onder de constructorfunctie:

public function set textBlocks (txt: Array): void _textBlocks = txt;  

Het leuke aan setters in Flash is dat we deze functie kunnen gebruiken alsof het een openbaar eigendom van de klasse RPGText is. Dat is precies wat we deden op regel 21 van de hoofdklasse in stap 11:

rpgText.textBlocks = textBlocks; 

Stap 14: voeg de UPDATETEXT Functie

Voeg deze functie toe aan de RPGText-klasse:

private functie updateText (e: Event): void if (txt.text.length < _currentTextBlock.length) txt.text = _currentTextBlock.substr(0, txt.text.length+1);  else  removeEventListener(Event.ENTER_FRAME, updateText); fillText();   

Dit is de kernfunctionaliteit van de klas, waarbij het letter voor letter typen plaatsvindt. Laten we eens kijken wat er hier gebeurt:

  • Regel 27: deze functie accepteert een gebeurtenis als een parameter omdat we hem zullen aanroepen met een ENTER_FRAME-gebeurtenis.
  • Regel 28: We vergelijken de lengte (aantal tekens) die momenteel in de tekst tekstveld naar het aantal tekens in de _currentTextBlock Draad.
  • Regel 29: Als er minder tekens in het tekstveld staan, gebruiken we de substr methode om alle karakters vanaf het begin te krijgen _currentTextBlock tot één meer dan het aantal tekens dat zich momenteel in het tekstveld bevindt. We plaatsen al die tekens in het tekstveld, waardoor er nog een teken aan het einde van de tekst in het tekstveld wordt toegevoegd.
  • Regel 31: Als er hetzelfde aantal tekens in het tekstveld zijn als in de _currentTextBlock Tekenreeks, verwijder de gebeurtenis ENTER_FRAME die deze functie aanroept.
  • Regel 32: Bel de fillText functie. We zullen deze functie in de volgende stap schrijven.

Stap 15: voeg de fillText Functie

Voeg deze functie toe aan de RPGText-klasse:

private functie fillText (e: MouseEvent = null): void txt.text = _currentTextBlock; if (_currentTextBlockIndex < _textBlocks.length-1) addEventListener(MouseEvent.CLICK, nextTextBlock);   

Het belangrijkste doel van deze functie is om de tekst tekstveld met de tekst van de _currentTextBlock (regel 37). Als we de animatie laten doorspelen, is de UPDATETEXT De functie moet daar voor zorgen, maar het is goed om ervoor te zorgen dat er niets fout gaat. We kunnen deze functie ook koppelen aan onze "volgende" knop zodat spelers de tekstanimatie kunnen overslaan en onmiddellijk het tekstveld kunnen vullen met het volledige tekstblok.

Merk op dat deze functie een MouseEvent accepteert als een argument, maar we stellen de standaardwaarde in op nul. Hierdoor kunnen we deze functie gebruiken met een MouseEvent-luisteraar, omdat deze de gebeurtenis accepteert. Omdat we het evenement een standaardwaarde geven, kunnen we de functie ook bellen zonder een gebeurtenis te verzenden, zoals we aan het einde van het evenement doen UPDATETEXT functie.

Nadat we het tekstveld hebben ingevuld, controleren we of dit het laatste tekstblok in de array is (als het _currentBlockIndex is minder dan het aantal elementen in de _textBlock array). Zo niet, dan voegen we een KLIK luisteraar toe om een ​​functie genaamd te activeren nextTextBlock welke we hierna zullen schrijven.

Stap 16: Over die klik luisteraar

Weet je nog dat we de knop 'volgende' hebben gemaakt en ik heb gezegd dat ik me geen zorgen hoef te maken over het geven van een instantienaam? Heb je in de laatste stap gezien hoe we de KLIK luisteraar aan de hele RPGText MovieClip vastmaakten in plaats van aan de knop? Dit zorgt ervoor dat de speler overal op de MovieClip kan klikken om de tekst vooruit te brengen. We hebben echt niet eens de knop nodig, maar ik zet er graag een in, dus er is een indicatie dat je klikt om de tekst verder te zetten.

Natuurlijk is dit gewoon een persoonlijke voorkeur van mij. Als u wilt, kunt u de knop een instantienaam geven en in plaats daarvan de KLIK luisteraar aan de knop koppelen. Ik vind gewoon dat het grotere hitgebied gemakkelijker te gebruiken is.

Stap 17: voeg de nextTextBlock Functie

Terug terzake. Voeg deze functie toe aan de RPGText-klasse:

private functie nextTextBlock (e: MouseEvent): void removeEventListener (MouseEvent.CLICK, nextTextBlock); txt.text = ""; // wis de tekst _currentTextBlockIndex ++; _currentTextBlock = _textBlocks [_currentTextBlockIndex] [TEXT]; // stel de tekst characterIcon.gotoAndStop in (_textBlocks [_currentTextBlockIndex] [SPEAKER]); // stel het tekensymbool addEventListener in (Event.ENTER_FRAME, updateText); // begin met het bijwerken van de tekst addEventListener (MouseEvent.CLICK, fillText);  

De eerste drie regels zijn vrij eenvoudig. Verwijder de MouseEvent-listener, wis het tekstveld en verhoog het _currentTextBlockIndex var om naar het volgende tekstblok te wijzen.

Lijn 47 gebruikt de TEKST constant om de huidige tekstreeks van de te krijgen _textBlocks array en wijs het toe _currentTextBlock.

Vervolgens gebruiken we de SPEAKER constant om de naam van het personage te krijgen. Omdat de tekennamen overeenkomen met de framelabels in onze characterIcon MovieClip die we kunnen gebruiken gotoAndStop om de characterIcon MovieClip naar het frame dat dat pictogram weergeeft.

Ten slotte voegen we een gebeurtenislistener toe om te beginnen met typen op de nieuwe tekstreeks en vervolgens een KLIK luisteraar toe te voegen om te worden uitgevoerd fillText wanneer op de MovieClip wordt geklikt.

Stap 18: voeg de starttekst Functie

We zijn bijna klaar, we hoeven alleen maar een functie toe te voegen waarmee alles op gang kan worden gebracht. We doen dat met een openbare functie genaamd "startText." Omdat dit een openbare functie is, laten we het dicht bij de top van de RPGText-klasse plaatsen, net onder de TextBlocks setter:

public function startText (): void _currentTextBlock = _textBlocks [_currentTextBlockIndex] [TEXT]; characterIcon.gotoAndStop (_textBlocks [_currentTextBlockIndex] [LUIDSPREKER]); addEventListener (Event.ENTER_FRAME, updateText); addEventListener (MouseEvent.CLICK, fillText);  

Bekend voorkomen? Deze code doet bijna precies hetzelfde als de nextTextBlock functie. Het stelt het huidige tekst- en tekensymbool in en voegt de gebeurtenislisteners toe UPDATETEXT en fillText. Aangezien deze functie alleen wordt uitgevoerd wanneer de tekst voor het eerst wordt gestart, hoeven we ons geen zorgen te maken over het wissen van het tekstveld of het verhogen van het _currentTextBlockIndex zoals we deden in nextTextBlock.

Stap 19: Roep de starttekst Functie

Nu hebben we een openbaar toegankelijke manier om de tekst te starten. Laten we het gebruiken.

Voeg deze regel toe aan de onderkant van de constructorfunctie van de hoofdklasse:

rpgText.startText (); 

Dit is gewoon de startText-functie aanroepen binnen de klasse RPGText. Dat zou alles op gang moeten krijgen.

Stap 20: Geluid toevoegen

Je zou nu je film moeten kunnen testen en alles zien werken. Er ontbreekt echter één ding: geluid.

Zoek (of creëer) een geluid om te spelen terwijl de tekst aan het typen is. Wanneer je een geluid kiest, houd dit dan erg kort, omdat dit geluid steeds opnieuw zal spelen als de tekstsoorten aanstaan. Een kleine "boop" of knopklik werkt het beste voor dit effect.

Importeer het geluid in de bibliotheek in uw Flash-bestand, vink "Exporteren naar Actionscript" aan en geef het de klassenaam "TypingSound".

Om dit geluid te laten spelen, hoeven we slechts twee regels toe te voegen aan de klasse RPGText. Eerst moeten we het geluid instantiëren. Voeg deze regel toe aan de bovenkant van de klasse onder de drie andere privévariabelen:

private var _typingSound: Sound = new TypingSound (); 

Ga nu naar de updateText-functie en voeg een regel toe die het geluid daadwerkelijk zal afspelen telkens wanneer de tekst wordt bijgewerkt (regel 38 is nieuw):

private functie updateText (e: Event): void if (txt.text.length < _currentTextBlock.length) txt.text = _currentTextBlock.substr(0, txt.text.length+1); _typingSound.play();  else  removeEventListener(Event.ENTER_FRAME, updateText); fillText();   

Stap 21: Verder gaan

Dat is het voor de demo. Alles zou op dit punt moeten werken, maar als je dit in een game wilt integreren, heb je nog steeds wat werk voor de boeg.

Ten eerste, afhankelijk van hoe je spel is ingesteld, wil je waarschijnlijk de tekstblokken uit de documentklasse halen. Je hebt misschien een scèneklasse die je gebruikt om de individuele gesprekken in je spel in te stellen, of een snarenklasse die alle tekst voor elk gesprek bevat.

Ten tweede, wil je nadenken over hoe en wanneer de tekstmodule in je spel verschijnt. Misschien wilt u een tween-animatie toevoegen waarmee deze van onderaf wordt in- en uitgeschoven wanneer een gesprek begint en eindigt. U wilt ook luisteren naar wanneer het gesprek voorbij is, om de tekstmodule te verbergen of om het volgende gesprek te starten.

Omdat we al controleren om te zien of het laatste tekstblok is bereikt in de fillText functie, zou je gemakkelijk iets kunnen toevoegen dat het einde van het gesprek afhandelt.

Ik neem deze onderwerpen niet op in de tutorial omdat de manier waarop je deze dingen aanpakt, heel specifiek is voor je game. Dit zou echter voldoende moeten zijn om u op weg te helpen.

Ik hoop dat je het leuk vond! Plaats een reactie en laat me weten wat je ervan vindt.