I keep getting the following error when I fire a Shot I made in Flash CS6 AS 3.0
1118: Implicit coercion of a value with static type Object to a possibly unrelated type flash.display:DisplayObject.
package
{
import flash.display.MovieClip;
import flash.ui.Mouse;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.ui.Keyboard;
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.media.SoundChannel;
public class AvoiderGame extends MovieClip
{
public var army:Array;
public var reishoot:ReiShoot;
public var enemy:Enemy;
public var avatar:Avatar;
public var gameTimer:Timer;
public var useMouseControl:Boolean;
public var downKey:Boolean;
public var bullets:Array = [];
public var backgroundMusic:BackgroundMusic;
public var enemySound:EnemySound;
public var bgmSoundChannel:SoundChannel;
public var sfxSoundChannel:SoundChannel;
function AvoiderGame()
{
/*useMouseControl = false;
downKey = false;
if( useMouseControl )
{
avatar.x = mouseX;
avatar.y = mouseY;
}
else
{
avatar.x = 200;
avatar.y = 250;
}
*/
backgroundMusic = new BackgroundMusic();
bgmSoundChannel = backgroundMusic.play();
bgmSoundChannel.addEventListener( Event.SOUND_COMPLETE, onBackgroundMusicFinished );
enemySound = new EnemySound();
army = new Array();
//Initial Position of the Enemy
var newEnemy = new Enemy( 2700, 600 );
army.push( newEnemy );
addChild( newEnemy );
avatar = new Avatar();
addChild( avatar );
avatar.height = 220;
avatar.width = 120;
avatar.addEventListener(MouseEvent.CLICK, shoot);
gameTimer = new Timer( 25 );
gameTimer.addEventListener( TimerEvent.TIMER, onTick );
gameTimer.start();
//addEventListener( Event.ADDED_TO_STAGE, onAddToStage );
}//End AvoiderGame
function shoot(e:MouseEvent):void
{
var b:Shot = new Shot();
b.addEventListener(Event.ENTER_FRAME, bulletflies);
stage.addChild(b);
bullets.push(b);
}
function bulletflies(e:Event):void
{
e.currentTarget.y -= 5;
if(e.currentTarget.y < 0 || e.currentTarget.y > stage.height)
{
stage.removeChild(e.currentTarget);
bullets.splice(bullets.indexOf(e.currentTarget), 1);
}
}
public function onBackgroundMusicFinished( event:Event ):void
{
bgmSoundChannel = backgroundMusic.play();
bgmSoundChannel.addEventListener( Event.SOUND_COMPLETE, onBackgroundMusicFinished );
}
public function onKeyPress(keyboardEvent:KeyboardEvent):void
{
if ( keyboardEvent.keyCode == Keyboard.DOWN )
{
downKey = true;
}
}
public function onKeyRelease( keyboardEvent:KeyboardEvent ):void
{
if ( keyboardEvent.keyCode == Keyboard.DOWN )
{
downKey = false;
}
}
public function onAddToStage(event:Event):void
{
stage.addEventListener( KeyboardEvent.KEY_DOWN, onKeyPress );
stage.addEventListener( KeyboardEvent.KEY_UP, onKeyRelease );
}
public function onTick( timerEvent:TimerEvent ):void
{
if ( Math.random() < 2800 )
{
var randomY:Number = Math.random() * 2800;
var newEnemy:Enemy = new Enemy( width, randomY );
army.push( newEnemy );
addChild( newEnemy );
gameScore.addToValue( 1 );
//sfxSoundChannel = enemySound.play();
}//End if statement
/*
if( useMouseControl )
{
avatar.x = mouseX;
avatar.y = mouseY;
}
else
{
if ( downKey )
{
avatar.moveDown();
}
}
*/
avatar.x = mouseX;
avatar.y = mouseY;
for each ( var enemy:Enemy in army )
{
enemy.moveDownABit();
if ( avatar.hitTestObject( enemy ) )
{
bgmSoundChannel.stop();
gameTimer.stop();
dispatchEvent( new AvatarEvent( AvatarEvent.DEAD ) );
}//End if statement
}//End for loop
}//End onTick function
public function getFinalScore():Number
{
return gameScore.currentValue;
}
}//End AvoiderGame class
}//End package
Line 90 is stage.removeChild(e.currentTarget);
With this, you need to cast e.currentTarget to a DisplayObject:
stage.removeChild(e.currentTarget as DisplayObject);
Just a guess: you've started your ENTER_FRAME loop, (which will remove 'b') before you've said addChild(b). Try putting 'b' on the display list before you try to remove it!!
Aha! I think I may have found your problem, though I am unsure of how it relates to the error code...
Take a look at your Shot class (which I have found here https://stackoverflow.com/questions/22244959/why-does-this-not-shoot). Every frame, you tell the Shot class to test whether it is in the boundaries of the stage still, and if so, to remove itself from the stage. In line 90, you also tell the stage to determine if the bullet is still in bounds, and if so, to remove it again.
You have tried to remove the bullet from the stage twice!
Again, I stress, this seems to be unrelated to the error code, but hopefully it points you in the right direction.
Related
I'm trying to remove this item from the stage and keep getting this error. The code seems to work and the object is removed but the game seems kinda buggy.
Here's the full error:
ArgumentError: Error #2025: The supplied DisplayObject must be a child
of the caller. at flash.display::DisplayObjectContainer/removeChild()
at
JumpingGame/onTick2()[E:\Folder\Folder\Folder\Folder\JumpingGame.as:95]
at flash.utils::Timer/_timerDispatch() at flash.utils::Timer/tick()
The error is pointing to:
removeChild(enemy)
removeChild(leg);
removeChild(life);
I'm also getting:
TypeError: Error #1009: Cannot access a property or method of a null
object reference
on this line theLives.text = liveLives.toString();
Here's my code:
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class JumpingGame extends MovieClip
{
public var army:Array;
public var powerups:Array;
public var pluslives:Array;
public var newDoodle:doodle;
public var enemyTimer:Timer;
public var legTimer:Timer;
public var lifeTimer:Timer;
public function JumpingGame()
{
enemyTimer = new Timer( 40 );
enemyTimer.addEventListener( TimerEvent.TIMER, onTick );
enemyTimer.start();
legTimer = new Timer( 20 );
legTimer.addEventListener( TimerEvent.TIMER, onTick2 );
legTimer.start();
lifeTimer = new Timer( 30 );
lifeTimer.addEventListener( TimerEvent.TIMER, onTick3 );
lifeTimer.start();
army = new Array();
var newEnemy = new Enemy( 100, -15 );
army.push( newEnemy );
addChild( newEnemy );
powerups = new Array();
var newLeg = new Leg( 300, -15 );
powerups.push( newLeg );
addChild( newLeg );
pluslives = new Array();
var newLife = new Plus1( 300, -15 );
pluslives.push( newLife );
addChild( newLife );
newDoodle = new doodle();
addChild( newDoodle );
newDoodle.y = stage.stageHeight - 50;
newDoodle.x = stage.stageWidth / 2;
}
public function onTick( timerEvent:TimerEvent ):void
{
if (Math.random() <0.005 )
{
var randomX:Number = Math.random() * 320;
var newEnemy:Enemy = new Enemy( randomX, -15 );
army.push( newEnemy );
addChild( newEnemy );
}
for each ( var enemy:Enemy in army )
{
enemy.moveDownABit();
if (newDoodle.hitTestObject( enemy ) )
{
//gotoAndPlay ("Game Over");
removeChild(enemy);
liveLives -= 1;
theLives.text = liveLives.toString();
}
}
}
public function onTick2( timerEvent:TimerEvent ):void
{
if (Math.random() <0.008 )
{
var randomX2:Number = Math.random() * 320;
var newLeg:Leg = new Leg( randomX2, -15 );
powerups.push( newLeg );
addChild( newLeg );
}
for each ( var leg:Leg in powerups )
{
leg.moveDownABit2();
if (newDoodle.hitTestObject( leg ) )
{
//gotoAndPlay ("Game Over");
removeChild(leg);
liveScore += 2000;
theScore.text = liveScore.toString();
}
}
}
public function onTick3( timerEvent:TimerEvent ):void
{
if (Math.random() <0.001 )
{
var randomX3:Number = Math.random() * 320;
var newLife:Plus1 = new Plus1( randomX3, -15 );
pluslives.push( newLife );
addChild( newLife );
}
for each ( var life:Plus1 in pluslives )
{
life.moveDownABit3();
if (newDoodle.hitTestObject( life ) )
{
//gotoAndPlay ("Game Over");
removeChild(life);
liveLives += 1;
theLives.text = liveLives.toString();
}
}
}
}
}
Try using:
enemy.parent.removeChild(enemy)
leg.parent.removeChild(leg);
life.parent.removeChild(life);
And there is no liveLives var, or theLives textfield on stage is misspelled.
The problem you have is caused by removing the objects from the display list without removing them from the data structure that you store them in.
Take a look at this excerpt from your code:
Let's say that powerups has only one element and hitTestObject returns true. The object is removed from display.
for each ( var leg:Leg in powerups )
{
if (newDoodle.hitTestObject( leg ) )
{
removeChild(leg);
the code is executed the second time. The object is still in the array. hitTestObject still returns true. The object cannot be removed from display, because it was removed already when the function was executed for the first time.
You have two data structures: the display list and your array and they are out of sync.
To solve this, remove the object from the array, not just the display list:
find the index of the object that you want to remove with indexOf()
remove the element at that index with splice()
In this case, you should not use 3 array to store child objects. Simple that, you create 3 empty movie clips and add child to them. After that, you remove them when hit test.
Something like that:
public function onTick( timerEvent:TimerEvent ):void
{
if (Math.random() <0.005 )
{
var randomX:Number = Math.random() * 320;
var newEnemy:Enemy = new Enemy( randomX, -15 );
armyContainer.addChild( newEnemy );
}
var childs:Array = [];
for (var i:int = 0; i<armyContainer.numChildren; i++) {
var enemy:Enemy = armyContainer.getChildAt(i) as Enemy;
enemy.moveDownABit();
if (newDoodle.hitTestObject( enemy ) )
{
//gotoAndPlay ("Game Over");
//removeChild(enemy);
childs.push(enemy);
liveLives -= 1;
theLives.text = liveLives.toString();
}
}
for each ( var child:Enemy in childs )
{
armyContainer.removeChild(child);
}
}
I know this is a common question, but I've looked through all of the others and couldn't figure out a solution for my problem.
I've debugged and found the offending line of code, but I'm not sure what exactly it is that's wrong with it or how to fix it.
Code below - the error is thrown when "enemy.movement();" calls the movement function in the Enemy class. The first 2 lines of code(var xDist and var yDist) or specifically flagged.
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.Event;
public class zombiestandoffMain extends MovieClip
{
static public var enemy:Enemy;
static public var player:Player;
public var gameTimer:Timer;
public var crosshair:Crosshair;
public var army:Array;
public function zombiestandoffMain()
{
//enemy = new Enemy();
//addChild( enemy );
army = new Array();
var newEnemy = new Enemy;
army.push( newEnemy );
addChild( newEnemy );
player = new Player();
addChild( player );
crosshair = new Crosshair();
addChild( crosshair );
crosshair.x = mouseX;
crosshair.y = mouseY;
gameTimer = new Timer( 25 );
gameTimer.addEventListener( TimerEvent.TIMER, onTick );
gameTimer.start();
}
public function onTick( timerEvent:TimerEvent ):void
{
var newEnemy:Enemy = new Enemy;
army.push( newEnemy );
addChild( newEnemy );
crosshair.x = mouseX;
crosshair.y = mouseY;
for each ( var enemy:Enemy in army ) {
enemy.movement();
}
//if ( player.hitTestObject( enemy ) )
//{
//}
}
}
}
And the Enemy class:
package
{
import flash.display.MovieClip;
import flash.geom.Point;
import flash.events.Event;
public class Enemy extends MovieClip
{
public var sideSpawn = int(Math.random() * 3)
public function Enemy()
{
if (sideSpawn == 0) {//top
x = Math.random() * 800;
y = 200;
} else if (sideSpawn == 1) {//left
x = -20;
y = (Math.floor(Math.random() * (1 + 800 - 200)) + 200);
} else if (sideSpawn == 2) {//right
x = 800 + 20;
y = (Math.floor(Math.random() * (1 + 800 - 200)) + 200);
} else { //bottom
x = Math.random() * 800;
y = 800 + 20;
//(Math.floor(Math.random() * (1 + high - low)) + low);
}
}
public function movement():void {
var xDist = Math.abs(zombiestandoffMain.enemy.x - zombiestandoffMain.player.x);
var yDist = Math.abs(zombiestandoffMain.enemy.y - zombiestandoffMain.player.y);
if (xDist > yDist) {
if (zombiestandoffMain.enemy.x > zombiestandoffMain.player.x)
zombiestandoffMain.enemy.x-=2;
else zombiestandoffMain.enemy.x+=2;
} else {
if (zombiestandoffMain.enemy.y > zombiestandoffMain.player.y)
zombiestandoffMain.enemy.y-=2;
else zombiestandoffMain.enemy.y+=2;
}
}
}
}
My best guess is that the x and y coords for enemy are null - but I've tried inserting values for the coords and still get the same error.
Thank you for any help!
You've only declared enemy, you must also define it. Set enemy inside zombiestandoffMain to a new Enemy obect:
enemy = new Enemy();
I guess it's with the zombiestandoffMain you are referencing in the movement() method. I do not see any definition of it in the Enemy Class. if it is meant to be defined manually in the flash environment or somewhere make sure that this property is (zombiestandoffMain) is reference properly. Hope that helps
so I'm new to AS3, and have struggled to get to this point, so sorry for any errors or nooby mistakes.
All I want now, is for my game to restart after 2 minutes has passed. Does anyone know how I can do this? I'm at a complete loss.
Here is my code:
package
{
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import Ship;
import Coin;
import CoinB;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.utils.getTimer;
public class Main extends Sprite
{
// constructor code
private var Player1:Ship;
private var Coin1:Coin;
private var Coin2:Coin;
private var Coin3:CoinB;
private var Coin4:CoinB;
private var score:int = 0;
private var container;
/*private var timer:Timer;*/
public function Main():void
{
//Sets the position of player
//adds player to stage
this.Player1 = new Ship(259,365);
addChild(this.Player1);
Cont.visible = false;
{
addChild(interval_timer);
/*addChild(frame_timer);*/
/*frame_timer.y = 50;*/
var time_count:Timer = new Timer(1000);
time_count.addEventListener(TimerEvent.TIMER, show_time);
stage.addEventListener(Event.ENTER_FRAME,on_enter_frame);
time_count.start();
}
//adds event listeners
stage.addEventListener(KeyboardEvent.KEY_DOWN, hit);
stage.addEventListener(Event.ENTER_FRAME, death);
stage.addEventListener(KeyboardEvent.KEY_DOWN, retry);
//add a Coin here
Coin1 = new Coin(stage.stageWidth / 2,stage.stageHeight / 2,75,10);
stage.addChild(Coin1);
Coin2 = new Coin(stage.stageWidth / 2,stage.stageHeight / 2,125,-5);
stage.addChild(Coin2);
Coin3 = new CoinB(stage.stageWidth / 2,stage.stageHeight / 2,25,15);
stage.addChild(Coin3);
this.addEventListener(Event.ENTER_FRAME, fire);
}
public function show_time(event:TimerEvent)
{
interval_timer.text = event.target.currentCount;
}
public function on_enter_frame(event:Event)
{
var elapsed = getTimer();
public function fire(e:Event)
{
if (Player1.hitTestObject(Coin1))
{
score += 50;
Score.text = score.toString();
}
if (Player1.hitTestObject(Coin2))
{
score += 10;
Score.text = score.toString();
}
}
public function death(e:Event)
{
if (Player1.hitTestObject(Coin3))
{
stage.removeEventListener(KeyboardEvent.KEY_DOWN, hit);
score = 0;
Score.text = score.toString();
/* gameOver.visible = true;*/
Cont.visible = true;
this.removeChild(this.Player1);
this.Player1 = new Ship(259,365);
Coin1.visible = false;
Coin2.visible = false;
Player1.visible = false;
Coin3.visible = false;
removeChild(interval_timer);
}
}
public function hit(evt:KeyboardEvent):void
{
//this will move the player right if the "Right" arrow key is pressed.
if (evt.keyCode == Keyboard.RIGHT)
{
this.Player1.right();
this.Player1.rotation = 90;
}
//this will move the player left if the "Left" arrow key is pressed.
else if (evt.keyCode == Keyboard.LEFT)
{
this.Player1.left();
this.Player1.rotation = 270;
}
if (evt.keyCode == Keyboard.DOWN)
{
this.Player1.down();
this.Player1.rotation = 180;
}
//this will move the player up if the "Up" arrow key is pressed.
else if (evt.keyCode == Keyboard.UP)
{
this.Player1.up();
this.Player1.rotation = 0;
}
}
public function retry(evt:KeyboardEvent):void
{
//restarts game.
//adds event listener so that the player can move again
if (evt.keyCode == Keyboard.R)
Cont.visible = false;
stage.addEventListener(KeyboardEvent.KEY_DOWN, hit);
Coin1.visible = true;
Coin2.visible = true;
Player1.visible = true;
Coin3.visible = true
addChild(this.Player1);
addChild(interval_timer);
}
}
}
Any help is greatly appreciated. Thanks.
Generally speaking, you would use a Timer to trigger a function when 2 minutes is up.
Something like this:
var gameTimer:Timer = new Timer(120 * 1000); // 120 seconds * 1000 milliseconds
gameTimer.addEventListener(TimerEvent.TIMER, onGameTimerTick);
gameTimer.start();
function onGameTimerTick(e:TimerEvent):void {
//stop the timer
gameTimer.removeEventListener(TimerEvent.TIMER, onGameTimerTick);
gameTimer.stop();
restartMyGame();
}
I'm a rather new to programming with AS3 and started with the rather old MJW AvoiderGame tutorial. Since this tutorial is a bit old, I have got a lot of errors while trying to learn AS3. Now I got an error that I cant figure out.
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at AvoiderGame/onTick()
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()
The problem seems to be in the onTick function in AvoiderGame class. Here is the AvoiderGame class:
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class AvoiderGame extends MovieClip
{
public var army:Array;
public var enemy:Enemy;
public var avatar:Avatar;
public var gameTimer:Timer;
public var gameClock:Clock;
public function AvoiderGame()
{
army = new Array();
var newEnemy = new Enemy( 200, -15 );
army.push( newEnemy );
addChild( newEnemy );
avatar = new Avatar();
addChild( avatar );
avatar.x = mouseX;
avatar.y = mouseY;
gameTimer = new Timer( 25 );
gameTimer.addEventListener( TimerEvent.TIMER, onTick );
gameTimer.start();
}
public function onTick( timerEvent:TimerEvent ):void
{
gameClock.addToValue( 25 );
if ( Math.random() < 0.1 )
{
var randomX:Number = Math.random() * 800;
var newEnemy:Enemy = new Enemy( randomX, -15 );
army.push( newEnemy );
addChild( newEnemy );
gameScore.addToValue( 10 );
}
avatar.x = mouseX;
avatar.y = mouseY;
for each ( var enemy:Enemy in army )
{
enemy.moveDownABit();
if ( avatar.hitTestObject( enemy ) )
{
gameTimer.stop();
dispatchEvent( new AvatarEvent( AvatarEvent.DEAD ) );
}
}
}
public function getFinalScore():Number
{
return gameScore.currentValue;
}
public function getFinalClockTime():Number
{
return gameClock.currentValue;
}
}
}
It's fairly obvious - in onTick() the first line is
gameClock.addToValue( 25 );
but you never initialize the gameClock field. That way it has the default null value hence the error you see. You should initialize it accordingly just the way you initialize the gameTimer field.
I have been trying to use BitmapData for collision detection, but have failed so far, and I don't know why. The code compiles, but doesn't do anything (when it should print "hit" ). Can anyone help me?
package
{
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.display.MovieClip;
import flash.ui.Keyboard;
import flash.display.BitmapData;
import flash.geom.Point;
public class Main extends MovieClip
{
private var spd:int = 5;
private var pressedKeys:Object = {};
private var bgMask:BitmapData;
private var plMask:BitmapData;
private var wall:Wall = new Wall();
public function Main()
{
var bgBitMapData:BitmapData = new BitmapData(bg.width,bg.height,true,0);
bgMask = bgBitMapData.clone();
wall.x = bg.x;
wall.y = bg.y;
bgMask.draw( wall );
var plBitMapData:BitmapData = new BitmapData(pl.width,bg.height,true,0);
plMask = bgBitMapData.clone();
bgMask.draw( pl );
stage.addEventListener(KeyboardEvent.KEY_DOWN,this.keyPressHandler);
stage.addEventListener(KeyboardEvent.KEY_UP,this.keyPressHandler);
stage.addEventListener(Event.ENTER_FRAME,this.gameLoop);
}
public function keyPressHandler( evt:KeyboardEvent ):void
{
if (evt.type == KeyboardEvent.KEY_DOWN)
{
pressedKeys[evt.keyCode] = 1;
}
else
{
delete pressedKeys[ evt.keyCode ];
}
}
public function inputHandler():void
{
var moveXBy:int;
var moveYBy:int;
if (pressedKeys[Keyboard.J])
{
moveXBy -= spd;
}
if (pressedKeys[Keyboard.K])
{
moveYBy += spd;
}
if (pressedKeys[Keyboard.L])
{
moveXBy += spd;
}
if (pressedKeys[Keyboard.I])
{
moveYBy -= spd;
}
pl.x += moveXBy;
pl.y += moveYBy;
}
public function playerWallCollision():void
{
if ( plMask.hitTest( new Point( wall.x, wall.y ), 1, bgMask, new Point( pl.x, pl.y ), 1))
{
trace( "hit" );
}
}
public function gameLoop( evt:Event ):void
{
wallUpdate();
inputHandler();
playerWallCollision();
}
private function wallUpdate()
{
wall.x = bg.x;
wall.y = bg.y;
}
}
}
as far as this script tells me, after the lines:
var bgBitMapData:BitmapData = new BitmapData(bg.width,bg.height,true,0);
// bgBitMapData is an empty BMP at this point cause its just freshly instanciated
bgMask = bgBitMapData.clone();
wall.x = bg.x;
wall.y = bg.y;
bgMask.draw( wall );
var plBitMapData:BitmapData = new BitmapData(pl.width,bg.height,true,0);
// no idea y you make this plBitMapData anyway
plMask = bgBitMapData.clone();
// now you clone the empty bgBitMapData to be plMask
bgMask.draw( pl );
plMask is never filled with anything! So compared with an empty BitmapData should allways return false.
So the answer to when should it output hit - never ;)
And as a sidenote try to keep it more readable by 1. write a comment every here and there what your intention is and 2. go for direct ways :
var bgBitMapData:BitmapData = new BitmapData(bg.width,bg.height,true,0);
bgMask = bgBitMapData.clone();
// this position seems just wrong to me wall.x or wall.y do not effect the draw so keep it somewhere else... since you will copy the inside of wall
wall.x = bg.x;
wall.y = bg.y;
bgMask.draw( wall );
For me it should look like:
// placing a wall to new / init coordinates
wall.x = bg.x;
wall.y = bg.y;
// drawing wall on bgMask for hittesting against player or what ever you intende here
bgMask = new BitmapData(bg.width,bg.height,true,0);
bgMask.draw( wall );