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

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

Related

AS3: Why is a line created with .graphics appearing in two different places and when removed with parent.visible = false, only one goes?

Nobody seems to have this question already so I asked it because I've spent a few hours trying to debug this and can't find a solution;
Essentially, I have a function called draw, which is declared in my document class:
public function draw(Target: MovieClip,mX: int,mY: int,lX: int,lY: int):void {
Target.graphics.clear();
Target.graphics.lineStyle(1,0x000000,1);
Target.graphics.moveTo(mX,mY);
Target.graphics.lineTo(lX,lY);
}
I call it later to draw two lines, on two different MovieClips:
draw(Line,Line.mX,Line.mY,Mirror.x + (Mirror.width / 2),Line.lY);
draw(nextLine,(Mirror.x + (Mirror.width / 2)),200,(Mirror.x + (Mirror.width / 2)),0);
where
var Line: MovieClip = new MovieClip();
var Mirror: MovieClip = new mirror();
and Mirror is draggable, so Mirror.x changes whenever it is dragged.
Line is a line made using .graphics and Line.mX is equal to the Line.graphics.moveTo X value last time it was modified. Line.mY is the same, but for the Y coordinate. I set these values by doing this:
Line.mX = 0;
Line.mY = 200;
Line.lX = 550;
Line.lY = 200;
But with whatever values I want to draw the line, with lX and lY being equal to the X and Y coordinates of Line.graphics.lineTo. Then I draw Line using my draw function like this:
draw(Line,Line.mX,Line.mY,Line.lX,Line.lY);
Then it gets more complex because, actually, Line is just one line in an array of lines, created like this:
public var lines = [line0,line1,line2,line3,line4,line5,line6,line7,line8];
and each of those lines is created like this (with 0 being replaced by the line's number, respectively):
public var line0: MovieClip = new MovieClip();
then I give each line a number and a name, add them to the stage and hide them like this:
for each(var setupLine:MovieClip in lines) {
setupLine.num = (lines.indexOf(setupLine));
setupLine.name = ('line' + setupLine.num);
addChild(setupLine);
setupLine.visible = false;
}
Then, after making line0 visible, because I need to see it at the start, I loop through each line in a function that runs on ENTER_FRAME, and set the value of nextLine to a different value each time I run the loop like this:
for each(var Line:MovieClip in lines) {
nextLine = this['line' + (Line.num + 1)];
}
Within that loop, I then loop through a few other arrays, then check for a collision with the selected Line and another selected MovieClip from another array, which I wont go into or this question will be longer than the code for node.js.
So essentially, if the collision with the two MovieClips is present, I draw the line that I mentioned at the top of my question. But for some reason, although Line draws correctly, nextLine draws correctly, but a duplicate of it is drawn across the Y axis at 0, and stops where nextLine is on the Y axis (nextLine is vertical, so it has the same Y value at the start as at the end).
Even stranger, when I try to hide nextLine if the collision with the two MovieClips is no longer present, using this code:
nextLine.visible = false;
it only hides the version of nextLine that runs along the top of the stage, which I didn't even intend to create in the start.
EDIT
here is a link to the current source code
Here is a link to the entire project files with the original source code
copy/paste the new source code from the pastebin link to get the new version
Thanks in advance,
-Raph
I figured out how to do this, code is
package {
import flash.events.*;
import flash.utils.*;
import flash.display.*;
[SWF(backgroundColor="0xbdc3c7")]
public class LightStage extends MovieClip {
//import classes
public var globeClass:Globe = new Globe();
public var mirrorClass:Mirror = new Mirror();
public var lineClass:Line = new Line();
//create all stage objects
public var curLine:Line
public var nextLine:Line;
public var curMirror:Mirror;
//create containers
public var mirrors:Vector.<Mirror> = new Vector.<Mirror>(); //a vector is an array, but every member has to be (or subclass) the specified class
public var globes:Vector.<Globe> = new Vector.<Globe>();
public var lines:Vector.<Line> = new Vector.<Line>();
trace('lightstage: working');
//create level object
public var curLevel:int = -1;
//create dependent variables
public var kill: Boolean = true;
//init function
public function LightStage() {
//setup MovieClips
var i:int = 0;
for (i = 0; i < 4; i++) {
mirrors.push(new Mirror());
}
for (i = 0; i < 4;i++ ) {
globes.push(new Globe());
}
var tmpLine:Line;
for (i = 0; i < 10; i++) {
tmpLine = new Line();
lines.push(tmpLine);
addChild(tmpLine);
tmpLine.visible = false;
}
//create ENTER_FRAME listener
stage.addEventListener(Event.ENTER_FRAME,enterFrame);
//start the game
levelUp();
}
//levelUp function
public function levelUp() {
curLevel++;
curLine = lines[curLevel]; //set line to the current level
curLine.curX = 0;
curLine.curY = 200;
curLine.draw(550, 200);
curLine.visible = true;
//show and position mirrors and globes
curMirror = mirrors[curLevel];
addChild(curMirror);
curMirror.x = 250;
curMirror.y = 350;
var curGlobe:Globe = globes[curLevel];
addChild(curGlobe);
curGlobe.x = 100;
curGlobe.y = 50;
//set mirror types
curMirror.gotoAndStop(2);
trace("you are now on level " + (curLevel + 1) + "!");
}
//ENTER_FRAME function
public function enterFrame(event:Event) {
//line1.visible = true;
for (var i:int = 0; i < lines.length;i++){
if (i < lines.length - 1) nextLine = lines[i + 1]; //check for out of bounds before assignment next line
if (lines[i].visible == true) {
kill = true;
for each(var mirror:Mirror in mirrors) {
if (lines[i].visible && mirror.stage && mirror.hitTestObject(lines[i])) { //for efficiency, do the hit test last in the if statement
for each(var globe:Globe in globes) {
//Looped through Mirrors and Lines and checked for collision - if collision is present, we loop through globes here
if (nextLine && nextLine.stage) {
addChild(nextLine);
}
//check for active globes
if (lines[i].visible && lines[i].hitTestObject(globe)) {
//check if the selected line touches the selected globe - if it does then we will start the timer for that globe
if (!globe.running){
globe.start();
//trace('timing');
kill = false;
}
}
else {
globe.reset();
}
switch(mirror.currentFrame) {
case 1:
break;
case 2:
//trace('live a life you will remember' + Math.random());
if(nextLine) nextLine.visible = true;
lines[i].draw(mirror.x + (mirror.width / 2),lines[i].curY);
if (nextLine) {
nextLine.curX = mirror.x + (mirror.width / 2);
nextLine.curY = 200;
nextLine.draw(mirror.x + (mirror.width / 2), 0);
}
kill = false;
break;
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
trace(mirror.currentFrame);
kill = false;
break;
}
}
}
else if (lines[i].visible && mirror.stage && lines[i].stage){
if (kill && nextLine){
nextLine.graphics.clear();
nextLine.visible = false;
}
}
}
}
}
}
}
}
//MIRROR CLASS DECLARATION
import flash.events.MouseEvent;
class Mirror extends MovieClip {
trace('mirror: working');
public function Mirror() {
this.addEventListener(MouseEvent.MOUSE_DOWN,onDown,false,0,true);
}
private function onDown(e:MouseEvent):void {
//add the mouse up listener on the stage, that way it's consistent even if the user drags so fast that the mouse leaves the bounds of the mirror
stage.addEventListener(MouseEvent.MOUSE_UP, onUp, false, 0, true);
this.startDrag();
}
private function onUp(e:MouseEvent):void {
//we need to remove the listener from the stage now
stage.removeEventListener(MouseEvent.MOUSE_UP, onUp, false);
this.stopDrag();
}
}
//LINE CLASS DECLARATION
import flash.display.Graphics;
class Line extends MovieClip {
trace('line: working');
public var curX:int;
public var curY:int;
public function Line():void {
}
public function draw(toX:int,toY:int):void {
graphics.clear();
graphics.lineStyle(1,0x000000,1);
graphics.moveTo(curX,curY);
graphics.lineTo(toX, toY);
curX = toX;
curY = toY;
}
}
//GLOBE CLASS DECLARATION
import flash.display.MovieClip;
import flash.events.TimerEvent;
import flash.utils.Timer;
class Globe extends MovieClip {
trace('globe: working');
private var timer:Timer = new Timer(3 * 100, 5);
public function Globe():void {
timer = new Timer(300, 5);
timer.addEventListener(TimerEvent.TIMER, repeatShine, false, 0, true);
}
public function reset():void {
timer.reset();
}
public function start():void {
timer.start();
}
public function get running():Boolean { return timer.running; };
private function repeatShine(e:TimerEvent):void {
}
}

addChild not displaying anything on stage

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.
}

Falling object and repeating in a loop ( Action Script 3.0)

I am trying to make a symbol (made a special class for it) to fall continuously until a timer reaches 0. Also I would like this rock to repeat and show in random places on the stage. I can't figure out how to code that. Pretty much I am still a newbie to action script 3.0.
This is what I have so far:
The Main
package {
import flash.display.Sprite;
import Game_Objects.TinyBird;
import Game_Objects.Rock;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public class Main extends Sprite {
private var userbird:TinyBird;
private var obstacle:Rock;
//containers.
private var obstacleContainer:Sprite = new Sprite();
//timers.
private var enemySpawn:Timer;
public function Main() {
// The main code of the game
// The Bird has to avoid rocks by moving left and right
// Obstacles = rocks
// The Birdie will be controlled by the keyboard
// As long as Birdie alive=1 the loop will continue until alive=0 (where 1=true and 0=false) or timer reaches 0
// if the bird will hit an object it will die (collision detection)
this.userbird = new TinyBird(stage.stageWidth/2, stage.stageHeight-20);
this.obstacle = new Rock;
obstacleContainer.addChild(obstacle);
addChild(userbird);
stage.addEventListener(Event.ENTER_FRAME, startpulse)
stage.addEventListener(KeyboardEvent.KEY_DOWN, keymove);
// event to count the passed rocks in order to set score.
stage.addEventListener(obstacle.KILLED, deadEnemy);
}
private function startpulse(evt:Event):void {
// makes the bird pulsate
this.userbird.pulse_animation();
}
private function keymove(evt:KeyboardEvent):void {
// the keyboard movements for the bird
// if leftArrow = pressed -> tiny bird will move left. Else if rightArrow = pressed -> tiny bird will move right
if (evt.keyCode == Keyboard.LEFT) {
this.userbird.left();
} else if (evt.keyCode == Keyboard.RIGHT) {
this.userbird.right();
}
}
// The obstacle objects are going to fall randomly
private function spawn(e:TimerEvent):void {
// calculate a random starting position
var xPos:Number = Math.floor(Math.random()*stage.stageWidth);
// calculate a random speed between 2 and 6
var speed:Number = Math.floor(Math.random()*4+2) ;
// create the new rock
var enemy:Rock = new Rock(xPos, 42, speed, stage.stageWidth, stage.stageHeight);
// add it to the container
this.obstacleContainer.addChild(enemy);
enemy.name = "Rock " + Rock.createdCount;
}
private function deadEnemy(e:Event) {
var obj:Rock = (e.object as Rock);
this.objectContainer.removeChild(obj)
}
}
}
And this is the rock symbol:
package Game_Objects {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.utils.Timer ;
import flash.events.TimerEvent ;
public class Rock extends Sprite {
// The Rock is the obstacle that, if colided with the bird, the game is over.
// public function properties
static public var _createdCount:int = 0;
// private function properties
private var speed:Number;
private var _score:Number = 4;
private var scoreCounter:Number = 0;
// Classes methods
public static function get createdCount():int {
return _createdCount;
}
// instance methods
// Initialization
public function Rock(x:Number, y:Number, s:Number, maxX:Number = 0, maxY:Number = 0) {
// set the speed
this.speed = s;
// If the rock goes off the stage, then
if (x < this.width/2) {
// Put on at left
this.x = this.width/2;
// else if x would put the rocks beyond right side of the stage then
} else if (x > maxX - this.width/2) {
// Position the rock on the stage.
this.x = maxX-this.width/2;
} else {
// Otherwise position at x
this.x = x;
}
// same for Y
if (y < this.height/2) {
this.y = this.height/2;
} else if (y > maxY - this.height/2) {
this.y = maxY-this.height/2;
} else {
this.y = y;
}
// Creating the animation loop in order to repeat the falling motion of the rocks.
configUI();
this.addEventListener(Event.ENTER_FRAME, drop);
// adding a boolean type of loop, taken from
// http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00001283.html#374074
this.cacheAsBitmap = true;
// Add 1 to the public var in order to keep track of the rocks
_createdCount++;
}
// protected function
protected function configUI():void {
}
// private function
private function drop(e:Event) {
// in order to show the dropping effect
// The falling of the rocks
this.y += this.speed;
// if at bottom of stage then
if (this.y-this.height >= stage.stageHeight) {
// Set score to +1 as reward for not hitting the rock.
this._score++;
// Kill the rock that has reached the bottom of the stage
}
}
}
}

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;