Q/A: Hoe haal ik vier willekeurige woorden uit een lijst in AS3?

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.

Laatst kreeg ik de vraag hoe je het best een aantal willekeurige woorden uit een lijst haalt.

Hier heb ik even snel een klasse in elkaar gedraait die een array maakt, met daarin de top 50 films van IMDB. Hierna haal ik 4 willekeurige woorden uit dit array.

/** randomWords.as -- Mar 8, 2011
 *
 * Beschrijving: voorbeeld willekeurige woorden uit een array halen
 * 
 * @author Mike van Rossum
 *
 * Copyleft 2011, all wrongs reversed.
 */
package
{
    // Importeer benodigde classes
    import flash.display.Sprite;

public class randomWords extends Sprite
{
    // Variabele declaratie
    private var woordenLijst:Array;
    // Constructor functie
    public function randomWords()
    {
        woordenLijst = new Array(
            "The Shawshank Redemption (1994)",
            "The Godfather (1972)",
            "The Godfather: Part II (1974)",
            "The Good, the Bad and the Ugly (1966)",
            "Pulp Fiction (1994)",
            "Schindlers List (1993)",
            "12 Angry Men (1957)",
            "Inception (2010)",
            "One Flew Over the Cuckoo's Nest (1975)",
            "The Dark Knight (2008)",
            "Star Wars: Episode V - The Empire Strikes Back (1980)",
            "The Lord of the Rings: The Return of the King (2003)",
            "Seven Samurai (1954)",
            "Fight Club (1999)",
            "Goodfellas (1990)",
            "Star Wars: Episode IV - A New Hope (1977)",
            "Casablanca (1942)",
            "City of God (2002)",
            "The Lord of the Rings: The Fellowship of the Ring (2001)",
            "Once Upon a Time in the West (1968)",
            "Rear Window (1954)",
            "Raiders of the Lost Ark (1981)",
            "The Matrix (1999)",
            "Psycho (1960)",
            "The Usual Suspects (1995)",
            "The Silence of the Lambs (1991)",
            "Se7en (1995)",
            "It's a Wonderful Life (1946)",
            "Memento (2000)",
            "The Lord of the Rings: The Two Towers (2002)",
            "Toy Story 3 (2010)",
            "Sunset Blvd. (1950)",
            "Forrest Gump (1994)",
            "The Professional (1994)",
            "Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb (1964)",
            "Apocalypse Now (1979)",
            "Citizen Kane (1941)",
            "North by Northwest (1959)",
            "American Beauty (1999)",
            "American History X (1998)",
            "Taxi Driver (1976)",
            "Terminator 2: Judgment Day (1991)",
            "Saving Private Ryan (1998)",
            "Vertigo (1958)",
            "Alien (1979)",
            "Amélie (2001)",
            "WALL·E (2008)",
            "Spirited Away (2001)",
            "The Shining (1980)",
            "Paths of Glory (1957)"
        );

        var willekeurigWoord1:String = new String;
        var willekeurigWoord2:String = new String;
        var willekeurigWoord3:String = new String;
        var willekeurigWoord4:String = new String;

        var random:int = new int;
        random = Math.random()*50;
        willekeurigWoord1 = woordenLijst[random];

        random = Math.random()*50;
        willekeurigWoord2 = woordenLijst[random];

        random = Math.random()*50;
        willekeurigWoord3 = woordenLijst[random];

        random = Math.random()*50;
        willekeurigWoord4 = woordenLijst[random];

        trace(willekeurigWoord1);
        trace(willekeurigWoord2);
        trace(willekeurigWoord3);
        trace(willekeurigWoord4);
    }

    // Eigen functies
}

(Je moet de code in debug runnen omdat ik antwoorden alleen trace, je kan de strings willekeurigWoord1-4 nu in textfields stoppen of wat je er ook mee wilt doen.)

Houd er rekening mee dat een woord meerdere keren kan voorkomen.

Posted at March 08, 2011, under AS3.

How to create beatiful snow in flash (using ActionScript 3)

In this article I’m going to make realistic snow in ActionScript 3, I programmed this in Adobe Flash Builder. I uploaded a youtube video with the result, but the realtime flash example looks a lot better.

First I post the code, which is licensed under copyleft (that means you can use it as long as you credit me and also license it under copyleft). and after that I’ll explain the code so you’ll understand it.

I’ll create 1000 snowflakes all falling down. You can manipulate the wind using your keyboard arrows and your mouse.

This was the first real program I ever created so the code is probably not very optimized (for example, when writing this I didn’t knew about the default drag capabilities of AS3) and/or ugly. To understand this article, basic programming knowledge is very useful.

There are two classes. The first class is Ball:

/** Ball.as -- Nov 24, 2010
 *
 *
 * @author Mike van Rossum 
 *
 *
 * Copyleft 2011, all wrongs reversed.
 */
package
{
    // Import everything we need
    import flash.display.Sprite;
    import flash.text.TextField;

public class Ball extends Sprite
{
    // Import everything we need
    public var baseX:int;
    public var angle:Number;
    public var sway:Number;
    public var largeness:int;

    public function Ball()
    {
        largeness = Math.random()*8;
        graphics.beginFill(0xffffff);
        graphics.drawCircle(0,0,largeness);
        graphics.endFill();
    }
}

And all the magic happens in the second class:

/** Snow.as -- Nov 24, 2010
 *
 *
 * @author Mike van Rossum 
 *
 * Copyleft 2011, all wrongs reversed.
 */
package
{
  // Import everything we need
  import flash.display.Bitmap;
  import flash.display.Sprite;
  import flash.display.StageAlign;
  import flash.display.StageScaleMode;
  import flash.events.Event;
  import flash.events.KeyboardEvent;
  import flash.events.MouseEvent;
  import flash.geom.Point;

public class Snow extends Sprite
  {
    //declare variables
    private var sleepStart:Point;
    private var sleepStop:Point;
    private var wind:int;
    private var line:Sprite;
    private var angle:Number;
    private var flakes:Array;
    private var screen:Sprite;

public function Snow()
{

  //I always add these lines in all my AS3 programs 
  //those make sure every 1 pixel we calculate really is 
  //1 pixel on the screen. The last one makes sure that 
  //the 0,0 point is in the left-upper corner of the screen.

  stage.scaleMode = StageScaleMode.NO_SCALE;
  stage.align = StageAlign.TOP_LEFT;

  //here I make sure all these functions are run when they are supposed to.

  addEventListener(Event.ENTER_FRAME, moveAll);
  stage.addEventListener(KeyboardEvent.KEY_DOWN, changeTheWind);
  stage.addEventListener(MouseEvent.MOUSE_DOWN, startLine);
  stage.addEventListener(MouseEvent.MOUSE_UP, endLine);

  //Here I make a rectangle with the same size as the 
  //screen and fill it black. This is our background.

  screen = new Sprite();
  screen.graphics.beginFill(0x000000,1);
  screen.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
  addChild(screen);

  //Here I call the function createSnow to be executed.
  createSnow();

  //Those are for my own drag and drop function
  sleepStart = new Point();
  sleepStop = new Point();

  //I add the line that will be drawed already
  //so I only have to manipulate it's form later
  line = new Sprite();
  addChild(line);
}

//This function is executed every frame, 
//and makes sure everything animates. 
//Note that I call the function moveSnow here, this means that 
//every frame the function moveSnow is executed.

public function moveAll(event:Event):void
{
  line.alpha -= .1;
  moveFlakes();
}  

//Here is the function where I create all the snow flakes. 
//I specify how I make one snow flake, and how I position it on 
//the screen. After that I put that code into a for loop so it will 
//be executed multiple times (in my case 1000). I use Math.random 
//function to calculate random numbers so that every time my code 
//is executed, the numbers are not the same.

public function createSnow():void
{
  var flake:Ball;

  //I put all those 1000 flakes in an array so I 
  //can easy manipulate them later on.

  flakes = new Array();

  for (var i:int = 0; i < 1000; i++)
  {
    flake = new Ball();
    flake.baseX = Math.random() * stage.stageWidth;
    flake.x = flake.baseX;
    flake.y = Math.random() * stage.stageHeight - stage.stageHeight;
    flake.angle = Math.random() * 10;
    flake.sway = flake.largeness * 7;
    addChild(flake);
    flakes.push(flake);
  }
}

//As you see probably have seen you can manipulate the 
//wind by using your mouse and the keyboard. The latter 
//is described in this function. The function is called 
//every time someone pushes any button on his keyboard. 

public function changeTheWind(Event:KeyboardEvent):void
{

  //We make use of the if statement so that something only happens 
  //when the button pressed is the right or left arrow.

  if (Event.keyCode == 39) // = arrow right
  {
    wind ++;
  }
  else if (Event.keyCode == 37) // = arrow left
  {
    wind --;
  }
}  

//These two functions check how far you dragged your mouse. 
//They save the location where you press you mouse and 
//compare that to where you release it. Based on the 
//difference in X position of the two locations the wind speed is set.

//These locations are stored in the vars we set in the function Snow. 
//So that we can re-use those vars when someone makes a new drag.

public function startLine(Event:MouseEvent):void
{
  sleepStart.x = Event.stageX;
  sleepStart.y = Event.stageY;
}  

public function endLine(Event:MouseEvent):void
{
  sleepStop.x = Event.stageX;
  sleepStop.y = Event.stageY;
  drawLine();
}

//After those mouse locations are saved a line is drawed. The 
//start point is the start point of the mous and the end 
//point is where you stop dragging it. In the function moveAll 
//there is a line which makes the line we just created every 
//frame a little les visable.

//Every second time someone makes a drag, the variable line is re-used.

public function drawLine():void
{
  var lengte:int;
  line.graphics.clear();
  line.graphics.lineStyle(5,0x7FD1E7);
  line.graphics.moveTo(sleepStart.x,sleepStart.y);
  line.graphics.lineTo(sleepStop.x,sleepStop.y);
  line.alpha = 1;
  lengte = sleepStop.x - sleepStart.x;
  wind = lengte/12;
}    

//This is where all the already created flakes are moved.

//Note that all the movement is relative to the size of the flake (the largeness 
//variable from Ball). This creates the illusion of depth. The smaller 
//flakes look further behind and therefor need to move slower.

public function moveFlakes():void
{
  //This line makes sure that all the 
  //code nested in the brackets ( { } ) is run everytime for every flake. 
  //Every flake is called one time during this. As you can imagine this puts 
  //a lot of stress to your PC because every bit of code inside these brackets 
  //has to be run 24 (frames per second) times 1000 (the number of flakes) = 24 000 times per second.

  for each (var vlok:Ball in flakes)
  {
    //For the X position of the flake I use a little math trick 
    //including the sinus (I go a lot further with that in this 
    //dutch tutorial about atoms). You don't have to understand this 
    //line, just know that this is the sway move of all the flakes. 
    //The size of the sway is decided by the largeness of the Flake 
    //(from the class Ball).

    vlok.x = vlok.baseX + Math.sin(vlok.angle) * vlok.sway;

    //On this line we pull down all the flakes, again relative 
    //to their size. When we add something to the Y position 
    //of a Sprite and the Y- zero position is on top. We're moving 
    //it downwards.

    vlok.y += vlok.largeness /2;
    vlok.angle += .1;
    vlok.baseX += wind/7*vlok.largeness;

    //Now we got all the snow moving but when 
    //it leaves the screen we're lost in an empty 
    //black screen and still your computer has to 
    //calculate the position of a Sprite 24 000 times 
    //every second. Therefor you can find 3 if statements here. 
    //They wrap your screen so to say. It just means that if a 
    //flake gets outside the screen, put it back on the other side. 
    //The first if statement is for the bottom border. The other two 
    //for the sides.

    if (vlok.y > stage.stageHeight)
    {
      vlok.y = 0 - vlok.sway;
      vlok.baseX = Math.random() * stage.stageWidth;
      vlok.x = vlok.baseX;
    }

    if (vlok.x - vlok.sway > stage.stageWidth)
    {
      vlok.baseX = 1 - vlok.sway;
      vlok.y = Math.random() * stage.stageHeight;
    }

    if (vlok.x < 0 - vlok.sway)
    {
      vlok.baseX = stage.stageWidth - 1 + vlok.sway;
      vlok.y = Math.random() * stage.stageHeight;
    }    

  }
}

In the detailed comments I explained how everything works.

Posted at January 26, 2011, under AS3.

Media Design opdracht: Ident voor Dolores Adventures

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.

For the subject Media Design we need to make an ident (introduction clip of something like 5 seconds) for a fictional game. We only had the name of the game and we could make the rest up. The name of the game is “Dolores Adventures” After designing a logo and style I had to make an ident.

We were free to make it in whatever we wanted (filming, stopmotion, animating), my love for ActionScript (since two months or so) made me make it in Flashbuilder.

Here is the ident for Dolores Adventures.

The code is fast written, easy and probably not very beautiful to look it, but you can use whatever you want from it. I use two classes. The class Bal (which is explained in my last tutorial in dutch) and the custom class for the ident. I work with a couple of timers to time everything out nice to the music.

/** Main.as -- Jan 16, 2011
 *
 * Beschrijving: [beschrijving van dit bestand]
 * 
 * @author Mike van Rossum
 *
 * Copyleft 2011, all wrongs reversed.
 */
package
{
    // Importeer benodigde classes
    import Bal;

import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.media.Sound;
import flash.net.URLRequest;
import flash.utils.Timer;
import flash.utils.getTimer;

public class Main extends Sprite
{
    // Variabele declaratie
    private var yellowScreen:Sprite;
    private var yellowBlock:Sprite;

    [Embed(source="pics/Naamloos-2.jpg")] // verwijzing naar het bestand in de pics map
    private var Plaatje:Class; // Abstracte klasse die gebruikt wordt om het plaatje in te laden
    private var cleanLogo:Bitmap; // Bitmap object waarmee je het plaatje op de stage zet

    [Embed(source="pics/boom.png")] // verwijzing naar het bestand in de pics map
    private var Boom:Class; // Abstracte klasse die gebruikt wordt om het plaatje in te laden
    private var boom:Bitmap; // Bitmap object waarmee je het plaatje op de stage zet

    [Embed(source="pics/horrors.gif")] // verwijzing naar het bestand in de pics map
    private var Horrors:Class; // Abstracte klasse die gebruikt wordt om het plaatje in te laden
    private var horrors:Bitmap; // Bitmap object waarmee je het plaatje op de stage zet

    [Embed(source="pics/hangman.gif")] // verwijzing naar het bestand in de pics map
    private var Hangman:Class; // Abstracte klasse die gebruikt wordt om het plaatje in te laden
    private var hangman:Bitmap; // Bitmap object waarmee je het plaatje op de stage zet

    private var countTillSlogan:Timer;
    private var countTillHorror:Timer;
    private var countTillHangman:Timer;
    private var countTillBoom:Timer;

    private var trilling:int;

    private var slogan:Sound;
    private var boomTime:Boolean;
    private var bloed:Array;

    // Constructor functie
    public function Main()
    {
        stage.align = StageAlign.TOP_LEFT;
        stage.scaleMode = StageScaleMode.NO_SCALE;

        yellowScreen = new Sprite;
        yellowScreen.graphics.beginFill(0xECE985);
        yellowScreen.graphics.drawRect(0,0,750,500);    
        addChild(yellowScreen);

        cleanLogo = new Plaatje();
        cleanLogo.alpha = 0;
        cleanLogo.x = 30;
        addChild(cleanLogo);

        horrors = new Horrors();
        horrors.x = 332;
        horrors.y = 312;
        horrors.alpha = 0;
        addChild(horrors);

        yellowBlock = new Sprite;
        yellowBlock.graphics.beginFill(0xECE985);
        yellowBlock.graphics.drawRect(0,0,20,70);
        yellowBlock.alpha = 0;
        yellowBlock.x = 382;
        yellowBlock.y = 200;
        addChild(yellowBlock);

        hangman = new Hangman();
        hangman.alpha = 0;
        hangman.x = 360;
        hangman.y = 155;
        hangman.rotation = 11;
        addChild(hangman);

        boomTime = new Boolean;
        boomTime = false;

        countTillSlogan = new Timer(1000,1);
        countTillSlogan.addEventListener(TimerEvent.TIMER, startSlogan);
        countTillSlogan.start();

        countTillHorror = new Timer(2392,1);
        countTillHorror.addEventListener(TimerEvent.TIMER, startHorror);
        countTillHorror.start();

        countTillHangman = new Timer(3392,1);
        countTillHangman.addEventListener(TimerEvent.TIMER, startHangman);
        countTillHangman.start();   

        countTillBoom = new Timer(5792,1);
        countTillBoom.addEventListener(TimerEvent.TIMER, startBoom);
        countTillBoom.start();

        bloed = new Array;

        for (var i:int=0; i<18; i++)
        {
            var bal:Bal;
            bal = new Bal(0xff0000,1.5);
            bal.cirkel.alpha = 0;
            addChild(bal.cirkel);
            bloed[i] = bal.cirkel;
            bloed[i].x = 370 + 15 * Math.random();
            bloed[i].y = 245 + 220 * Math.random(); 
        }
    }

    // Eigen functies

    public function startSlogan(event:TimerEvent):void 
    {
        slogan = new Sound();
        slogan.load(new URLRequest("sounds/slogan-ident.mp3"));
        slogan.play();

        addEventListener(Event.ENTER_FRAME, fadeCleanLogo);
    }

    public function fadeCleanLogo(event:Event):void 
    {

        if (cleanLogo.alpha < 1)
        {
            cleanLogo.alpha += .15;
            trilling = (trilling + 5) % 10;
            cleanLogo.y = 80 + trilling;
        }
        else
        {
            removeEventListener(Event.ENTER_FRAME, fadeCleanLogo);
        }
    }
    public function fadeHorrors(event:Event):void 
    {               
        if (horrors.alpha < 1)
        {
            horrors.alpha += .3;
        }
        else
        {
            removeEventListener(Event.ENTER_FRAME, fadeHorrors);
        }
    }

    public function startHorror(event:TimerEvent):void 
    {
        addEventListener(Event.ENTER_FRAME, fadeHorrors);
    }

    public function startHangman(event:TimerEvent):void 
    {
        addEventListener(Event.ENTER_FRAME, moveHangman);
    }

    public function moveHangman(event:Event):void 
    {
        if (hangman.alpha < 1)
        {
            yellowBlock.alpha += .15;
            hangman.alpha += .15;
        }   
        else
        {
            startBloed();
        }

        if (hangman.rotation > 2 )
        {
            hangman.rotation -= 1;
        }   
    }

    public function startBloed():void 
    {
        for (var i:int=0; i<18; i++)
        {
            setBloedAlpha(i);
        }
        addEventListener(Event.ENTER_FRAME, moveBloed);
        removeEventListener(Event.ENTER_FRAME, moveHangman);
    }

    public function setBloedAlpha(j:int):void 
    {
        bloed[j].alpha = 1;
    }

    public function moveBloed(event:Event):void 
    {
        for (var i:int=0; i<18; i++)
        {
            bloed[i].y ++;

            if (bloed[i].y > 445 || boomTime == true)    
            {
                bloed[i].alpha -= .05;
            }

            if (bloed[i].alpha <= 0 && boomTime == false)
            {
                bloed[i].y = 245;
                setBloedAlpha(i);
            }
        }
    }

    public function startBoom(event:TimerEvent):void 
    {   

        boomTime = true;

        removeChild(cleanLogo);
        removeChild(horrors);
        removeChild(hangman);

        boom = new Boom();
        boom.alpha = 1;
        boom.x = 40;
        boom.y = 107;
        addChild(boom);

        addEventListener(Event.ENTER_FRAME, BoomLogo);
    }

    public function BoomLogo(event:Event):void 
    {       
        boom.scaleX *= 1.05;
        boom.x -= boom.width / 40;

        boom.scaleY *= 1.05;
        boom.y -= boom.height / 40;

        boom.alpha -= .05;
    }
}

Let me know what you think!

Posted at January 17, 2011, under AS3design.

ActionScript 3 Tutorial: Atomen animeren

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 tutorial ga ik uitleggen hoe ik de atomen uit mijn laatste opdracht voor het vak programmeren (in AS3) heb gemaakt. Het niveau van deze tutorial is niet heel hoog zodat het voor een stuk meer mensen toegankelijk is.

Eerst ga ik een class Bal maken met nogal simpele code, ik richt de class zo in dat wanneer ik een bolletje nodig heb ik deze zo kan importeren. Ik werk met hierbij met zogeheten arguments/parameters.

Arguments/parameters De makkelijkste manier om dit uit te leggen is om een situatie te schetsen. Stel je voor dat je een huisrobot programmeert om boodschappen voor je te doen: Je programmeert dat hij naar de supermarkt moet lopen, hoe hij met betalen en hoe hij terug moet lopen. Nu zijn deze dingen altijd hetzelfde, alleen moet je elke keer iets anders hebben van de supermarkt. Het makkelijkste zou zijn om hem naar de supermarkt te sturen met een boodschappenlijstje, dit is precies wat een argument is. De syntax ziet er als volgt uit:

voerFunctieUit(argument1, argument2, etc);

(dit is dus in principe je booschappenlijstje)

Hier is de code van de class Bal:

/** Bal.as -- Jan 6, 2011
 *
 * Beschrijving: [beschrijving van dit bestand]
 * 
 * @author Mike van Rossum
 *
 * Copyleft 2011, all wrongs reversed.
 */
package
{
    import flash.display.Sprite;

// Importeer benodigde classes
public class Bal
{
    public var cirkel:Sprite;   
    // Constructor functie
    public function Bal(kleur:uint, grootte:int)
    {
        cirkel = new Sprite;
        cirkel.graphics.beginFill(kleur);
        cirkel.graphics.drawCircle(0,0,grootte);
        cirkel.graphics.endFill();
    }
    // Eigen functies
}

Zoals je ziet zijn er twee argumenten, kleur en grootte. Elke keer als je een Bal wilt maken kan je meegeven welke kleur en hoe groot hij moet zijn. Op deze manier hoef je niet elke keer alle code te kopiëren en de kleur en grootte aan te passen.

En dan nu de Classe voor de atomen, ik begin met de basis variant en maak hem steeds moeilijker. Maar eerst een klein beetje theorie om te snappen hoe hij werkt. Hier is een stukje code van Justus dat een Sprite rond laat draaien. Dit stukje code hoef je niet te begrijpen, je moet alleen weten dat die 2 regels code iets in een cirkel kunnen laten bewegen. De beweging zit in Angle, dit staat voor een getal dat elk frame veranderd. Hij begint als 0 en elke keer komt er 0,1 bij.

Hierin zijn 2 waardes belangrijk als je er mee wilt gaan spelen: angle: als je deze kleiner maakt gaat de bal langzamer. En de waarde die nu 100 is. Deze staat gelijk aan de grootte van de cirkel.

Hieronder staat de code om een rode bal (half doorzichtig) te maken en hierin kleinere blauwe balletjes die volgens Justus zijn formule allemaal een rondje draaien.

/** Atoms.as -- Jan 10, 2011
 *
 * Beschrijving: [beschrijving van dit bestand]
 * 
 * @author Mike van Rossum
 *
 * Copyleft 2011, all wrongs reversed.
 */
package
{
    // Importeer benodigde classes
    import Bal;

import flash.display.Sprite;
import flash.events.Event;

public class Atoms extends Sprite
{
    // Variabele declaratie
    private var array:Array;
    private var angle:Number;
    private var rodeBal:Bal;
    private var defCircling:int;

    // Constructor functie
    public function Atoms()
    {
        addEventListener(Event.ENTER_FRAME, MoveAtoms);     

        array = new Array;

        angle = new Number;
        angle = 0;

        for (var i:int=0; i<15; i++)
        {
            var bal:Bal;
            bal = new Bal(0x0000ff,10);
            addChild(bal.cirkel);
            array[i] = bal.cirkel;
        }

        defCircling = new int;
        defCircling = 100;

        rodeBal = new Bal(0xff0000,160);
        rodeBal.cirkel.y = stage.stageHeight/2;
        rodeBal.cirkel.x = stage.stageWidth/2
        rodeBal.cirkel.alpha = .5;
        addChild(rodeBal.cirkel);   
    }

    // Eigen functies
    public function MoveAtoms(event:Event):void 
    {
        angle += .1;
        for (var i:int=0; i<15; i++)
        {
            array[i].x = stage.stageWidth/2 + Math.sin(angle) * 100;
            array[i].y = stage.stageHeight/2 + Math.cos(angle) * 100;
        }
    }
}

Hier is het resultaat gecompileerd

Ik maak eerst een rode bal en een Array aan. in de Array ga ik zometeen een aantal kleine balletjes stoppen. Dat doet ik met een foor loop om mijn werk te besparen. Het principe werkt als volgt: Alles wat in een for loop staat wordt niet 1 maar meerdere keren uitgevoerd. het nummertje I wat je overal in de foor loop ziet staan is iets wat gelijk is aan een nummer, hoeveel dit nummer is is afhankelijk van hoe vaak de for loop de code al heeft uitgevoerd. In mijn geval voert hij hem 15 keer uit. In het begin is i 0, de volgende keer 1, enzovoorts. Er worden dus gewoon 15 ballen aangemaakt.

Als je nu nog iets met een bal uit een Array wil doen kan je hem niet aanspreken als bal (daar zijn er namelijk meer van) maar als Array[nummer uit array]. Als je ze allemaal aan wilt spreken is het makkelijk om gewoon dezelfde for loop te gebruiken waarmee je ze hebt gemaakt. In ons geval is dat precies wat we willen. dus daarom zie je in de functie MoveAtoms dezelfde for loop als in de constructor.

Hoe komt het dat je maar 1 balletje ziet bewegen? We hebben 15 ballen en die bewegen we precies hetzelfde. Ze zitten dus elk frame precies op elkaar. Om te zorgen dat ze allemaal zichtbaar zijn kan je een aantal dingen doen:

  • Je kan de de draaicirkel van de een kleiner maken dan de ander
  • Je kan de een sneller laten gaan dan de ander
  • Je kan de cirkels op een ander punt laten starten

Laten we beginnen met optie 1 Met een for loop pas je de beweging van de balletjes aan, deze is voor elke bal hetzelfde dus het lijkt heel moeilijk. Maar dat is het niet want je hebt namelijk het getal i (een variabele die gelijk staat aan een getal, zelfs elke keer een ander getal) meenemen om de grootte van de draaicirkel te bepalen.

In dit geval is dat 100 maar we kunnen daar ook een rekensommetje inzetten: Laten we doen (i * 25). Dit betekend dat de for loop elke keer dezelfde code uitvoert en dan 1 bij i optelt. i begint bij 0 en wordt elke keer groter. Op deze manier wordt de grootte van de cirkel afhankelijk van de i.

Zie hier het resultaat.

Laten we de een sneller laten draaien dan de ander We kunnen weer met de i werken om elke bal een andere snelheid te geven. Ik zou al dat het met angle te maken had dus we maken hier een sommetje van om de i hier ook in te verwerken. Na wat spelen met verschillende getallen vond ik deze combinatie:

(angle *(i+7)/10)

Ik doe angle (wat elke keer veranderd) keer i + 7 en dat deel ik door 10. Al je dat doet krijg je dit resultaat (ik heb de balletjes ondertussen iets kleiner gemaakt).

Dit is de basis voor atomen, om het resultaat te krijgen wat lijkt op een atoom passen we alles dubbel toe wat we nu hebben. Om dit uit te leggen gebruik ik een voorbeeld van de aarde. De aarde draait net als een van onze blauwe balletjes om de zon (de rode bal). Om de aarde draait weer een maan. Probeer je dit te visualiseren en maak dan de aarde onzichtbaar. hier kan je zien wat ik bedoel. De half doorzichtige blauwe cirkels draaien rond en op basis van die positie draaien de kleine balletjes erin ook rond.

Zolang de binnenste draaibeweging heel klein blijft vergeleken met de buitenste draaibeweging blijf je het planeet met maan idee krijgen. Maar wanneer je de binnenste draaibeweging een stuk groter maakt krijg je andere vormen.

Hoe doe je dit in code?

Eerst hadden we een som en daarmee rekende we rechtstreeks de x en y positie uit van de bal per frame. Nu moeten we eerst de positie van de “aarde” opslaan (ook al is de aarde zelf niet zichtbaar) en vanuit dit punt een nieuwe berekening doen voor de maan.

voor het opslaan van getallen (namelijk een x en y positie van de “aarde”) gebruiken we variabelen. Net als angle. Het voordeel van een variabele ten opzichte van een direct getal is dat we de variabele kunnen aanpassen en op deze manier de uitkomst van de som veranderen zonder de som zelf te veranderen. We gaan nu twee variabelen maken waarin we elk frame de locatie van “aarde” opslaan.

private var cirkely:int = new int;
        private var cirkelx:int = new int;

Als je dit voor je constructor zet dan kan je ze later gebruiken.

En de code voor atomen ziet er zo uit:

cirkely = positieXCirkel + Math.sin(angle(i+7)/10) * 100;
            cirkelx = positieYCirkel + Math.cos(angle(i+7)/10) * 100           

        array[i].y = cirkely + Math.sin(-angle*(i+7)/20) * 50;
        array[i].x = cirkelx + Math.cos(-angle*(i+7)/20) * 50;

Zoals je ziet zie je twee keer de formule om iets in een cirkelbeweging te laten gaan. Alleen bij de eerste slaan we alleen de positie op in twee variabelen (de aarde: cirkely en cirkels) en vanuit die relatieve positie beginnen we de formule opnieuw. Door te spelen met de getallen kom je tot verschillende resultaten.

Het resultaat ziet er dan uit zoals in het filmpje (de atoom die links begint).

Na wat spelen met de getallen kom ik uit op hier kan zien.

Hier is de uiteindelijke broncode van het bovenstaande voorbeeld.

/** Atoms.as -- Jan 10, 2011
 *
 * Beschrijving: [beschrijving van dit bestand]
 * 
 * @author Mike van Rossum
 *
 * Copyleft 2011, all wrongs reversed.
 */
package
{
    // Importeer benodigde classes
    import Bal;

import flash.display.Sprite;
import flash.events.Event;

public class Atoms extends Sprite
{
    // Variabele declaratie
    private var arrayLinks:Array;
    private var arrayRechts:Array;

    private var grootteBal:int;
    private var angle:Number;

    private var linkerCirkel:Bal;
    private var rechterCirkel:Bal;

    private var LinkerCirkely:int;
    private var LinkerCirkelx:int;

    private var rechterCirkely:int;
    private var RechterCirkelx:int;

    private var vis:Number;

    // Constructor functie
    public function Atoms()
    {
        addEventListener(Event.ENTER_FRAME, MoveAtoms);     

        LinkerCirkely = new int;
        LinkerCirkelx = new int;

        rechterCirkely = new int;
        RechterCirkelx = new int;

        arrayRechts = new Array;
        arrayLinks = new Array;

        vis= new Number;
        vis = .035

        angle = new Number;
        angle = 0;

        for (var i:int=0; i<15; i++)
        {
            var bal:Bal;
            bal = new Bal(0x0000ff,6);
            addChild(bal.cirkel);
            arrayLinks[i] = bal.cirkel;
        }

        for (var j:int=0; j<15; j++)
        {
            var bal:Bal;
            bal = new Bal(0x0000ff,6);
            addChild(bal.cirkel);
            arrayRechts[j] = bal.cirkel;
        }

        linkerCirkel = new Bal(0xff0000,117);
        linkerCirkel.cirkel.y = stage.stageHeight/2; 
        linkerCirkel.cirkel.x = stage.stageWidth/20;
        linkerCirkel.cirkel.alpha = .5;
        addChild(linkerCirkel.cirkel);  

        rechterCirkel = new Bal(0xff0000,30);
        rechterCirkel.cirkel.y = stage.stageHeight/2;
        rechterCirkel.cirkel.x = stage.stageWidth/20*18; 
        rechterCirkel.cirkel.alpha = .5;
        addChild(rechterCirkel.cirkel); 
    }

    // Eigen functies
    public function MoveAtoms(event:Event):void 
    {

        //dit moeten we elk frame verhogen om te zorgen dat er een draaibeweging is
        angle += .1;

        //laat de rechterCirkel in en uit faden.
        rechterCirkel.cirkel.alpha -= vis;
        if (rechterCirkel.cirkel.alpha >= 1 || rechterCirkel.cirkel.alpha <= 0 )
        {
            vis *= -1;
        }

        //beweeg linkerballetjes
        for (var i:int=0; i<15; i++)
        {   
            LinkerCirkely = stage.stageHeight/2 + Math.sin(angle*(i+7)/8) * 50;
            LinkerCirkelx = stage.stageWidth/20  + Math.cos(angle*(i+7)/8) * 50;

            arrayLinks[i].y = LinkerCirkely + Math.sin(-angle*(i+7)/100) * 60;
            arrayLinks[i].x = LinkerCirkelx + Math.cos(-angle*(i+7)/100) * 60;
        }

        //beweeg rechterballetjes
        for (var j:int=0; j<15; j++)
        {
            rechterCirkely = stage.stageHeight/2 + Math.sin(angle*(j+7)/8) *  60;
            RechterCirkelx = stage.stageWidth/20*18 + Math.cos(angle*(j+7)/8) * 60;

            arrayRechts[j].y = rechterCirkely + Math.sin(-angle*(j+7)/20) * 25;
            arrayRechts[j].x = RechterCirkelx + Math.cos(-angle*(j+7)/20) * 25;
        }
    }
}

Posted at January 13, 2011, under AS3.

deeltoets 3: The origin of Snow

Today we had to hand in our final assignment for the subject Programming: Action Script 3. After my last assignment snow I wasn’t sure what to make next that would be at least as good as snow was. After a some time I knew I couldn’t just add stuff into snow to make it work better, so I thought: Why not make an intro movie or something? In the meantime I was practicing some things like arrays in arrays and the z index and I already had some half project lying around.

Here is everything combined together, into a full science science documentary! For the full experience sound is required. Here is The Origin of Snow (and basically everything else)!

When you see snow, you can make drag movements with your mouse.

Let me know what you think!

Posted at January 11, 2011, under AS3.