Communication between the Document Class and MovieClip Class: error 1009 - actionscript-3

I am learning how to make MovieClip classes. All I am trying to do is give the MovieClip the ability to move with the left and right arrow keys, but it's not working.
Here is my code for my Document Class Main:
package {
import flash.display.MovieClip;
public class Main extends MovieClip{
var blueBall:Ball = new Ball; //This is line 7
public function Main()
{
addChild(blueBall)
}
}
}
My code for my Ball class is:
package
{
import flash.display.MovieClip;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public class Ball extends MovieClip
{
public function Ball()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed); //This is Line 11
}
function keyPressed(evt:KeyboardEvent):void
{
switch (evt.keyCode)
{
case Keyboard.RIGHT :
this.x += 10;
break;
case Keyboard.LEFT :
this.x -= 10;
break;
}
}
}
}
When I run this in the debug, I get this error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Ball()[C:\Users\Joel\Desktop\Flash\Projects\DropClassTest\Ball.as:11]
at Main()[C:\Users\Joel\Desktop\Flash\Projects\DropClassTest\Main.as:7]
Now, if I just leave my Main document class blank, and just drag and drop the blueBall Movieclip out of the Library, it works the way I want it to, but once I try to use the document class to do it, it's not working.
Needless to say, I am quite lost, even thought the debugger is telling me what lines are wrong.
Any ideas?

The problem is that you are trying to access the stage from inside the Ball class before the ball is added to the stage. Before an object is added to the stage, it does not have direct access to the stage.
Option 1: You could pass the stage from the main class to the Ball constructor.
Add this to your Ball class' imports:
import flash.display.Stage;
Add a stage parameter to the Ball class' constructor:
public function Ball(stage:Stage):void {
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
}
And pass the stage to your Ball instance (in Main)
var blueBall:Ball = new Ball(stage);
Option 2: You can listen for the ADDED_TO_STAGE event inside of the Ball class and add the KEY_DOWN listener once ADDED_TO_STAGE occurs:
Inside the Ball class import the Event class:
import flash.events.Event;
Replace your constructor with this:
public function Ball():void {
addEventListener(Event.ADDED_TO_STAGE, addedToStage);
}
Then add your KEY_DOWN listener inside the ADDED_TO_STAGE listener:
function addedToStage(evt:Event):void {
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
}

Related

Adobe Animate ActionScript 3 Error 1009 for a MovieClip

I am writing code to have enemies detect collision with the player. In my Enemy class I have the following:
import flash.display.MovieClip;
import flash.events.Event;
public class Enemy extends MovieClip {
var Player: MovieClip;
public function Enemy() {
this.addEventListener(Event.ENTER_FRAME, EnemyUpdate);
}
function setPlayer(_Player: MovieClip) {
Player = _Player;
}
function EnemyUpdate(_event: Event) {
var enemyHit: Boolean = this.hitTestObject(Player.Character.Legs);
if (enemyHit) {
trace("OUCH!!");
}
}
}
In my Main Class, I attempt to send the Player MovieClip to the Enemy Class script using the following:
public function Main() {
enemy.setPlayer(player);
}
The MovieClip enemy has the Enemy script attached to it. When I run the program, the Player variable is null. How do I get the Player to recognize the Player MovieClip?
This happens because you set your player after an Enemy had been instantiated. In Enemy constructor you have EnterFrame listener. To fix the error change your code as follows:
public function Enemy() {
// empty constructor, you can remove it if there is no other logic in it
}
function setPlayer(_Player: MovieClip) {
Player = _Player;
// the Player variable is not null anymore.
this.addEventListener(Event.ENTER_FRAME, EnemyUpdate);
}

Creating a rectangle with stage sizes

This is my first class and i try to make rectangle with stage sizes, but flash gives me these errors:
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
// 1180: Call to a possibly undefined method addEventListener.
removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
// 1180: Call to a possibly undefined method removeEventListener.
stageW = stage.stageWidth;
// 1120: Access of undefined property stage.
stageH = stage.stageHeight;
// 1120: Access of undefined property stage.
addChild(mc_background);
// 1180: Call to a possibly undefined method addChild.
My code is:
package {
import flash.display.MovieClip;
import flash.events.Event;
public class main {
var mc_background:MovieClip = new MovieClip();
var stageW:Number;
var stageH:Number;
public function init() {
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
private function addedToStageHandler(evn:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
stageW = stage.stageWidth;
stageH = stage.stageHeight;
drawBackground();
}
private function drawBackground():void {
mc_background.beginFill(0xFF00CC);
mc_background.graphics.drawRect(0,0,stageW,stageH);
mc_background.graphics.endFill();
addChild(mc_background);
}
}
}
Your class "main" should extend a Sprite to use the addChild() and removeEventListener() methods.
So you should import the Sprite class and extends your class from Sprite, like so:
package {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
public class main extends Sprite
And it's also considered a nice practice to call class names with first capital letter, e.g main > Main. All lower-case are usually variables, so it will confuse you later.

how to add a movieclip to second frame of main timeline through document class?

i simply have one layer which has two frames
frame 1 : menu with only one button
frame 2 : blank but with document class want to put Movie Clip named circle
I want to put it that way because i will program the symbol to draw ....(till now wrote nothing)
In document class till now i have written
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 ourShip:circle = new circle()
//our constructor function. This runs when an object of
//the class is created
public function engine()
{
ourShip.x = stage.stageWidth / 2;
ourShip.y = stage.stageHeight / 2;
addChild(ourShip)
}
}
}
First frame button as file :
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
{
}
}
}
By the way i only know addchild (which i wrote in as here,right now it would display circle in both frame 1 and frame 2 but i want it in only frame 2)
Because of how the Flash timeline works, you can only add something to a frame when you are there. So you can do,
goToAndStop(3);
addChild(myClip);
But then if you leave frame 3 it is gone forever.
You can
Add the code to the individual frame of the timeline, or
You can create a simple Event listener like below
Adding Event Listener:
addEventListener(Event.ENTER_FRAME, function() {
if (this.currentFrame == 3) {
addChild(myClip)
}
})

calling movieclip of a class from another class, error#1009

i got error: method of null object reference. I'm so confused and don't know what is the real cause.
So i got a player movieClip on the stage which has an instance of "player_mc", which will be pass thru my Document class and into the Player class.
Player.as
import flash.display.*;
import flash.events.*;
public class Player extends MovieClip
{
public var myPlayer:MovieClip;
public function Player(player:MovieClip)
{
myPlayer = player;
addEventListener(Event.ENTER_FRAME,on_enter);
}
Document.as
import flash.display.*;
import Components.Player.Player;
public class Game_Main extends MovieClip
{
public var player:Player;
public function Game_Main()
{
player = new Player(player_mc);
}
}
now here i think is where the problem comes from. I have a green_enemy movieclip on the stage which has base class Enemy.
Enemy.as
import flash.display.MovieClip;
import Components.Player.Player;
import flash.events.Event;
public class Enemy extends MovieClip
{
var theplayer:Player;
public function Enemy()
{
this.addEventListener(Event.ENTER_FRAME,on_enter);
}
public function on_enter(e:Event):void
{
if (this.hitTestObject(theplayer.myPlayer)) //calls player_mc from Player class
{
trace("hi");
}
}
}
what I like to do on Enemy function is when Enemy collides with "player_mc" (which is on the stage) it will do something. Maybe my code is wrong.
Any help/tips will be appreciated. Thanks!
In your Enemy.as I see
var theplayer:Player;
not initialized. It is private, so you can not define it from outside. That means that exception comes from here
this.hitTestObject(theplayer.myPlayer)
You are trying to call myPlayer from null.
Try to define this variable while constructing Enemy class.
To prevent null exception you can check if theplayer is null
public function on_enter(e:Event):void
{
if (theplayer && this.hitTestObject(theplayer.myPlayer))
{
trace("hi");
}
}
To expand on what ZuyEL said, your variable isn't globally defined in your enemy class since you're just adding a var inside your enemy function. Instead, do the following
public var thePlayer:Player;
write the above after your Enemy class, before the Enemy function. Now it is available to the whole class and will no longer be null when you call it later.

addChild(object) isn't working, variables are correct, x/y are set

Following code isn't addchilding a lv1 to the stage for some reason, this is the stage class and is attached to the stage, both classes are correct (triple checked...) and no errors are generated...
package
{
import flash.events.*;
import flash.display.*;
public class TankDrive extends MovieClip
{
public var lev1:lv1;
public function TankDrive()
{
lev1 = new lv1();
lev1.x = 0;
lev1.y = 0;
addChild(lev1);
}
}
}
Also I checked against other code that worked and found no differences other the specific variable names which I quadruple-checked...
In your imports try adding the lv1.as file and see if it helps kill that null error.
import flash.events.*;
import flash.display.*;
import lv1; //imports the lv1.as file
public class TankDrive extends MovieClip
{
public var lev1:lv1;
public function TankDrive()
{
lev1 = new lv1();
lev1.x = 0;
lev1.y = 0;
addChild(lev1);
}
}
EDIT TWO ------------ After re-reading comments -----------
null line in other class is
stage.addEventListener(KeyboardEvent.KEY_DOWN, keypush);... I do have
public function keypush(event:KeyboardEvent):void { } in it...
Get rid of stage. and only just have addEventListener(KeyboardEvent.KEY_DOWN, keypush);
The line addChild(lev1); in TankDrive already gives contents of lv1 some access to stage so in lv1 just writing addChild is enough.
NOTE: This is true for most eventListeners (mouse/timers etc) and also display objects.
When you need to explicitly access the stage (especially for stage+keyboard listeners) you must setup your lv1.as like so:
Add a listener to check for when the stage is available to lv1 contents.
If available then get entire stage to listen for keyboard controls.
public function lv1() {
addEventListener(Event.ADDED_TO_STAGE, stageAvailable);
//Your other code here...
}
private function stageAvailable(e:Event):void {
trace("(LV1.AS): ADDED_TO_STAGE was successful");
removeEventListener(Event.ADDED_TO_STAGE, stageAvailable);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keypush);
//Your other keyboard listeners code...
}
You must inherit lev1 class from DisplayObject or any class inherited from DisplayObject (eg. Sprite, MovieClip etc). addChild method accepts only DisplayObject instances.