Hoe ik deeltoets 1 heb gemaakt: Part 2

Posted at December 05, 2010

You’ve found a dinosaur. This is one of my first posts about programming and the code quality is very poor, it is only here for archiving purposes.

In deze post ga ik stap voor stap omschrijven hoe ik een hondje via ActionScript 3 ga animeren. Dit is een vervolg op een andere post waar ik inga op de denkwijze die je nodig hebt om te programmeren.

Dit is het niveau van deeltoets 1. Ik ga op alles redelijk uitgebreid in dus als je iets niet helemaal meer snapte dan kan je het hier opzoeken. En als je er helemaal niks van snapt kan je alles lezen.

Waar waren we gebleven? O ja, we gaan een hondje gaan animeren over het scherm. Justus heeft voor de voorbereiding op deeltoets 1 een opzet gemaakt, dit bestand gebruiken we om onze eigen animatie te maken. Hier zie je de opzet met wat basis aanpassingen.

/** HondInKamer.as -- Nov 24, 2010
 *
 * Copyleft 2010, all wrongs reversed.
 * 
 * 
 * background: http://www.flickr.com/photos/maurice_flower/152750470/sizes/z/in/photostream/
 */
package
{
    // Importeer benodigde classes
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;

public class HondInKamer extends Sprite
{
    // Variabele declaratie
    public var woefie:Hond;

    // Plaatje embedden *dit heb je nodig voor de achtergrond*
    [Embed(source="pics/woonkamer.jpg")] // verwijzing naar het bestand in de pics map
    private var BackgroundPicture:Class; // Abstracte klasse die gebruikt wordt om het plaatje in te laden
    private var background:Bitmap; // Bitmap object waarmee je het plaatje op de stage zet

    // Constructor functie
    public function HondInKamer()
    {
        // Stel de stage in op niet meeschalen
        stage.scaleMode = StageScaleMode.NO_SCALE;
        stage.align = StageAlign.TOP_LEFT;

        // Voeg het achtergrondplaatje toe aan de display list
        background = new BackgroundPicture();
        addChild(background);

        // Zet de placeholder neer
        woefie = new Hond();
        woefie.x = 320;
        woefie.y = 330;
        addChild(woefie);
    }

    // Eigen functies
}

Regel 1 Ons project heet niet meer DT1_opzet maar we moeten hem een naam geven die iets zegt over onze klasse. Ik heb gekozen voor HondInKamer. Ook heb ik de variabele Placeholder vernoemd naar Hond en in de Hond wat aanpassingen gedaan met de Draw Api. Op de Draw Api ga ik niet diep in aangezien iedereen dit al gehad heeft en ik hier geen ster in ben. Ik maak onze hond woefie aan, van de klasse Hond. Let op: Klasses beginnen altijd met een hoofdletter en variabelen met een kleine letter!

Regel 22 Standaard heeft Justus een plaatje met sneeuw / ruis / noise op de achtergrond staan. Ik heb in het mapje pics (in je project map) een plaatje woonkamer gestopt, op regel 22 geef ik aan dat de woonkamer mijn achtergrond plaatje is.

Regel 40 Ik heb de Y positie van hond iets aangepast zodat hij beter op het scherm geplaatst wordt.

Als we nu kijken naar ons lijstje waar de animatie omschreven wordt:

  • In het begin is er een hond
  • De hond is op het midden van het scherm
  • Het scherm heeft een plaatje van een woonkamer
  • Wanneer flash een nieuw frame maakt wordt de hond iets meer naar rechts neergezet
  • Als de hond rechts is spiegel hem en laat hem naar links gaan
  • Als de hond links is spiegel hem en laat hem naar rechts gaan
  • Wanneer iemand op de hond klikt, maakt de hond een sprongetje.

Dan zien we dat stap 1 , 2 en 3 al gedaan zijn. We zijn al bijna op de helft van de eisen en we hebben tot nu toe alleen enkele regeltjes veranderd!

Als je dit zou uitvoeren dan krijg je dit resultaat: HondInKamer – Versie 0.1

Animatie En dan komt nu een moeilijker gedeelte, namelijk de Animatie. Ik had gezegd “Wanneer flash een nieuw frame maakt wordt de hond iets meer naar rechts neergezet.” We moeten dus bij elk nieuw frame de positie van de hond iets veranderen. Dit gaan we doen met het ENTER_FRAME event. Dit is een gebeurtenis die elke keer gebeurd wanneer flash een nieuw frame wil gaan tekenen.

Deze regel code zorgt ervoor dat de functie beweegWoefie voor elk frame wordt uitgevoerd:

addEventListener(Event.ENTERFRAME, beweegWoefie);

_Deze zet je in je constructor, Het enige wat je hierover hoeft te weten is dat beweegWoefie wordt aangeroepen zodra de EventListener merkt dat het event ENTER_FRAME gebeurd. Er is nog een extra dingetje dat je moet doen voordat je het ENTER_FRAME event mag aanroepen in je programma. Je moet het importeren. Dit doe je door op regel 15 deze code neer te zetten.

import flash.events.Event;

Nu gaan we onze eigen functie maken, namelijk beweegWoefie. We zetten onze eigen functies neer na regel 44. Dit is de code voor onze eigen functie:

public function beweegWoefie(event:Event):void 
    {
        //hier komt onze code
    }

Vanaf regel 3 zetten we onze eigen code erin. wat moeten we hier nou typen dan? Laten we kijken naar ons af te werken lijstje.

  • Wanneer flash een nieuw frame maakt wordt de hond iets meer naar rechts neergezet

Ow dus hier moeten we ervoor zorgen dat woefie steeds iets meer naar rechts moet. Woefie begint op x as op 320 pixels. Dus als we hier nou 325 zetten dan gaat woefie naar rechts, toch? Het antwoord is ja, hij gaat naar rechts, alleen hij gaat maar een keer naar rechts, namelijk wanneer het eerste frame wordt gemaakt. Wat we in deze functie eigenlijk moeten zeggen is: Kijk naar de x positie van Woefie en tel daar 5 bij op. In het begin is woefie op x = 320. Op het eerstvolgende frame is woefie op 325, op het frame daarna 330 en ga zo maar door. Omdat er in 1 seconde heel veel frames zitten wordt het een vloeiende beweging.

We moeten dus een stukje code hebben die zegt “Kijk naar de x positie van Woefie en tel daar 5 bij op”. Als we dit vertalen naar Wiskunde dan krijgen we: woefie.x + 5 = woefie.x Dit is precies wat we in ActionScript ook doen, alleen daar zetten we het + 5 achter het =. Waarom doen we dit? Nou in ActionScript betekend = helemaal niet is gelijk aan, het betekend wordt (is gelijk aan heb je wel in ActionScript, maar dat druk je uit als ==). Als je zegt woefie.x + 5 wordt woefie.x dan verander je woefie.x niet, in ieder geval niet zoals we het willen. Daarom zeggen we woefie.x wordt woefie.x + 5. In code zetten we dit in de beweegWoefie functie, zodat woefie.x elk frame wordt veranderd.

woefie.x = woefie.x + 5;

Dit werkt wel, maar je kan het nog makkelijker opschrijven. Omdat iets optellen en iets aftrekken redelijk standaard is, hebben ze er iets makkelijks van gemaakt, namelijk:

woefie.x += 5;

Dit ziet er anders uit maar het betekend precies hetzelfde.

Als je dit zou uitvoeren dan krijg je dit resultaat: HondInKamer – Versie 0.2

if statement Maar Woefie rent het scherm uit! Dat mag niet de bedoeling zijn. Al helemaal niet als we kijken naar

  • Als de hond rechts is spiegel hem en laat hem naar links gaan

Hoe gaan we dit aanpakken? We zien een “als” dit wijst op een if statement (if = als in het engels). Een if statement ziet er zo uit:

if (conditie)
    { 
        dan
    }

Als [conditie] [dan] Als [de hond rechts is] [dan spiegel hem en laat hem naar links gaan] Maar ActionScript weet niet wat rechts is en wat we hiermee bedoelen, hier moeten we een formule van maken.

Het scherm heeft een X en een Y as. links boven is op beide assen 0. Maar waar zit dan de rechterkant? De rechtergrens is net zo groot als het plaatje breed is. Als het plaatje 100 pixels breed is en 0 is links boven, dan is 100 rechtsboven. Mijn woonkamer plaatje is 639 pixels breed. De rechtergrens is dus op de x as op 639. Je kan ook met stageHeight werken, dat maakt niet uit zolang je het principe maar snapt!

We moeten dus een formule maken die zegt: Als Woefie verder is op de x as dan 639, spiegel hem en laat hem de andere kant op gaan. Als we het dikgedrukte gedeelte weer wiskundig vertalen kunnen we zeggen: Als woefie op de X as groter is dan 369. En dat is hetzelfde als: als (woefie op de X as > 639) En dat is hetzelfde als:

if (woefie.x > 639)

Ok dat was het als gedeelte van de if statement: wanneer moet woefie omdraaien en spiegelen? Als zijn x groter is dan 369! En wat moet er gebeuren als dat klopt? Als dat klopt moet woefie omdraaien en spiegelen.

Om woefie makkelijk de andere kant op te laten gaan is het beter als we de regel binnen onze beweegWoefie functie wat aanpassen. De regel was:

woefie.x += 5;

maar het is makkelijk als we die 5 veranderen in een variabele die ook voor 5 staat maar we kunnen veranderen. Huh een variabele? Een variabele is iets waar je gegevens in op kan slaan van een bepaalt type, en elk moment wijzigen: Ons object woefie is ook een variabele (kijk maar toen we zeiden woefie = new var, var = variabele).

Als we die 5 nou eens opslaan in een variabele snelheid. Zolang de var snelheid 5 blijft veranderd er niks aan ons resultaat. Hoe maak je een variabele?

Als we kijken naar woefie, hij is gedefined op regel 19. Hieronder kan je onze nieuwe variabele maken:

public var snelheid:int

he int? Elk type variabele kan zijn eigen soort gegevens aan. het type int kan getallen opslaan (negatief en positief) dus in dit geval is een int handig. Nu moeten we zeggen dat de int snelheid in het begin 5 is, “in het begin” zegt het al een beetje: alles wat in het begin moet doe je in de contructor. We zetten dus onder de constructor:

snelheid = 5

Nu we een variabele snelheid hebben kunnen we gemakkelijk spelen met de snelheid. Als je zegt:

snelheid = -1

_dan heb je het al opgelost, huh hoe deed ik dat zo snel? snelheid *= -1 is hetzelfde als 5 = 5-1_. Altijd als je iets keer -1 doet dan zet je er een minnetje voor of haal je er een minnetje af. Ok er staat nu -5, waarom -5?

De snelheid bepaald waar woefie elk frame naar toe gaat. als de snelheid 5 is betekend dat: pak de huidige X positie en tel er 5 bij op. Maar nu krijgen we: pak de huidige X positie en tel er -5 bij op. Als je ergens een negatief getal bij optelt dan haal je het er eigenlijk gewoon van af: 5 +- 5 = 0 is hetzelfde als 5 – 5 = 0. En als we 5 van de X van woefie afhalen dan veranderd de X dus in een kleiner getal, een getal dichter bij 0. Op een X is dat dus richting links (0 punt), oftewel hij beweegt naar links.

Om ervoor te zorgen dat woefie het scherm niet uit kan rennen aan de rechterkant maken we dus deze if statement:

if (woefie.x > 639)
    {
        snelheid *= -1;
    }

Hah het werkt! maar nu gaat woefie links net zo makkelijk het scherm uit :(

We hebben al een if statement die er heel veel op lijkt dus we kunnen hem bijna kopieren.

if (woefie.x > 639)

639, dat is toch de grens aan de rechterkant? De grens aan de linkerkant is 0 dus dat veranderen we. woefie.x wordt steeds kleiner, moeten we dan kijken wanneer woefie.x groter is dan 0? Nee wanneer hij kleiner is dan 0.

if (woefie.x < 0)

woefie stuitert nu lekker heen en weer, alleen hij komt nooit helemaal links, het is meer alsof hij zijn kont stoot tegen de zijkant. Dit komt omdat het 0 punt van woefie ergens bij zijn kont zit. We kunnen 0 gewoon iets kleiner maken om het wel mooi te hebben. Ik maak er nu -100 van.

Maar woefie moet ook nog gespiegeld worden op het moment dat hij rechts op links het scherm uitgaat. Daarvoor kunnen we de scaleX variabele van woefie. Net als woefie.x is woefie.scaleX standaard beschikbaar alleen normaal doe je hier niet zoveel mee. Maar nu dus wel!

woefie.scaleX = -1;

Dit betekend spiegel woefie linksom.

woefie.scaleX = 1;

Dit betekend spiegel woefie niet (of reset hem als hij gespiegeld was). Als we deze toevoegen in de if statements kunnen we hem precies op het goede moment elke keer laten omdraaien.

Waar moeten we deze 2 if statements nou neerzetten? Om dat te weten moet je jezelf afvragen: Wanneer moet flash checken of woefie links of rechts het scherm uit gaat? Elk frame natuurlijk, dus je kan hem binnen je beweegWoefie functie zetten.

Onze functie beweegWoefie ziet er inmiddels zo uit:

public function beweegWoefie(event:Event):void 
        {
            woefie.x += snelheid;
            if (woefie.x > 639)
            {
                snelheid *= -1
                woefie.scaleX = -1;
            }
            if (woefie.x < -100)
            {
                snelheid *= -1
                woefie.scaleX = 1;
            }
        }

En als je dit alles uitvoerd, is dit ons resultaat: HondInKamer – Versie 0.3

Als we nu kijken naar ons lijstje:

  • In het begin is er een hond
  • De hond is op het midden van het scherm
  • Het scherm heeft een plaatje van een woonkamer
  • Wanneer flash een nieuw frame maakt wordt de hond iets meer naar rechts neergezet
  • Als de hond rechts is spiegel hem en laat hem naar links gaan
  • Als de hond links is spiegel hem en laat hem naar rechts gaan
  • Wanneer iemand op de hond klikt, maakt de hond een sprongetje.

zien we dat we alleen het laatste dingetje nog af moeten strepen. Dit ga ik in een andere post uitleggen.

Posted at December 05, 2010, under AS3.