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.
Related
I am trying to code a script in which a movieclip drops a rope and catches fishes that follows it up if it touches it. here is the issue , i am using hitTestObject to detect collision . Ofcourse the problem is that i trigger the function when it touches but as soon as it doesnt touch the function for moving the movie starts so basically the fish goes up for few seconds and then starts moving straight again .
To try and fix that i tried to make a boolean variable which changes to true or false according to hit and accordingly makes the movieclip moves but also doesnt work because as soon as one mc is not touching the other it changes from true to false or 1 to 0 ..tried both (as in with boolean variable and Number variable) . Any help or putting me on the right direction would be highly appreciated . Thank you so much
// fish capture code
this.addEventListener(Event.ENTER_FRAME,handleCollision);
function handleCollision(e:Event):void
{
if (ropeHit.hitTestObject(fishy_1_a))
{
stopFish1();
trace(movefish1);
}
else
{
moveFish1();
}
}
//code enemy fishy
//fish 1 A
function moveFish1()
{
if (fishy_1_a.x < 800)
{
fishy_1_a.x += xSpeed;
}
else if (fishy_1_a.x >= 800)
{
fishy_1_a.x = -100;
}
}
function stopFish1()
{
fishy_1_a.y -= xSpeed;
}
Define some flag, that you can test:
function handleCollision(e:Event):void {
//Check if fishy is caught
if (!fishy_1_a.catched && ropeHit.hitTestObject(fishy_1_a)) {
//Change flag
fishy_1_a.catched = true;
trace("Gotcha!");
}
if (fishy_1_a.catched) {
stopFish1();
}else {
moveFish1();
}
}
I'm new to AS3 and although I was looking for a solution to my problem truly long time, I was not successful. I have an animated presentation and I just want to make navigation through that by arrows. Everything is on the main timeline. In the first frame I made this code
var zpet: Number;
if (currentFrame == 1) {
zpet = 1;
}
stage.addEventListener(KeyboardEvent.KEY_DOWN, posun);
function posun(event: KeyboardEvent): void {
if (event.keyCode == 37) {
addEventListener(Event.ENTER_FRAME, playReverse);
function playReverse(event: Event): void {
if (currentFrame == zpet) {
stopPlayReverse();
} else {
prevFrame();
}
}
function stopPlayReverse(): void {
if (hasEventListener(Event.ENTER_FRAME)) {
removeEventListener(Event.ENTER_FRAME, playReverse);
}
}
} else if (event.keyCode == 39) {
if (currentFrame < totalFrames - 1) {
play();
} else {
stop();
}
}
}
stop();
Moving forward works perfect as I put stop(); in every keyframe of the presentation. The problem is how to go back just to the previous keyframe (and I also want to go back in reverse playing). I thought it would be quite easy if I made a variable (called "zpet") and set it the specific number of frame where to go back in each keyframe. But it doesn't work, all the time it's going back to frame 1. For example I put in the frame 26 the code zpet = 13; that should say when playing back from the frame 26 stop at the frame 13. Any ideas how to solve this? I would be really grateful for that..
You can label each keyframe of your animation anything you want directly from the timeline and then something like this :
function playReverse(event: Event): void
{
prevFrame();// You can also use gotoAndStop(currentFrame - 1)
if(currentFrameLabel != null)
stopPlayReverse();
}
Looks cleaner imo, plus you can use labels value later in case you make a scene selection menu.
Well the problem is that I'm having troubles with the fighter in my game. If I use the KEY_DOWN event and/or ENTER_FRAME, when I hold down the kick or punch button the fighter continuously causes damage to the enemy but I want him either to, for example kick and then return to still position or kick and be able to hold the position but only cause the damage one time. Here's some code:
stage.addEventListener(KeyboardEvent.KEY_DOWN, enterAttack);
stage.addEventListener(KeyboardEvent.KEY_UP, exitAttack);
stage.addEventListener(Event.ENTER_FRAME, attackYes);
stage.addEventListener(Event.EXIT_FRAME, attackNo);
function enterAttack(evt:KeyboardEvent):void
{
if (evt.keyCode == 84)
{
attack = true;
}
}
function exitAttack(evt:KeyboardEvent):void
{
attack = false;
}
function attackYes(evt:Event):void
{
if (attack)
{
hero.gotoAndStop("punch1");
checkHitRed();
checkIfDead();
}
}
function attackNo(evt:Event):void
{
if (!attack)
{
hero.gotoAndStop("still");
}
}
I was trying to remove the listener somewhere but that always made it look like the fighter didn't do any attack.
Is there any way to prevent holding down kick/punch button?
Any help is appreciated
You have to devise cooldowns for your abilities, e.g. "kick" can happen only once per 20 frames. So, when the player presses kick button, char does a kick, does damage, and sets the cooldown variable. Enter frame listener starts to decrement the counter, and subsequent kick commands are ignored while the cooldown is active.
stage.addEventListener(KeyboardEvent.KEY_DOWN, enterAttack);
stage.addEventListener(Event.ENTER_FRAME, enterFrame);
var kickCooldown:int=0;
function enterAttack(evt:KeyboardEvent):void
{
if (evt.keyCode == 84)
{
if (!kickCooldown) {
attack = true;
kickCooldown=15;
}
}
}
function enterFrame(evt:Event):void
{
if (attack)
{
hero.gotoAndStop("punch1");
attack=false; // we have attacked once, now dealing damage
checkHitRed();
checkIfDead();
}
if (kickCooldown>0) kickCooldown--; // waiting for cooldown end
else hero.gotoAndStop("still"); // if ends, return hero to "still" posture
}
Character state, divide into three types. As follows.
stage.addEventListener(KeyboardEvent.KEY_DOWN, enterAttack);
stage.addEventListener(KeyboardEvent.KEY_UP, exitAttack);
stage.addEventListener(Event.ENTER_FRAME, onAction);
var characterState:String = "wait"
function enterAttack(evt:KeyboardEvent):void
{
if (evt.keyCode == 84)
{
characterState = "attack";
}
}
function exitAttack(evt:KeyboardEvent):void
{
characterState = "attack_ended";
}
function onAction(evt:Event):void
{
if(characterState == "wait") return;
if(characterState == "attack")
{
hero.gotoAndStop("punch1");
checkHitRed();
checkIfDead();
}
else if(characterState == "attack_ended")
{
hero.gotoAndStop("still");
//Revert to wait state after the attack termination .
characterState = "wait";
}
}
Essentially I am trying to create a game, where the player has to dodge certain items, so far I have a piece of code that randomly adds 3 sharks to the stage.
The idea is that once the player has hit a shark he/she returns to the start location, I have an Action Script file that contains the speed,velocity etc of the shark, the every time the program is run the sharks will appear in a different location.
However, when I attempt to do a collision test of the sharks only one of the sharks respond, I cannot figure out how to make it that all 3 sharks effect the player (square_mc). Any help would be greatly appreciated.
//Pirate game, where you have to avoid particular object and get to the finish line to move onto the final level.
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveMode );
function moveMode(e:KeyboardEvent):void {
//movements for the pirate ship, this will allow the ship to move up,down,left and right.
if (e.keyCode == Keyboard.RIGHT) {
trace("right");
square_mc.x = square_mc.x + 25;
}
else if (e.keyCode == Keyboard.LEFT) {
trace("left");
square_mc.x = square_mc.x - 25;
}
else if (e.keyCode == Keyboard.UP) {
trace("up");
square_mc.y = square_mc.y - 25;
}
else if (e.keyCode == Keyboard.DOWN) {
trace("down");
square_mc.y = square_mc.y + 25;
}
}
//for.fla
//this program uses a for loop to create my Sharks
//a second for loop displays the property values of the sharks
function DisplayShark():void{
for (var i:Number=0;i<3;i++)
{
var shark:Shark = new Shark(500);
addChild(shark);
shark.name=("shark"+i);
shark.x=450*Math.random();
shark.y=350*Math.random();
}
}
DisplayShark();
for(var i=0; i<3;i++){
var currentShark:DisplayObject=getChildByName("shark"+i);
trace(currentShark.name+"has an x position of"+currentShark.x+"and a y position of"+currentShark.y);
}
//here we will look for colliosion detection between the two move clips.
addEventListener(Event.ENTER_FRAME, checkForCollision);
function checkForCollision(e:Event):void {
if (square_mc.hitTestObject(currentShark))
{
trace("The Square has hit the circle");
square_mc.x=50
square_mc.y=50 //these lines of code return the square back to it's original location
}
}
Just move your for loop into the ENTER_FRAME:
addEventListener(Event.ENTER_FRAME, checkForCollision);
function checkForCollision(e:Event):void {
for(var i=0; i<3;i++){
var currentShark:DisplayObject=getChildByName("shark"+i);
if (square_mc.hitTestObject(currentShark))
{
trace("The Square has hit the circle");
square_mc.x=50;
square_mc.y=50;
}
}
}
You can't just go through the for loop once and set the currentShark variable - you'll just end up testing against one shark every time you perform the collision test. Rather, every time you want to check collisions you must loop through all the sharks and do the collision testing.
I want to stop the movieclips movement when it hits a wall (another movieclip).
The example below works, but after the collision the movieclip 'blocks' all movement to the left...
My question to you is, is this a good way and why isn't it working well?
There will be something wrong in this code, but i'm learning.
For now the example with the leftArrow key;
variables to check the key, if it's hitting the walls and if it's moving or not:
var leftArrow:Boolean;
var speed:int = 10;
var hitting:Boolean;
var ismoving:Boolean;
event listeners for the keys/movement and detecting collision:
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener(Event.ENTER_FRAME, walking);
stage.addEventListener(Event.ENTER_FRAME, detectHit);
detecting collision function:
function detectHit(e:Event) :void
{
if(char.hitTestObject(bounds))
{
hitting = true;
}
}
function to the left arrow key:
function keyPressed(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
leftArrow = true;
}
}
function keyReleased(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
leftArrow = false;
}
}
And the reason it's not working is probably here, but I don't understand why not:
function walking(event:Event):void {
if (rightArrow) {
char.x += speed;
}
if (leftArrow && ! hitting) {
char.x -= speed;
}
else
{
ismoving = false
}
if (leftArrow && ! hitting)
char will move if hitting is false. When char.hitTestObject(bounds) is true you are setting hitting to true. You are not setting hitting again to false anywhere. That's why once left wall is hit it stops left movement permanently. You need to figure out suitable condition to set hitting to false again.
Adding an else branch in detectHit should solve the problem.
function detectHit(e:Event):void {
if(char.hitTestObject(bounds))
{
hitting = true;
} else {
hitting = false; // add this
}
}
Allthough Taskinoor's method should work, I would suggest another way to do your hittests.
Since you probably are creating a game (character and bounds), you will have more than one bound. In that case, I would strongly suggest bitmap-hittesting. This way, you can create all your bounds in one movieclip and test for a hit.
I will explain this by using the example of a maze. The maze would then be some lines in a movieclip, randomly put together. If you use HitTestObject and you aren't hitting one of the lines, but your character is over the movieclip, hitTestObject will return true, even though you are not hitting a wall. By using bitmapHitTesting, you can overcome this problem (BitmapHitTest takes transparant pixels into account, whereas hitTestObject does not).
Below you can find an example of how to do bitmapHitTesting. Creating the bitmaps in this function is not necesarry if they do not change shape. In that case, I would suggest placing the code for the bitmapdata in a added_to_stage-method.
private var _previousX:int;
private var _previousY:int;
private var _bmpd:BitmapData ;
private var _physicalBitmapData:BitmapData;
private function walkAround(e:Event):void
{
var _xTo:int = //Calculate x-to-position;
var _yTo:int = //Calculate y-to-position;
//If your character doesn't change shape, you don't have to recalculate this bitmapData over and over.
//I suggest placing it in a ADDED_TO_STAGE-Event in that case.
_bmpd = new BitmapData(char.width, char.height, true, 0);
_bmpd.draw(char);
//If your bounds are static, you don't have to recalculate this bitmapData over and over.
//I suggest placing it in a ADDED_TO_STAGE-Event in that case.
_physicalBitmapData = new BitmapData(bounds.width, bounds.height, true, 0);
_bmpd.draw(bounds);
//The below line is the actual hittest
if(_physicalBitmapData.hitTest(new Point(0, 0), 255, _bmpd, new Point(char.x, char.y), 255))
{
char.x = _previousX;
char.y = _previousY;
}
else
{
char.x = _xTo;
char.y = _yTo;
}
_previousX = char.x;
_previousY = char.y;
}
Look at my hint,
function loop(Event)
{
if(isHit==false)
{
if(isRight==true){head_mc.x+=1}
if(isLeft==true){head_mc.x-=1}
if(isUp==true){head_mc.y-=1}
if(isDown==true){head_mc.y+=1}
}
if(head_mc.hitTestObject(build_mc))
{
isHit=true;
if(isRight==true){head_mc.x-=1}
if(isLeft==true){head_mc.x+=1}
if(isUp==true){head_mc.y+=1}
if(isDown==true){head_mc.y-=1}
}
else
{
isHit=false;
}
}
I use step back to opposite direction instead.