PDA

View Full Version : [AS3] Call public function from different actionscript file?



Tauschung
April 30th, 2010, 01:17 AM
Game is pretty much complete, but I am having a problem that is driving me nuts. At the end of a game, I am trying to give an option to start the game over again. The problem is I am having to try to do this from a different object than the start of the game is located.

Here is the code for my two classes, I've added a comment on the part that is giving me the problems.

Main.as:


package
{
// Imports \\
import fl.transitions.Tween;
import flash.display.MovieClip;
import flash.events.Event;
import com.greensock.TweenLite;
import fl.motion.easing.Bounce;
import flash.events.MouseEvent;
import flash.ui.Mouse;

public class Main extends MovieClip {

public function begin() : void {
// rotates stage 30º
bg.rotationX = -30;
// listens for mouse to press "Click here to start"
Mouse.show ();
startText.addEventListener (MouseEvent.MOUSE_UP, gameStart );
startText.visible = true;
startText.buttonMode = true;
}// end function
public function gameStart ( _e : Event ) : void {
// turns button off and hides the mouse
startText.buttonMode = false;
startText.visible = false;
Mouse.hide ();

// rotates the walls onto stage 90º
new TweenLite( bg.wallRight, 2, { rotationY: 90, alpha: 1, ease: Bounce.easeOut } );
new TweenLite( bg.wallLeft, 2, { rotationY: -90, alpha: 1, ease: Bounce.easeOut } );
new TweenLite( bg.wallTop, 2, { rotationX: 90, alpha: 1, ease: Bounce.easeOut } );
new TweenLite( bg.wallBottom, 2, { rotationX: -90, alpha: 1, ease: Bounce.easeOut, onComplete: ball.drop } );
}// end function
}// end class
}// end package

Ball.as:


package {
// Imports \\
import flash.display.MovieClip;
import flash.events.Event;
import com.greensock.TweenLite;
import fl.motion.easing.Bounce;
import flash.events.MouseEvent;
import flash.ui.Mouse;

public class Ball extends MovieClip {
// declares ball variables
public var xspeed:Number=0;
public var yspeed:Number=0;
// declares fScore score variable
public var fscore:Number=0;
public var scoreRight:Number = 0;
public var scoreLeft:Number = 0;
public var maxScore:Number = 2;

public function Ball():void {
}

public function drop():void {
// stops ball's movement and removes the moveBall listener
this.visible = true;
xspeed=yspeed=0;
removeEventListener(Event.ENTER_FRAME, moveBall);
// sets balls height to above the center of the stage
y=- height;
x=stage.stageWidth/2;
//resets ball's depth perception
var scale : Number = (0.5 * 0.6) + 0.6;
// drops ball back onto the stage to start new round
new TweenLite(this,1.5,{y:stage.stageHeight/2,scaleX:scale,scaleY:scale,ease:Bounce.easeOut,on Complete:start});
}

public function start():void {
// starts ball movement
xspeed=-15;
yspeed=12;
addEventListener(Event.ENTER_FRAME, moveBall);
}

private function moveBall(_e:Event):void {
// call to depth and collision functions
depth();
collision();
// makes ball move
x+=xspeed;
y+=yspeed;
}

private function depth():void {
// allows ball to change size to give depth perseption to tha ball
var smaller : Number = ((y/stage.stageHeight) * 0.6) + 0.6;
scaleX=scaleY=smaller;
}

private function collision():void {
// sets maximum wall values
if (y>=380||y<=155) {
// reverses ball's direction if collision detected
yspeed*=-1;
}// end if
// sets hit test to detect if ball hits player or AI paddles
if (x > (stage.stageWidth / 2) && hitTestObject(MovieClip(parent).bg.wallRight)) {
// changes direction of ball if collision detected
xspeed*=-1;
if (xspeed>0) {
xspeed=- xspeed;
}
}
if (x < (stage.stageWidth / 2) && hitTestObject( MovieClip(parent).bg.wallLeft) ) {
xspeed*=-1;
if (xspeed<0) {
xspeed=- xspeed;
}
}

// checks to see if ball is still located on floor
if (!MovieClip(parent).bg.floor.hitTestPoint(x, y + (height / 2 * scaleY), true)) {
// if not on stage detect which side ball exits on and add score to appropriate side
if (x<stage.stageWidth/2) {
scoreRight++;
MovieClip(parent).bg.wallTop.scoreRight.text = scoreRight;
} else {
scoreLeft++;
MovieClip(parent).bg.wallTop.scoreLeft.text = scoreLeft;
}

if ((scoreLeft >= maxScore) || (scoreRight >= maxScore)) {
fScore();
} else {
drop();
}
}
}

public function fScore():void {
//trace(MovieClip(parent).fScore.winOrLose);
//trace(MovieClip(parent).fScore.winOrLose.textField )

MovieClip(parent).bg.wallRight.alpha=0;
MovieClip(parent).bg.wallLeft.alpha=0;
MovieClip(parent).bg.wallTop.alpha=0;
MovieClip(parent).bg.wallBottom.alpha=0;
MovieClip(parent).bg.floor.lines.alpha=0;
MovieClip(parent).bg.rotationX=0;
this.visible = false;
Line 110 MovieClip(parent).startText.addEventListener (MouseEvent.MOUSE_UP, gameStart );// THIS IS THE LINE OF CODE THAT IS GIVING ME THE ERROR
MovieClip(parent).startText.visible = true;
MovieClip(parent).startText.buttonMode = true;


if (scoreRight >= maxScore) {
MovieClip(parent).fScore.visible = true;
MovieClip(parent).fScore.winOrLose.text = "You Win! ";
//trace ("you win");
}

if (scoreLeft >= maxScore) {
MovieClip(parent).fScore.visible = true;
MovieClip(parent).fScore.winOrLose.text = "You Lose! ";
//trace ("you lose");
}
}
}// end class
}// end package

Here is the error I am getting in the Compiler:

Location: Ball.as, Line 110

Description: 1120: Access of undefined property gameStart.

Source: MovieClip(parent).startText.addEventListener (MouseEvent.MOUSE_UP, gameStart );

Can someone please point me in the right direction?

therobot
April 30th, 2010, 12:37 PM
you're trying to call gamestart but the function doesn't exist within the scope of the object that is calling it;

it looks like what you want to do is call the gamestart function in your Main.as

try this, assuming MovieClip(parent) refers to the Main.as object :)



MovieClip(parent).startText.addEventListener (MouseEvent.MOUSE_UP, MovieClip(parent).gameStart );


This should work...but i really don't approve of any this. your ball class makes wayyyy too many assumptions about it's parent. :)

the other thing you can do to make things more effecient, assign MovieClip(parent) to a var and refer to the var rather than than checking if the parent is a movieclip a skajillion times. for example:



var myParent:MovieClip = parent as MovieClip;
myParent.addEventListener(someEvent.EVENT, someFunction);
myParent.whatever();

Tauschung
April 30th, 2010, 03:46 PM
I did what you said, and created


public var myParent:MovieClip = parent as MovieClip;

Then, I used Find (ctrl + F) to find and replace all instances of MovieClip(parent) with myParent.

Now, the compiler gives no errors, but my game quit working completely. This is my first attempt at OOP, and I'd rather learn to do it right, so I don't want to go back to the way it was coded before if that is not correct practices.

Any ideas on why it will now no longer work?

Tauschung
May 1st, 2010, 03:35 AM
UPDATE:

Game working again, and have the myParent variable in place. However, this line of code is still not working:


myParent.startText.addEventListener (MouseEvent.MOUSE_UP, myParent.gameStart );


Anyone else have any ideas?

Tauschung
May 1st, 2010, 11:35 PM
Anyone else have any ideas? I am at a loss here, and can't figure out why this isn't working.

I understand that no one here is obligated to help, but it would be very much appreciated.

therobot
May 2nd, 2010, 10:51 PM
Anyone else have any ideas? I am at a loss here, and can't figure out why this isn't working.

I understand that no one here is obligated to help, but it would be very much appreciated.

well, you could try adding the event listener in your main.as instead of the ball.as file. I haven't looked over your code too closely, but it does seem odd that a child of your main.as is setting up listeners for other chldren of its parent, no?

the other thing you could do is add (to ball.as) the function to be called, and not try to call a function in a different object.

since it seems like you're looking for tips, I would consider adding a function to your main.as, something like so:



public function setStartGameEnabled(enabled:Boolean):void
{
startText.visible = enabled;
startText. buttonMode = enabled;

if(enabled)
{
Mouse.show ();
startText.addEventListener (MouseEvent.MOUSE_UP, gameStart );
}
else
{
Mouse.hide ();
startText.removeEventListener (MouseEvent.MOUSE_UP, gameStart );
}
}


then in your ball.as file, you can get rid off all the stuff in the score function and just call myParent. setStartGameEnabled(true)

Make sense?

then you can clean up the repetitious code in your Main.as that does roughly the same thing in the constructor. AND you can ensure better stability since your logic for starting/stopping the front end UI is in one spot, instead of nested in game logic :)

Tauschung
May 2nd, 2010, 11:10 PM
Going to test this now. Thanks again for your help thus far!!

Tauschung
May 2nd, 2010, 11:59 PM
I have done like you suggested and cleaned up the code and added in the code you suggested, although slightly modified to make it work.

Instead, I changed MouseEvent.MOUSE_UP to MouseEvent.CLICK, to make it work.

Now, I am still not able to get the game to restart though. There are no errors reported in the coding, or in the compiler. After it finishes, and the startText is CLICKed, it never seems to run the gameStart function.

Here's a link to my current source files. The .zip folder was too large with Tween Lite included.

http://www.megaupload.com/?d=175975WC

therobot
May 3rd, 2010, 09:17 AM
any chance you can save it to cs3 or lower?

Tauschung
May 3rd, 2010, 04:24 PM
Give me just a minute and I'll upload a version for you.

Tauschung
May 3rd, 2010, 04:34 PM
Link to the CS3 compatible version:

http://www.megaupload.com/?d=SBH55GQ6

Said that the XMP file data would not be saved though, don't know if that will affect you being able to run it or not.

kadaj
May 3rd, 2010, 06:35 PM
/* Main.as */
//...
public class Main extends MovieClip {

public static var mainInstance:Main;

public function Main()
{
mainInstance = this;
}

public function begin() : void {
//....
}
public function gameStart ( _e : Event ) : void {
//add remove listerners if needed
}
}


//Ball.as
public class Ball extends MovieClip {
//....
}

public function fScore():void
{
//...
Main.mainInstance.startText.addEventListener(Mouse Event.MOUSE_UP, gameStart );
}
//....