Ismerkedés az ActionScript 3-mal, 3. rész

Az előző két részben eljutottunk odáig, hogy van egy jó randa pattogó labdánk. Szebb lehetne, ha mondjuk nem méreteződne át a böngészőablakkal együtt, jó lenne a framerate-je, meg lenne valami mögötte. Nosza, az első két dologra a Stage osztály a gyógyír, a harmadik problémát pedig eddigi tudásunkkal is meg tudjuk oldani.

Először is importáljuk a Stage osztályt, és a hozzátartozó konstansokat tartalmazó osztályokat.

import flash.display.Stage;
import flash.display.StageScaleMode;
import flash.display.StageAlign;	

Aztán már csak egy private változó kell alá, és lehet példányosítani.

private var myStage:Stage;
//
..
//
myStage = new Stage( );
myStage.frameRate = 25;
myStage.scaleMode = StageScaleMode.NO_SCALE;
myStage.align = StageAlign.TOP;
//

Amint látjátok, beállítottuk a framerate-et, a scalemode-ot, és az igazítást, ha most ráindítunk, már egy fokkal jobban fog kinézni.
Azért hányjunk mögé egy hátteret is, nem csak a dizájn miatt lesz hasznos ez a későbbiekben ( spoiler :) )

private var myBack:MovieClip;
//
..
//
myBack = new MovieClip( );
myBack.graphics.beginFill( 0x900000 , 1 );
myBack.graphics.lineStyle( 2 , 0xffffff , 1 );
myBack.graphics.moveTo( 0 , 0 );
myBack.graphics.lineTo( 400 , 0 );
myBack.graphics.lineTo( 400 , 200 );
myBack.graphics.lineTo( 0 , 200 );
myBack.graphics.lineTo( 0 , 0 );
addChild( myBack );

Kircsi, most már van egy fehérkeretes bordó hátterünk is. Módosítsuk a BallClip osztályunkban néhány méretet és koordinátát, hogy ne tudjon kimenni a hátterünkből.

graphics.drawCircle( 0 , 0 , 20 );
..
if ( x + xspeed > 390 ) xspeed *= -1;
if ( x + xspeed < 10 ) xspeed *= -1;
if ( y + yspeed > 190 ) yspeed *= -1;
if ( y + yspeed < 10 ) yspeed *= -1;

Most már egész jó. Akkor most jön a két karika: interakciót viszünk bele!!! Bizony!!! Modnjuk lehessen megfogni a lasztit, és lehessen dobálni egérrel, az tök jó lenne.
Izzíthatjuk is az új eseménykezelő modellt: a BallClip osztály figyelni fogja, hogy reá lett-e kattintva, és ha igen, akkor kiszól a vezérlő osztálynak, hogy mozgass már meg, meg szedjél valahonnan globális egérkoodinátákat, meg ilyenek.

Szükségünk lesz két új függvényre, amit az egéresemények triggerelnek, invokálnak, indukálnak, nincs erre magyar szó?

//
//
//
public function mouseDownHandler ( eventOBJ:MouseEvent ):void
{
	//
	father.dragBall( );
	//
}
//
//
//
public function mouseUpHandler ( eventOBJ:MouseEvent ):void
{
	//
	father.releaseBall( );
	//
}	

A konstruktorában meg hozzárendelünk két eseményt

//
addEventListener( MouseEvent.MOUSE_DOWN , mouseDownHandler );
addEventListener( MouseEvent.MOUSE_UP , mouseUpHandler );		
//

Ne feledkezzünk meg a flash.events.MouseEvent osztály importálásáról !

No, most már tudni fogja a BallClip, ha ráböktünk az egérrel, írjuk meg az apaosztályhoz tartozó függvényeket. Itt jön egy fontos dolog: ha akárhol létrehozunk egy új objektumot, rögtön, lehetőleg a konstruktorában tudassuk vele, hogy mi vagyunk az apja, így közvetlenül vissza tud ránk utalni amikor akar, ez irtó hasznos dolog. Tehát amikor a TestBall-on belül létrehozzuk a BallClip objektumot, csináljunk olyat, hogy

myBall = new BallClip( this );

A BallClip osztályban hozzunk létre egy privát father MovieClip típusú változót, és a konstruktor rögtön pakolja is bele az apa MoveiClipet vagy Objektumot:

	public function BallClip ( myRoot:MovieClip )
	{
		//
		father = myRoot;

Most már tudni fogja a mouseDownHandler meg a mouseUpHandler, hogy kinek szóljon egéreseménykor.

Kell tehát a vezérlő osztályba is dragBall fúggvény, ami ideiglenesen leállítja a labda mozgását, létrehoz egy egérmozgás-eseményfigyelőt, és mozgatja a labdát. Ezért két függvényre érdemes bontani: a dragBall-ra és a moveBall-ra. A moveBall végzi a tényleges mozgást, és ő jegyzi meg a labda előző állapotának koordinátáit is. A releaseBall pedig belövi a myBall új sebességértékeit, és indítja a mozgatást.

Még két fontos változtatás szükséges a kódhoz:

1. A moveTimer objektum eddig csak lokális változóként létezett a TestBall konstruktorában, őt globálissá kell tennünk, hogy más függvények is elérjék az osztályon belül.

2. A BallClip osztály xspeed és yspeed privát változóit publikussá kell tennünk, hogy a TestBall elérhesse őket.

Továbbá a Timer intervallumot is levettem 50 millisecről 20-ra, így folyamatosabb a mozgás.

A végleges kód:

//begin
//
//
package
{
	//
	//
	//
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	import flash.events.MouseEvent;
	import flash.display.Stage;
	import flash.display.StageScaleMode;
	import flash.display.StageAlign;	
	import flash.display.MovieClip;
	//
	//
	//
	public class TestBall extends MovieClip
	{
		//
		//
		//
		private var myStage:Stage;		
		private var myBack:MovieClip;
		private var myBall:BallClip;
		private var moveTimer:Timer;
		//
		private var xspeed:Number = 0;
		private var yspeed:Number = 0;
		//
		private var oldx:Number;
		private var oldy:Number;		
		//
		//
		//
		public function TestBall( )
		{
			//
			myStage = new Stage( );
			myStage.frameRate = 25;
			myStage.scaleMode = StageScaleMode.NO_SCALE;
			myStage.align = StageAlign.TOP;
			//
			myBack = new MovieClip( );
			myBack.graphics.beginFill( 0x900000 , 1 );
			myBack.graphics.lineStyle( 2 , 0xffffff , 1 );
			myBack.graphics.moveTo( 0 , 0 );
			myBack.graphics.lineTo( 400 , 0 );
			myBack.graphics.lineTo( 400 , 200 );
			myBack.graphics.lineTo( 0 , 200 );
			myBack.graphics.lineTo( 0 , 0 );
			addChild( myBack );					
			//
			myBall = new BallClip( this );
			addChild( myBall );
			//
			moveTimer = new Timer( 20 );
			moveTimer.addEventListener( TimerEvent.TIMER , myBall.step );
			moveTimer.start( );
			//
		}
		//
		//
		//
		public function dragBall ( ):void
		{
			//
			addEventListener( MouseEvent.MOUSE_MOVE , moveBall );
			moveTimer.stop( );
			//
		}
		//
		//
		//
		public function releaseBall ( ):void
		{
			//
			removeEventListener( MouseEvent.MOUSE_MOVE , moveBall );
			myBall.xspeed = xspeed;
			myBall.yspeed = yspeed;
			moveTimer.start( );
			//
		}
		//
		//
		//
		public function moveBall ( eventOBJ:MouseEvent ):void
		{
			//
			myBall.x = mouseX;
			myBall.y = mouseY;
			//
			xspeed = mouseX - oldx;
			yspeed = mouseY - oldy;
			//
			oldx = mouseX;
			oldy = mouseY;
			//
		}		
		//
		//
		//
	}
	//
	//
	//
}
//
//
//
import flash.display.MovieClip;
import flash.events.TimerEvent;
import flash.events.MouseEvent;
//
//
//
class BallClip extends MovieClip
{
	//
	//
	//
	private var father:MovieClip;
	public var xspeed:Number;
	public var yspeed:Number;
	//
	//
	//
	public function BallClip ( myRoot:MovieClip )
	{
		//
		father = myRoot;
		//
		graphics.beginFill( 0xff0000 , 1 );
		graphics.drawCircle( 0 , 0 , 20 );
		graphics.endFill( );
		//
		x = 20;
		y = 20;
		//
		xspeed = Math.random( )*5;
		yspeed = Math.random( )*5;
		//
		addEventListener( MouseEvent.MOUSE_DOWN , mouseDownHandler );
		addEventListener( MouseEvent.MOUSE_UP , mouseUpHandler );		
		//
	}
	//
	//
	//
	public function step ( timeEvent:TimerEvent ):void
	{
		//
		if ( x + xspeed > 390 ) xspeed *= -1;
		if ( x + xspeed < 10 ) xspeed *= -1;
		if ( y + yspeed > 190 ) yspeed *= -1;
		if ( y + yspeed < 10 ) yspeed *= -1;
		//
		x += xspeed;
		y += yspeed;
		//
	}
	//
	//
	//
	public function mouseDownHandler ( eventOBJ:MouseEvent ):void
	{
		//
		father.dragBall( );
		//
	}
	//
	//
	//
	public function mouseUpHandler ( eventOBJ:MouseEvent ):void
	{
		//
		father.releaseBall( );
		//
	}	
	//
	//
	//
}
//
//
//end

Így már állatfantasztikusinteraktív a cucc, de nekem nem tetszik a labda mozgása, miért nem pattog? Ezen könnyen lehet segíteni, a BallClip osztályba be kell vezetnünk egy gravity változót, aminek az értékét folyamatosan hozzáadjuk yspeed-hez , így életszerű lesz a labda mozgása:

private var gravity:Number = 0.5;
//
..
//
//
//
public function step ( timeEvent:TimerEvent ):void
{
	//
	yspeed += gravity;
	//
	if ( x + xspeed > 390 ) xspeed *= -1;
	if ( x + xspeed < 10 ) xspeed *= -1;
	if ( y + yspeed > 190 ) { yspeed -= gravity; yspeed *= -1; }
	if ( y + yspeed < 10 ) yspeed *= -1;
	//
	x += xspeed;
	y += yspeed;
	//
}
//

Na? Na? Mekkora királyság, ugye? A következő részben valami grafikát és hangot fogunk embeddelni a movie-ba, utána meg megcsináljuk hogy a kamera inputtal lehessen pattogtatni a labdát.

MilGra

A cikkhez kapcsolódó hozzászólásokat a fórum "Actionscript 3" topicjában várjuk.

1 hozzászólás

  1. Hali!

    A következő sor

    40
    
    myStage = new Stage( );

    nekem nem működött ([Fault] exception, information=ArgumentError: Error #2012: Stage class cannot be instantiated. Fault, TestBall.as:40). Amikor a kezdeti pánikom elmúlt, rájöttem, hogy a TestBall a MovieClip-ből származik, annak van saját Stage referenciája.

    Ez jónak tűnik:

    40
    
    myStage = this.stage;

HOZZÁSZÓLOK A CIKKHEZ

Kérjük, írja be véleményét!
írja be ide nevét