HUD cooldown bars zijn visuele elementen in het spel die niet noodzakelijkerwijs behoren tot de wereld van het spel, maar zijn een indicatie voor de speler van een periode waarin ze wel of niet een actie kan uitvoeren.
In role-playing games, multiplayer online gevechtsarena's (zoals League of Legends of DOTA), of zelfs real-time strategiespellen, zijn deze indicatoren vaak cruciaal voor de speler.
In deze zelfstudie zullen we bekijken hoe deze cooldown-balken kunnen worden geïmplementeerd, ongeacht de coderingstaal of -tool, op basis van pseudo-code en de gebruikte mechanica. De tutorial beweert niet de beste of de enige manier te zijn om cooldown-bars te implementeren, maar analyseert en toont gewoon een werkende, praktische manier om dit te doen.
Alle demo's zijn gemaakt met de stabiele versie van Construct 2 R168 en kunnen worden geopend en uitgevoerd in de gratis versie. Alle broncode van de voorbeelden is becommentarieerd.
Laten we erin duiken.
Een afkoelbalk is meestal een visuele feedback voor de afkoelautomaat zelf, en de afkoelmechaniek is in feite een timer. Overweeg een actie die een personage uitvoert. Op het moment dat de actie wordt uitgevoerd, start een timer en terwijl deze timer aftelt, kan het personage de actie niet opnieuw uitvoeren. Dat is de cooldown.
Vanuit een codeperspectief, om te voorkomen dat de actie wordt uitgevoerd tijdens de afkoelperiode, wordt een Booleaanse variabele ingesteld op waar
wanneer de actie wordt uitgevoerd. Wanneer u probeert uw actie uit te voeren, controleert de code of de waarde van de Booleaanse variabele is vals
, en staat niet toe dat de actie anders wordt uitgevoerd. Aan het einde van de timer wordt de Booleaanse variabele ingesteld op vals
, toestaan dat de actie opnieuw wordt uitgevoerd.
Beschouw het volgende voorbeeld als een illustratie van dit concept:
Als u eenmaal op de Actie knop, voert het teken een actie uit en de Actie knop is uitgeschakeld. Tijdens het afkoelen wordt met regelmatige tussenpozen de resterende tijd in de afkoeling weergegeven. Aan het einde van de cooldown is het personage klaar om de actie opnieuw uit te voeren, dus de Actie knop is opnieuw ingeschakeld.
Laten we de pseudo-code eens bekijken:
// Een object Teken heeft een Booleaanse variabele "Cooldown", een numerieke variabele "cTimer" en een andere numerieke variabele "cEndTime" Op de aangeklikte knop txtHistory.text = txtHistory.text & newline & "Het teken voert een actie uit" Character.cTimer = 0 Character.cEndTime = txtTimer.text // Het tekstobject "Cooldown-duur" Character.Cooldown = True Button.Enabled = False If Character.Cooldown = True Character.cTimer = Character.cTimer + dt If Character.cTimer> = Character. cEndTime txtHistory.text = txtHistory.text & newline & "Het personage is klaar om een actie uit te voeren" Character.cTimer = -1 Character.Cooldown = False Button.Enabled = True Else & Every 0.5 seconds txtHistory.text = txtHistory.text & newline & "De actie is op cooldown." & Character.cEndTime - Character.cTimer & "seconden van cooldown resterend."
De Op de geklikte knop
functie kan alleen worden uitgevoerd als de knop is ingeschakeld en de code wordt slechts eenmaal na de klik uitgevoerd. Dat is de gebruikersactie die de timer start en instelt Kalmeer
zijn waar
.
Wanneer op de knop wordt geklikt, wordt de Character.cEndTime-variabele
is het tijdstip waarop de afkoeltijd zal eindigen; deze waarde wordt ingesteld op basis van de waarde in de txtTimer
tekstobject, te zien naast de Actie knop.
Ook op dit punt, de cTimer
waarde is "reset" naar 0
omdat het een "nieuwe" timer is, en Kalmeer
ingesteld op waar
om het tweede deel van de code in te schakelen. Ten slotte schakelen we de knop uit. (We zouden het gewoon ingeschakeld kunnen laten en een andere voorwaarde aan onze toevoegen Op de geklikte knop
functie controleren of de waarde van Kalmeer
is vals
voordat je doorgaat, maar het uitschakelen van de knop voelt als betere feedback.)
Notitie: In het voorbeeld en deze pseudo-code wordt er geen fout gevonden om te voorkomen dat u iets anders invoert dan een getal in dat tekstobject. Het invoeren van iets anders wordt effectief ingesteld cEndTime
zijn 0
-dus eigenlijk helemaal geen cooldown.
Regel 10 van de bovenstaande pseudo-code wordt elke tik uitgevoerd; het controleert of de waarde van Character.Cooldown
is waar
en, zo ja, voegt de waarde toe van dt
naar de huidige waarde van Character.cTimer
.
dt
, afkorting van 'delta time', is een systeemvariabele die de tijd retourneert die is verstreken tussen de weergave van het vorige frame en de weergave van het huidige frame. Dit betekent dat hoe krachtig de computer van de speler ook is en in welke framerate de game draait, we ervoor kunnen zorgen dat de afkoelperiode even lang duurt. (Als we de afkoelperiode hebben gedefinieerd in termen van een aantal tikken of frames die zijn verstreken, zou de lengte van de periode in seconden variëren op verschillende machines.) De naam van deze dt
variabele of het gebruik ervan kan verschillen afhankelijk van uw codeerengine.
Als de cooldown nog steeds actief is, controleren we of de huidige waarde van cTimer
is groter dan of gelijk aan cEndTime
; als dat zo is, moeten we het einde van de afkoelperiode hebben bereikt. We geven een beetje feedback weer en stellen in Character.Cooldown
naar vals
zodat dit gedeelte van de code niet opnieuw wordt uitgevoerd totdat de gebruiker op de knop klikt Actie knop. We schakelen het ook opnieuw in Actie knop.
Als de cooldown nog steeds actief is, geven we in plaats daarvan feedback die dit uitlegt. Dit specifieke stukje feedback is eigenlijk onze "cooldown bar" voor dit op tekst gebaseerde voorbeeld.
Dus dat is een basis cooldown monteur gebaseerd op een basistimer. Laten we voor de rest van dit artikel focussen op de cooldown bars zelf en zien hoe ze moeten worden geïmplementeerd.
Een cooldown-balk is eigenlijk slechts een sprite die in de loop van de tijd, tijdens een afkoelperiode, van grootte of zicht verandert. Het is een feedbackmechanisme waarmee de speler haar kan laten weten wanneer ze de actie opnieuw kan uitvoeren.
Bekijk het volgende voorbeeld:
Klik ergens op het scherm om de actie uit te voeren. Merk op dat de groene balk tijdens het afkoelen rood wordt en van een breedte van groeit 0
terug naar zijn oorspronkelijke breedte. Net als in het eenvoudige tekstuele voorbeeld, kunt u de afkoelduur instellen.
In dit voorbeeld is de balk (genaamd CooldownBar
) is niets meer dan een gekleurde sprite die is uitgerekt tot een breedte van 100 pixels. Wanneer de actie wordt uitgevoerd, wordt de breedte ervan ingesteld op 0 pixels. Dan, elke tik die de Kalmeer
variabele is waar
, de breedte wordt ingesteld op basis van de huidige waarde van cTimer
.
Laten we de pseudo-code eens bekijken:
// Met hetzelfde "teken" -object als in het basisvoorbeeld, deze keer is het object zichtbaar op het scherm. Met elke muisklik & Character.Cooldown = False Character.cTimer = 0 Character.cEndTime = txtEndTimer.text Character.Cooldown = True CooldownBar.Width = 0 CooldownBar.AnimationFrame = 1 If Character.Cooldown = True Character.cTimer = Character.cTimer + dt CooldownBar.Width = (CooldownBar.MaxWidth / Character.cEndTime) * Character.cTimer If Character.cTimer> = Character. cEndTime Character.cTimer = -1 Character.Cooldown = False CooldownBar.Width = CooldownBar.MaxWidth CooldownBar.AnimationFrame = 0
De cooldown-mechanic zelf lijkt op die in het vorige voorbeeld, dus laten we ons concentreren op de CooldownBar
zelf. Het object heeft twee animatieframes: een groen vierkant van 32x32px en een rood vierkant van 32x32px. Het heeft ook een Maximale wijdte
numerieke instantievariabele die is ingesteld op 100
(pixels), de werkelijke maximale breedte van de balk.
Elk vinkje, als Kalmeer
is waar
, CooldownBar.width
is ingesteld op een fractie van CooldownBar.MaxWidth
. We bepalen deze breuk door de maximale breedte van de balk te delen door de afkoeltijd van de afkoeltijd en dit resultaat vervolgens met de stroom te vermenigvuldigen cTimer
tijd.
Aan het begin en aan het einde van de afkoelperiode, zorgen we er ook voor dat het animatieframe dienovereenkomstig wordt gewijzigd: naar rood, wanneer de cooldown start en dan weer terug naar groen zodra de afkoeling is voltooid.
We kunnen wat verder gaan op het visuele aspect. Hier zijn enkele gedachten:
Het beginpunt van CooldownBar
is ingesteld op het midden, waardoor het een gevoel van totale groei geeft. Als u wilt, kunt u dit oorsprongpunt aan de linker- of rechterrand van het object instellen om het een "lineair" gevoel te geven.
Dit voorbeeld is erg basic; de balk zelf is alleen samengesteld uit twee frames met verschillende kleuren om het cooldown-aspect te versterken. Zolang de balk rood is, begrijpt de gebruiker dat de actie niet kan worden uitgevoerd, omdat rood over het algemeen een kleur is die wordt gebruikt om "stop" te betekenen. Maar vergeet je kleurenblinde spelers niet! Zorg ervoor dat u kleuren gebruikt die echt van elkaar verschillen, zodat zelfs zij het verschil kunnen zien, of gebruik een andere methode van visuele feedback naast de kleurverandering.
U kunt ook een omtrek aan de balk toevoegen, een vaste rechthoek waarmee de gebruiker de resterende tijd in de afkoelperiode beter kan inschatten..
Hier is een korte illustratie van de vorige punten:
Het is nog steeds een erg eenvoudige hervulbar en er is nog meer dat je aan de visuals zou kunnen toevoegen. De balk kan bestaan uit een animatie in plaats van slechts twee gekleurde frames. De sprite onder de balk kan zodanig worden gestileerd dat de achtergrond ervan transparant lijkt, of je kunt er zelfs een andere sprite over toevoegen om een "glazen" indruk te krijgen. Er zijn veel manieren om de cooldown-balk te styliseren om het beste bij het ontwerp van je spel te passen.
In sommige spellen heeft de speler vaardigheidsknoppen tot zijn beschikking. Deze knoppen geven niet alleen de cooldown of beschikbaarheid van de vaardigheid weer; ze zijn ook een interface voor de gebruiker om de aangegeven vaardigheid uit te voeren (vaak naast een aantal sneltoetsen op het toetsenbord).
Overweeg dit voorbeeld, waarin klikken op een van de knoppen het juiste wapen zal werpen en ook de cooldown weergeven die nog over is:
Zoals u kunt zien, toont elke vaardigheidsknop een "niet-vullende" zwarte balk en een timer tijdens de afkoelperiode. De zwarte balk is slechts een zwart gekleurde sprite die over de vaardigheidsknop is geplaatst met een dekking van 45% en de timer is een tekstobject. Elke instantie van de vaardigheidsknop heeft zijn eigen instantie hiervan SkillCover
en txtSkillTimer
voorwerpen.
Deze keer is de Kalmeer
, STIME
en sEndTime
variabelen zijn "gehecht" aan elk SkillButton
aanleg. Ook het beginpunt voor de SkillCover
zwarte sprite bevindt zich aan de onderkant.
Overweeg deze pseudo-code:
// Object "SkillButton" met variabelen "Cooldown" (boolean), "sTime" (numeriek), "sEndTime" (numeriek) en een specifiek animatieframe om te weten op welk exemplaar wordt geklikt / geselecteerd. // Object "SkillCover" met een variabele "Skill" stelt u in overeenkomstig het animatieframe van de SkillButton waarmee ze verwant zijn. // Object "txtSkillTimer" met een variabele "Vaardigheid" voor hetzelfde doel als hierboven. Op SkillButton aangeklikt & SkillButton.Cooldown = False SkillButton.sTime = 0 SkillButton.Cooldown = True Create Proj & ProjImage-objecten ProjImage.AnimationFrame = SkillButton.AnimationFrame // Om een dolk of een ninja-ster te gooien txtSkillTimer.Skill = SkillButton.AnimationFrame & positie SkillCover.Skill = SkillButton.AnimationFrame Set txtSkillTimer tot de basis van de positie SkillButton Set SkillCover aan de onderkant van SkillButton Set txtSkillTimer in front van SkillButton Set SkillCover achter txtSkillTimer // Nog in de voorkant van SkillButton txtSkillTimer.Visible = True SkillCover.Visible = True SkillCover.Height = SkillButton.Height Voor elke SkillButton & SkillButton.Cooldown = True SkillButton.sTime = SkillButton.sTime + dt txtSkillTimer.Skill = SkillButton.AnimationFrame & SkillCover.Skill = SkillButton.AnimationFrame txtSkillTimer.text = SkillButton.sEndTime - SkillButton. sTime SkillCover.height = SkillButton.Height - ((SkillButton.Height / SkillButton.sEndTime) * SkillButton. STIME) Als SkillButton.sTime> = SkillButton.sEndTime SkillButton.sTime = -1 SkillButton.Cooldown = False txtSkillTimer.Skill = SkillButton.AnimationFrame & SkillCover.Skill = SkillButton.AnimationFrame txtSkillTimer.Visible = False SkillCover.Visible = False
Hier selecteren we de juiste instantie van txtSkillTimer
en SkillCover
. (Dit is een Construct 2-techniek: we bepalen de juiste instanties volgens de waarde van bekwaamheid
, die moet overeenkomen met het animatieframe van de stroom SkillButton
waarop is geklikt of geselecteerd in de Voor elk
lus.)
In tegenstelling tot onze vorige cooldown-bars, SkillCover
begint "volledig", over de hele hoogte van de SkillButton
, en dan, tijdens het afkoelen, neemt langzaam af en onthult het beeld van de knop.
Om dit te doen, geven we SkillCover
een hoogte die overeenkomt met die van SkillButton
om te beginnen, en dan trekt elk frame af (SkillButton.Height / SkillButton.sEndTime) * SkillButton.sTime
van deze volledige hoogte. Het is in feite dezelfde formule die we eerder hebben gebruikt om de fractie van de afgekoelde periode die is verstreken, maar in omgekeerde volgorde te berekenen.
Sommige spellen formatteren de tijd anders en laten de speler het scherm configureren dat zij verkiest. Bijvoorbeeld, één minuut en veertig seconden kan worden weergegeven als 01:40 of als 100s. Om dit in je eigen spel toe te passen, voer je een Als
controleer voordat u de tekst van txtSkillTimer
, om te zien welk formaat de speler heeft geselecteerd en dienovereenkomstig de tekst op te maken. Sommige games of spelers geven er zelfs de voorkeur aan om de tijd helemaal niet als tekst weer te geven.
Er is meer dat je zou kunnen doen met de SkillCover
. Je zou kunnen spelen met zijn dekking om de knop meer of minder dan 45% te versluieren. Aangezien het een sprite is die een andere afbeelding bestrijkt, kunt u ook met de overvloeimodus spelen, bijvoorbeeld om de onderliggende afbeelding te desatureren en de kleuren steeds meer te laten zien wanneer de cooldown wordt doorgegeven. U kunt zelfs overwegen om er webGL- of arceringseffecten aan toe te voegen zodat deze bij de rest van uw gebruikersinterface of ontwerp passen. Wat betreft de cooldown bar, het is aan je verbeelding en artistieke richting.
We hebben gezien dat een cooldown-balk een visuele feedback is voor een eenvoudige monteur die voorkomt dat een actie gedurende een bepaalde tijd wordt uitgevoerd.
U kunt eenvoudige sprites gebruiken en hun breedte of hoogte in de loop van de tijd oprekken om uw gebruiker te laten weten dat er een cooldown gaande is. U kunt de resterende tijd weergeven in niet-gecodeerde tekst en deze in minuten of in seconden formatteren. Je kunt zelfs elk soort animatie, overvloeimodus of shader-effect toepassen dat past bij de artistieke richting van je spel.
Als je er even over nadenkt, kun je deze methode ook gebruiken om de vuursnelheid van een wapen te regelen: zolang het pistool op cooldown is, zal het geen ander projectiel schieten, zelfs als het Brand toets is ingedrukt; op het moment dat de afkoeling is voltooid, kan een ander projectiel worden afgevuurd. Er is in dit geval geen cooldown-balk vereist.
Je kunt alle voorbeelden downloaden en ze openen in Construct 2 gratis editie R168 of later.
Ik hoop dat je dit artikel interessant hebt gevonden en ik kijk uit naar je eigen ontwerpen van cooldown-bars.