Gepost door: gert | februari 19, 2008

Polyformisme in ActionScript 2

ActionScript ondersteunt ook polyformisme, zij het in een eenvoudiger vorm dan in programmeertalen als Java bvb.

Dit voorbeeld maak ik in FlashDevelop 3 beta 6.

Wat is polyformisme?

Polyformisme is één van de belangrijkste pijlers van OO programmeren. Het is een toepassing van overerving, waarbij dezelfde methode in de superklasse en de subklassen, een andere implementatie krijgen.

Overerving

Ik maak twee testklassen.

class Class1 {
public function talk():Void {
trace(“Hello world 1″) ;
}
}

class Class2 extends Class1 {
public function count():Void {
trace(“2″)
}
}

Class2 overerft Class1 en voegt een count() functie toe.

De Application klasse zal Class1 en Class2 implementeren. Let op de static functie ‘main() ‘ (! case-sensitive). Default zal FlashDevelop deze functie gebruiken als startpunt voor de swf. Je hebt dan geen Flash IDE nodig.

class Application {
public static function main() {
var c1_1:Class1 = new Class1()
c1_1.talk() ;

var c2_2:Class2 = new Class2()
c2_2.talk() ;
c2_2.count() ;
}
}

We testen de movie en krijgen de volgende output:

Hello world 1
Hello world 1
2

Class2 gebruikt de functie talk() die geïmplementeerd is in Class1. Als je met overerving werkt, moet je dus niet alleen de functies kennen van de klasse waarin je werkt, maar ook van al de superklassen. Een goede IDE als FlashDevelop zal je snel naar deze functies leiden (via F4).

Een functie overschrijven

Je kan nu in Class2 de functie ‘talk()’ van de superklasse, overschrijven en op een andere manier implementeren.

class Class2 extends Class1 {
public function count():Void {
trace(“2″)
}
public function talk():Void {
trace(“Hello world 2″) ;
}
}

We testen de movie. De output is nu:

Hello world 1
Hello world 2
2

Polyformisme

Afhankelijk van de implementatie, kan een object van een bepaald datatype, zich ‘anders’ gedragen. Voeg de volgende regels toe aan de Application klasse:

var c2_1:Class1 = new Class2()
c2_1.talk() ;

Wat zal de output nu zij, “Hello world 1″ of “Hello world 2″? We testen de movie.

Hello world 1
Hello world 2
2
Hello world 2

c2_1 wordt gedeclareerd als van het datatype Class1, maar geïnstantieerd met Class2.

Omdat Class1 een Class2 is (zie bovenstaande regels), is dit geldig. De compiler genereert geen fout. At runtime, zal c2_1 een object toegewezen krijgen van het datatype Class2 en de implementatie van de functie ‘talk’ van de klasse Class2 uitvoeren.

Opmerking i.v.m. overerving

Overerving van klassen is essentieel binnen OO programmeren. Maar wordt meestal te snel toegepast, zodat je aan flexibiliteit inboet. Je mag pas een klasse overerven, indien de subklasse voldoet aan de volgende 2 eenvoudige, maar zeer belangrijke regels:

  1. De subklasse voldoet aan de “is een…“-regel. Bvb. een student is een persoon.
  2. De subklasse implementeert alle functies van de superklasse waarvan ze wil overerven.

In alle ander gevallen dient compositie i.p.v. overerving gebruikt te worden. Overerving is zeer verlijderlijk omdat het initieel (type)werk bespaart, maar het wordt moeilijker om terug te vinden, welke klasse een bepaalde functie implementeert.

In ActionScript wordt er – naar mijn mening – veel te snel een MovieClip overgeërft en daarmee gezondigd tegen bovenstaande regels (vooral de eerste). Ik zal voor het gebruik van een MovieClip in een klasse, altijd compositie gebruiken, waarbij ik meestal de MovieClip meegeef in de constructor.

Besluit

Met polyformisme wordt bedoeld dat een bepaald datatype, zich kan ‘gedragen’ als een datatype van de subklassen, omdat deze subklassen een functie van de superklasse anders implementeren.

Gepost door: gert | februari 16, 2008

Expressies, wat zijn het?

Wat is een expressie?

Een expressie is een verwijzing naar een waarde.

vb.:

dim s as String ‘Dit is geen expressie, maar een initialisatie.
s = “Hello Word” ‘Dit zijn 2 expressies

  1. s is een expressie. Inderdaad, het verwijst naar een waarde.
  2. s = “Hello World” is ook expressie. Het toekennen van een waarde is zowiezo een expressie.
Vb.:

Dim s As Persoon = new Student()

Dit zijn 3 expressies

  1. new Persoon() verwijst naar een Persoon object
  2. = new Persoon() is een toekenning
  3. s verwijst naar een Student object
Vb.:

a < b ‘een booleaanse expressie.
a = 5 ‘een integer expressie
a = “yo de manne” ‘een string expressie

enz.

Gepost door: gert | februari 7, 2008

Arguments van function

Het keyword arguments

Je weet niet altijd op voorhand hoeveel parameters je moet voorzien in een functie.

Alle argumenten van een functie worden bijgehouden in de array arguments van die functie, een gereserveerd keyword.

Voorbeeld: het gemiddelde berekenen van een aantal getallen

trace(gemiddelde(1,2,3,4,5,6,7))

function gemiddelde() : Number{
var som:Number = 0;
for (var i:Number = 0; i < arguments.length; i++) {
som += arguments[i];
}
return som / arguments.length ;
}

Gepost door: gert | februari 7, 2008

Circle- circle collision detection

Een botsing tussen twee cirkels detecteren, is niet zo eenvoudig. Het vraagt een goede basis van Wiskunde. Even diep ademhalen… daar gaan we.

Doel

We berekenen of er een botsing zal optreden tussen twee cirkels, na een bepaalde tijd, in memory. Daarvoor hebben we nodig:

  • de plaats van de cirkels: x1, y1, x2, y2
  • de snelheid waarmee ze bewegen: x1Mov, y1Mov, x2Mov, y2Mov
  • de tijd waarnaar we rekenen: t

Wanneer is er een botsing?

Twee cirkels botsen als de som van hun stralen kleiner of gelijk is aan de afstand tussen de cirkels.

circle-circle-collision.gif

We berekenen

snelheid = afstand / tijd
afstand = snelheid * tijd

x1 = xo1 + x1Mov * t -> xo1 is de oude x1
y1 = yo1 + y1Mov * t
x2 = xo2 + x2Mov * t
y2 = yo2 + y2Mov * t

afstand = Math.sqrt((x1 – x2)² + (y1 – y2)²) -> Pythagoras
afstand = R1 + R2 = d -> zie tekening

d² = (x1 – x2)² + (y1 – y2)²
d² = x1² – 2*x1*x2 + x2² + y1² – 2*y1*y2 + y2²

De afstand berekenen na een bepaalde tijd

x1² = ( xo1 + x1Mov * t)²
x1² = xo1² + 2*xo1*x1Mov * t + x1Mov²*t²

-2*x1*x2 = -2*(xo1 + x1Mov * t)*(xo2 + x2Mov * t)
-2*x1*x2 = -2*(xo1*xo2 + xo1*x2Mov*t + x1Mov*t*xo2 + x1Mov*x2Mov*t²)
-2*x1*x2 = (-2* x1Mov*x2Mov)*t² + (-2*xo1*x2Mov -2*xo2* x1Mov) *t – 2*xo1*xo2

x2² = ( xo2 + x2Mov * t)²
x2² = xo2² + 2*xo2*x2Mov * t + x2Mov²*t²

y1² = ( yo1 + y1Mov * t)²
y1² = yo1² + 2*yo1*y1Mov * t + y1Mov²*t²

-2*y1*y2 = -2*(yo1 + y1Mov * t)*(yo2 + y2Mov * t)
-2*y1*y2 = -2*(yo1*yo2 + yo1*y2Mov*t + y1Mov*t*yo2 + y1Mov*y2Mov*t²)
-2*y1*y2 = (-2* y1Mov*y2Mov)*t² + (-2*yo1*y2Mov -2*yo2* y1Mov) *t – 2*yo1*yo2

y2² = ( yo2 + y2Mov * t)²
y2² = yo2² + 2*yo2*y2Mov * t + y2Mov²*t²

We vereenvoudigen door constanten in te voegen

Om tot een kwadratische functie te komen, voegen we de factoren van t² en t, samen.

Voor x

ax = x1Mov² -2* x1Mov*x2Mov + x2Mov² -> t²
bx = 2*xo1*x1Mov -2*xo1*x2Mov -2*xo2* x1Mov + 2*xo2*x2Mov -> t
cx = xo1² – 2*xo1*xo2 + xo2² -> geen t

Voor y

ay = y1Mov² -2* y1Mov*y2Mov + y2Mov² -> t²
by = 2*yo1*y1Mov -2*yo1*y2Mov -2*yo2* y1Mov + 2*yo2*y2Mov -> t
cy = yo1² – 2*yo1*yo2 + yo2² -> geen t

x en y samentellen

a = ax + ay
b = bx + by
c = cx + cy – d² (zie hoger)

Alles samenvoegen

a*t² + b*t + c = 0

Berekenen van de tijd

Met deze kwadratische vergelijking kunnen we de tijd berekenen, nadat een bepaalde afstand is afgelegd.

t = -b +/- Math.sqrt(b² – 4ac)/2a

Dit levert 2 oplossingen op. Inderdaad, als twee cirkels naar elkaar toe bewegen, zullen ze exact 2 maal raken: als ze elkaar tegenkomen en als ze elkaar verlaten.

Gepost door: gert | februari 6, 2008

Wrijving, niet correct, maar wel voldoende

In de meeste gevallen zien correcte wrijvingsberekeningen een beetje overkill. Het onderstaande script ziet er ook goed uit en is eenvoudiger (KISS).

Het script

var xMov:Number = 15;
var wrijving:Number = 0.95 ;

onEnterFrame = function () {
xMov *= wrijving ;
bal_mc._x += xMov;
};

Gepost door: gert | februari 6, 2008

Wrijving

Als objecten de neiging te hebben om in hun toestand te blijven (eeuwig te blijven voortbewegen bvb.), waarom vallen ze dan stil? Wrijving!

Wrijving

Objecten verliezen energie in de vorm van warmte omdat ze in contact staan met een ander object.
Bvb.: als je koude handen hebt, dan wrijf je ze over elkaar en ze worden warm.
Wrijving is een kracht in de tegenovergestelde richting van het object.

De formule

F = u * massa * zwaartekracht

u is hier de coëfficiënt van de wrijving van een bepaald materiaal. Het is steeds een getal tussen 0 en 1. Bvb.: ijs heeft een wrijvingscoëfficiënt van 0.01, terwijl hout een wrijvingscoëfficiënt van 0.2 kan hebben.

Om te berekenen hoeveel de wrijving een bepaald object vertraagt, rekenen we uit:

F = m * a = u * m * zwaartekracht
a = u * zwaartekracht

De code

var xMov:Number = 15;
var zwaartekracht:Number = 2;
var u:Number = 0.2;
var a:Number = u * zwaartekracht;
//
onEnterFrame = function () {
xMov -= a;
trace(xMov)
if (xMov <= 0) {
delete onEnterFrame;
}
bal_mc._x += xMov;
};

Zie ook 

Gepost door: gert | februari 6, 2008

Zwaartekracht, niet correct, maar voldoende

In veel gevallen is het niet nodig om de wetten van Newton toe te passen. Als je game zich gewoon op de grond bevindt, kan je voor de zwaartekracht eenvoudig een constante gebruiken, waarmee je de beweging over de y-as verhoogd.

Een voorbeeld

var yMov:Number = 0;
var zwaartekracht:Number = 2;
//
onEnterFrame = function () {
yMov += zwaartekracht;
bal_mc._y += yMov;
if (bal_mc._y > Stage.height – bal_mc._height / 2) {
yMov *= -1;
}
};

Gepost door: gert | februari 6, 2008

Zwaartekracht Correct

Zwaartekracht zal het realiteitsgehalte van je game sterk verhogen. Hieronder vind je de correcte berekening.

In veel gevallen voldoet een simpel truukje.

De formule

We gebruiken de volgende formule om de aantrekkingskracht tussen twee objecten te berekenen:

F = G * (massa1 * massa2) / afstand²

G is hier de gravitale constante. Onze games zullen er niet onder lijden indien we deze constante gelijk stellen met 1, of een andere waarde om de presentatie te verbeteren.

Een voorbeeld

// teken 3 planeten op de stage en plaats ze in een MovieClip
aarde_mc.massa = 60;
maan_mc.massa = 10;
mars_mc.massa = 20;
var planeten:Array = new Array(aarde_mc, maan_mc, mars_mc);
// de graviteitsconstante (fictief)
var G:Number = 200;
//
function animate() {
var len:Number = planeten.length;
for (var i:Number = 0; i < len ; i++) {
for (var j:Number = 0; j < len; j++) {
if (i == j) {
continue; // planeten niet t.o.v. zichzelf berekenen
}
var distance:Number = Math.sqrt(Math.pow(planeten[i]._x – planeten[j]._x, 2) + Math.pow(planeten[i]._y – planeten[j]._y, 2));
var F:Number = G * planeten[i].massa * planeten[j].massa / Math.pow(distance, 2);
// F = ma
var a1:Number = F / planeten[i].massa;
var a2:Number = F / planeten[j].massa;
//
var angle:Number = Math.atan2(planeten[i]._y – planeten[j]._y, planeten[i]._x – planeten[j]._x);
// de krachten zijn tegengesteld, vandaar + en -
planeten[i]._x -= a1 * Math.cos(angle);
planeten[i]._y -= a1 * Math.cos(angle);
planeten[j]._x += a2 * Math.cos(angle);
planeten[j]._y += a2 * Math.sin(angle);
}
}
}
onEnterFrame = animate;

Gepost door: gert | februari 6, 2008

De wetten van Newton

De basiswetten van Newton i.v.m. beweging, zijn handig, als je realistische games wil maken. Alleen de tweede wet is rechtstreeks interessant voor ActionScript. Maar voor de volledigheid, geef ik de drie wetten.

De eerste wet van Newton

Een lichaam in rust, wil in rust blijven. Een lichaam in beweging, wil in beweging blijven.

Dat betekent dat als je geen externe kracht uitoefent op een object, het in zijn huidige toestand blijft (stilstaand of bewegend tegen een bepaalde snelheid).

Bvb.: een astronaut hangt in de ruimte en wat hij ook doet, hij blijft daar ten ewigen dage hangen.

De tweede wet van Newton

De versnelling van een object is omgekeerd evenredig met zijn massa en evenredig tot het totaal van alle krachten die erop inwerken.

F = m * a

Dit is een interessante formule. Als we de krachten kennen die op een object worden uitgeoefend, kunnen we ook de versnelling berekenen.

Een voorbeeld: een zwevende ballon

var yMov:Number = 0;
var massa:Number = 2;
var g:Number = 9.81; // de valversnelling op aarde

var kracht1:Number = massa * g; // het gewicht van de ballon
var kracht2:Number = -20; // de opwaartse kracht van de ballon
var totaleKracht:Number = kracht1 + kracht2;

var yAccel:Number = totaleKracht / massa;

onEnterFrame = function() {
yMov += yAccel;
this.balloon_mc._y += yMov;
};

De derde wet van Newton

Voor elke kracht die wordt uitgeoefend, is er een gelijke en tegengestelde reactie.

Vb.: als je zit op een stoel, duwt de stoel je naar boven met een kracht die gelijk is aan je gewicht. Daarom blijf je zitten.

Gepost door: gert | februari 6, 2008

Muisvolger

Oriënteren van een MovieClip

Het is erg eenvoudig om een MovieClip naar een bepaald punt te laten ‘kijken’, bvb. naar de muis.

We moeten de hoek berekenen die deze mc maakt t.o.v. dit punt. Dit gaat zeer snel met de functie atan2 van het Math object. Deze functie geeft de hoek van een driehoek terug, via de boogtangens.
pijl.gif

Het script

onMouseMove = function () {
var x:Number = this.pijl_mc._x – _xmouse;
var y:Number = this.pijl_mc._y – _ymouse;
var angle:Number = Math.atan2(y, x);
angle = angle * 180 / Math.PI ;
this.pijl_mc._rotation = angle;
};

De implementatie

  • Plaats dit script op het eerste frame van de _root.
  • Teken een pijl die naar links wijst in een MovieClip en noem hem ‘pijl_mc’.

Analyse

  • De plaats van de muis en het registratiepunt van de mc maken een driehoek, via de x- en y-coördinaat. De overstaande en de aanliggende zijden van deze driehoek worden in de functie atan() geplaatst.
  • De hoek wordt teruggegeven in radialen en wordt geconverteerd naar graden, de eenheid van _property.

Conclusie

De atan2 functie kan gebruikt worden om allerlei objecten (auto’s, raketten, …) naar een bepaald punt te draaien.

Oudere Berichten »

Categorieën

Follow

Get every new post delivered to your Inbox.