What causes stack overflows to occur? Why do these lines cause stack overflowing and how do I fix it? - actionscript-3

I'm getting stack overflow errors and i'm not sure what a stack overflow error is or how to fi it. I've looked online to try to understand stack overflows but i'm pretty lost. If anyone could explain to me what in my code is causing the overflow that'd be great
Here is my Hero class:
package {
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.display.MovieClip;
public class Hero extends DocumentMainNew
{
public var health:Number;
public var mana:Number
public var vx:Number;
public var vy:Number;
public var allowJump:Boolean;
public var collision:Boolean;
public function Hero():void
{
this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
}
public function enterFrameHandler(e:Event):void
{
//Gravitates the player
vy += 2;
//Moves the player
angela.x += vx;
angela.y += vy;
//processes collisions
processCollisions();
//scrolls the stage
scrollStage();
}
public function keyDownHandler(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case 37: //left arrow
vx = -7;
break;
case 39: //right arrow
vx = 7;
break;
case 38: //up arrow
if(allowJump)
{
vy = -20;
}
break;
default:
}
}
public function keyUpHandler(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case 37:
vx = 0;
break;
case 39:
vx = 0;
break;
case 38:
break;
default:
}
}
public function processCollisions():void
{
//detects when player is falling
if(vy > 0)
{
//respawns the player if they fell of the stage
if(angela.y > stage.stageHeight)
{
angela.x = _startMarker.x;
angela.y = _startMarker.y;
_boundaries.x = 0;
_boundaries.y = 0;
vy = 0;
}
//otherwise, processes collisions with boundaries
while(_boundaries.hitTestPoint(angela.x, angela.y, true))
{
allowJump = true;
angela.y -= 0.1
vy = 0;
}
}
}
}
}
And here is my main document:
package {
import flash.display.MovieClip
import flash.events.Event
import flash.events.KeyboardEvent
import Hero
public class DocumentMainNew extends MovieClip
{
public var angela:Hero = new Hero;
public var enemy1:Enemy = new Enemy;
public var _boundaries:Boundaries;
var _startMarker:StartMarker;
public function DocumentMainNew():void
{
_startMarker.visible = false;
addChild(angela);
addChild(enemy1);
angela.health = 100;
angela.mana = 100;
stage.focus = stage;
}
public function scrollStage():void
{
_boundaries.x += (stage.stageWidth * 0.5) - angela.x;
angela.x = stage.stageWidth * 0.5;
enemy1.x = _boundaries.x + 30;
_powerup.x = _boundaries.x - 200;
}
}
}
Heres the error:
Error: Error #1023: Stack overflow occurred.
at DocumentMainNew()[/Users/s2111908/Desktop/Game/DocumentMainNew.as:9] at Hero()[/Users/s2111908/Desktop/Game/Hero.as:16]
Line 9 of DocumentMainNew is: public var angela:Hero = new Hero;
Line 16 of Hero is: public function Hero():void
It says at DocumentMainNew() and at Hero() many many times but i didn't want to paste all of it. If the number of times is important let me know and i'll ad a picture. I'm fairly new to AS3 so if anyone has any tips on how to improve my code in anyway please let me know.

First. Please learn how to format your code while posting. The whole code block must be indented. There's a {} button just for that.
Second. Your mistake is Hero extending DocumentMainNew class. The problem is not extending itself but the fact you call new Hero in the DocumentMainNew variable declaration area. Lets see, how it goes.
Root instance of DocumentMainNew is created.
Declaring angela variable and assigning a new Hero to it.
An instance of Hero is created.
Hero is extending DocumentMainNew so the superclass initializes first.
Declaring angela variable and assigning a new Hero to it.
An instance of Hero is created.
...and so on.
I don't know why did you inherited the Hero class from the DocumentMainNew class, but that was a totally wrong move. You should explain what you did try to solve doing so. It should probably be solved in a very different way.

Related

How can I stop a colliding object from continuing falling after several seconds (AS3)?

I have a problem that is related to AS3, it involves two code locations (MainTimeline and an MC-extending class), as well as a basic physics engine function. The problem is that when the objects collide (enemy and ground), they stay collided, but after a short period of time (2-6 seconds), the object that is gravitated teleports under the object it collided with, and continues to fall.
Thank you for any assistance.
P.S. I do not prefer document class solutions.
Timeline code:
`
stop();
var ground: MovieClip;
var enemy:Enemy = new Enemy();
stage.addChild(enemy);
enemy.x = 400;
enemy.y = 150;
enemy.rotation = 0;
enemy.addEventListener("enterFrame", collisions);
function collisions(e: Event): void {
var collision: Boolean = false;
if (ground.hitTestObject(enemy)) {
collision = true;
}
if (collision) {
while (collision) {
enemy.y -= 0.1;
collision = false;
if (ground.hitTestObject(enemy)) {
collision = true;
}
}
Class(Enemy).yVel = 0;
}
}
Class code:
package {
import flash.display.MovieClip;
import flash.events.Event;
public class Enemy extends MovieClip {
var xVel: int;
var yVel: int;
public function Enemy() {
// constructor code
addEventListener("enterFrame", onEnterFrame);
}
function onEnterFrame(e: Event): void {
yVel += 2;
this.x = xVel;
this.y = yVel;
}
}
}

AS3 Projectile moves incorrectly

So I'm currently attempting to make a prototype for a Bullet Hell game and I've run into a bit of a dead end.
So far I can move my player perfectly, the boss moves back and forth as he is supposed to, however the projectiles have some funny behaviour. Basically, when the boss moves left/right, so do the projectiles as if they are stuck to him. They move on the y as they are supposed to, except they stop just short of the player and move no further, so I'm hoping anyone can take a look at my code and give me a hand with what's going on.
Note: Ignore the rotation stuff, that's for later implementation, I was just laying the ground work.
Projectile.as
package
{
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
public class Projectile extends MovieClip
{
private var stageRef:Stage;
private var _xVel:Number = 0;
private var _yVel:Number = 0;
private var rotationInRadians = 0;
private const SPEED:Number = 10;
public function Projectile(stageRef:Stage, x:Number, y:Number, rotationInDegrees:Number)
{
this.stageRef = stageRef;
this.x = x;
this.y = y;
this.rotation = rotationInDegrees;
this.rotationInRadians = rotationInDegrees * Math.PI / 180;
}
public function update():void
{
this.y += SPEED;;
if(x > stageRef.stageWidth || x < 0 || y > stageRef.stageHeight || y < 0)
{
//this.removeChild(this); <- Causing a crash, will fix later
}
}
}
}
Boss.as
package
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class Boss extends MovieClip
{
private var stageRef:Stage;
private var _vx:Number = 3;
private var _vy:Number = 3;
private var fireTimer:Timer;
private var canFire:Boolean = true;
private var projectile:Projectile;
public var projectileList:Array = [];
public function Boss(stageRef:Stage, X:int, Y:int)
{
this.stageRef = stageRef;
this.x = X;
this.y = Y;
fireTimer = new Timer(300, 1);
fireTimer.addEventListener(TimerEvent.TIMER, fireTimerHandler, false, 0, true);
}
public function update():void
{
this.x += _vx;
if(this.x <= 100 || this.x >= 700)
{
_vx *= -1;
}
fireProjectile();
projectile.update();
}
public function fireProjectile():void
{
if(canFire)
{
projectile = new Projectile(stageRef, this.x / 200 + this._vx, this.y, 90);
addChild(projectile);
canFire = false;
fireTimer.start();
}
}
private function fireTimerHandler(event:TimerEvent) : void
{
canFire = true;
}
}
}
Edit: Current suggestions have been to do the following:
stage.addChild(projectile); and this.parent.addChild(projectile); both which have the projectile firing from the top left corner (0, 0) and not constantly firing from the current center of the Boss.
The other issue, which has been untouched, is the fast that the projectile stops moving after a certain point and remains on the screen.
Another Edit:
After commenting out the code with the timer I have found that the projectile stops moving entirely. The reason why it was stopping after a certain amount of time was due to the timer, when the timer elapsed the projectile stopped and another would fire.
So now I need the projectile to constantly fire and move until it hits the edge of the screen, any ideas?
The problem is you are 'addChild'ing your projectiles to your Boss as opposed the stage (or the same display level as your Boss). When your Boss moves, your projectiles will move relative to him (ie, when he moves sideways, so will they).
When your boss fires a projectile, use a custom event to trigger a fireProjectile method in the Class that is your Boss' display parent. Instantiate your projectiles there and addChild them to the same object to which you addChild your Boss (possibly the stage?).
Alternatively, if you don't want to use a custom event, in your current fireProjectile method change the addChild line to:
this.parent.addChild(projectile);
This will add projectiles to the parent object of your Boss. Although that line seems, slightly, like cheating to me.

AS3 Game - Jump Doesn't Alter Velocity

I'm having problems making my Player jump in AS3. I'll upload everything relevant, I'm really struggling to figure out exactly what I've done wrong. It used to work but now it doesn't, I spent so long fixing errors I can't figure out where this messed up. The Player Class is extended from the BoundaryObject class. I know the function is activated because the Player's this.gotoAndStop("jump"); works.
Player Class - Function for Jump
public function startJumping():void
{
if (isJumping == false)
{
isJumping = true;
this.gotoAndStop("jump");
downwardVelocity = -28;
}
}
BoundaryObject Class - Variables/Loop for gravity
public var downwardVelocity:Number;
protected var isRunning:Boolean;
public var isJumping:Boolean;
public function BoundaryObject()
{
trace("i am any object that collides with the boundary");
downwardVelocity = 0;
isRunning = false;
this.gotoAndStop("jump");
addEventListener(Event.ENTER_FRAME,enterFrameHandler);
// constructor code
}
private function enterFrameHandler(event:Event):void
{
downwardVelocity += 2; //equals itself plus 2
this.y += downwardVelocity;
}
public function incrementUpward()
{
//increment the y up until not colliding
this.y -= 0.1;
}
public function keepOnBoundary()
{
downwardVelocity = 0;//stops pulling the object down
}
Just at first glance, maybe set your jump boolean to true as you are setting this frame in constructor.
Try setting the downwardVelocity of the parent.
parent.downwardVelocity = -28;

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();
}

My class has some timing issues

I have a class that I use to display text on stage, with some number effects. It works pretty well, but when I chain it like this
public function onAdd(e:Event) {
//stuff
addChild(new messager("Welcome."));
addChild(new messager("WASD to move, mouse to shoot."));
addChild(new messager("Kill zombies for XP and collect ammo boxes.",waveOne));
}
public function waveOne(){
addChild(new messager("Good luck and have fun.",newWave));
}
The text (Good luck and have fun) is not displayed, but newWave is called. The reason why I don't call waveOne in onAdd is so that it doesn't happen too quick - my class just throws the text at the user once every 50 frames (which is intended, for later when you kill enemies and the text needs to catch up).
Here is my class (with the effects removed):
package {
import flash.display.MovieClip;
import flash.events.*;
import flash.utils.Timer;
public class Messager extends MovieClip{
var actualText:String;
var callback:Function;
var upTo:int = 0;
static var waitingFor:int = 0;
public function Messager(text:String,callback:Function=null) {
this.callback = callback;
actualText = text;
x = 320 - actualText.length * 6.5;
y = 0 - waitingFor * 60;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
waitingFor++;
}
public function onEnterFrame(e:Event) {
y+= 1;
if(y > 60){
waitingFor--;
}
if(y > 200){
alpha -= 0.03;
if(alpha <= 0){
if(callback != null){
callback();
}
removeEventListener(Event.ENTER_FRAME, onEntFrm);
this.parent.removeChild(this);
}
}
}
}
It is set to linkage with a movieclip that has a textfield.
Thanks for any help.
y = 0 - waitingFor * 60; Maybe y of the last Mesager is a big negative number? Have you tried to trace waitingFor?