Math Basic 6: Den Trillende Kugle - del 4


I denne tutorial vi vil forsøge at skabe mulighed for at man med musen kan ”samle” kuglen op og ”kaste” den.

Husk at du kan finde en gennemgang af de brugte termer og begreber i "Introduktion til Math. i Flash"

Pre Script

De sidste par uger har vi set på hvordan vores vi kan sætte en række forhold op det miljø vores kugle befinder sig i. Det har både været tyngde, friktion, bounce og lidt afprøvning af hvordan vi kan vende én retning til en anden.

Introduktion

Denne 4. part af den trillende kugle har ikke så meget med selve miljøet at gøre længere. I stedet skal vi se lidt på hvordan vi kan styre vores kugle på andre måder end kun med piletasterne, som vi har gjort det indtil nu. I denne tutorial vi vil forsøge at skabe mulighed for at man med musen kan ”samle” kuglen op og ”kaste” den. Det vil sige vi skal arbejde lidt videre med principperne omkring dynamiske faktorer. Vi har tidligere set på dynamisk acceleration i "Den Trillende Kugle Part 3".
Vi arbejder i denne tutorial videre med koden fra "Den Trillende Kugle Part 3"
Du kan hente start filen her.

Teori

Hvis vi kan opsætte og foretage to målinger for et objekts placering på en akse, kan vi ved at sammenligne afstanden mellem de to punkter, og den tid der er gået mellem de to målinger bestemme objektets fart/velocitet. I mere praktiske ord vil det sige at hvis vi måler objektets placering på y aksen, x antal gange i sekundet (frames per sekund) kan vi bestemme objektets velocitet. Ved at holde de to tal, for y akseplaceringen der er mellem to frames, op mod hinanden kan bestemme hvor mange PPF (pixels per frame) objektet flytter sig. Lad os se hvordan vi kan implementere det i vores lille miljø.

Eksemplet

Det første vi skal have set på, inden vi kaster os over målingerne, er at få bolden til at reagere på musens ”greb”. Heldigvis har vi i Action Script en indbygget metode på alle MovieClips der hedder ”startDrag()” som vi kan bruge til at ”samle” vores bold op. Ligeledes findes der en metode der stopper vores flytning af bolden, som har det sigende navn ”stopDrag()”.
Ligesom vi har lavet en central funktion med vores ”flytBold”, laver vi også to centrale funktioner til at tage og til at slippe vores bold.

bold.onPress = tagBold;
bold.onRelease = bold.onReleaseOutside = slipBold;

Disse to funktioner skal vi selvfølgelig selv definere et andet sted i vores kode, men det vigtige at bemærke her er at vi tilføjer dem til boldens eventhåndterende funktioner: ”onPress” som automatisk kaldes når musens knap trykkes ned, over bolden, og modsat ”onRelease” og ”onReleaseOutside” som kaldes når musens knap slippes over bolden, eller når musen spilles uden for bolden. Grunden til at vi sætter denne sidste ”onReleaseOutside” på også, er for at sørge for at bolden automatisk slippes, hvis vi kører musen uden for vores flash applikation, mens vi har fat i bolden. (du kan prøve at fjerne denne og se hvilken effekt det har)
Inden vi kaster os over at definere vores to nye funktioner skal vi lige have instantiseret 3 nye variabler vi skal bruge til vores udregning.

Den første vi skal have instantiseret er en boolean se mere om boolean i den tillende kugle part 1 som vi kan bruge til når vi skal måle boldens hastighed. Variablen skal indeholde en indikator for om vi har fat i den med musen eller ej:

var boldenErGrebet:Boolean = false;

Vi stiller altså ”boldenErGrebet” til at være falsk fra start, da vi jo, når applikationen starter, ikke har fået fat i bolden endnu.

De næste to variabler vi skal have lavet er til at holde x og y koordinator. Når vi skal bruge to målinger for x og for y kan vi jo bruge objektets nuværende x og y, og så holde dem op i mod de koordinater hvor objektet var før. Derfor kan vi tale om ”gamle” koordinator:

var gammelX:Number;
var gammleY:Number;

Det var hvad vi skulle bruge af variabler, så lad os hoppe ned til vores første funktions definition af ”tagBold”.

”tagBold” skal altså kaldes når musen trykkes over vores bold. Derfor kan vi starte med at kalde den tidligere omtalte ”startDrag()” metode som vores bold har:

function tagBold():Void
{
	this.startDrag(true);
//…

I vores definition bruger vi ”key” – ordet ”this” som i Action Script (1 og 2) referere til det objekt der kalder funktionen. I vores tilfælde er det jo ”bold” der kalder ”tagBold” med sin ”onPress” event metode. – Så når vi skriver ”this” er det, det samme som at skrive ”bold”. Men ved at bruge ”this” har vi samtidig mulighed for at bruge ”tagBold” på andre objekter også. ”this” virker som en joker, som peger på den der kalder ”tagBold”.
På ”this” kalder vi metoden ”startDrag” og passere argumentet ”true” med i ”startDrag” metoden. Dette argument betyder at vi vil have at det objekt vi ”dragger” skal låses til midten” Det vil sige at selv om vi trykker på bolden, uden for boldens midte, vil alligevel resultere i at bolden flyttes hen så midten/registreringspunktet af bolden er præcist ud for musens spids.
(Du kan prøve at skrive ”false” i stedet og se hvilket resultat det måtte have på resultatet).

Det næste vi skal have gjort i vores ”tagBold” funktion er at fortage vores første måling. Det gør vi ved at give de to tidligere variabler værdier:

gammelX = this._x;
gammelY = this._y;

Vi siger altså at den første måling, eller de “gamle” koordinator er der hvor bolden “løftes” fra.
Igen bruger vi ”this” som betydning for ”bold”.
Det sidste vi skal have gjort i vores ”tagbold” funktion er at sætte vores indikator ”boldenErGrebet” til at være sandt:

boldenErGrebet = true;
};

På den måde kan vi om lidt skal arbejde inde i ”flytBold” funktionen bruge ”boldenErGrebet” til at udføre to forskellige koder, alt afhængigt af hvad ”boldenErGrebet” siger.

Det var vores ”tagBold” funktion. Nu skal vi have sat ”slipBold” op, så vi kan slippe af med bolden igen:

function slipBold():Void
{
this.stopDrag();
boldenErGrebet = false;
};

Det første vi gør, er at stoppe flytning med bolden, ved at kalde ”stopDrag” metoden. Herefter skal vi have sat vores indikator tilbage til ”false” så vi kan se at bolden ikke længere er grebet.

Resten af det vi skal have sat op, forgår i vores ”flytBold” funktion. Og heri er det første vi skal gøre at sætte en betingelse op. Vi kan bruge ”if” (altså ”hvis”) betingelsen til at teste for om vores bold er grebet. Vi bruger ”!” operatoren til at sige ”hvis IKKE boldenErGrebet…”:

if(!boldenErGrebet)
{
if(Key.isDown(Key.RIGHT))
{
vx += ax;
}
else if(Key.isDown(Key.LEFT))
{
vx -= ax;
}
if(Key.isDown(Key.UP))
{
vy -= ay;
}
else if(Key.isDown(Key.DOWN))
{
vy += ay;
}
 
if(bold._y > maxFald - halvBold)
{
bold._y = maxFald - halvBold;
//vi har tilføjet en linie hvor vi ganger med bounce faktoren
vy *=-bounce;
}
else if(bold._y < minFald + halvBold)
{
bold._y = minFald + halvBold;
vy *= - bounce;
}
if(bold._x > maxSide - halvBold)
{
bold._x = maxSide - halvBold;
vx *= - bounce;
}
else if(bold._x < minSide + halvBold)
{
bold._x = minSide + halvBold;
vx *= - bounce;
}
//vi lægger vores tyngde til velociteten på på y aksen:
vy += boldsTyngde;
vx *= friktion;
bold._x += vx;
bold._y += vy;
}
else
{

Ovenstående er vores kode vi har lavet tidligere, blot pakket ind i en ”if” betingelse. Læg mærke til at jeg har flyttet linierne:

//vi lægger vores tyngde til velociteten på på y aksen:
vy += boldsTyngde;
vx *= friktion;
bold._x += vx;
bold._y += vy;

- nederst, da det er mere naturligt at det er de sidste der bliver gjort, da det er at selve flytningen af vores bold.

Efter ”else” sætningen kan vi så tilføje den kode der skal udføres når bolden rent faktisk ER grebet:

vx = bold._x - gammelX;
		vy = bold._y - gammelY;
		gammelX = bold._x;
		gammelY = bold._y;

Det første vi gør er at sige at velociteten på x og y er lig med boldens nuværende placering minus den tidligere måling. Videre siger vi at gammelX og gammelY nu skal være lig med boldens nuværende placering. På den måde søger vi for, hver gang vores ”onEnterFrame” funktion bliver kaldt, og betingelsen om at vores bold er grebet er sandt, at måle afstanden mellem sidste ”onEnterFrame” kald, og sørger for at gemme den nye placering.
På den måde vil vi, så snart vi slipper bolden, og vores ”boldenErGrebet” er falsk, eksekvere den kode vi hele tiden har brugt. Dog er der sket det, at vores vx og vy værdier nu har en værdi der er målt ud fra hvor hurtigt vi har flyttet bolden rundt med musen, og derfor vil bolden nu pludseligt fortsætte med samme fart som vi har ”kastet” den med.
Her er den samlede kode:

/***********************************************************
* Matematisk Mandag
* Basic 6: "Den trillende kugle"
* - Part 4
* <a href="http://www.flashforum.dk" title="www.flashforum.dk">www.flashforum.dk</a> (flashger)
***********************************************************/

/**********************************************************
* VIGTIGE FORMLER I DENNE TUTORIAL:
**********************************************************/

 
//--------------------VARIABLER---------------------------
var bold:MovieClip = _root.bold;
var vy:Number = 0;
var vx:Number = 0;
var ax:Number = .5;
var ay:Number = .5;
 
//Vores tyngdelov:
var tyngde:Number = .3;
var boldsTyngde:Number = tyngde;
 
var maxFald:Number = Stage.height;
var minFald:Number = 0;
var minSide:Number = 0;
var maxSide:Number = Stage.width;
var halvBold:Number = bold._height/2;
 
//Vores Bounce effekt
var bounce:Number = .7;
 
//vores friction på x aksen
var friktion:Number = .99;
 
//vores vars til at løfte, slippe og måle boldens fart.
var boldenErGrebet:Boolean = false;
var gammelX:Number;
var gammelY:Number;
 
 
//--------------------EVENT HÅNDTERING--------------------
bold.onEnterFrame = flytBold;
bold.onPress = tagBold;
bold.onRelease = bold.onReleaseOutside = slipBold;
 
 
//-----------------EKSEKVERENDE FUNKTION-------------------
 
//vore funktion der kan løfte bolden:
function tagBold():Void
{
this.startDrag(true);
gammelX = this._x;
gammelY = this._y;
boldenErGrebet = true;
}
 
//Vores funktion der slipper bolden igen:
function slipBold():Void
{
this.stopDrag();
boldenErGrebet = false;
}
 
 
function flytBold()
{
if(!boldenErGrebet)
{
if(Key.isDown(Key.RIGHT))
{
vx += ax;
}
else if(Key.isDown(Key.LEFT))
{
vx -= ax;
}
if(Key.isDown(Key.UP))
{
vy -= ay;
}
else if(Key.isDown(Key.DOWN))
{
vy += ay;
}
 
if(bold._y > maxFald - halvBold)
{
bold._y = maxFald - halvBold;
//vi har tilføjet en linie hvor vi ganger med bounce faktoren
vy *=-bounce;
}
else if(bold._y &lt; minFald + halvBold)
{
bold._y = minFald + halvBold;
vy *= - bounce;
}
if(bold._x > maxSide - halvBold)
{
bold._x = maxSide - halvBold;
vx *= - bounce;
}
else if(bold._x &lt; minSide + halvBold)
{
bold._x = minSide + halvBold;
vx *= - bounce;
}
//vi lægger vores tyngde til velociteten på på y aksen:
vy += boldsTyngde;
vx *= friktion;
bold._x += vx;
bold._y += vy;
}
else
{
vx = bold._x - gammelX;
vy = bold._y - gammelY;
gammelX = bold._x;
gammelY = bold._y;
}
};

Link til et fungerende eksempel

Link til den færdige fla fil

Nu har vi en bold vi kan kaste med musen, styre med pilene og som arter sig alt efter om den falder eller rammer noget. Nu kan du selv bygge små miljøer hvor du bruger de fysiske elementer.
Denne tutorial var den sidste i rækken om den Trillende Kugle og Math. Basic i det hele taget. Næste uge tager vi fat på Intermediate delen og skal starte med at se på "Easing og Fjeder-matematik".

Asger Laursen
Developer / Technical Architect
Company: www.webyte.dk | Blog: www.asgerlaursen.com |Twitter: www.twitter.com/Flashger

Om forfatteren
User picture

Asger er til dagligt Technical Architect hos webyte i Århus, hvor han arbejder med Rich Internet Application arkitektur med særlig vægt på Flash Platformen, med Flash Player og AIR runtime på klient siden, og BlazeDS/LCDS på server siden. Asger er Certificeret Flex og AIR expert, Dansk Adobe User Group Manager samt Dansk Adobe Community Expert.

Kommentarer

Se thedbp's brugerprofil
Indmeldt: 07-01-2007
Indlæg: 75
Er offline

jeg kan ikke få det fungerende eksembel Sad

Siden du efterspurgte kunne ikke findes. Istedet har vi lavet en søgning på Flashgers ff tuts FFTutorials Math Basic b6 denTrillendeKuglePart4 denTrillendeKuglePart4 finished.

så må jeg bare lave det selv ^^