How do I stop automatic stretching of the other axis for instances when stretching one of its axis? - actionscript-3

When applying code for a laser weapon projectile (an instance of the laser beam itself) which would enable the laser to to act similarly to that of a real one, I had everything working great... except for the fact that the projectile kept stretching in the y axis as well as the x axis, instead of just the x axis. Now, I've found out that something like scaleMode needs to be disabled, but the best I've found is a line of code that goes like "stage.scaleMode = StageScaleMode.NO_SCALE;", which is meant for the stage and not instances themselves and if I tried to apply something like this for an ADDED event within the laser beam's class code I get error 1120 saying . Here is the code I think is necessary to present here from the beam's class:
package
{
import flash.display.MovieClip;
import flash.events.*;
public class weapon3projectileCode extends MovieClip
{
private var _root:Object;
public function weapon3projectileCode()
{
addEventListener(Event.ADDED, beginClass);
}
private function beginClass(event:Event):void
{
_root = MovieClip(root);
this.scaleMode = StageScaleMode.NO_SCALE;
this.scaleX = .25;
this.scaleY = .2;
}
private function entFrame(event:Event):void
{
if (_root.gamePaused == false)
{
x += speed;
if (stretchWhile < stretchTill)
{
this.width += 25;
this.x = _root.playerShip.x;
this.y = _root.playerShip.y;
}
else if (stretchWhile < shrinkTill)
{
this.width -= 25;
}
else if (stretchWhile >= shrinkTill)
{
this.width = .25;
removeEventListener(Event.ENTER_FRAME, entFrame);
_root.projectilePlayerContainer.removeChild(this);
}
stretchWhile ++;
if(this.x > (stage.width+ this.width))
{
removeEventListener(Event.ENTER_FRAME, entFrame);
_root.projectilePlayerContainer.removeChild(this);
}
}
if (_root.removeProjectiles == true)
{
removeEventListener(Event.ENTER_FRAME, entFrame);
_root.projectilePlayerContainer.removeChild(this);
}
}
}
}

You should specifically alter scaleX instead of width. You need to have your laser drawn by say 100 pixels long and say 10 pixels wide (to taste), then once you determine the desired distance of your laser, you set its scaleX to desiredWidth/100, this should eliminate your laser scaling by Y.

Related

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

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.

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.

I added animation to the timeline of my movie clip, now its no longer colliding with objects as it did before

I'm working on a platform game in AS3 for Flash. There is of course a player character and enemies for him to interact with. I first made a simple placeholder graphic for the enemy while I worked on the code. I got the enemy to move back and forth between two bumpers with code. He also collides with the player, sending them back to the start screen. Now that I got the code working, I wanted to add some animations to the enemies so they walk instead of just skate across the ground. I added the animations to the timeline of the enemy movie clip. Now when I test the game, the animations play fine and the enemy begins to move, but he passes through the first bumper and doesn't collide with the player at all. If I force the movie clip to stop and not play the collision starts to work again. What would be causing this?
This is the code within the main timeline of the .fla file.
addEnemiesToLevel1();
addBumpersToLevel1();
function addEnemiesToLevel1():void
{
addEnemy(700, -54);
addEnemy(1341, -54);
addEnemy(2187, -54);
}
function addBumpersToLevel1():void
{
addBumper(900, -80);
addBumper(644, -80);
addBumper(1135, -90);
addBumper(1380, -90);
addBumper(2053, -90);
addBumper(2226, -90);
}
function addEnemy(xLocation:int, yLocation:int):void
{
var enemy:Enemy = new Enemy(xLocation, yLocation);
back.addChild(enemy);
enemy.addEventListener(Event.REMOVED, enemyRemoved);
enemyList.push(enemy);
}
function addBumper(xLocation:int, yLocation:int):void
{
var bumper:Bumper = new Bumper(xLocation, yLocation);
back.addChild(bumper);
bumper.visible = false;
bumperList.push(bumper);
}
//corralling the bad guys with bumpers
if (enemyList.length > 0){ //enemies left in the enemyList?
for (var k:int = 0; k < enemyList.length; k++){ // for each enemy in the enemyList
if (bumperList.length > 0){
for (var h:int = 0; h < bumperList.length; h++){ // for each bumper in the List
if ( enemyList[k].hitTestObject(bumperList[h]) ){
enemyList[k].changeDirection();
}
}
}
}
}
//player and enemy collisions
if (enemyList.length > 0){ //enemies left?
for (var m:int = 0; m < enemyList.length; m++){ // for each enemy in the enemyList
if ( enemyList[m].hitTestObject(player) ){
trace("player collided with enemy");
gotoAndStop(4);
enemyList[m].removeSelf();
}
}
}
}
This is the enemy class file.
package {
import flash.display.MovieClip;
import flash.events.Event;public class Enemy extends MovieClip {
private var xSpeedConst:int = 2;
private var flip:int = 1;
public function Enemy(xLocation:int, yLocation:int) {
// constructor code
x = xLocation;
y = yLocation;
addEventListener(Event.ENTER_FRAME, loop);
}
public function loop(e:Event):void {
if ((flip%2) == 1){
x += xSpeedConst;
} else if((flip%2) == 0){
x += (-xSpeedConst);
}
}
public function removeSelf():void {
trace("remove enemy");
removeEventListener(Event.ENTER_FRAME, loop);
this.parent.removeChild(this);
}
public function changeDirection():void{
trace("x ="+x);
flip++;
this.scaleX *= -1;
}
}
}
I had a problem that was very similar to this:
2D Platform Game using hitTestPoint:glitches
My problem was that my character's hitTestPoint wouldn't work after I animated the character. However, it wasn't because of the animation, it was because of my turning code for the character. I was using scaleX to flip the character. However, this flipped the points nested within the character as well (which were used to handle my collisions). I notice that you also flipped the character's scale:
public function changeDirection():void{
trace("x ="+x);
flip++;
this.scaleX *= -1;
}
Perhaps you are having the same problem as I did. If so, try removing this line of code for now:
this.scaleX *= -1;
...and see what happens...We can figure out what to do next from there
Drake Swartzy

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?

Problem with collision detection in AS3?

I'm trying to have a rotatable line, controlled by the arrow keys. When you click the mouse, a ball drops from the cursor, and stops when it hits the line.
However, the balls always stop at the highest point of the line, across a line parallel to the x-axis.
My document class is as follows:
package
{
import flash.display.MovieClip;
import flash.events.*
import flash.display.Stage
import ball
public class Engine extends MovieClip
{
public static var stageRef:Stage
private static var leftKey:Boolean = false
private static var rightKey:Boolean = false
public static var pi = Math.PI
public static var lineRotate:Number = 0
public static var spinRate:Number = 60
public static var ground:line = new line()
public function Engine()
{
// constructor code
stage.addEventListener(Event.ENTER_FRAME, loop)
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler)
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler)
stage.addEventListener(MouseEvent.CLICK, addBall)
stageRef = stage
ground.x = 300
ground.y = 200
stage.addChild(ground)
}
private static function keyDownHandler(e:KeyboardEvent)
{
if (e.keyCode == 37) //left
{
leftKey = true
}
if (e.keyCode == 39)
{
rightKey = true
}
}
private static function keyUpHandler(e:KeyboardEvent)
{
if (e.keyCode == 37) //left
{
leftKey = false
}
if (e.keyCode == 39) //right
{
rightKey = false
}
}
public function loop(e:Event)
{
spin()
}
public static function addBall(e:MouseEvent) //adds ball
{
var tempBall:ball = new ball()
tempBall.x = e.stageX
tempBall.y = e.stageY
stageRef.addChild(tempBall)
}
private static function spin() //spins the "ground" line
{
if (leftKey) // minus
{
lineRotate -= spinRate
}
if (rightKey) // plus
{
lineRotate += spinRate
}
ground.rotation = lineRotate * (pi / 180) //convert to radians
}
}
}
The class for the ball is as follows:
package
{
import flash.display.MovieClip;
import flash.events.*
public class ball extends MovieClip
{
public var vX:Number = 0
public var vY:Number = 2
private var gravity:Number = 0
public function ball()
{
// constructor code
addEventListener(Event.ENTER_FRAME, loop)
}
public function loop(e:Event)
{
this.x += vX
this.y += vY
this.vY += gravity
if (this.x > stage.stageWidth || this.x < 0 || this.y < 0 || this.y > stage.stageHeight)
{
removeSelf()
}
if (Engine.ground.hitTestObject(this))
{
trace('yep')
stopBall()
}
else
{
trace('nope')
}
}
public function removeSelf()
{
removeEventListener(Event.ENTER_FRAME, loop)
this.parent.removeChild(this)
}
public function stopBall()
{
gravity = 0
vY = 0
vX = 0
}
}
}
I've uploaded my .swf to here.
The easiest thing you can do, for balls is a hitTestPoint with the third argument as true, that turns on shape detection.
ground.hitTestPoint(x,y,true);
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/DisplayObject.html#hitTestPoint()
Ok, so, hm, you can check a single point on the ball, like it's bottom point, or you can check an array of points along the bottom of the ball for easier precision... this is the quickest way to do this if you're not planing anything more complex then this. If, however, you want to create a full fleshed game, leave it to a 2d physics library like http://www.box2dflash.org/.
Forget skinners collision detection for a bigger game(something small like this could survive with it though), as it is bitmap based and would kill performance much more then box2D, it's a nice mask example, but it not a good idea to use for performance reasons.
I've changed your code a little bit. I've hittested a bunch of points on the bottom part of the ball, bear in mind that the ball's 0,0 inside the movieclip is centered on the balls center.
package
{
import flash.display.MovieClip;
import flash.events.*;
import flash.geom.Point;
public class ball extends MovieClip
{
public var vX:Number = 0;
public var vY:Number = 2;
private var gravity:Number = 0;
public function ball()
{
// constructor code
addEventListener(Event.ENTER_FRAME, loop);
}
public function loop(e:Event)
{
this.x += vX;
this.y += vY;
this.vY += gravity;
if (this.x > stage.stageWidth || this.x < 0 || this.y < 0 || this.y > stage.stageHeight)
{
removeSelf();
}
/*we will now check something like 18 points on the bottom side of the ball for colision
instead of just the bottom, you can probably guess why... if you cant, replace i on line
43 (var angleInRadians...) with 270 to test and then drop balls on a slopped ground surface... of course
you should definitely juse a physics engine like http://www.box2dflash.org/ for anything more complex.
*/
for (var i:int = 180; i<=360; i+=10)
{
/*keep in mind that ball.rotation property has 0 at the top of the ball, while here for these we are using the standard
Cartesian coordinate system. The effect of this on rotation would be that it is +90 and for X(yes, X) it would be Math.SIN(),
not Math.COS()!!!, and for Y it would be Math.sin() with a minus in front because of the flash coordinate system y axis rotation.
It's not really related to this, but it's a point that has anoyed me to no end in trig related stuff in flash when I was starting.
*/
var angleInRadians:Number = i / 180 * Math.PI;
var posX:Number = this.x + Math.round(Math.cos(angleInRadians) * width / 2);
var posY:Number = this.y - Math.round(Math.sin(angleInRadians) * height / 2);//minus because y in flash is upside down
Engine.ground.hitTestPoint(posX,posY, true);
if (Engine.ground.hitTestPoint(posX,posY, true))
{
stopBall();
}
else
{
}
}
/*if (Engine.ground.hitTestObject(this))
{
trace('yep')
stopBall()
}
else
{
trace('nope')
}*/
}
public function removeSelf()
{
removeEventListener(Event.ENTER_FRAME, loop);
this.parent.removeChild(this);
}
public function stopBall()
{
gravity = 0;
vY = 0;
vX = 0;
}
}
}
Unrelated to this above, you need to rethink your OOP a little bit, you are doing things a little bit wrong :). A project this small would cope, but anything bigger would give you headaches. Don't take this as an attack, I want to try to guide you to the "right" path and show you the logical fallacies in your code, I am not mentioning this to "pwn" you cause your oop is bad :).
For example, gravity, inside class ball? Yikes... what if you wanted to have gravity for ninjas, shurikens, ragdolls, etc? Are you going to subclass Ninjas out of the ball class?
Ninja extends ball? That would be fun.
Do you think that there might be a better place for that gravity thing? Is "gravity" a property of the ball at all(err, tehnically it is, but not this homogeneous gravity you are putting here, it's more like a permeating, all present thing, cause there is some huge body that we are too close to)? It should be in the Engine...
Also, you did Engine.ground thing... now, this is a static variable... this is another bad thing, very bad thing :)
The reason is similar to the previous example, but a little bit turned around. What if you want to reuse ball inside, say Engine2? Or Crytek engine? or UDK? I think it might be sligtely problematic, don't you think? You would have to go in and change the ball class... Imagine if every code you used forced you to do that...
Basically, you probably could have done something like this:
var bla:ball = new ball(ground);
this is better, muuuch better... now we can use it in crytek, udk and Engine2 easily...
Technically, you want to avoid things like static variables of this kind in your code, the idea is called encapsulation. The idea is that you hide the internal workings of classes from other classes that are unrelated to it or should not know about it. The less you NEED to know, the more portable, reusable (yada yada) your classes are. Engine.ground is a huge encapsulation breaker because ball has absolutely zero need to know about class Engine, it should only be concerned with a reference to the ground itself...
In time you will learn all of this, patterns in programming, and particularly , which patterns save time, and which are appalling, and why (static variables have their use, but only for ultra simple stuff, avoid Singletons as well if you know what they are).
http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)
Sorry for the headache I've caused you...
Remember, use a physics engine for more complex code, don't reinvent the wheel(reuse everything for your projects that is good for them/sufficient for them)... It's fun to test stuff like this, but other folks have done it better before you, and unless you specifically need to delve into their domain, you don't need to concern yourself with every little detail. You are probably trying to build games/something, not bother with Newtonian dynamics...
HitTest is just fine for simple stuff though, but this is bordering on simple... :)we are already slightly into physics here, and you might find you need a more robust solution soon...
So generally, try to make your code "robust" by thinking about encapsulation and dependencies between your classes. If a dependency feels unatural (ie ball depends on Engine) then something is probably wrong, and will break later, will break for another game or engine or... I'll end it here...
Take care and have fun.
According to the article Collision detection methods: hit-test and hit-testobject alternatives, that is by design:
As you can see Flash uses the bounding
boxes of objects - it takes the
highest and lowest possible points,
the leftmost and rightmost points and
draws a rectangle around them.
The author mentions several alternatives to workaround this limitation, such as using hitTestPoint or Grant Skinner's Shape based collision detection.