简体   繁体   中英

Flash As3 key press issue

Ok so my main problem here is that the KeyboardEvent for flash is wayyy to slow. Lets say i press the left arrow. For some reason, the movement delays and then moves. When I was doing double jumping or jumping at all, I had to hold the button rather than do a single press. My question is is there a way for flash to detect a single press of any key and how do I solve the movement delay for keyCode?

import flash.ui.Keyboard;
import flash.events.KeyboardEvent;
import flash.events.Event;

//Initialized variables

var theKey:KeyObject = new KeyObject(stage);//Help the stage checks for keypressed objects
var hspeed:Number = 0;// horizontal speed
var vspeed:Number = 0;// vertical speed
var gravity:Number = 2;//Gravity
var friction:Number  = .5;//Friction
var ground:int = 800;//Bottom of the stage
var JumpMax:Number = 0;//Double jump

//All Booleans (Mainly player states)
var aDown:Boolean = false;//Press left key
var dDown:Boolean = false;//Press right key
var Jumped:Boolean = false;//Player in jumping state
var AttackMode:Boolean = false;//Player in attacking state
var CrouchMode:Boolean = false;//Player in crouched state
var RightSide:Boolean = false;//Player hitting right side of block
var LeftSide:Boolean = false;//Player hitting left side of block
var DownSide:Boolean = false;//Player hitting the top of block
var UpSide:Boolean = false;//Player hits bottom of block

ultraDaimyo.gotoAndStop("idleDaimyo");

stage.addEventListener(KeyboardEvent.KEY_DOWN, keyYeet);
function keyYeet(e:KeyboardEvent):void 
{
if(e.keyCode == Keyboard.D)
    {
        dDown = true;

    }
if(e.keyCode == Keyboard.A)
    {
        aDown = true;

    }
if(e.keyCode == Keyboard.C)
  {
    AttackMode = true;

  }
if(e.keyCode == Keyboard.W || Jumped == true)
  {
    Jumped = true;
  }
 }

 stage.addEventListener(KeyboardEvent.KEY_UP, keyNot);
 function keyNot(e:KeyboardEvent):void 
{
if(e.keyCode == Keyboard.D)
 {
    dDown = false; 
 }
if(e.keyCode == Keyboard.A)
 {
    aDown = false; 
 }
if(e.keyCode == Keyboard.C)
 {
    AttackMode = false; 
 }
if(e.keyCode == Keyboard.W)
 {
    Jumped = false; 
 }
 }


 stage.addEventListener(Event.ENTER_FRAME, gameCycle);
 function gameCycle(e:Event):void
{
hspeed *= friction;
ultraDaimyo.x += hspeed;
ultraDaimyo.y += gravity;

if(AttackMode)
      {
        ultraDaimyo.gotoAndStop("attackDaimyo");
        ultraDaimyo.x += 5;
        if(ultraDaimyo.scaleX == -1)
          {
            ultraDaimyo.gotoAndStop("attackDaimyo");
            ultraDaimyo.x -= 10;
          }
      }
if(Jumped == true)
  {
     ultraDaimyo.y -= 30;
     ultraDaimyo.gotoAndStop("jumpDaimyo");
  } 
if(dDown)
  {
     hspeed += 20;
     ultraDaimyo.gotoAndStop("runDaimyo");
     ultraDaimyo.scaleX = 1;
  }
if(aDown)
  {
     hspeed -= 20;
     ultraDaimyo.gotoAndStop("runDaimyo");
     ultraDaimyo.scaleX = -1;
  }
if(!aDown && !dDown && !AttackMode && !Jumped)
  {
    ultraDaimyo.gotoAndStop("idleDaimyo");
  }


if(ultraDaimyo.x - ultraDaimyo.width/2 < 0)//If the player goes past the left side
  {
    ultraDaimyo.x = ultraDaimyo.width/2;
  }
if(ultraDaimyo.x + ultraDaimyo.width/2 > 1400)//If the player goes past right
  {
    ultraDaimyo.x = 1400 - ultraDaimyo.width/2;//Player cant go past
  } 
if(ultraDaimyo.y + ultraDaimyo.height/2 < floor && Jumped)//If we are above the floor
  {
    if(Jumped)
      {
          ultraDaimyo.gotoAndStop("jumpDaimyo");
      }
    gravity++;//Accelerate gravity in the process
  }
if(ultraDaimyo.y + ultraDaimyo.height/2 > floor)
  {
    Jumped = false;//If we are on the floor then we're not jumping
    gravity = 0;//Gravity can no longer be applied
    ultraDaimyo.y = floor - ultraDaimyo.height/2;//Player sits on top of the floor
  }
}

KeyboardEvent does not fire continuously, because that would make it hard to detect single keystrokes.

What you have to do is use the KeyboardEvent to only change the speed variable, but apply the speed to the position variable in a different continuous Event , namely Event.ENTER_FRAME .

I created an example based on your code:

import flash.ui.Keyboard;
import flash.events.KeyboardEvent;
import flash.events.Event;

//Initialized variables
var speedX:Number = 0;

stage.addEventListener(KeyboardEvent.KEY_DOWN, keyYeet);

function keyYeet(e:KeyboardEvent):void
{
    if(e.keyCode == Keyboard.D)
    {
        speedX = 20;
    }

    if(e.keyCode == Keyboard.A)
    {
        speedX = -20;
    }
}

stage.addEventListener(KeyboardEvent.KEY_UP, keyNot);

function keyNot(e:KeyboardEvent):void
{
    if(e.keyCode == Keyboard.D || e.keyCode == Keyboard.A)
    {
        speedX = 0;
    }
}

addEventListener(Event.ENTER_FRAME, gameCycle);

function gameCycle(e:Event):void
{
    ultraDaimyo.x += speedX;
}

The idea is to set the speed when the key goes down to a certain value and to set it back to 0 when the key goes back up.

The speed is continuously applied to the position.


from the comments:

Please double check your first sentence.

Sure enough there was a typo, but the content is as I intended it to be.

the result is continous firing = continuous movement.

Not for me. Chances are this is different for different (keyboard) hardware or software (operating system, flash runtime). Other people have similar experiences as can be seen in these duplicates of the question at hand.

Let's not look at display objects moving around and comparing opinions about whether they move continuously or not. Let's collect some comparable data instead.

Here's a little document class that counts the delay between 5 occurrences of the KEY_DOWN event.

To use it, make sure the application has focus and press down any button until the trace appears in the output panel.

Releasing the key resets the array and another key can be held down.

package 
{
    import flash.utils.getTimer;
    import flash.events.KeyboardEvent;
    import flash.display.Sprite;

    public class Main extends Sprite 
    {
        private var oldTime:Number = 0;
        private var deltaTimes:Array = [];

        public function Main() 
        {
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
            stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
        }

        private function onKeyDown(e:KeyboardEvent):void
        {
            var currentTime:Number = getTimer();

            // collect 5 time differences between two consecutive occurrences of this event

            if (deltaTimes.length < 5)
            {
                deltaTimes.push(currentTime - oldTime)    
            }
            else
            {
                stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
                trace(deltaTimes);
            }

            oldTime = currentTime;           
        }

        private function onKeyUp(e:KeyboardEvent = null):void
        {
            deltaTimes = [];

            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
        }
    }
}

Here are my results:

7584,499,49,51,50
2117,500,50,50,50
1786,500,50,50,49
1375,499,48,50,52
1395,500,50,50,50
1385,500,50,50,50
1243,501,47,52,49
2167,501,49,50,50
1587,500,50,50,50
3871,500,50,48,53
2237,500,49,51,49
1715,500,47,53,50

Three important things can be observed:

  1. The first value is obviously not interesting as it is the time between two button presses. (I just wanted to put this together quickly)
  2. The second value is roughly 500ms, which means between the first and second occurrence of the event, half a second of time passed.
  3. The last 3 values are roughly 50ms, which is much shorter than 500ms. This is the rate at which the event will keep firing as long as the key is pressed

The code I provided in my answer above fixes this problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM