In the code below I have several MovieClips that are all TheBeetle(). They are in another MovieClip called gamelevel and also pushed in an array called bArray. previously I have indexed them in the gamelevel but after the event listener is called I cannot index them anymore and receive the error "1118: Implicit coercion of a value with static type Object to a possibly unrelated type flash.display:DisplayObject.". As the user clicks them, they die (and change the frame) and the dead body goes under other alive bodies, thats the reason I need to index them to 1 as they die. I understand what the error says but how can i do what i need to do?
The code works just fine but it wouldn't in the two lines i've mentioned in it, so take a look please:
public function clicked (event:MouseEvent)
{
if (event.target is TheBeetle && event.target.currentFrame <= 2)
{
var mc:Object = event.target
// TheBeetle is actually a MovieClip but i cannot write: var mc:MovieClip = event.target, if i do i receive 1118
if (mc.currentFrame == 1)
{
mc.gotoAndStop (Math.floor(Math.random() * 3 + 4));
}
else
{
mc.gotoAndStop (3);
}
mc.filters = null;
// Here i need to index the TheBeetle as i did before like gamelevel.setChildIndex(mc,1) but i'd receive 1118!
bArray.splice (bArray.indexOf(mc),1);
if (bArray.length == 0)
{
removeEventListener (Event.ENTER_FRAME,frameHandler);
waveTimer.removeEventListener (TimerEvent.TIMER_COMPLETE, changeLocation);
}
}
}
You need to explicitly cast target to the MovieClip Class:
var mc:MovieClip = MovieClip(event.target);
You may need to do this BEFORE the line that checks target's currentFrame, as 'Object' doesn't have a currentFrame method.
I would recommend to use soft casting when you work with events and targets. By soft casting, if you have catched wrong target, you will not have problems - cast process simply returns null.
public function clicked (e:MouseEvent){
var beetle: TheBeetle = e.target as TheBeetle;
if(beetle != null && beetle.currentFrame <= 2){
//Work with beetle as you want
}
}
Related
So I'm creating a platform game in Actionscript 3.0, trying to call a function that spawns blocks based on an array. The code is in a 'Game' class and is directed towards a movieclip on my .fla
When it is ran I get the error:
"cannot convert flash.display::Stage#2a2cdf99 to flash.display.MovieClip."
Here's the code:
public function GameScreen(stageRef:Stage = null )
{
this.stageRef = stageRef;
btnReturn.addEventListener(MouseEvent.MOUSE_DOWN, returnMainMenu, false, 0, true);
mcMain.addEventListener(Event.ENTER_FRAME, moveChar);
this.addEventListener(Event.ENTER_FRAME, createLvl);
this.stageRef.addEventListener(KeyboardEvent.KEY_DOWN, checkKeysDown);
this.stageRef.addEventListener(KeyboardEvent.KEY_UP, checkKeysUp);
this.stageRef.addChild(blockHolder);
}
And
private function createLvl(event:Event):void
{
var lvlArray:Array = MovieClip(root)['lvlArray' +lvlCurrent];
var lvlColumns:int = Math.ceil(lvlArray.length/16);
for(var i:int = 0;i<lvlArray.length;i++){
if(lvlArray[i] == 1){
if(i/lvlColumns == int(i/lvlColumns)){
row ++;
}
var newBlock:Block = new Block();
newBlock.graphics.beginFill(0xFFFFFF);
newBlock.graphics.drawRect(0,0,50,50);
newBlock.x = (i-(row-1)*lvlColumns)*newBlock.width;
newBlock.y = (row - 1)*newBlock.height;
blockHolder.addChild(newBlock);
} else if (lvlArray[i] == 'MAIN'){
mcMain.x = (i-(row-1)*lvlColumns)*newBlock.width;
mcMain.y = (row-1)*newBlock.height;
}
}
row = 0;
}
Please help =(
Thanks!
First of all:
Turn on "permit debugging" in your publish settings. This will give you line numbers with your errors, so you can determine the exact location of your error.
Post the entire stack trace. That error by itself is not a lot to go on.
Given the error and the code you've posted, the error must be caused by your use of MovieClip(root). The root property does not always point to the main timeline in Flash, it will point to the Stage if the display object is added directly to the stage. For example:
trace(stage.addChild(new Sprite()).root) // [object Stage]
Documentation on root: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html#root
Alright, so i've got some code that says that if a hit test is preformed, a variable is increased by 1. However, when I run it, I get crazy numbers like 1,1,1,2,5,3,2,5,2,3,4,1,1
There's no pattern, it's just random. Here's the code:
public function loop(e:Event)
{
y += speed;
if (y > stage.stageHeight)
{
setupAsteroid(false);
}
//hittest for the asteroid
if (hitTestObject(target))
{
stageRef.addChild(new Explosion(stageRef, x, y));
trace("Hit");
kills ++;
trace(kills);
if(kills == 3){
trace("Success");
}
}
I've included all the code in the function used, and not all of it is necessary to the hit test as you can see. also, the variable is declared correctly as
private var kills:Number = 0;
inside the same .as file and class.
You add an Explosion to the stage but there is no sign of you removing anything from the stage, or at least stopping the check for hitTest. Also I'm guessing that your function loop(e:Event) listens for an ENTER_FRAME event and in that case if you're not removing anything from the stage that hitTest is going to be returning true every frame and creating a new Explosion every frame. Why not just add a public variable to target, like public var destroyed:boolean = false; and reconstruct your hitTest to read if(hitTestObject(target) && !target.destroyed) and in the body of your conditional just add target.destroyed = true;
More code would definitely help though.
I have a working drag and drop game, but it's not perfect. All my movieclips drag and drop to their targets when you are exactly lined up with the target.
However, if you let go of the mouse up when dragging the mc outside of the target zones, it will sometimes, but not always, throw the 1010 term undefined error and will not snap the mc back to its original start x/y coordinates (it just leaves the mc in the spot it was during mouse up). I ran the debugger and it deals with this line in my drop function:
if (event.currentTarget.dropTarget != null && MovieClip(event.currentTarget.dropTarget.parent).allowed.indexOf(event.currentTarget) >= 0){
FYI, allowed is a set of target arrays since I wanted "zones" for targets and not specific targets for some of the movieclips.
Any ideas?
Updated Code Below:
if (event.currentTarget.dropTarget != null) {
var mc:MovieClip=event.currentTarget.dropTarget as MovieClip;
if (mc==null) { // typecast fails. Say there's a Sprite below
reply_txt.textColor = 0xEE1212
reply_txt.text = "Oops! Try Again!";
event.currentTarget.alpha = 1;
event.currentTarget.x = startX;
event.currentTarget.y = startY;
return; // nothing to do here
}
mc=mc.parent;
if (mc && mc.allowed) {
// this MC has "allowed" property not "undefined" - we're in the grid
// so now we can check indexOf() safely
if (mc.allowed.indexOf(event.currentTarget)>=0){
reply_txt.textColor = 0x33BC10
reply_txt.text = "Good Job!";
event.currentTarget.alpha = 1;
event.currentTarget.removeEventListener(MouseEvent.MOUSE_DOWN, pickUp);
event.currentTarget.removeEventListener(MouseEvent.MOUSE_UP, dropIt);
event.currentTarget.buttonMode = false;
event.currentTarget.x = MovieClip(event.currentTarget.dropTarget.parent).x;
event.currentTarget.y = MovieClip(event.currentTarget.dropTarget.parent).y;
stored.push(event.currentTarget);
startXarray.push(startX);
startYarray.push(startY);
counter++;
}
}
}
Yes, when you stopDrag an object, it checks what kind of a DisplayObject is below the cursor, and that one is returned as dropTarget property in your event. So, if your object is dropped onto another MC that does not have allowed property, your 1010 error is thrown. You need to check this situation in a nested if statement like this:
if (event.currentTarget.dropTarget != null) {
var mc:MovieClip=event.currentTarget.dropTarget as MovieClip;
if (mc==null) { // typecast fails. Say there's a Sprite below
returnThisBack();
return; // nothing to do here
}
mc=mc.parent;
if (mc && mc.allowed) {
// this MC has "allowed" property not "undefined" - we're in the grid
// so now we can check indexOf() safely
if (mc.allowed.indexOf(event.currentTarget)>=0) snapThisToGrid();
} else returnThisBack();
} else returnThisBack();
I have items in an array, each is a movieclip, which play at delayed intervals of 1 second and a target movieclip (carTarget) controlled by arrow keys where the aim is to avoid a collision with the array items (obstacleArray[i]). I have been attempting to create a hitTestObject statement to notify when there is a collision. However I have received errors such as parameter hitTestObject most be non-null and cannot figure out how to resolve it.
//obstacles
function randomSort(a:*, b:*):Number
{
if (Math.random() < 0.5) return -1;
else return 1;
}
var obstacleArray:Array = [obstacleCar,obstacleCar2,obstacleCar3];
obstacleArray.sort(randomSort);
trace(obstacleArray);
trace(obstacleArray.length);
//OBSTACLE START DELAY
var timerPlay:Timer = new Timer(1000,1);
timerPlay.addEventListener(TimerEvent.TIMER, ontimerPlay);
timerPlay.start();
var i:int = 0;
var timerDelay:Timer = new Timer(1000, 3);
function ontimerPlay(evt:TimerEvent):void{
obstacleArray[i].addEventListener(Event.ENTER_FRAME,checkHitTest);
//FOR EACH OBSTACLE
timerDelay.addEventListener(TimerEvent.TIMER, ontimerDelay);
timerDelay.start();
}
function checkHitTest(event:Event):void{
if(carTarget.hitTestObject(obstacleArray[i]))
{
trace("HIT!");
}
}
function ontimerDelay(evt:TimerEvent):void{
obstacleArray[i].play();
trace(obstacleArray[i]);
i++;
}
Most likely, the problem is in this block of code:
function checkHitTest(event:Event):void{
if(carTarget.hitTestObject(obstacleArray[i]))
{
trace("HIT!");
}
}
After i changes with the timer calls, then obstacleArray[i] will be null or worse - another object other than the one you need to check.
You should change this to:
function checkHitTest(event:Event):void{
if(carTarget.hitTestObject(event.target))
{
trace("HIT!");
}
}
event.target will get the current obstacle calling the checkHitTest from Enterframe event
It is very likely that hitTestObject does not exist at the moment you're trying to use it. From the code you shared, I do not see where you create it in your code. So, assuming carTarget is an object on the stage and that it has the property or object hitTestObject initialized when you want to use it -assuming those things, then you need to make sure that when this code is running, that object still exists.
I get a very similar problem when I uncomment the mcMain. method calls. When I try to call an instance on the stage it says "1061: Call to a possibly undefined method addEventListener through a reference with static type Class."
I have done similar stuff before on another computer and I am not sure why this is doing this. I am Using Adobe Flash CS5.5 and AS3.0.
//These variables will note which keys are down
//We don't need the up or down key just yet
//but we will later
var leftKeyDown:Boolean = false;
var upKeyDown:Boolean = false;
var rightKeyDown:Boolean = false;
var downKeyDown:Boolean = false;
//the main character's speed
var mainSpeed:Number = 7;
//adding a listener to mcMain which will make it move
//based on the key strokes that are down
mcMain.addEventListener(Event.ENTER_FRAME, moveChar);
function moveChar(event:Event):void
{
//if certain keys are down then move the character
if (leftKeyDown)
{
trace("left");
//mcMain.x -= mainSpeed;
}
if (rightKeyDown)
{
trace("right");
//mcMain.x += mainSpeed;
}
//if(upKeyDown || mainJumping){
////mainJump();
//}
}
http://i.stack.imgur.com/PtR7F.png
I believe from your screenshot that you named the object mcMain as the class name but not as the instance of the object's name. Click the properties panel and give the instance a name, that's the name you'll use to refer to it in AS3, the other name you made is what you would use if you wanted to make new instances of the object in AS3 (it's effectively the class name).
Check how mcMain is defined. Should be something like var mcMain:MovieClip;.