TypeError: Error #2007: Parameter hitTestObject must be non-null - actionscript-3

I've a question here.
I'm doing a game, space invader.
It prompt me an error
TypeError: Error #2007: Parameter hitTestObject must be non-null.
at flash.display::DisplayObject/_hitTest()
at flash.display::DisplayObject/hitTestObject()
at Enemy/eFrame()
I hope that anyone of you could help me with it.
Thank you very much!
//This is the basic skeleton that all classes must have
package{
//we have to import certain display objects and events
import flash.display.MovieClip;
import flash.events.*;
//this just means that Enemy will act like a MovieClip
public class Enemy extends MovieClip{
//VARIABLES
//this will act as the root of the document
//so we can easily reference it within the class
private var _root:Object;
//how quickly the enemy will move
private var speed:int = 5;
//this function will run every time the Bullet is added
//to the stage
public function Enemy(){
//adding events to this class
//functions that will run only when the MC is added
addEventListener(Event.ADDED, beginClass);
//functions that will run on enter frame
addEventListener(Event.ENTER_FRAME, eFrame);
}
private function beginClass(event:Event):void{
_root = MovieClip(root);
}
private function eFrame(event:Event):void{
//moving the bullet up screen
y += speed;
//making the bullet be removed if it goes off stage
if(this.y > stage.stageHeight){
removeEventListener(Event.ENTER_FRAME, eFrame);
_root.removeChild(this);
}
//checking if it is touching any bullets
//we will have to run a for loop because there will be multiple bullets
for(var i:int = 0;i<_root.bulletContainer.numChildren;i++){
//numChildren is just the amount of movieclips within
//the bulletContainer.
//we define a variable that will be the bullet that we are currently
//hit testing.
var bulletTarget:MovieClip = _root.bulletContainer.getChildAt(i);
//now we hit test
if(hitTestObject(bulletTarget)){
//remove this from the stage if it touches a bullet
removeEventListener(Event.ENTER_FRAME, eFrame);
_root.removeChild(this);
//also remove the bullet and its listeners
_root.bulletContainer.removeChild(bulletTarget);
bulletTarget.removeListeners();
//up the score
_root.score += 5;
}
}
//hit testing with the user
if(hitTestObject(_root.mcMain)){
//losing the game
_root.gameOver = true;
_root.gotoAndStop('lose');
}
if(_root.gameOver){
removeEventListener(Event.ENTER_FRAME, eFrame);
this.parent.removeChild(this);
}
}
public function removeListeners():void{
this.removeEventListener(Event.ENTER_FRAME, eFrame);
}
}
}

The error means you have called hitTestObject(null) in your code, which is invalid.
From the code you shared, either bulletTarget or _root.mcMain could be the reason.

Related

making a symbol move by keyboard not showing result and when published it not reads stop(); but replays it again and again

I am new to actionscript ,
My document class is ,
package
{
//list of our imports these are classes we need in order to
//run our application.
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
public class engine extends MovieClip
{
// moved ourShip to a class variable.
private var Circle:circle = new circle()
//our constructor function. This runs when an object of
//the class is created
public function engine()
{
addFrameScript(0, frame1);
addFrameScript(1, frame2);
}
// frame 1 layer 1 --------------------------------------------------
public function frame1()
{
stop();
}
//-------------------------------------------------------------------
// frame 2 layer 1 --------------------------------------------------
public function frame2()
{
Circle.x = stage.stageWidth / 2;
Circle.y = stage.stageHeight / 2;
addChild(Circle);
}
//-------------------------------------------------------------------
}
}
i made two frames first contains button and the other circle which i want to move but it not moves and it stays in the middle on second frame
My button class is
package
{
//imports
import flash.events.MouseEvent;
import flash.display.SimpleButton;
import flash.display.MovieClip;
//-------
public class start extends SimpleButton
{
public function start()
{
addEventListener(MouseEvent.CLICK, onTopClick);
addEventListener(MouseEvent.MOUSE_OVER, onBottomOver);
}
function onTopClick(e:MouseEvent):void
{
MovieClip(root).gotoAndStop(2)
}
function onBottomOver(e:MouseEvent):void
{
}
}
}
And my as of circle movieclip is
package
{
//imports
import flash.display.MovieClip;
import flash.display.Stage;
import flash.ui.Keyboard;
import flash.events.Event;
import flash.events.KeyboardEvent;
public class circle extends MovieClip
{
private var speed:Number = 0.5;
private var vx:Number = 0;
private var vy:Number = 0;
private var friction:Number = 0.93;
private var maxspeed:Number = 8;
public function circle()
{
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
public function loop(e:Event) : void
{
addEventListener(KeyboardEvent.KEY_DOWN, keyHit);
x+=vx;
y+=vy
}
function keyHit(event:KeyboardEvent):void {
switch (event.keyCode) {
case Keyboard.RIGHT :
vx+=speed;
break;
case Keyboard.LEFT :
vx-=speed;
break;
case Keyboard.UP :
vy-=speed;
break;
case Keyboard.DOWN :
vy+=speed;
break;
}
}
}
}
I am sorry to post so much for you guys to read but stackoverflow is the only website where anyone helps me !
You have made several major errors. First, addFrameScript() isn't a proper way to place code on frames, use Flash's editor to place code on timeline. (IIRC you will have to make a single call out of your two in order to have all the code you add to function) And, whatever code you added to a frame of a MC is executed each frame if the MC's currentFrame is the frame with code. Thus, you are adding a function "frame2()" that places the Circle in the center of the stage each frame! You should instead place it at design time (link it to a property) into the second frame, or in a constructor, or you can use one single frame and Sprite instead of MovieClip, and instead of using frames you can use container sprites, adding and removing them at will, or at an action.
The other major mistake is adding an event listener inside an enterframe listener - these accumulate, not overwrite each other, so you can have multiple functions be designated as listeners for a particular event, or even one function several times. The latter happens for you, so each frame another instance of a listening keyHit function is added as a listener. The proper way to assign listeners is either in constructor, or in any function that listens for manually triggered event (say, MouseEvent.CLICK), but then you have to take precautions about listening for more than once with each function, and listening only with those functions you need right now.
EDIT:
Okay. Your code was:
addFrameScript(0, frame1);
addFrameScript(1, frame2);
The more correct way should be:
addFrameScript(0,frame1,1,frame2);
The reason is, the call to addFrameScript replaces all the timeline code with what you supply within here. The function is undocumented, perhaps by the reason of its affects on the stage and AS3 environment. The closest thing to the documentation on addFrameScript() so far is this link.
Next: Your code is:
public function circle()
{
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
public function loop(e:Event) : void
{
addEventListener(KeyboardEvent.KEY_DOWN, keyHit);
x+=vx;
y+=vy
}
The correct way of writing this is as follows:
public function circle()
{
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(e:Event=null):void
{
removeEventListener(Event.ADDED_TO_STAGE,init);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyHit);
}
public function loop(e:Event) : void
{
x+=vx;
y+=vy
}
The listeners should be assigned in constructor, if they are permanent or you want them to be active as soon as you create an object. The KeyboardEvent listeners are separate case, as in order for them to function you have to assign them to stage, which is not available right at the time of creating the object, so you need an intermediate layer - the init() function, that is only called when the object is added to stage. At this point stage is no longer null, and you can assign an event listener there. Note, if you want to make your circles eventually disappear, you have to remove the listener you assigned to stage at some point of your removal handling code.
Next: Your code:
public function frame2()
{
Circle.x = stage.stageWidth / 2;
Circle.y = stage.stageHeight / 2;
addChild(Circle);
}
Correct code should be:
public function frame2():void
{
if (Circle.parent) return; // we have added Circle to stage already!
Circle.x = stage.stageWidth / 2;
Circle.y = stage.stageHeight / 2;
addChild(Circle);
}
See, you are calling this every time your MC is stopped at second frame, thus you constantly reset Circle's coordinates to stage center, so you just cannot see if it moves (it doesn't, as you have assigned the keyboard listener not to stage).
Perhaps there are more mistakes, but fixing these will make your MC tick a little bit.

AS3 - Access MovieClip from stage within a class

I have been stuck on this for a long time and have looked at past questions on here about this similar issue such as this post: How do I access a movieClip on the stage using as3 class?.
I use the constructor to listen for the ADDED_TO_STAGE event, and then initiate the main function to set up the eventListeners from the ADDED_TO_STAGE handler. Within the same handler I also try to get a MovieClip from the stage using the following code:
player = stage.getChildByName("player") as MovieClip;
player is defined globally as a MovieClip.
Within another handler (after the class has been added to the stage) I set the player to go to an particular frame label using player.gotoAndStop("jump");. However an output warning shows up saying "Cannot access a property or method of a null object reference".
Here is the code which I use:
public var player:MovieClip;
public function PlayerControl():void {
this.addEventListener(Event.ADDED_TO_STAGE, addedToStage);
}
private function addedToStage(event:Event):void{
removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
player = stage.getChildByName("player") as MovieClip;
}
private function enterFrameHandler(event:Event):void{
if(up == true && moviePlaying == false){
player.gotoAndStop("jump");
moviePlaying = true;
}
}

Actionscript 3.0, error with hitTestObject

I'm getting an error I can't seem to fix. I think I know kind of what is going on but I'm not sure enough to be able to fix it. I keep getting error
"TypeError: Error #2007: Parameter hitTestObject must be non-null.
at flash.display::DisplayObject/_hitTest()
at flash.display::DisplayObject/hitTestObject()"
Basically I fire an attack in my game. It hits an enemy and he is killed just fine. BUT, he has an animation as he dies that takes a couple seconds. It seems if I fire another attack during his animation, my attack IMMEDIATELY gives this error (before striking anything, that is). Once the animation is over, everything is fine again. Also, the game was working 100% fine before I put in this animation.
Here is my document class
package com.classes
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
public class DocumentClass extends MovieClip
{
// we need to keep track of our enemies.
public static var enemyList1:Array = new Array();
// moved stickobject1 to a class variable.
private var stickobject1:Stickman2;
public function DocumentClass() : void
{
//removed the var stickobject1:Stickman2 because we declared it above.
var bg1:background1 = new background1();
stage.addChild(bg1);
stickobject1 = new Stickman2(stage);
stage.addChild(stickobject1);
stickobject1.x=50;
stickobject1.y=300;
//running a loop now.... so we can keep creating enemies randomly.
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
//our loop function
private function loop(e:Event) : void
{
//run if condition is met.
if (Math.floor(Math.random() * 90) == 5)
{
//create our enemyObj1
var enemyObj1:Enemy1 = new Enemy1(stage, stickobject1);
//listen for enemyObj1 being removed from stage
enemyObj1.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemyObj1, false, 0, true);
//add our enemyObj1 to the enemyList1
enemyList1.push(enemyObj1);
stage.addChild(enemyObj1);
}
}
private function removeEnemyObj1(e:Event)
{
enemyList1.splice(enemyList1.indexOf(e.currentTarget), 1);
}
}
}
And here is my attack1 class
package com.classes {
import flash.display.MovieClip;
import flash.display.Stage;
import com.senocular.utils.KeyObject;
import flash.ui.Keyboard;
import flash.events.Event;
public class attack1 extends MovieClip {
private var stageRef:Stage;
private var bulletSpeed:Number = 16;
public function attack1 (stageRef:Stage, x:Number, y:Number) : void
{
this.stageRef = stageRef;
this.x = x;
this.y = y;
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
private function loop(e:Event) : void
{
//move bullet up
x += bulletSpeed;
if (x > stageRef.stageWidth)
removeSelf();
for (var i:int = 0; i < DocumentClass.enemyList1.length; i++)
{
if (hitTestObject(DocumentClass.enemyList1[i].hit))
{
trace("hitEnemy");
removeSelf();
DocumentClass.enemyList1[i].takeHit();
}
}
}
private function removeSelf() : void
{
removeEventListener(Event.ENTER_FRAME, loop);
if (stageRef.contains(this))
stageRef.removeChild(this);
}
}
}
Don't think you should need any other of my classes to figure out what's going on, but let me know if you do! Thanks very much =)
You don't want to do a hit test against any object that may have been removed from the scene (or from the enemyList array). The extra condition added to attack1.loop's for loop should get rid of your error. A better fix is to splice out the items you remove, so they are never tested against in the loop.
The break line will make it stop trying to hit other enemies after the bullet is removed. If the line "DocumentClass.enemyList1[i].takeHit();" removes the item from the enemyList1, you need to make sure you use "i--;" at the bottom of the loop as well, if you plan on looping through the remainder of the enemies. "i--" or "break", you will probably need one of them in that loop.
Double check the order in which you are executing your removal methods. Sometimes it's better to flag the items for removal and remove them in a separate loop than to remove an item that may be needed later in the same loop.
for (var i:int = 0; i < DocumentClass.enemyList1.length; i++){
if(DocumentClass.enemyList1[i] && DocumentClass.enemyList1[i].hit){
if (hitTestObject(DocumentClass.enemyList1[i].hit)){
trace("hitEnemy");
removeSelf();
DocumentClass.enemyList1[i].takeHit();
break;
}
}
}
Not the correct solution in this question. You can always do != null in a conditional statement.
if(object!=null){
party.drink();
}

as3 Error 1009 at Coin1/coin1go(), i am trying to get an enemy to drop a coin

So the enemy does drop a coin but i does not get the properties of the coin( if it hits the player it gives him +5 coins)
The coin will be removed if it hits the bottom of the stage, if the player dies or if the player hits it. Sadly, it does not work.
But this does work if i place a coin on the stage before i start the game, it gets all its properties, so then it must be the moment it gets added to the stage that it does not get linked with the coding or something..... and that is where i am right now.
this is the .as file for the coin:
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class Coin1 extends MovieClip
{
private var _root:Object;
private var speed:int = 0;
public function Coin1()
{
addEventListener(Event.ENTER_FRAME, Speed1);
addEventListener(Event.ADDED, beginClass);
addEventListener(Event.ENTER_FRAME, coin1go);
}
private function beginClass(event:Event):void
{
_root = MovieClip(root);
}
private function Speed1(event:Event):void
{
y += speed;
}
private function coin1go(event:Event):void
{
if (this.y > stage.stageHeight)
{
removeEventListener(Event.ENTER_FRAME, coin1go);
_root.removeChild(this);
}
if (hitTestObject(_root.player_mc))
{
_root.coin += 1;
removeEventListener(Event.ENTER_FRAME, coin1go);
_root.removeChild(this);
}
if (_root.playerhealth <= 1)
{
removeEventListener(Event.ENTER_FRAME, coin1go);
_root.removeChild(this);
}
}
}
}
This is the part from where it gets added to the stage:
if (enemy2health <= 0)
{
removeEventListener(Event.ENTER_FRAME, eFrame);
_root.score += _root.Enemy2Score * _root.scoremultiplyer;
stage.addChild(newExplosionSmall)
newExplosionSmall.x = this.x;
newExplosionSmall.y = this.y;
stage.addChild(newCoin1)
newCoin1.x = this.x;
newCoin1.y = this.y;
Ass you can see there is also an addchild for an explosion wich works perfectly fine but that may jus be because it does nothing else than appear and remove itself.
So long story short: enemy drops coin but it does nothing and floats to the bottom of the screen and i get a constant stream of 1009 errors. so does anyone know how to fix this?
You should add an enterframe listener only after receiving a valid stage reference, which only appears when Event.ADDED_TO_STAGE event is received. This is because your enterframe listener refers stage.
public function Coin1()
{
addEventListener(Event.ENTER_FRAME, Speed1);
addEventListener(Event.ADDED_TO_STAGE, beginClass);
}
private function beginClass(event:Event):void
{
_root = MovieClip(root);
addEventListener(Event.ENTER_FRAME, coin1go);
}

Make Flash Parent Fade Out & adding sound BrickBreaker Game

Hi i am trying to get this brick to fade out when the ball hits it in my brickbreaker game in flash AS3. Here is the code. At the moment there is just a removechild function which makes it just dissapear i want to know how to make it fade out instead. Also i have a breaking sound i would like to add when the ball hits the brick and wonder how i would add this aswell?
EDIT: I have managed to add sound by using Var & Play after the remove child line
package {
import flash.display.*;
import flash.events.*;
public class Brick extends MovieClip {
private var _root:MovieClip;
public function Brick(){
addEventListener(Event.ADDED, beginClass);
addEventListener(Event.ENTER_FRAME, enterFrameEvents);
}
private function beginClass(event:Event):void{
_root = MovieClip(root);
}
private function enterFrameEvents(event:Event):void{
if(this.hitTestObject(_root.Ball)){
_root.ballYSpeed *= -1;
this.parent.removeChild(this);
removeEventListener(Event.ENTER_FRAME, enterFrameEvents);
}
}
}
}
No need for any tweener pack for just one tween.
You can use the Tween class provided in AS3 itself. Try this :
new Tween(mc,"alpha",
Strong.easeIn,
mc.alpha,
0,
2,
true).addEventListener(
TweenEvent.MOTION_FINISH,
function() { removeChild(mc); },
false, 0, true);
Note:
mc is the movieclip (or the brick).
The code removes the movieclip from stage after the tween completes.
You may play the sound as soon as the ball touches the brick & put
this code after that.
The last three parameters (false, 0, true) set the motion finish listener to be garbage collected.
How I would do it would be to first create a variable hit:Boolean and set it to true when it gets hit and change your code inside enterFrameEvents function to something like this
if(!hit && this.hitTestObject(_root.Ball)){
hit = true;
_root.ballYSpeed *= -1;
//this.parent.removeChild(this);
//removeEventListener(Event.ENTER_FRAME, enterFrameEvents);
}
if(hit){
this.alpha -= 0.1; //change value to preference
if(this.alpha <= 0){
this.parent.removeChild(this);
removeEventListener(Event.ENTER_FRAME, enterFrameEvents);
}
}