Twee keer per maand bekijken we enkele van onze favoriete lezers uit de geschiedenis van Activetuts +. Deze tutorial werd een jaar geleden voor het eerst gepubliceerd in januari 2010.
In deze zelfstudie leert u hoe u de klasse DisplacementMapFilter van AS3 gebruikt om een herbruikbaar statisch vervormingseffect te creëren voor knooprollen..
Laten we eens kijken naar het eindresultaat waar we naartoe zullen werken:
Een verplaatsingskaart werkt door de kleurwaarden van één afbeelding te gebruiken om de positie van pixels in een andere afbeelding te wijzigen. Dit effect wordt vaak gebruikt om een platte grafische 'wrap' rond een dimensionaal beeld te maken. We gaan het hier gebruiken om een knop te vervormen, zodat het lijkt alsof het statische interferentie ontvangt.
U kunt hier meer lezen over verplaatsingstoewijzingen.
Maak een nieuw Flash-bestand (ActionScript 3).
Je filminstellingen zijn afhankelijk van je game. Voor deze demo installeer ik mijn film als 500x300, zwarte achtergrond en 30 fps.
Maak een nieuw knopsymbool op het werkgebied (invoegen> nieuw symbool). Ontwerp de 4 toestanden voor uw knop. Het exacte ontwerp moet iets zijn dat overeenkomt met je spel. Iets glinsterend en semi-transparant werkt goed met dit effect.
Ik heb een lettertype Genetrix Square voor de mijne gebruikt, maar je moet iets gebruiken dat overeenkomt met het uiterlijk van je spel.
Geef je knop een instantienaam van 'button1'.
Als u uw film opslaat en test (Controle> Film testen), zou u nu moeten zien dat uw knop in het werkgebied reageert op de muis met de rollover-statussen die u hebt ontworpen. Zoals dit:
We moeten aangepaste functionaliteit toevoegen aan onze knop. We doen dit door een nieuwe aangepaste klas te maken en onze eenvoudige knop erin te plaatsen.
Maak een nieuw ActionScript-bestand met de naam 'JitteryButton.as'. Bewaar dit bestand in dezelfde map als uw hoofd Flash-bestand. Voeg deze code toe om de wrapper voor onze knop te maken:
pakket import flash.display.Sprite; import flash.display.SimpleButton; public class JitteryButton breidt Sprite uit private var myButton: SimpleButton; // bevat de verwijzing naar onze eenvoudige knop // CLASS CONSTRUCTOR public function JitteryButton (button: SimpleButton) myButton = button; // de knop op het podium wordt ingevoerd
Al deze code doet tot dusverre de eenvoudige knop accepteren en een verwijzing ernaar opslaan. We zullen later meer functionaliteit toevoegen.
Maak een nieuw ActionScript-bestand met de naam 'Game.as'. Dit wordt de documentklasse voor onze film. Sla het op in dezelfde map als het hoofd Flash-bestand.
Deze code voegt onze aangepaste knopwikkel toe rond de knop op het podium:
pakket import flash.display.MovieClip; public class Game breidt MovieClip uit private var startButton: JitteryButton; // CLASS CONSTRUCTOR public function Game () // maak de jittery-knop van de eenvoudige knop in de start van de etappeButton = new JitteryButton (button1); // voeg de nieuwe knop toe aan de stage addChild (startButton);
Deze code maakt een nieuwe instantie van onze aangepaste JitteryButton-klasse en geeft deze de knop op het werkvlak ('knop 1').
Natuurlijk zal je documentklasse er heel anders uitzien omdat hij de code voor je game erin zal hebben. Hier zijn we alleen maar bezig met de code voor onze knop.
Terug in je Flash-bestand zet je de documentklasse op 'Game'. Denk eraan, u neemt hier de bestandsextensie niet op.
Als je je film nu opslaat en test, zou je precies hetzelfde moeten zien als toen we in stap 4 testten. Het enige verschil is dat nu onze code is ingesteld om ons aangepaste gedrag toe te voegen.
We maken nu de afbeelding van het statische patroon dat we gebruiken om onze knopafbeelding te vervormen.
Open Photoshop en maak een nieuwe afbeelding gevuld met neutraal grijs (# 808080). De afbeelding moet iets breder zijn dan je knop en ongeveer 3 of 4 keer zo hoog. Mijn knop is 277x56 en mijn afbeelding is 310x220.
We beginnen met een neutraal grijs omdat dat ons imago niet beïnvloedt.
We voegen nu een beetje ruis toe aan onze afbeelding. Dit zal niet erg opvallen in ons statische effect, maar geeft het een beetje extra glans. U kunt deze stap overslaan als u dat wilt.
Dupliceer de achtergrondlaag en noem de nieuwe laag 'Ruis'. U zou nu 2 lagen gevuld moeten hebben met neutraal grijs. Selecteer de nieuwe ruislaag en kies Filter> Ruis> Ruis toevoegen. set Bedrag tot 120% en Distributie Uniform. Controleren Monochromatisch.
Druk op OK.
Zet de laag 'Ruis' op 10% dekking.
Maak een nieuwe laag met de naam 'Lijnen'. Gebruik nu een potloodpenseel van 1 px om een aantal horizontale zwarte en grijze lijnen aan de afbeelding toe te voegen.
Onthoud hoe deze lijnen ons beeld beïnvloeden: alles wat donkerder is dan neutraal, verschuift ons beeld in één richting en alles wat lichter zal het in de andere verschuiven.
Kies Bestand> Opslaan voor web en apparaten en sla uw afbeelding op als een 8-kleuren gif met de naam 'staticMap.gif'.
Terug in Flash importeert u de 'staticMap.gif' in uw bibliotheek (Bestand> Importeren> Importeren in bibliotheek?). Open de koppelings-eigenschappen, vink aan Exporteren voor ActionScript, en stel de klassenaam in op 'StaticMap'.
We kunnen nu verwijzen naar deze afbeelding in onze code met behulp van de klasse naam StaticMap.
Voeg deze functie toe aan uw JitteryButton-klasse:
// maak de verplaatsingskaart filter persoonlijke functie createDMFilter (): DisplacementMapFilter var mapBitmap: BitmapData = new StaticMap (0,0); // gebruik de bitmapgegevens van onze StaticMap-afbeelding var mapPoint: Point = new Point (0, 0); // positie van de StaticMap-afbeelding ten opzichte van onze knopvariabelen: uint = BitmapDataChannel.RED; // welke kleur moet worden gebruikt voor verplaatsing var componentX: uint = kanalen; var componentY: uint = channels; var scaleX: Number = 5; // de hoeveelheid horizontale verschuiving var-schaalY: Number = 1; // de hoeveelheid verticale verschuiving var-modus: String = DisplacementMapFilterMode.COLOR; var kleur: uint = 0; var alpha: Number = 0; retourneer nieuwe DisplacementMapFilter (mapBitmap, mapPoint, componentX, componentY, schaalX, schaalY, modus, kleur, alpha);
Met deze functie wordt eenvoudig het verplaatsingskaartfilter gemaakt met behulp van de BitmapData uit onze StaticMap-afbeelding. Dit hoeft niet in zijn eigen functie te zijn, ik doe het gewoon voor de duidelijkheid.
Om het te laten werken, moeten we deze klassen bovenaan onze JitteryButton-klasse importeren:
import flash.display.BitmapData; import flash.display.BitmapDataChannel; import flash.filters.DisplacementMapFilter; import flash.filters.DisplacementMapFilterMode; import flash.geom.Point;
(U kunt meer leren over de klasse DisplacementMapFilter in de AS3-documentatie)
We maken nu een variabele om het filter vast te houden. We passen het toe op de knop door de eigenschap 'filters' van de knop in te stellen op een array met ons filter.
Hier is de JitteryButton-klasse tot nu toe (regels 18 en 25 zijn nieuw):
pakket import flash.display.Sprite; import flash.display.SimpleButton; import flash.display.BitmapData; import flash.display.BitmapDataChannel; import flash.filters.DisplacementMapFilter; import flash.filters.DisplacementMapFilterMode; import flash.geom.Point; import caurina.transitions.Tweener; public class JitteryButton breidt Sprite uit private var myButton: SimpleButton; // maak een variabele aan om de verplaatsingstoewijzaar te houden private var dmFilter: DisplacementMapFilter = createDMFilter (); // CLASS CONSTRUCTOR openbare functie JitteryButton (knop: SimpleButton) myButton = button; // pas het filter toe op de knop myButton.filters = new Array (dmFilter); // maak de verplaatsing kaart filter persoonlijke functie createDMFilter (): DisplacementMapFilter var mapBitmap: BitmapData = new StaticMap (0,0); // gebruik de bitmapgegevens van onze StaticMap-afbeelding var mapPoint: Point = new Point (0, 0); // dit is de positie van de StaticMap-afbeelding ten opzichte van onze knop-var-kanalen: uint = BitmapDataChannel.RED; // welke kleur moet worden gebruikt voor verplaatsing var componentX: uint = kanalen; var componentY: uint = channels; var scaleX: Number = 5; // de hoeveelheid horizontale verschuiving var-schaalY: Number = 1; // de hoeveelheid verticale verschuiving var-modus: String = DisplacementMapFilterMode.COLOR; var kleur: uint = 0; var alpha: Number = 0; retourneer nieuwe DisplacementMapFilter (mapBitmap, mapPoint, componentX, componentY, schaalX, schaalY, modus, kleur, alpha);
Als we het bestand nu opslaan en testen, kunnen we het verplaatsingkaartfilter zien dat op onze knop wordt toegepast:
U kunt zien hoe de horizontale lijnen die we in de StaticMap hebben getekend, de pixels links en rechts van onze knop verschuiven. De hoeveelheid verschuiving is afhankelijk van de duisternis van de lijnen in de afbeelding en de scaleX-instelling in ons verplaatsingskaartfilter.
Helaas is de static niet aan het animeren, dus het ziet er behoorlijk zwak uit. Laten we dat nu oplossen?
Dit is een eenvoudige functie die een willekeurig geheel getal binnen een opgegeven bereik retourneert:
// geeft een willekeurig getal tussen het opgegeven bereik (inclusief) privéfunctie randRange (min: int, max: int): int var randomNum: int = Math.floor (Math.random () * (max - min + 1) ) + min; return randomNum;
Ik vind het een beetje makkelijker om willekeurige waarden te genereren. We zullen een paar verschillende waarden randomiseren voor ons statische effect, zodat het van pas zal komen.
Voeg het toe aan uw JitteryButton-klasse.
Er zijn een aantal manieren om het statische effect te animeren. De eerste zal zijn om de hoeveelheid horizontale verschuiving aan te passen die op onze knop is toegepast. Dit gebeurt via de scaleX-eigenschap van de DisplacementMapFilter.
We kunnen ook de positie van de StaticMap-afbeelding in relatie tot onze knop animeren. Dit zorgt ervoor dat dezelfde delen van de knop niet altijd worden verschoven.
Om het effect te animeren, voegen we een functie toe genaamd 'displayStatic' die elk frame wordt genoemd om deze twee eigenschappen van het filter bij te werken. Voeg deze functie toe aan uw JitteryButton-klasse:
// opgeroepen ENTER_FRAME persoonlijke functie displayStatic (e: Event): void dmFilter.scaleX = randRange (fuzzMin, fuzzMax); dmFilter.mapPoint = new Point (0, randRange (0, -160)); myButton.filters = new Array (dmFilter);
De eerste regel van deze functie maakt de hoeveelheid horizontale verschuiving willekeurig naar een waarde tussen de variabelen fuzzMin en fuzzMax. Voeg deze twee variabelen toe aan uw JitteryButton-klasse:
private var fuzzMin: int = 0; private var fuzzMax: int = 2;
De tweede regel van de displayStatic-functie maakt de Y-positie van de StaticMap in relatie tot onze knop willekeurig. We hebben het filter al verteld om onze StaticMap-afbeelding te gebruiken, dus we moeten alleen de positie bijwerken.
De derde regel past het filter opnieuw toe op onze knop.
Het laatste wat we moeten doen om deze animatie te krijgen, is om de gebeurtenislistener ENTER_FRAME toe te voegen. Voeg deze regel toe aan de constructorfunctie van JitteryButton:
// begin met het weergeven van het statische effect addEventListener (Event.ENTER_FRAME, displayStatic);
En vergeet niet de klasse Event bovenaan het JitteryButton-bestand te importeren:
import flash.events.Event;
Als je de film nu opslaat en test, zie je het effect waardoor onze knop glinstert en springt:
Dat is best gaaf, maar we willen ook dat het effect reageert op de muis. Voorwaarts?
We voegen nu twee functies toe om de intensiteit van het jittereffect aan te passen. We noemen het effect dat we momenteel hebben, lage intensiteit, dus we voegen een instelling toe voor gemiddelde en hoge intensiteit. Voeg deze functies toe aan uw JitteryButton-klasse:
// verhoog de intensiteit van de statische naar MEDIUM privéfunctie setStaticMedium (e: MouseEvent = null): void fuzzMin = 2; fuzzMax = 6; staticLength = randRange (8, 12); // verhoog de intensiteit van de statische naar HIGH private functie setStaticHigh (e: MouseEvent = null): void fuzzMin = 12; fuzzMax = 25; staticLength = 12;
U kunt zien dat we de intensiteit aanpassen door de waarden van de variabelen fuzzMin en fuzzMax in te stellen. Op deze manier gebruikt onze displayStatic-functie deze nieuwe waarden bij het instellen van de horizontale verschuiving van het filter.
We hebben ook een variabele met de naam staticLength toegevoegd. We gebruiken dit om in te stellen hoe lang het intensere effect moet duren (het aantal frames) voordat het terugkeert naar lage intensiteit. Voeg deze variabele toe aan uw JitteryButton-klasse en wijzig uw displayStatic-functie als volgt:
private var staticLength: int; // opgeroepen ENTER_FRAME persoonlijke functie displayStatic (e: Event): void dmFilter.scaleX = randRange (fuzzMin, fuzzMax); dmFilter.mapPoint = new Point (0, randRange (0, -160)); myButton.filters = new Array (dmFilter); staticLength--; if (staticLength <= 0) fuzzMin = 0; fuzzMax = 2;
Deze nieuwe code verlaagt de staticLength-variabele en stelt fuzzMin en fuzzMax opnieuw in op de lage intensiteitswaarden zodra de waarde van staticLength nul bereikt.
Om onze knop op de muis te laten reageren, moeten we voor elk twee muisgebeurtenislisteners en een gebeurtenishandlerfunctie toevoegen.
Voeg de muislisteners toe aan de constructorfunctie van uw JitteryButton-klasse:
// voeg de luisteraars van de rollover-gebeurtenis toe aan de knop myButton.addEventListener (MouseEvent.ROLL_OVER, onButtonRollOver); myButton.addEventListener (MouseEvent.ROLL_OUT, onButtonRollOut);
Maak nu de twee gebeurtenishandlers waarnaar in die twee nieuwe regels wordt verwezen. Deze gaan ook in de klasse JitteryButton:
// opgeroepen knop ROLL_OVER private function onButtonRollOver (e: MouseEvent): void setStaticHigh (); // opgeroepen knop ROLL_OUT persoonlijke functie onButtonRollOut (e: MouseEvent): void setStaticMedium ();
Om dit allemaal te laten werken, moeten we de MouseEvent-klasse bovenaan ons JitteryButton-bestand importeren:
import flash.events.MouseEvent;
Wanneer onze knop een ROLL_OVER-gebeurtenis detecteert, wordt de gebeurtenishandler aangeroepen, die op zijn beurt onze setStaticHigh-functie aanroept. Deze functie verhoogt de waarden van fuzzMin en fuzzMax (gebruikt voor het instellen van de horizontale verschuiving) voor de duur gespecificeerd door de staticLength variabele.
We kunnen hier stoppen. Ons effect is leuk animeren en reageert op de muis-rollovers. Ik heb echter nog steeds het gevoel dat er iets ontbreekt. Laten we een klein schaaleffect toevoegen.
U moet de Tweener-bibliotheek voor deze stap downloaden als u deze nog niet hebt. Plaats de map 'caurina' in uw projectdirectory en importeer de Tweener-klassen boven aan uw JitteryButton-bestand:
import caurina.transitions.Tweener;
Tweener stelt ons in staat om een paar mooie schalingseffecten toe te voegen met slechts een paar regels code. We kunnen één regel toevoegen aan elk van onze rollover-gebeurtenishandlers:
// opgeroepen knop ROLL_OVER persoonlijke functie onButtonRollOver (e: MouseEvent): void Tweener.addTween (myButton, scaleX: 1.1, time: .5, transition: "easeOutElastic"); setStaticHigh (); // opgeroepen knop ROLL_OOUT persoonlijke functie onButtonRollOut (e: MouseEvent): void Tweener.addTween (myButton, scaleX: 1, time: .5, transition: "easeOutElastic"); setStaticMedium ();
Hier voegen we een animatie toe aan de rollover-handler die de scaleX-eigenschap van de knop schaalt naar 110% over 0,5 seconden. We gebruiken een elastisch overgangstype om het een veerkrachtig gevoel te geven. In de uitroloperator doen we hetzelfde in omgekeerde richting, waardoor het terug wordt gebracht naar 100%.
U kunt meer lezen over het gebruik van Tweener in de Tweener-documentatie.
Het laatste wat we moeten doen om dit effect compleet te maken is om wat geluid toe te voegen. Ik heb mijn geluidseffect gemaakt in Garage Band. Je kunt er zelf een maken of een online proberen te vinden.
Zodra je er een hebt die je leuk vindt, importeer je deze in je bibliotheek en stel je de koppeling om te exporteren in als 'StaticSound'.
Om het toe te voegen aan onze JitteryButton, moeten we eerst de klasse Sound importeren:
import flash.media.Sound;
Vervolgens initialiseren we het (voeg deze regel toe net voor de constructorfunctie):
private var staticSound: Sound = new StaticSound ();
In de rollover-handler vertellen we het geluid dat moet worden afgespeeld:
// opgeroepen knop ROLL_OVER persoonlijke functie onButtonRollOver (e: MouseEvent): void Tweener.addTween (myButton, scaleX: 1.1, time: .5, transition: "easeOutElastic"); setStaticHigh (); staticSound.play ();
Nu zijn we goed om te gaan. Test je film en alles zou moeten werken. Als uw knop of geluid niet goed werkt, controleer dan de bronbestanden om mijn voltooide JitteryButton-klasse te zien.
Het leuke aan het bouwen van dit effect als een aparte klasse die onze knop omhult, is dat we deze gemakkelijk kunnen hergebruiken op andere knoppen.
Als u meer knoppen aan uw gamemenu wilt toevoegen, maakt u gewoon een nieuwe knop en voegt u deze toe aan het podium. Geef het de instantie naam 'button2'. Maak vervolgens in je documentklasse (het 'Game.as'-bestand) een nieuwe JitteryButton en geef deze de nieuwe knop. Hier ziet u hoe dat eruit zou kunnen zien:
pakket import flash.display.MovieClip; public class Game breidt MovieClip uit private var startButton: JitteryButton; privé var-menu Knop: JitteryButton; // CLASS CONSTRUCTOR public function Game () // maak de jittery-knoppen met de eenvoudige knoppen in de start van de etappeButton = new JitteryButton (button1); addChild (startknop); // een nieuwe knop toevoegen is eenvoudig! menuButton = new JitteryButton (button2); addChild (MENUknop);
Je zult deze code bijna zeker een beetje moeten veranderen om hem in de structuur van je spel te laten passen. Hopelijk geeft deze tutorial je een goed startpunt.
Als u het uiterlijk van dit effect wilt wijzigen, kunt u proberen verschillende soorten afbeeldingen te gebruiken voor uw StaticMap-afbeelding en de waarden aan te passen voor fuzzMin en fuzzMax.
Dit is mijn eerste zelfstudie, dus laat me weten of er iets is dat ik de volgende keer beter kan doen. Bedankt voor het lezen!