as3 continuous movement of object with touch event - actionscript-3

i am attempting to make an interactive scene fot my nexus 7 using actionscript. i am attempting to make a nape body to move continuously while a button is being pressed. the trace(event.target.name); in the tap handler is returning the instance name of the button being pressed as i expected it to but the same trace statement in the enter_frame pressed function is returning the buttons parent name and thus the movement is not happening below is my code..
resetBtn.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler);
ballBtn.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler );
leftArrow.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler );
rightArrow.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler );
private function tapHandler(event:TouchEvent):void
{
//listen for mouse up on the stage, in case the finger moved off of the button accidentally when they release.
rightArrow.addEventListener(TouchEvent.TOUCH_END, endTouch);
//while the mouse is down, run the tick function once every frame as per the project frame rate
addEventListener(Event.ENTER_FRAME, pressed);
trace(event.target.name);
//ball.applyImpulse(new Vec2(25,0));
}
function endTouch(e:Event):void
{
removeEventListener(Event.ENTER_FRAME, pressed);
//stop running the tick function every frame now that the mouse is up
this.removeEventListener(TouchEvent.TOUCH_END,endTouch);
//remove the listener for endTouch
}
function pressed(e:Event):void
{
space.step(1 / stage.frameRate);
trace(e.target.name);
if(e.target.name == "leftArrow")
{
trace("going left");
crane.position.x -= 5;
boom.position.x -= 5;
c.position.x -= 5;
}
if(e.target.name == "rightArrow")
{
trace("going Right");
crane.position.x += 5;
boom.position.x += 5;
c.position.x += 5;
}
}
if you can help me fix this or suggest a better way of achieving this wour help would be greatly appreciated.

Your issue is basically that you're adding the listener to the parent for the Enter_frame events so the target when that event dispatches isn't your buttons as you desire. I think instead of moving the listener though you're better off using a variable to hold a reference to your buttons like this:
private var curButton:Sprite;
resetBtn.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler);
ballBtn.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler );
leftArrow.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler );
rightArrow.addEventListener(TouchEvent.TOUCH_BEGIN , tapHandler );
private function tapHandler(event:TouchEvent):void
{
curButton = event.target;
curButton.addEventListener(TouchEvent.TOUCH_END, endTouch);
addEventListener(Event.ENTER_FRAME, pressed);
}
function endTouch(e:Event):void
{
trace("touch end received");
removeEventListener(Event.ENTER_FRAME, pressed);
curButton.removeEventListener(TouchEvent.TOUCH_END, endTouch);
curButton = null;
}
function pressed(e:Event):void
{
trace("currently pressed");
space.step(1 / stage.frameRate);
if(curButton == leftArrow)
{
trace("going left");
crane.position.x -= 5;
boom.position.x -= 5;
c.position.x -= 5;
}
if(curButton == rightArrow)
{
trace("going Right");
crane.position.x += 5;
boom.position.x += 5;
c.position.x += 5;
}
}
Okay see my edits above, hopefully should help resolve. Also as it seems you've probably already figured out the instance name that you give a variable when you define it, isn't the same as the .name property or the .id property, the instance name is no longer available at run time (if you really want to you can use the name property but you have to populate it yourself, and generally it's best to just use the instance names in the code instead, as this is checked at compile time, and incurs no extra run-time overhead).

Related

Need help fixing player jumping diagonally Flash CS4

I can't figure out why when I try and get my player to jump diagonally by pressing the right and up arrow key it does nothing, I've used trace to see if anything was happening and nothing was when they were used together.
Up won't work by itself or with right but when right is by itself it works.
player is named hero, platforms are named platform, platform2, platform3 etc
platforms are in the platform layer
stop();
var gravity:Number=5; //Very important, allows player to fall
var movex:Number=0; // Moving players X
// Moving player
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveHero);
var speed=10;
function moveHero(event:KeyboardEvent) {
if (event.keyCode==Keyboard.LEFT) {
hero.x-=speed;
hero.play();
}
if (event.keyCode==Keyboard.RIGHT) {
hero.x+=speed;
hero.play();
}
}
hero.addEventListener(Event.ENTER_FRAME, testCollision2);
// Allowing player to jump when on platform
function testCollision2(e: Event) {
//Allowing player to jump when on platform continued
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveHeroUP);
function moveHeroUP(event:KeyboardEvent) {
if (hero.hitTestObject(platform) && event.keyCode==Keyboard.UP) {
gravity=-50;
hero.y=hero.y+gravity;
} else if (hero.hitTestObject(platform2) && event.keyCode==Keyboard.UP) {
gravity=-50;
hero.y=hero.y+gravity;
} else if (hero.hitTestObject(platform4) && event.keyCode==Keyboard.UP) {
gravity=-50;
hero.y=hero.y+gravity;
}
if(hero.hitTestObject(platform) && event.keyCode==Keyboard.UP && event.keyCode==Keyboard.RIGHT){
movex = 20;
hero.x = hero.x + movex;
gravity =-50;
hero.y = hero.y + gravity;
}
}
I'm trying to get the player to jump in the code chunk at the very end
Flash CS4
AS3
To start, let's go through how you've set up this code and explain what's happening.
You have this line:
hero.addEventListener(Event.ENTER_FRAME, testCollision2);
Which is saying, every frame tick that hero exists, run the function testCollision2. Frame tick here doesn't relate to timeline frames, it relates to the frame rate of your application. So if that is set to 12, that function will run 12 times every second.
Inside testCollision2, you add another listener:
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveHeroUP);
and create an inline function called moveHeroUP. So every frame tick, you create a new function, and attach it to a key down event. So (assuming 12 frames per second) 5 seconds into your application, you'll have 60 keyboard listeners all doing the same thing. This is also a memory leak (as you keep creating a new function every frame), so eventually your program will crash.
To get to the actual question, a keyboard event is tied to one specific key. This means the event's keyCode is only ever one key (the key that triggered the event). So doing something like (event.keyCode==Keyboard.UP && event.keyCode==Keyboard.RIGHT) will always be false because event.keyCode only ever holds one value.
A common approach to your situation, is to have one global key down and key up listener. Then use a dictionary to store which keys are currently down:
//create just one key down listener
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
//create a dictionary to store key presses
var keyboardDown:Dictionary = new Dictionary();
function keyDownHandler(e:KeyboardEvent):void {
keyboardDown[e.keyCode] = true;
}
function keyUpHandler(e:KeyboardEvent):void {
keyboardDown[e.keyCode] = false;
}
What you're doing here, is when a key down event fires, you set the value in the dictionary to true (with the keycode as the dictionary key), then on the key up event you set it to false.
Now, in your ENTER_FRAME handler, you use the dictionary values to check for key combinations:
hero.addEventListener(Event.ENTER_FRAME, moveHero);
function moveHero(event:Event) {
//DO ALL YOUR MOVEMENTS IN ONE ENTER FRAME FUNCTION
if (keyboardDown[Keyboard.LEFT]) {
hero.x-=speed;
hero.play();
}
if (keyboardDown[Keyboard.RIGHT]) {
hero.x+=speed;
hero.play();
}
if (hero.hitTestObject(platform) && keyboardDown[Keyboard.UP]) {
gravity=-50;
hero.y=hero.y+gravity;
} else if (hero.hitTestObject(platform2) && keyboardDown[Keyboard.UP]) {
gravity=-50;
hero.y=hero.y+gravity;
} else if (hero.hitTestObject(platform4) && keyboardDown[Keyboard.UP]) {
gravity=-50;
hero.y=hero.y+gravity;
}
if(hero.hitTestObject(platform) && keyboardDown[Keyboard.UP] && keyboardDown[Keyboard.RIGHT]){
movex = 20;
hero.x = hero.x + movex;
gravity =-50;
hero.y = hero.y + gravity;
}
}

Action script 3 walking animation

i need some help. im trying to make my character walk both direction(left and right) and an idle animation when standing still. i manage to make the character walk to the right and make the idle animation work. now if I copy the code from the right button to the left button, the walking animation gets stuck in the first frame on both direction. I tried to experiment with it but with no luck. im sorry if i sounded noob. i just started with studying programming.
here are the code that i used
RightBtn.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
function mouseDown(e:MouseEvent): void {
if(RightBtn){
isRight = true;
}
}
RightBtn.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
function mouseUp(e:MouseEvent): void {
if(RightBtn){
isRight = false;
}
}
stage.addEventListener(Event.ENTER_FRAME, loop);
function loop(Event){
if(isRight==true && mcPlayer.x < 750){
mcPlayer.x += 7;
mcPlayer.gotoAndStop (2);
mcPlayer.walkR.play ();
}
else{
mcPlayer.gotoAndStop (1)
mcPlayer.Idle.play ();
}
}
LeftBtn.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown2);
function mouseDown2(e:MouseEvent): void {
if(LeftBtn){
isLeft = true;
}
}
LeftBtn.addEventListener(MouseEvent.MOUSE_UP, mouseUp2);
function mouseUp2(e:MouseEvent): void {
if(LeftBtn){
isLeft = false;
}
}
stage.addEventListener(Event.ENTER_FRAME, loop2);
function loop2(Event){
if(isLeft==true && mcPlayer.x > 65){
mcPlayer.x -= 7;
mcPlayer.gotoAndStop (3);
mcPlayer.walkL.play ();
}
else{
mcPlayer.gotoAndStop (1)
mcPlayer.Idle.play ();
}
}
That's what you get from blatant copy&paste without learning the mechanics of how does it internally work. You set two listeners to stage, both altering mcPlayer regardless of whether it was already altered by the other one. So, you need to write both sets of code in one listener, and walk the code with your pen and paper to ensure that both isRight==true and isLeft==true branches work separately and don't interfere with each other. The proper condition statement should be like this:
if (isRight==true && mcPlayer.x < 750) {
// do a step right
} else if (isLeft==true && mcPlayer.x > 65){
// do a step left
} else {
// do idle animation
}
Your codes of initiating animation are correct themselves, they just get overridden by the listeners that are unaware of some other code altering mcPlayer.

EventListener AS3 problems reset problems

Hey guys I am having a problem with Event Listeners in my AS3 file. I am trying to make this object that lasts for 83 frames to appear in a different location every time the parent (83 frame) movie clip resets. The problem is I have a function that places the object at a random y value which works great once. When it resets the ojbect appears on the same Y point. This is because I removeEventListener the function otherwise the object goes shooting off the screen when it loads. How do I call that event listener again without causing a loop that will shoot the object off screen?
Here is my code:
import flash.events.Event;
stop();
addEventListener(Event.ENTER_FRAME, SeaWeedPostion);
//stage.addEventListener(Event.ADDED_TO_STAGE, SeaWeedPostion);
function SeaWeedPostion(e:Event):void{
// if(newSeaWeed == 1) {
var randUint:uint = uint(Math.random() *500 + 50);
this.seaweedSet.y += randUint;
trace(randUint);
stopPos();
//}else{
//nothing
// }
}
function stopPos():void{
removeEventListener(Event.ENTER_FRAME, SeaWeedPostion);
//var newSeaWeed = 0;
}
function resetSeaWeed():void{
addEventListener(Event.ENTER_FRAME, SeaWeedPostion);
}
I have some // code in there from trying different things.
Anyone have any suggestions?
Thanks!
ENTER_FRAME event is triggered every frame, so rather than changing position on each frame maybe it's better to create a counter, count frames and if it reaches 82 change position of SeaWeed.
var counter:uint = 0;
Now add ENTER_FRAME listener
addEventListener(Event.ENTER_FRAME, onEnterFrame);
function SeaWeedPostion(e:Event):void {
counter++;
//Are we there yet?
if(counter < 83) {
//Nope, carry on
}
else {
//Yey!
changePosition();
counter = 0;
}
}
//Reset SeaWeed position when called
function changePosition() {
var randUint:uint = uint(Math.random() *500 + 50);
this.seaweedSet.y += randUint;
trace(randUint);
}

AS3 gotoAndStop causes object to remove itself

I have a student who is working on a Tower Defense game in AS3 and has an issue that has stumped me. He is using hitTestObject to change the direction that a movieClip is moving. The movieClip has its own timeline with frames for the different directions that the object is facing and a linked .as file with the code for the behavior of the object.
When he calls gotoAndStop to change the internal frame of the movieClip, the removed event is triggered, but the object stays on the screen and no longer moves.
All of my searches find answers about removing objects, but I have not seen anything about preventing an object from removing itself.
The following code is a loop triggered by an ENTER_FRAME event in the .as class file for the movieClip object:
private function eFrame(event:Event):void
{
if (_root.isPaused == false)
{
//MOVING THE ENEMY
this.x += speed * xDir;
this.y -= speed * yDir;
if (health <= 0)
{
_root.currency += 4;
this.parent.removeChild(this);
}
if (this.x > 770)
{
this.parent.removeChild(this);
_root.health -= 10;
_root.gotHit = true;
}
//checking if touching any invisible markers
for (var i:int=0; i<_root.upHolder.numChildren; i++)
{
//the process is very similar to the main guy's testing with other elements
var upMarker:DisplayObject = _root.upHolder.getChildAt(i);
if (hitTestObject(upMarker))
{
yDir = 1;
xDir = 0;
this.gotoAndStop(3);
}
}
for (i=0; i<_root.downHolder.numChildren; i++)
{
//the process is very similar to the main guy's testing with other elements
var downMarker:DisplayObject = _root.downHolder.getChildAt(i);
if (hitTestObject(downMarker))
{
yDir = -1;
xDir = 0;
this.gotoAndStop(7);
}
}
for (i=0; i<_root.rightHolder.numChildren; i++)
{
//the process is very similar to the main guy's testing with other elements
var rightMarker:DisplayObject = _root.rightHolder.getChildAt(i);
if (hitTestObject(rightMarker))
{
yDir = 0;
xDir = 1;
this.gotoAndStop(6);
}
}
for (i=0; i<_root.leftHolder.numChildren; i++)
{
//the process is very similar to the main guy's testing with other elements
var leftMarker:DisplayObject = _root.leftHolder.getChildAt(i);
if (hitTestObject(leftMarker))
{
yDir = 0;
xDir = -1;
this.gotoAndStop(2);
}
}
}
}
private function remove(event:Event):void
{
trace("remove");
removeEventListener(Event.ENTER_FRAME, eFrame);
_root.enemiesLeft -= 1;
}
}
When the gotoAndStop line executes, the frame of the movieClip changes and then the code jumps directly to a function that is triggered by the REMOVED event.
Does anyone have an idea why the REMOVED event might be triggered by this code?
Thank you for your help.
The REMOVED Event is triggered by anything that is removed from the stage inside the MovieClip or Sprite that is containing it, if I'm not mistaken. And especially with MovieClips that have animation, things get removed and added everytime, for instance if some part of the animation ends on the timeline, or at keyframes.
Event.REMOVED_FROM_STAGE is dispatched only when the container itself is removed from stage. Maybe that's causing your confusion? I can't see from your code example exactly what event type you're listening for.
Where are you adding the remove-listener?
Without more information, I would guess that you are listening to a clip inside an animation, and that it's not there on all frames (or, maybe even more likely - that the instance is being swapped out for another, identical one, by flash pro. This can happen depending on in what order you added keyframes, the alignment of the moon and fluctuations in the ionosphere. It's easiest fixed by simply removing all key-frames and then re-creating them. And then never using flash pro for anything ever again.)

AS3 : How to remove movieclip properly without Error 1009 overflow?

I have a class Catcher which lets you control a movieclip in a game. I'm trying to program the game so it finishes and you can restart. So I need to remove everything and go back to the menu. Should be a simple thing to solve but I can't seem to find out how.
So far I just have ourCatcher.parent.removeChild(ourCatcher); to remove my movieclip from the stage. And an if statement to stop one of the functions which drops things onto the stage. SoundMixer.stopAll(); to stop the music.Then I just have it going to frame 3 which is the gameover screen.
It looks fine but I get constant 1009 errors overflowing in the error console and when I restart the game, it's super slow. It seems the function for movement within Catcher is still running and creating an error because the Catcher was removed from stage and is null now.
I know I need to un-reference everything to do with the Catcher but I can't find out any documentation online to do it in my situation. Everyone seems to have different methods which I've tried and don't work.
The two functions in the Catcher class I'm using to move the character :
public function Catcher(stageRef:Stage)
{
stop();
this.stageRef = stageRef;
key = new KeyObject(stageRef);
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
//movement
public function loop(e:Event):void
{
if (key.isDown(Keyboard.A))
vx -= walkSpeed;
else if (key.isDown(Keyboard.D))
vx += walkSpeed;
else
vx *= friction;
//update position
x += vx;
//speed adjustment
if (vx > maxspeed)
vx = maxspeed;
else if (vx < -maxspeed)
vx = -maxspeed;
//stay inside screen
if (x > stageRef.stageWidth)
{
x = stageRef.stageWidth;
vx = -vx
}
else if (x < 0)
{
x = 0;
vx = -vx;
}
if (key.isDown(Keyboard.A))
{
scaleX = -1;
}
else if (key.isDown(Keyboard.D))
{
scaleX = 1;
}
movement();
// Jumping
jump += gravity;
if (y > stage.stageHeight /1.5)
{
jump = 0;
canJump = true;
}
if (key.isDown(Keyboard.SPACE) && canJump)
{
jump = -10;
canJump = false;
}
y += jump;
}
The other class where I'm removing the things from the stage is called CatchingGame and it has a function which drops objects, I put the game over code there for when playerlives == 0 .
if (playerLives == 0 )
{
stop();
ourCatcher.parent.removeChild(ourCatcher);
SoundMixer.stopAll();
gotoAndStop(3);
}
I've probably made an elementary mistake since this is my first flash game. Any help is greatly appreciated as this is pretty much the last step in finishing my game.
Instead of just removing the child by referencing its parent to remove itself (I had to test to make sure this actually worked). Create a function in same place that you create/instantiate the Catcher that removes first the eventListener ENTER_FRAME, then removes the Catcher.
if (playerLives == 0 ) {
stop();
removeCatcher();
SoundMixer.stopAll();
gotoAndStop(3);
}
// new location in the main code where the catcher is created
function removeCatcher():void {
ourCatcher.cleanUp();
removeChild(ourCatcher);
}
// in the Catcher class
function cleanUp():void {
removeEventListener(Event.ENTER_FRAME, loop);
}
if (ourCatcher.parent) ourCatcher.parent.removeChild(ourCatcher);
else trace("Catcher without a parent still plays! DEBUG THIS!");
Basically, you are most likely losing control flow of your catcher, that is, it seemingly tries to remove itself from the stage twice. After it removes itself first time, its parent becomes null, hence the 1009. And, seeing as you've hit a 2028, the same reason applies, your catcher is no longer a child of anywhere.