addChild not displaying anything on stage - actionscript-3

So I'm trying to make a spaceship fire lasers when the spacebar is pressed. I've done this before in a pure flex project but have recently gotten creative cloud and am trying to recreate the same effect using flash professional/flash builder.
Unfortunately when I create a new instance of my "Laser" class and try and put it on the stage with addChild() nothing seems to happen.
Here is the main file/document class
public class PlayerShip extends Sprite
{
private var laserTimer:Timer;
private var shipTime:Timer;
private var upKey:Boolean;
private var downKey:Boolean;
private var leftKey:Boolean;
private var rightKey:Boolean;
private var spacebar:Boolean;
private var utils:Utils = new Utils();
//tuning variables
private var MOVE_SPEED:int = 5;
private var REVERSE_SPEED:int = 3;
private var TURN_SPEED:int = 5;
private var laserEmitter:shipLasers = new shipLasers(stage);
public function PlayerShip():void
{
super();
addEventListener(Event.ENTER_FRAME, fly);
stage.addEventListener(KeyboardEvent.KEY_DOWN, movementKeysDown);
stage.addEventListener(KeyboardEvent.KEY_UP, movementKeysUp);
laserTimer = new Timer(1000/1000);
laserTimer.addEventListener(TimerEvent.TIMER, fireLasers);
laserTimer.start();
addChild(laserEmitter);
}
public function fly(e:Event):void {
if(downKey) {
SpaceShip.x -= Math.sin(utils.degreesToRadians(SpaceShip.rotation)) * REVERSE_SPEED;
SpaceShip.y += Math.cos(utils.degreesToRadians(SpaceShip.rotation)) * REVERSE_SPEED;
}
if(upKey) {
SpaceShip.x += Math.sin(utils.degreesToRadians(SpaceShip.rotation)) * MOVE_SPEED;
SpaceShip.y -= Math.cos(utils.degreesToRadians(SpaceShip.rotation)) * MOVE_SPEED;
}
if(leftKey) {
SpaceShip.rotation -= TURN_SPEED;
}
if(rightKey) {
SpaceShip.rotation += TURN_SPEED;
}
}
public function movementKeysUp(e:KeyboardEvent):void { //rotators is key_up :P
switch(e.keyCode) {
case 83:
downKey = false;
break;
case 65:
leftKey = false; // on "a" key_up sets left turn to false. Simple enough.
break;
case 68:
rightKey = false; // K. "d" released makes me not turn right.
break;
case 87:
upKey = false; // I guess case 87 is "w"
break;
case 32:
spacebar = false;
break;
}
}
public function movementKeysDown(e:KeyboardEvent):void { // key_down for movers
switch(e.keyCode) {
case 83:
downKey = true;
break;
case 65:
leftKey = true; //so now on key_down for the "a" key it makes me go left! :D
break;
case 68:
rightKey = true; //same as lft...
break;
case 87:
upKey = true;
break;
case 32:
spacebar = true;
break;
}
}
public function fireLasers(e:TimerEvent) {
if(spacebar) {
laserEmitter.Emit(SpaceShip.x, SpaceShip.y, SpaceShip.rotation);
addChild(laserEmitter);
}
}
public function getShip():MovieClip {
return SpaceShip;
}
}
}
and this is the separate class that is supposed to create new instances of the Laser class and put them on the stage.
public class shipLasers extends Sprite implements Emittable
{
var tempLaserRight:MovieClip;
var tempLaserLeft:MovieClip;
var laserArray:Array = [];
public function shipLasers(stage:Stage):void
{
}
public function Emit(x:int, y:int, rotation:Number):void {
tempLaserRight = new Laser();
tempLaserLeft = new Laser();
tempLaserRight.rotation = tempLaserLeft.rotation = rotation;
tempLaserRight.x = 200;
tempLaserLeft.x = 210;
tempLaserRight.y = 200;
tempLaserLeft.y = 200;
laserArray.push(tempLaserRight);
laserArray.push(tempLaserLeft);
stage.addChild(tempLaserRight);
stage.addChild(tempLaserLeft);
trace("Oh come on!");
}
}
}
Thanks!

You never store passed stage reference in shipLasers class, thus you are trying to refer its own built-in stage ref, which is likely null because your instances of shipLasers don't get added to display list themselves. You need to store the stage ref passed in the constructor and use that to add children.
public class shipLasers ... {
var theStage:Stage;
public function shipLasers(aStage:Stage){
theStage = aStage;
}
public function Emit(...) {
...
theStage.addChild(tempLaserRight);
thestage.addChild(tempLaserLeft);
}
}
Update: It's also a good practice to first check stage availability, then use stage reference. To do this, you need to listen to Event.ADDED_TO_STAGE event in your ship class, as it uses stage left right and center. The common code of achieving this is as follows:
public function PlayerShip() {
....
// leave here only code that does not require stage
if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(e:Event=null):void {
removeEventListener(Event.ADDED_TO_STAGE,init);
// here place all code that's left from your initialization process
laserEmitter=new shipLasers(stage);
stage.addEventListener(KeyboardEvent.KEY_DOWN, movementKeysDown);
stage.addEventListener(KeyboardEvent.KEY_UP, movementKeysUp);
// etc.
}

Related

Why is in my code a delay when it tries to display an object (AS3)?

I recently wrote down a flash programm using as3. In the Main class for the project I have an addChild method that is giving me some problems. The thing is that, when I run the movie and the child is supposedly displayed on the stage, there is a big delay in time before the image is rendered.
Here is the code in the Main class: (exact code lines below)
package code {
import flash.display.MovieClip;
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Sprite;
import flash.display.Graphics;
import code.particles.*;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.text.TextField;
// import this to access to the particles
public class Main extends MovieClip {
// set player vars
public var player1:Player;
public var player2:Player;
public var ball:Ball;
// set pause vars
public var pauseParticle:Particle2; // var used for the pause visual effects
public var pauseEffectMC:MovieClip = new MovieClip(); // var used for the pause visual effects
public var gameIsPaused:Boolean;
// set buff vars
public var buffTimer:Timer = new Timer(10000, 0);
public function Main() {
// constructor code
if (stage) init(); // init function
else addEventListener(Event.ADDED_TO_STAGE, init);
}
// init function:
public function init():void
{
// set movieClip class vars
player1 = new Player(stage, 75, 200); // important values: (stage, and two numbers for position)
player2 = new Player(stage, 650, 200); //same for player two
ball = new Ball(stage); // same for the ball
pauseParticle = new Particle2(stage, stage.stageWidth/2, stage.stageHeight/2);
// define movie clips (calling a function)
definePauseEffectMC();
// start timer
buffTimer.start();
// important: add childs (create the visuals)
stage.addChild(player1);
stage.addChild(player2);
stage.addChild(ball);
// add event listeners
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyIsPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyIsReleased);
stage.addEventListener(Event.ENTER_FRAME, entFrame);
buffTimer.addEventListener(TimerEvent.TIMER, buffClock);
}
// constant function
public function entFrame(e:Event):void
{
ball.ballRotation(player1, player2); // call the function for movement in the ball class
ball.ballReset();
}
// key handlers function
public function keyIsPressed(e:KeyboardEvent):void
{
switch(e.keyCode) //key cases:
{
/* player 1:
*/
case 65: // a key
player1.left = true; // change values for vars inside player1
break;
case 68: // d key
player1.right = true;
break;
case 87: // w key
player1.up = true;
break;
case 83: // s key
player1.down = true;
break;
/* player 2:
*/
case 37: // left arrow
player2.left = true; // change values for vars inside player2
break;
case 39: // right arrow
player2.right = true;
break;
case 38: // up arrow
player2.up = true;
break;
case 40: // down arrow
player2.down = true;
break;
/* pause button
*/
case 32: // spacebar button
pauseGame();
break;
}
}
public function keyIsReleased(e:KeyboardEvent):void
{
switch(e.keyCode) //key cases:
{
/* player 1:
*/
case 65: // a key
player1.left = false; // change values for vars inside player1
break;
case 68: // d key
player1.right = false;
break;
case 87: // w key
player1.up = false;
break;
case 83: // s key
player1.down = false;
break;
/* player 2:
*/
case 37: // left arrow
player2.left = false; // change values for vars inside player2
break;
case 39: // right arrow
player2.right = false;
break;
case 38: // up arrow
player2.up = false;
break;
case 40: // down arrow
player2.down = false;
break;
}
}
// function to pause the game
public function pauseGame():void
{
if(gameIsPaused == false)
{
gameIsPaused = true; // revert boolean
buffTimer.stop();
ball.timer.stop();
stage.addChild(pauseEffectMC); // add the effect
stage.addChild(pauseParticle); // add the pause symbol
trace("Paused");
stage.frameRate = 0;
}
else
{
gameIsPaused = false; // revert boolean
buffTimer.start();
ball.timer.start();
stage.removeChild(pauseEffectMC); // remove the effect
stage.removeChild(pauseParticle); // remove the pause symbol
trace("Continue");
stage.frameRate = 60;
}
}
// function to define the pause effect mc
public function definePauseEffectMC():void
{
pauseEffectMC.graphics.beginFill(0x000000); // fill with color (black)
pauseEffectMC.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
pauseEffectMC.alpha = 0.6 // change the alpha
pauseEffectMC.graphics.endFill();
}
/* Buffs
*/
//
public function buffClock(e:TimerEvent):void
{
var buffOn:Boolean = randBoolean(0.3);
if(buffOn == true)
{
var buff:Buff = new Buff(stage, ball, player1, player2);
stage.addChild(buff);
}
}
// random boolean with probability (to get "true" in return) ("prob" must be between 0 and 1)
public function randBoolean(prob:Number):Boolean
{
var randNum:Number = Math.random(); // get a random number between 0 and 0.99
if(randNum <= prob)
{
return(true);
}
else
{
return(false);
}
}
}
}
And here is the exact code that is giving me problems:
// function to pause the game
public function pauseGame():void
{
if(gameIsPaused == false)
{
gameIsPaused = true; // revert boolean
buffTimer.stop();
ball.timer.stop();
stage.addChild(pauseEffectMC); // add the effect
stage.addChild(pauseParticle); // add the pause symbol
trace("Paused");
stage.frameRate = 0;
}
else
{
gameIsPaused = false; // revert boolean
buffTimer.start();
ball.timer.start();
stage.removeChild(pauseEffectMC); // remove the effect
stage.removeChild(pauseParticle); // remove the pause symbol
trace("Continue");
stage.frameRate = 60;
}
}
// function to define the pause effect mc
public function definePauseEffectMC():void
{
pauseEffectMC.graphics.beginFill(0x000000); // fill with color (black)
pauseEffectMC.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
pauseEffectMC.alpha = 0.6 // change the alpha
pauseEffectMC.graphics.endFill();
}
I tried different things, but I did not find a solution. I have run the programm in another computer, but it is still having a delay.
I just wanted to know if there is something wrong with my code that I have to modify, or if it is a flash error.
Thank you for reading.
~m5

Error #1009- Only when there is code present in main class

Please do forgive me if this is a stupid question, by I really need to know the solution. So here I have a program that generates particles every set distance of space. My program consists of a document class, called supportForce and an object class(of the particle) called TheDot.
In the TheDot object class, I have the following code-
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class TheDot extends MovieClip
{
var base:Object = MovieClip(root);
public function TheDot()
{
this.addEventListener(Event.ENTER_FRAME, eFrame);
}
private function eFrame(event:Event):void
{
if (base.currentFrame == 1){
trace ("G");
}
}
}
}
This code works perfectly (outputs G) until I add the following code into the document class, suportForce, under an ENTER_FRAME event-
var ctX:int = 0,ctY:int = 0,done:Boolean = false;
while (done == false)
{
var dots:TheDot = new TheDot ;
dots.alpha = 0;
dots.x += (25 * ctX);
dots.y += (25 * ctY);
ctX++;
if (ctX == 22 && ctY == 20)
{
done = true;
break;
}
else if (ctX == 22)
{
ctX = 0;
ctY++;
}
stage.addChild(dots);
}
So now, there is an Error #1009: Cannot access a property or method of a null object reference at TheDot/eFrame(). I have declared all the variables in the correct place, and also the functions. Thanks in advance. I have the link to the .fla and .as files in my drive here, do use it if necessary.
https://drive.google.com/folderview?id=0B8QnUfRAn9lKLUVqRjNSRHNpRkU&usp=sharing
FIRST
var dots:TheDot = new TheDot(stage);
public class TheDot extends MovieClip
{
var base:Object;
public function TheDot(stageRef:Stage)
{
base = stageRef;
this.addEventListener(Event.ADDED_TO_STAGE, init);
}
public function init(e:Event) {
this.removeEventListener(Event.ADDED_TO_STAGE, init);
this.addEventListener(Event.ENTER_FRAME, eFrame);
}
private function eFrame(event:Event):void
{
if (base.currentFrame == 1){
trace ("G");
}
}
Try this!

My Character Won't Move :( Multiple .as files AS3

I have a few .as files. They are: MainClass.as, FrontEnd.as, Levels.as, and Hero.as. My problem (as far as I know) is in my Hero.as file. Let me descibe how I have it all set up thusfar because I have been a bit concerned that there are better ways of doing things in AS3.
MainClass.as makes a variable of FrontEnd (menus, namely the main menu) and calls it up (addChild).
FrontEnd.as are my menus. buttons and whatnot...
Levels.as right now just calls up level 1 when the start new game button is pressed on the main menu. Had one hell of a time figuring out how to use functions from a different .as file. Hero.as I will add my code for. I'm posting the whole thing because I don't know where my problem is.
public class Hero extends MovieClip
{
public var roger:player = new player();
private var animationState:String = "down";
public var facing:String = "down";
private var isLeft:Boolean = false;
private var isRight:Boolean = false;
private var isUp:Boolean = false;
private var isDown:Boolean = false;
public var currentPlayer:MovieClip = roger;
public function Hero()
{
addEventListener(Event.ENTER_FRAME, loop);
addEventListener(Event.ADDED_TO_STAGE, onStage);
trace(currentPlayer);
}
public function onStage( event:Event ):void
{
removeEventListener( Event.ADDED_TO_STAGE, onStage );
}
public function addCurrentPlayer():void
{
roger.x = stage.stageWidth * .5;
roger.y = stage.stageHeight * .5;
addChild(roger);
currentPlayer = roger;
setBoundaries();
}
public function keyDownHandler(event:KeyboardEvent)
{
if (event.keyCode == 39)//right press
{
isRight = true;
}
if (event.keyCode == 37)//left pressed
{
isLeft = true;
}
if (event.keyCode == 38)//up pressed
{
isUp = true;
}
if (event.keyCode == 40)//down pressed
{
isDown = true;
}
}
public function keyUpHandler(event:KeyboardEvent)
{
if (event.keyCode == 39)//right released
{
isRight = false;
}
if (event.keyCode == 37)//left released
{
isLeft = false;
}
if (event.keyCode == 38)//up released
{
isUp = false;
}
if (event.keyCode == 40)//down released
{
isDown = false;
}
}
public function loop(Event):void
{
if (currentPlayer == null)
{
addCurrentPlayer();//make sure at least roger is on the screen
}
currentPlayer.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
currentPlayer.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
//----------------------------------0
//Animation States
//----------------------------------0
if (isDown == true)
{
currentPlayer.y += 5;
animationState = "walk_down";
facing = "down";
currentPlayer.gotoAndStop(animationState);
}
else if (isUp == true)
{
currentPlayer.y -= 5;
animationState = "walk_up";
facing = "up";
currentPlayer.gotoAndStop(animationState);
}
else if (isRight == true)
{
currentPlayer.x += 5;
animationState = "walk_right";
facing = "right";
currentPlayer.gotoAndStop(animationState);
}
else if (isLeft == true)
{
currentPlayer.x -= 5;
animationState = "walk_left";
facing = "left";
currentPlayer.gotoAndStop(animationState);
}
//----------------------------------0;
//IDLE STATES
//----------------------------------0
else if (isDown == false)
{
currentPlayer.gotoAndStop(facing);
}
else if (isUp == false)
{
currentPlayer.gotoAndStop(facing);
}
else if (isRight == false)
{
currentPlayer.gotoAndStop(facing);
}
else if (isLeft == false)
{
currentPlayer.gotoAndStop(facing);
}
}
public function setBoundaries():void
{
var halfHeight:int = currentPlayer.height * .5;
var halfWidth:int = currentPlayer.width * .5;
if(currentPlayer.y <= 1)
{
currentPlayer.y += halfHeight;
}
else if(currentPlayer.y > stage.stageHeight)
{
currentPlayer.y -= halfHeight;
}
else if(currentPlayer.x <= 1)
{
currentPlayer.x += halfWidth;
}
else if(currentPlayer.x > stage.stageWidth)
{
currentPlayer.x -= halfWidth;
}
}
}
}
trace(currentPlayer); is giving me [object player] instead of the instance name "roger". (Later on I want more playable characters.) I'm not sure if the problem is there or in my levels file, which I'll post here. (not as long as Hero.as)
public class Levels extends MovieClip
{
var currentLevel:MovieClip;
public function Levels()
{
addEventListener(Event.ADDED_TO_STAGE, onStage);
}
private function onStage(event:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, gotoLevelOne);
}
public function gotoLevelOne():void
{
var levelOne:LevelOne = new LevelOne();
var hero:Hero = new Hero();
addChild(hero);
levelOne.x = stage.stageWidth * .5;
levelOne.y = stage.stageHeight * .5;
addChild(levelOne);
currentLevel = levelOne;
hero.currentPlayer.x = 100;
hero.currentPlayer.y = 100;
addChild(hero.currentPlayer);
}
}
}
If I remove = roger; from var currentPlayer:MovieClip = roger; it gives me #1009 null object even though I told it in addCurrentPlayer() to change currentPlayer to roger. On level 1, everything shows up but I can't move my character. I know that it worked when I was working on his animations and I would call him to the main menu. Everything worked on him. What's the problem now?
Firstly, there's a lot of things wrong with your code:
In your Hero Class, the 'onStage' Event handler doesn't actually do anything other than remove the event listener that triggers it. While it's good practice to remove the event listener, there should be some other purpose to the Event handler. If there isn't you can remove it and not bother listening for the ADDED_TO_STAGE Event.
Similarly, in your Levels Class 'onStage' Event handler you attempt to remove the event, but name the wrong handler. I assume you want to remove the event handler and then run the 'gotoLevelOne' method. If so, just have the Event.ADDED_TO_STAGE listener call 'gotoLevelOne' and then remove the Event listener there:
public function Levels()
{
addEventListener(Event.ADDED_TO_STAGE, gotoLevelOne);
}
public function gotoLevelOne():void
{
removeEventListener(Event.ADDED_TO_STAGE, gotoLevelOne);
// class continues....
OK, so to your question:
You will be getting the null error because you are referring to currentPlayer from outside the Hero Class, before calling addCurrentPlayer (where it is set).
If you temporarily define currentPlayer as a private variable, the compiler should give you a line number where you first refer to currentPlayer from OUTSIDE the Hero Class (the error will be something like 'Class X is trying to access a private (or non-existent) property of Y Class').
You can then sort out WHY you are accessing currentPlayer before calling addCurrentPlayer. You may also want to think about if currentPlayer NEEDS to be public (if so, then what is 'addCurrentPlayer' for? That function effectively works as a setter for currentPlayer).
EDIT:
At the moment you are adding new KEY_DOWN and KEY_UP event listeners EVERY frame of your game loop. This is unnecessary. Add them both ONCE in the initialisation of your game (perhaps in your Hero's onStage handler), and count on them to trigger the appropriate handlers.
You will want to add the KEY_DOWN and KEY_UP listeners to 'stage', not currentPlayer, so:
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
You will need to add the listeners AFTER your Hero instance has been added to the Stage though, so it has access to 'stage'. That's why it makes sense to add the listeners in the Hero's onstage handler.

Actionscript 3 Making the character to Jump

I am making a platformer game. But I am having issue because whenever I pressed the spacebar to jump, the character will stuck in the mid-air. However, I can resolved the problem by holding spacebar and the character will land.
The issue is at mainJump() located inside Boy class.
I seen many people solved the problem by using action timeline, but my main problem is, are there anyway I can solve the problem by using an external class?
Main class
package
{
import flash.display.*;
import flash.text.*;
import flash.events.*;
import flash.utils.Timer;
import flash.text.*;
public class experimentingMain extends MovieClip
{
var count:Number = 0;
var myTimer:Timer = new Timer(10,count);
var classBoy:Boy;
//var activateGravity:gravity = new gravity();
var leftKey, rightKey, spaceKey, stopAnimation:Boolean;
public function experimentingMain()
{
myTimer.addEventListener(TimerEvent.TIMER, scoreUp);
myTimer.start();
classBoy = new Boy();
addChild(classBoy);
stage.addEventListener(KeyboardEvent.KEY_DOWN, pressTheDamnKey);
stage.addEventListener(KeyboardEvent.KEY_UP, liftTheDamnKey);
}
public function pressTheDamnKey(event:KeyboardEvent):void
{
if (event.keyCode == 37)
{
leftKey = true;
stopAnimation = false;
}
if (event.keyCode == 39)
{
rightKey = true;
stopAnimation = false;
}
if (event.keyCode == 32)
{
spaceKey = true;
stopAnimation = true;
}
}
public function liftTheDamnKey(event:KeyboardEvent):void
{
if (event.keyCode == 37)
{
leftKey = false;
stopAnimation = true;
}
if (event.keyCode == 39)
{
rightKey = false;
stopAnimation = true;
}
if (event.keyCode == 32)
{
spaceKey = false;
stopAnimation = true;
}
}
public function scoreUp(event:TimerEvent):void
{
scoreSystem.text = String("Score : "+myTimer.currentCount);
}
}
}
Boy class
package
{
import flash.display.*;
import flash.events.*;
public class Boy extends MovieClip
{
var leftKeyDown:Boolean = false;
var upKeyDown:Boolean = false;
var rightKeyDown:Boolean = false;
var downKeyDown:Boolean = false;
//the main character's speed
var mainSpeed:Number = 5;
//whether or not the main guy is jumping
var mainJumping:Boolean = false;
//how quickly should the jump start off
var jumpSpeedLimit:int = 40;
//the current speed of the jump;
var jumpSpeed:Number = 0;
var theCharacter:MovieClip;
var currentX,currentY:int;
public function Boy()
{
this.x = 600;
this.y = 540;
addEventListener(Event.ENTER_FRAME, boyMove);
}
public function boyMove(event:Event):void
{
currentX = this.x;
currentY = this.y;
if (MovieClip(parent).leftKey)
{
currentX += mainSpeed;
MovieClip(this).scaleX = 1;
}
if (MovieClip(parent).rightKey)
{
currentX -= mainSpeed;
MovieClip(this).scaleX = -1;
}
if (MovieClip(parent).spaceKey)
{
mainJump();
}
this.x = currentX;
this.y = currentY;
}
public function mainJump():void
{
currentY = this.y;
if (! mainJumping)
{
mainJumping = true;
jumpSpeed = jumpSpeedLimit * -1;
currentY += jumpSpeed;
}
else
{
if (jumpSpeed < 0)
{
jumpSpeed *= 1 - jumpSpeedLimit / 250;
if (jumpSpeed > -jumpSpeedLimit/12)
{
jumpSpeed *= -2;
}
}
}
if (jumpSpeed > 0 && jumpSpeed <= jumpSpeedLimit)
{
jumpSpeed *= 1 + jumpSpeedLimit / 120;
}
currentY += jumpSpeed;
if (currentY >= stage.stageHeight - MovieClip(this).height)
{
mainJumping = false;
currentY = stage.stageHeight - MovieClip(this).height;
}
}
}
}
First of all, formalize your code, eliminating sassy things like 'pressTheDamnKey,' which doesn't even describe the function very well because a function cannot press a key. That is an event handler and should be named either keyDownHandler or onKeyDown, nothing else.
Secondly, you rarely want to do any actual work in event handlers beyond the immediate concerns of the event data. Instead call out to the function which does the actual work. A handler handles the event, then calls the code which does the work. This separates out concerns nicely for when you want something else to be able to also make the little boy animate besides the enterFrameHandler, like perhaps a mouse.
I can imagine your trace log is getting filled up pretty quickly with "Score" lines since your timer is firing 100 times a second (10 milliseconds per). I would change that to not fire on a timer, but to be refreshed when the score actually changes.
The problem with the jumping, aside from spaghetti code, is that you are basing his movements upon whether the key is pressed or not by saving the state of the key press in a variable and having him continually inspect it. This is bad for a couple of reasons: 1. he should not need to reach out to his environment for information, it should be given to him by whatever object owns him or by objects that are responsible for telling him and 2. It requires you to continually hold down the spacebar or he will stop moving, since he checks to see if it is being held down (see problem 1).
I will address all these issues below, leaving out the scoring, which is another matter altogether.
package
{
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.*;
// Sprite is preferred if you are not using the timeline
public class Application extends Sprite
{
private var boy:Boy;
public function Application()
{
boy = new Boy();
addChild(boy);
boy.x = 600; // set these here, not in the boy
boy.y = 540;
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler );
}
public function keyDownHandler(event:KeyboardEvent):void
{
switch(event.keyCode)
{
case 32: boy.jump();
break;
case 37: boy.moveLeft();
break;
case 39: boy.moveRight();
break;
default:
// ignored
break;
}
}
public function keyUpHandler(event:KeyboardEvent):void
{
switch(event.keyCode)
{
// ignored for jumping (32)
case 37: // fall through
case 39: boy.stop();
break;
default:
// ignored
break;
}
}
}//class
}//package
package
{
import flash.display.*;
import flash.events.*;
// It is assumed that there is an asset in the library
// that is typed to a Boy, thus it will be loaded onto
// the stage by the owner
public class Boy extends Sprite
{
private var horzSpeed :Number = 0;
private var vertSpeed :Number = 0;
private var floorHeight :Number;
private var jumpHeight :Number;
private var amJumping :Boolean = false;
public function Boy()
{
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
public function moveLeft():void
{
horzSpeed = -1;
}
public function moveRight():void
{
horzSpeed = 1;
}
public function stop():void
{
horzSpeed = 0;
}
public function jump():void
{
if (amJumping) return;
floorHeight = y;
jumpHeight = floorHeight + 20;
vertSpeed = 2;
amJumping = true;
animateJump();
}
private function enterFrameHandler(event:Event):void
{
animate();
}
private function animate():void
{
x += horzSpeed;
if( amJumping )
{
animateJump();
}
}
// Doing a simple version for this example.
// If you want an easier task of jumping with gravity,
// I recommend you employ Greensock's superb
// TweenLite tweening library.
private function animateJump():void
{
y += vertSpeed;
if( y >= jumpHeight )
{
y = jumpHeight;
vertSpeed = -2;
}
else if( y <= floorHeight )
{
y = floorHeight;
amJumping = false;
}
}
}//class
}//package
Another way to approach this, and probably the better way long-term, is for the boy to not even be responsible for moving himself. Instead, you would handle that in the parent, his owner or some special Animator class that is responsible for animating things on schedule. In this even more encapsulated paradigm, the boy is only responsible for updating his own internal look based upon the outside world telling him what is happening to him. He would no longer handle jumping internally, but instead would be responsible for doing things like animating things he owns, like his arms and legs.
You've got a mainJumping variable that is only true while the jump is running. Why not just use that?
if (MovieClip(parent).spaceKey || mainJumping)
{
mainJump();
}

Error: #1009: Type Error (Line #114)

I'm sort of a noob to flash, but I am programming a game right now, and I am trying to make my character move but i am getting error #1009 Here is my code in my "GameState".
Basically it errors out on any Keypress, I have my character named player (Player in the library) and it has another movie clip within it named WalkDown (I gave it an instance name of walkDown on the timeline) I am not really sure whats going on. Specifically it errors out on the line where its calling the frame name. Any help would be appreciated!
package {
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.geom.Point;
public class GameState extends MovieClip {
private var player:MovieClip;
private var walking:Boolean = false;
// is the character shooting
//private var shooting:Boolean = false;
// wlaking speed
private var walkingSpeed:Number = 5;
private var xVal:Number = 0;
private var yVal:Number = 0;
public function GameState() {
// constructor code
player = new Player();
addChild(player);
player.x = 300;
player.y = 300;
player.gotoAndStop("stance");
this.addEventListener(Event.ADDED_TO_STAGE, initialise);
}
private function initialise(e:Event){
// add a mouse down listener to the stage
//addEventListener(MouseEvent.MOUSE_DOWN, startFire);
// add a mouse up listener to the stage
//addEventListener(MouseEvent.MOUSE_UP, stopFire);
player.addEventListener(Event.ENTER_FRAME,motion);
stage.addEventListener(KeyboardEvent.KEY_UP,onKey);
// add a keyboard down listener
stage.addEventListener(KeyboardEvent.KEY_DOWN, offKey);
stage.focus = stage;
// Add keyboard events
}
private function motion(e:Event):void{
// if we are currently holding the mouse down
//if (shooting){
//FIRE
//fire();
//}
player.x += xVal;
player.y += yVal;
}
//private function startFire(m:MouseEvent){
//shooting = true;
//}
//private function stopFire(m:MouseEvent){
//shooting = false;
//}
private function onKey(evt:KeyboardEvent):void
{
trace("key code: "+evt.keyCode);
switch (evt.keyCode)
{
case Keyboard.W :
yVal = walkingSpeed;
if (! walking)
{
trace("walking up");
player.walkDown.gotoAndPlay("walking");
walking = true;
}
break;
case Keyboard.S :
yVal = - walkingSpeed;
if (! walking)
{
player.walkDown.gotoAndPlay("walking");
walking = true;
}
break;
case Keyboard.A :
xVal = walkingSpeed;
if (! walking)
{
player.walkDown.gotoAndPlay("walking");
walking = true;
}
break;
case Keyboard.D :
xVal = walkingSpeed;
if (! walking)
{
player.walkDown.gotoAndPlay("walking");
walking = true;
}
break;
}
}
private function offKey(evt:KeyboardEvent):void
{
switch (evt.keyCode)
{
case Keyboard.W :
//for now just reset velocity to zero
yVal = 0;
//also stop walk cycle etc.
player.gotoAndStop("stance");
//don't forget to update your Boolean
walking = false;
break;
case Keyboard.S :
//for now just reset velocity to zero
yVal = 0;
//also stop walk cycle etc.
player.gotoAndStop("stance");
//don't forget to update your Boolean
walking = false;
break;
case Keyboard.A :
//for now just reset velocity to zero
xVal = 0;
//also stop walk cycle etc.
player.gotoAndStop("stance");
//don't forget to update your Boolean
walking = false;
break;
case Keyboard.D :
//for now just reset velocity to zero
xVal = 0;
//also stop walk cycle etc.
player.gotoAndStop("stance");
//don't forget to update your Boolean
walking = false;
break;
}
}
// Players Motion
private function fire():void{
var b= new Bullet();
// set the position and rotation of the bullet
b.rotation = rotation;
b.x = x;
b.y = y;
// add bullets to list of bullets
MovieClip(player).bullets.push(b);
// add bullet to parent object
player.addChild(b);
// play firing animation
player.shooting.gotoAndPlay("fire");
}
}
}
You were saying the Error #1009 ( Cannot access a property or method of a null object reference ) arises when you do
player.walkDown.gotoAndPlay("walking");
If so, that is because you have to first go to the frame where the WalkDown MovieClip is in before you can access it.
If say your "stance" frame is in frame 1 and your WalkDown MovieClip is in frame 2. Your code in the onKey function should look like:
case Keyboard.W :
yVal = walkingSpeed;
if (! walking)
{
trace("walking up");
player.gotoAndStop(2); // player.walkDown is now accessible //
player.walkDown.gotoAndPlay("walking");
walking = true;
}
break;