flash error 1010 when trying to snap a puzzle piece - actionscript-3

i am trying to create a puzzle game and so far had no problems with moving the pieces and all but when i tried to check piece position after stopDrag i got an error message:Error #1010: A term is undefined and has no properties.
this is the relevant code:
full1 is a movieclip that contains a picture of the puzzle with a low alpha and the puzzle pieces,each with it's own instance name.
in this example tr is an instance name of one of the pieces.
public function Move(even:MouseEvent)
{
even.target.startDrag();
}
public function stopMove(even:MouseEvent)
{
this.stopDrag();
checkPos(even.target.name);
}
public function checkPos(nameStr:String)
{
if(nameStr=="tr1")
{
if(this.full1.tr1.x>=460&&this.full1.tr1.x<=465.5&&this.full1.tr.y>=99&&this.full1.tr.y<=103)
{
this.full1.tr.x=460.2;
this.full1.tr.y=101.95;
}
}
}
if anyone sees any problem with what i wrote or has a better idea of how to approach this i would appreciate your help.
thanks.

Looks like it should be even.target.stopDrag() instead of this.stopDrag() (since you started the drag on even.target). Unless the error is occurring after stopDrag(), in which case it doesn't look like enough info to answer.
Side note, it would be better to do the name checking outside of the checkPos() function. e.g.:
this.stopDrag();
if(even.target.name == "tr1")
{
checkPos();
}
And remove the name checking from checkPos().

On one occasion, you use "even.target.startDrag();" to start dragging.
But in the other function, you use "this.stopDrag();" to stop dragging.
You should either always use "this" or always use "even.target". This could be the cause of your error.
It would also be good to know in which line exactly the crash happens.

Related

Checking a Boolean variable in another class

Let me set the stage because it's too much code to post everything:
I have a Main.as that is setting up my SoundController.as so I can trigger sounds from any other class (SoundController.as has all the functions needed to call all my sounds as needed)
I have a ControlPanel.as that can access these sounds by using docRef.soundControl.laserFire or whatever other function name I want, and in this case the laserFire sound would trigger once.
So here is my question. I want to let this laser sound effect finish playing before you can fire another laser. So in SoundController.as I've set up the following pieces of code:
private var _laserPlaying:Boolean = false;
internal function laserFire():void {
_sfxChannel = _laser.play(25);
_laserPlaying=true;
_sfxChannel.addEventListener(Event.SOUND_COMPLETE, laserFinished);
}
internal function laserFinished(event:Event):void {
_sfxChannel.removeEventListener(Event.SOUND_COMPLETE, laserFinished);
_laserPlaying=false;
}
public function get laserPlaying():Boolean {
return _laserPlaying;
}
public function set laserPlaying(value:Boolean):void {
_laserPlaying = value;
}
Now in my ControlPanel class in the enterFrameHandler function I want to do an
if (docRef.soundControl.laserPlaying()==false)
or something to that effect so I can check when the sound is done and allow the player to once again press the trigger to fire the laser. So far any variant I've tried on this either gives me an error (in this case 1195; Attempted access of inaccessible method laserPlaying through a reference with static type SoundController) or it actually compiles but after firing the first laser shot it never allows the trigger to be pressed again. So I'm obviously doing something wrong and am hoping someone can help.
Let me just state that the laser sound is playing just fine that first time, so don't worry about all the code I'm not bothering to show to make that portion of the code work. However, if more info is needed to understand how I'm making anything work just let me know. And Thanks in advance!
If your soundController AND ControlPanel are instantiated in Main:
handle the firing event, in ControlPanel, like this:
if(MovieClip(parent).soundController.soundChannel.position==0)
{
MovieClip(parent).soundController.laserfire();
}else{do nothing;}
Of course use proper instance names.
If this doesn't work you'll have to make your code a little easier to understand.
Sorry for wasting everyone's time. I ended up figuring out what I needed to do to make this work. This probably won't be of much use to anyone else since my setup was probably unique to my layout and not something that anyone else will try, but here is what I did anyway.
In my ControlPanel.as I added the following code:
private var _soundController:SoundController;
And then I have a function that waits for the ControlPanel to be added to the stage and once that occurs I fired:
_soundController = new SoundController(docRef);
Now by adding those I was able to simply call:
if(!_soundController.laserPlaying) { do stuff; }
It now seems to wait for laserPlaying to be false and then moves on as intended.

Check the existence of an object instance

I'm surprised I don't know how to do this, but as it turns out I really don't; simply put, I'm trying to make a side-scrolling shooter game, a basic one and in it, I have 50 stars spawned on-screen through a "for" loop upon the game starting. There is a function which does this and a listener is at the beginning. Problem is, when you lose the game and go back to main menu, 50 more stars would be spawned, which isn't what I want. So, I'm trying to make an "if" statement check at the beginning, so that the game checks whether there is an instance/movie clip of the star object/symbol before determining whether the function that spawns stars should be called out with a listener. So, how do I do this? I looked through some other checks and they didn't help as the codes presented were vastly different there and so I'm just getting errors.
Let me know if a better explanation is needed or if you would like to see some of the code. Note that the game overall already has a lot of code, so just giving all of it would probably not be helpful.
I suggest you rethink your approach. You're focusing on whether stars have been instantiated. That's ok but not the most basic way to think about it.
I would do this instead
private function setup():void{
loadLevel(1);
addListeners();
loadMusic();
// etc...
// call all functions that are needed to just get the app up and running
}
private function loadLevel(lev:int):void{
addStars();
// call all functions that are needed each time a new level is loaded
}
private function restartLevel():void{
// logic for restarting level,
// but this *won't* include adding star
// because they are already added
}
There are other ways to do this but this makes more sense to me than your approach. I always break my game functions into smaller bits of logic so they can be reused more easily. Your main workhorse functions should (IMHO) primarily (if not exclusively) just call other functions. Then those functions do the work. By doing it this way, you can make a function like resetLevel by assembling all the smaller functions that apply, while excluding the part about adding stars.
Here's what I did to solve my problem... Here's what I had before:
function startGame():void
{
starsSpawn();
//other code here
}
This is what I changed it to:
starsSpawn();
function startGame():void
{
//other code here
}
when you said existance, so there is a container, i named this container, (which contain stars , and stars was added to it) as starsRoot, which absolutely is a DisplayObject (right?)
now, to checking whole childrens of a DisplayObject, we have to do this :
for (var i:int=0; i<starsRoot.numChildren; i++) {
var child = starsRoot.getChildAt[i];
}
then, how to check if that child is really star!?
as you said
whether there is an instance/movie clip of the star
so your stars's type is MovieClip, and they don't have any identifier (name), so how to find them and make them clear from other existing movieclips. my suggestion :
define a Linkage name for stars from library, thats a Class name and should be started with a capital letter, for example Stars
now, back to the code, this time we can check if child is an instance of Stars
for (var i:int=0; i<starsRoot.numChildren; i++) {
var child = starsRoot.getChildAt[i];
if (child is Stars) {
// test passed, star exist
break;
}
}

How can i get a function to use any movie clip?

I'm a little lost in understanding this kind of function, i get the feeling this has been asked a thousand times but cannot find an explanation of what the code is doing.
Basically i just want a movie clip with instance name box to do something, then reuse the function for other movie clips afterwards
a little like this, but working.
Many Thanks
//my function to be used on "instance name" box
myfunc (box);
function myfunc ();
{
while (this is happening);
{
//in this case box.x = goes where ever i put it
.x = goes here
.y = goes here
}
}
Sorry it's not quite English, my communication skills are terrible
Sure you can do that. You give the function a parameter, then refer to a parameter to change its properties. With such a simple movement function it could accept a DisplayObject - a distant superclass of a MovieClip and thus a superclass to many other possible classes of those objects that can be displayed by Flash.
function myfunc(param:DisplayObject):void {
// no semicolon after declaring the function!
while (somethingIsHappening(param)) {
// why not call a query on that object?
param.x+=1; // move right by 1 pixel
}
}
You might want to look at this manual on ActionScript 3 syntax, and the following pages on variables, functions and classes, to learn more.

Actionscript3 Simple platform collision confusion

I'm making a 2D platformer game and i'm trying to add collisions to the platforms so that when the character hits it it cannot pass through. I'm struggling to find the syntax to use to create this collision. So far this is what I have.
Also i would still like to be able to use hitTestObject within the if statement.
thanks
public function platform1Collision():void
{
if (fireboy1.hitTestObject(Platform1))
{
//fireboy1 cannot pass through
}
}
You'll probably want to prevent fireboy1's y property from extending past Platform1's y property:
function platform1Collision():void
{
if(fireboy1.hitTestObject(Platform1))
{
if(fireboy1.y > Platform1.y)
{
fireboy1.y = Platform1.y + Platform1.height;
}
else
{
fireboy1.y = Platform1.y - fireboy1.height;
}
}
}
NOTE: The above code sample assumes top-left orientation for both fireboy1 and Platform1.
EDITED: The above edited code will allow fireboy1 to walk beneath Platform1, but not pass through it.
This is a very rudimentary example to give you an idea of the type of logic you can use. If you want to allow fireboy1 to pass through Platform1 from below, you'll have to update the logic to allow for that. For example, if you take out the if/else and just automatically place fireboy1 above Platform1 every time they collide, it will appear as if player1 is jumping onto Platform1 when it is approached from below.

Tweening with actionscript 3

I have been working on this one a while. I have an object in this case a movieClip called "mcBall". I set up two buttons "btnLeft" and "btnRight"with a tween so that the mcBall will ease between the two points smoothly.
Works fine, but where it gets glitchy is the the two buttons are still active an if the user clicks on either button of course the ball goes back to the starting point like it's supposed to.
My question is this ... What is the best way to have the buttons be de-activated while the "mcBall" object is moving. Would it be best to use a removeEventListener for the buttons and then have it added again. Would it be better to use an if statement like "If (mcBall.x = >=81 || <=469) removeEventListener"? Maybe use the tweenEvent.MOTION_FINISH to set up the eventListener again.
Any help would be greatly appreciated. Thanks
using Flash cs3
In this code I managed to turn off one button so that while the ball is moving it remains inactive but the other is still active. I'm not sure of the placement of the removeEventListener.
import fl.transitions.Tween;
import fl.transitions.easing.*;
function moveBallRight(evt:MouseEvent):void {
var moveBall:Tween=new Tween(mcBall,"x",Regular.easeOut,80,470,4,true);
btnRight.removeEventListener(MouseEvent.CLICK,moveBallRight);
btnLeft.addEventListener(MouseEvent.CLICK,moveBallLeft);
}
btnRight.addEventListener(MouseEvent.CLICK,moveBallRight);
function moveBallLeft(evt:MouseEvent) {
var moveBall:Tween=new Tween(mcBall,"x",Regular.easeOut,470,80,4,true);
btnRight.addEventListener(MouseEvent.CLICK,moveBallRight);
btnLeft.removeEventListener(MouseEvent.CLICK,moveBallLeft);
}
btnLeft.addEventListener(MouseEvent.CLICK,moveBallLeft);
Personally, I would recommend using the Actuate tween library. Unlike TweenLite/Max, it is fully opensource, and has most of the features, and is faster, with no pro/pay version.
I also like Actuate's interface much better than TweenLite. It is very similar so easy for people to start using it, but I like how tween modifiers are added in a more explicit way.
Simple example:
Actuate.tween(mySprite, 1, { alpha:1 });
Then is you want to specify an easing equation, just chain it on the end:
Actuate.tween(mySprite, 1, { alpha:1 }).ease(Quad.easeOut);
Want a delay as well? Add that to the chain:
Actuate.tween(mySprite, 1, { alpha:1 }).delay(1).ease(Quad.easeOut);
Of course you can also call a function onComplete, even with parameters:
Actuate.tween(mySprite, 1, { alpha:1 }).onComplete(trace, 'Tween finished');
Check out the Actuate Google Code page linked above for the full list of methods with examples.
I would recommend not using the native Tween class from fl.transitions.Tween. Its not very good. The industry standard is TweenMax from greensock.
Using TweenMax it is trivially easy to respond to end-of-tween events. You simply add an onComplete:myhandlerfunction to your tween.
An example from your above code would look like this:
Instead of
var moveBall:Tween=new Tween(mcBall,"x",Regular.easeOut,80,470,4,true);
You would have:
TweenMax.to(mcBall, 4, {x:470, ease:Expo.easeOut, onComplete:onBallMovedLeftComplete};
Hope that helps. And I hope you never have to use those native tween classes again. They are the pits.
I agree that you should use TweenLite or TweenMax as the other answers suggests.
From what I gather though, the question is the best approach in activating/deactivating your event listeners for the buttons.
I'd say the best approach is to have a function for adding your button listeners and another function for removing them.
Then, whenever you call a tween, you first call the removal function before executing the tween.
Then upon completion, you call the function to add them again. You can use the onComplete parameter with Tweenlite to specify the function to add the button listeners.
for example :
function moveBallRight(evt:MouseEvent):void
{
removeButtonListeners();
TweenLite.to(mcBall, 4, {x:470, ease:Expo.easeOut, onComplete:addButtonListeners};
}
function moveBallLeft(evt:MouseEvent):void
{
removeButtonListeners();
// do your tween
TweenLite.to(mcBall, 4, {x:80, ease:Expo.easeOut, onComplete:addButtonListeners};
}
function addButtonListeners():void
{
// add both listeners here
}
function removebuttonListeners():void
{
// remove both listeners here
}
Also, you'd obviously want to call addButtonListeners at the beginning of your program as well, so that the listeners are initially active when the program runs.