This discussion is archived
6 Replies Latest reply: Oct 2, 2011 12:03 AM by 875749 RSS

Movement Delay JFrame

875749 Newbie
Currently Being Moderated
Hey, guys! I seem to be having a slight little problem with the programs I'm working with. I'm creating a game, and presently I have a world map renderer and a little program that is going to render a level and has a little character in the middle that animates walking left or right depending on which key you press. The world map renderer works fine, except for the fact that when I move using a KeyListener that I put into it and hold a given key down, it moves right away in the right direction, pauses for half a second, and then moves fluidly until I release the key. Does anybody know how I can get rid of that little delay? I'm using a JFrame that encapsulates everything, basically. My other little program that I mentioned does the same thing, only it has to deal with a character animating on the screen. When I press a key, he will begin his animation, pause for half a second, and then continue the animation properly until the key is released. Perhaps this is something common that has to deal with events and listeners and whatnot, and since the code is so long I won't post it just yet unless it's needed just to save space and time. Any help with this issue would be much appreciated. Thanks!

Colton
  • 1. Re: Movement Delay JFrame
    793415 Pro
    Currently Being Moderated
    coltonoscopy wrote:
    ..unless it's needed just to save space and time. ..
    In those cases, I call upon The Doctor.
    ..Any help with this issue would be much appreciated.
    <ol>
    <li>Take a breath. I couldn't manage to wade through that mess of words, try breaking it into paragraphs.
    <li>What is your question?
    </ol>
  • 2. Re: Movement Delay JFrame
    875749 Newbie
    Currently Being Moderated
    Sorry Andrew, I didn't intend to present garble. The main question I have is the following:

    How can I make it so that input to a JFrame results in instant movement or response, with the user pressing the key down, and continues this movement or response without a slight pause like it seems to be doing every time I use a KeyListener within a JFrame?

    Here's an example. I have a program that allows the user to scroll over a 2-dimensional world map in all directions. If the user presses and holds the key down, it will move in the direction, pause for just half a second, and then move continuously after that. What I want is for that pause not to occur and for the movement just to happen fluidly.

    Another example is a program I have that animates a character sprite depending on whether the user presses left or right. The sprite will animate briefly, pause, and then engage in a continued animation. It's the same problem as the world map viewer, and they both are using KeyListeners from within a JFrame.

    I'm not exactly sure if there is a fix to this, but I'm hoping perhaps there could be and that you may know the answer. Thank you for your time.

    (By the way, is there something actually called the "Doctor"?)

    Colton
  • 3. Re: Movement Delay JFrame
    793415 Pro
    Currently Being Moderated
    coltonoscopy wrote:
    ..The main question I have is the following:
    ..
    I'm not exactly sure if there is a fix to this..
    OK I get the basic problem now, but this is something that is best investigated with an SSCCE.
    (By the way, is there something actually called the "Doctor"?)
    No not 'the "Doctor"', but "The Doctor". You know, the time traveling character in Dr Who? He is constantly saving the universe (space) and the time continuum from various bad-guys. Go on, read my quip again in that context - it's funny (in my head at least). ;)
  • 4. Re: Movement Delay JFrame
    875749 Newbie
    Currently Being Moderated
    Oh, LOL, now I get your reference. That is quite funny, indeed. I like the warped interpretation of space and time and how it magically created an altogether new context there ;]

    Anyways, here's my attempt at providing what relevant code I'm believing will aid enough to hopefully pinpoint the problem. I'm just now getting into larger projects than I've ever been used to, so please bear with me and provide any advice you think would be necessary in regard to my example providing. :] And thanks for looking it over!

    Here's the constructor for what will eventually be rendering a level for me, but which right now is only rendering the character that animates in the middle of the screen:
    // CONSTRUCTOR
        public LevelRenderer()
        {
            setPreferredSize(new Dimension(1280, 768));
    
            setFocusable(true);
            requestFocus();
            
            setResizable(false);
            
            addKeyListener( new KeyAdapter() 
            {
                public void keyPressed(KeyEvent e)
                { 
                    processKey(e);  
                }
            });
            
            myPlayer = new Player();
            Level myLevel = new Level("obstaclemap");
            tileSheet = loadImage("obstacletiles.png");
            tiles = splitImage(tileSheet, 1, 2);
            
            endGame = false;
            
            buffer = new BufferedImage(1280, 768, BufferedImage.TYPE_INT_ARGB);
            
            buffer.createGraphics();
            gr = buffer.getGraphics();
            gr.setColor(Color.BLACK);
            
            cameraView = new BufferedImage(1280, 768, BufferedImage.TYPE_INT_ARGB);
            
            levelX = 700;
            levelY = 400;
            
            offsetX = 0;
            offsetY = 0;
        }
    Then I have here the run method for the same class:
    // Run method for class
        public void run(DisplayMode dm)
         {     
            setBackground(Color.WHITE);
              s = new Screen();
            
            try
            {   
                s.setFullScreen(dm, this);
            }
            catch (Exception ex)
            {
                System.out.println("Error creating rendered tiles!");
            }
              
              while (!endGame)
            {
                try
                {
                    Thread.sleep(2);
                    cameraView = renderCamera();
                    myPlayer.animatePlayer();
                    repaint();
                }
                catch (Exception ex) 
                { 
                    System.out.println("Couldn't read input!");
                }
            }
            
              s.restoreScreen();
         }
    Lastly for that class is the method that processes keyboard input:
    // method to handle inputs and adjust the player accordingly
        public void processKey(KeyEvent e)
        {
            int keyCode = e.getKeyCode();
            boolean moved = false;
            int xDisplace, yDisplace;
            
            // termination key
            if (keyCode == KeyEvent.VK_ESCAPE)
            {
                endGame = true;
            }
            
            // 1 - up
            // 2 - left
            // 3 - right
            // 4 - down
            // 5 - jump
            
            if (keyCode == KeyEvent.VK_UP)
            {
                myPlayer.updatePlayer(0);
            }
            if (keyCode == KeyEvent.VK_LEFT)
            {
                myPlayer.updatePlayer(1);
            }
            if (keyCode == KeyEvent.VK_RIGHT)
            {
                myPlayer.updatePlayer(2);
            }
            if (keyCode == KeyEvent.VK_DOWN)
            {
                myPlayer.updatePlayer(3);
            }
            if (keyCode == KeyEvent.VK_SPACE)
            {
                myPlayer.updatePlayer(4);
            }
        }
    All of that code works hand-in-hand with the Player class, which you'll probably need to see the constructor and a couple methods from:
    // CONSTRUCTOR
        public Player()
        {
            playerSheet = makeColorTransparent("playersheet1.png", 0xFFFF65F6);
            playerFrames = splitImage(playerSheet, 4, 2);
            movementTimer = System.nanoTime();
            stillTimer = movementTimer;
            currentState = PlayerState.STILL_LEFT;
            lastState = PlayerState.STILL_LEFT;
        }
        
        // this method will draw to whatever graphics context is passed to the method (game window)
        public void drawPlayer(Graphics gr, int x, int y)
        {
            gr.drawImage(playerFrames[currentIndex], x, y, null);
        }
    
    // method to update the player based on user input
        public void updatePlayer(int input)
        {
            // update the still timer to manage when the last key press was
            stillTimer = System.nanoTime();
            
            switch (input)
            {
                // up
                case 0:
                    break;
                // left
                case 1:
                    if (currentState != PlayerState.MOVE_LEFT)
                    {
                        movementTimer = System.nanoTime();
                    }
                    currentState = PlayerState.MOVE_LEFT;
                    lastState = PlayerState.MOVE_LEFT;
                    break;
                // right
                case 2:
                    if (currentState != PlayerState.MOVE_RIGHT)
                    {
                        movementTimer = System.nanoTime();
                    }
                    currentState = PlayerState.MOVE_RIGHT;
                    lastState = PlayerState.MOVE_RIGHT;
                    break;
                // down
                case 3:
                    break;
                // jump
                case 4:
                    break;
            }
        }
        
        // method to manage the player's animation
        public void animatePlayer()
        {   
            // if it's been a little while since the last key press, make the player still
            if (System.nanoTime() - stillTimer > 100000000)
            {
                if (lastState == PlayerState.MOVE_LEFT)
                {
                    currentState = PlayerState.STILL_LEFT;
                }
                else
                {
                    currentState = PlayerState.STILL_RIGHT;
                }
            }
            
            switch (currentState)
            {
                case STILL_LEFT:
                    currentIndex = 0;
                    break;
                case STILL_RIGHT:
                    currentIndex = 4;
                    break;
                case MOVE_LEFT:
                    // if set to a still frame, set it to start running left
                    if (currentIndex == 0 || currentIndex == 4)
                    {
                        currentIndex = 1;
                    }
                    // if a 300 nanosecond gap has passed, allow the next frame
                    if (System.nanoTime() - movementTimer > 100000000)
                    {
                        if (currentIndex == 1)
                        {
                            currentIndex = 2;
                        }
                        else
                        {
                            currentIndex = 1;
                        }
                        
                        movementTimer = System.nanoTime();
                    }
                    break;
                case MOVE_RIGHT:
                    // if set to a still frame, set it to start running right
                    if (currentIndex == 0 || currentIndex == 4)
                    {
                        currentIndex = 5;
                    }
                    // if a 300 nanosecond gap has passed, allow the next frame
                    if (System.nanoTime() - movementTimer > 100000000)
                    {
                        if (currentIndex == 5)
                        {
                            currentIndex = 6;
                        }
                        else
                        {
                            currentIndex = 5;
                        }
                        
                        movementTimer = System.nanoTime();
                    }
                    break;
                case JUMP:
                
                    break;
            }
        }
    I trimmed as much from the classes in showing them as I could, disregarding all of the methods that do things like load images and do anything non-related to the issue at hand. Thank you for your time, and I hope this aids a little bit in making the problem evident.

    Colton

    Edited by: coltonoscopy on Oct 1, 2011 3:55 PM
  • 5. Re: Movement Delay JFrame
    anotherAikman Explorer
    Currently Being Moderated
    This is called typematic delay(or something, I keep forgetting). It´s there so when you press a key, you don´t have the character showing up ten times.

    To circumnavigate it, you can use booleans that are toggled when a key is pressed or released. Then, move your figure according to the booleans.

    So if KeyEvent.VK_RIGHT is pressed, you set your movementRight boolean to true. if it is released, you set it to false. In your main loop, move your figure right if movementRight is true.

    I use a class with a HashMap<Integer, Boolean> to map the keycodes to their states, but there are lots of possibilities, I guess.
  • 6. Re: Movement Delay JFrame
    875749 Newbie
    Currently Being Moderated
    Brilliant! Thank you so much, Aikman. Got it working perfectly, and it was actually very easy. You've been very helpful.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points