keyboard input problem

in my new 4k game th ekeyboard is very slow to respond keypresses. I was following the same ideia from kevglass source code of Neb4k:


public N() {
                super("N");
            
            setSize(640,510);
            setResizable(false);
            show();

            enableEvents(56);
            
            createBufferStrategy(2);
            BufferStrategy strategy = getBufferStrategy();

            long lastLoopTime = System.currentTimeMillis();
            
            while (true)
            {
                  int delta = (int) (System.currentTimeMillis() - lastLoopTime);
                  logic(delta);
                  
                  lastLoopTime = System.currentTimeMillis();
                  
                  draw((Graphics2D) strategy.getDrawGraphics());
                  
                  strategy.show();
                  if (!isVisible()) {
                        System.exit(0);
                  }
            }
}

In the logic method I test the controls variable to check what key was pressed.

The code for keyboard is:


protected void processKeyEvent(KeyEvent e)
      {
            int[] keys = new int[] {KeyEvent.VK_LEFT,KeyEvent.VK_RIGHT,KeyEvent.VK_UP,KeyEvent.VK_DOWN,KeyEvent.VK_SPACE};
            for (int i=0;i<keys.length;i++) 
            {
                  if (e.getKeyCode() == keys[i]) {
                        controls[i] = e.getID() == KeyEvent.KEY_PRESSED;
                  }
            }
            if (e.getKeyCode() == 27) 
            {
                  System.exit(0);
            }
      }

Do u have some tip about it? Why the keypresses take too long to respond with this structure.

Guess it’s because you have no Thread.sleep or yield in your game loop, but it’s only a guess. :slight_smile:
Or perhaps because you create new array each time you listen to the keypressed event, but I guess this is not the problem too :stuck_out_tongue:

so anyone has a tip? Hey, Kev what about you? Neb4k is very smooth controlled by the keyboard and my loop above is very similiar to yours, I think the only difference is that I call logic just one time, but I think that is does not matter with the keyboard input stuff. In the end of the loop I have added a Thread.sleep(1) and the response of the keyboard got much better, but I could not understand why in your there is no Thread.sleep or Thread.yield and the responsive of the keyboard is very good. ???

actually I would like to run my game as fast as possible without having to put a Thread.sleep… If I add a Thread.sleep(1) the reponse is good, but without it is very bad… Is there any other way of doing this without using Thread.sleep? I am wasting this 1ms… :frowning:

I am wasting this 1ms

No. The minimum amount you can sleep is actually (usually) ~5msec.

Try Thread.yield();

Don’t use Thread.sleep() with values of less than 10ms! It will cause the Windows’ clock to speed up and can cause all sorts of drift issues! Loop on Thread.yield() instead.

tks jbanes and onyx I will try using Thread.yield instead of Thread.sleep. I’ve got curious about this:

[quote]It will cause the Windows’ clock to speed up and can cause all sorts of drift issues! Loop on Thread.yield() instead.
[/quote]
What kind of issues?Maybe damage my processor?

[quote]What kind of issues?Maybe damage my processor?
[/quote]
Erm… no. What happens is that the JVM reprograms the clock crystal to produce a different frequency. This allows the Windows scheduler to return the thread faster, but also results in some nasty side effects. In particular, the system clock runs off of that crystal. As a result, the Windows clock will temporarily speed up every time you sleep with a value of less than 10ms.

On a micro level, this can throw off your game’s timing because of an inaccurate time. At a macro level, you’ll cause the user’s clock to slowly get ahead of other clocks in their house. You may have already noticed it on your own computer.

now I understand why my clock computer is always wrong… ;D I will remove all Thread.sleep(1) in my games and change to Thread.yield() ;D Tks

ok…the Thread.yield() did not give me the result that I expected…the keyboard is too slow to respond… then I modify the code:


 public N() {
      super("N");
   
  setSize(640,510);
  setResizable(false);
  show();
 
  enableEvents(56);
   
  createBufferStrategy(2);
  BufferStrategy strategy = getBufferStrategy();
 
  while (true)
  {
   logic();
   
   draw((Graphics2D) strategy.getDrawGraphics());
   
   strategy.show();
   Toolkit.getDefaultToolkit().sync();
   }
  }
} 

Please note the method sync() of the Toolkit…

As u can see, there is no timing code…The game got very fast and the keyboard responds well…I am using frame based movement. I have a maze like Pacman where each square is 15x15 so I have to move my player in a speed that is a multiple of 15 for the collision (check if the player can enter in the corridor) works correctly.

what exactly does Toolkit.getDefaultToolkit().sync();; ? Do I need to have it in my main loop?

Now I am using the following code that I have found on the sun’s forum:


import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
public class Game extends Frame implements Runnable, KeyListener{
      static final int FPS = 60;
   static final int SCREEN_WIDTH = 640,
                    SCREEN_HEIGHT = 480,
                    BIT_DEPTH = 16,
                    REFRESH_RATE = 60;
 
   public Game(boolean fullscreen)   {
      GraphicsConfiguration gc = getGraphicsConfiguration();
      GraphicsDevice gd = gc.getDevice();
      if(fullscreen) {
         setUndecorated(true);
         gd.setFullScreenWindow(this);
         gd.setDisplayMode(new DisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,BIT_DEPTH,REFRESH_RATE));
      }
      else {
         setBounds(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
         setVisible(true);
      }
 
      addKeyListener(this);
 
      Thread t = new Thread(this);
      t.start();
   }
 
   public void run() {
      final int NANO_FRAME_LENGTH = 1000000000/FPS;
      long startTime = System.nanoTime();
      int frameCount = 0;
      while(controls[KeyEvent.VK_ESCAPE]==0) {
         BufferStrategy bs = getBufferStrategy();
         Graphics g = bs.getDrawGraphics();
 
         //misc rendering
         g.setColor(new Color(frameCount&0xFFFFFF));
         g.fillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
         //misc rendering;
 
         bs.show();
         frameCount++;
         // note:System.nanoTime in 1.5+
         while((System.nanoTime()-startTime)/NANO_FRAME_LENGTH <frameCount) {
            Thread.yield();
         }
      }
 
      dispose();
   }
 
   int [] controls = new int[256];
 
   public void keyPressed(KeyEvent ke) {
      controls[ke.getKeyCode()] = 1; //key handlers should ONLY set flags. The interpretation of the flags is best left to the game loop
   }
 
   public void keyReleased(KeyEvent ke)   {
      controls[ke.getKeyCode()] = 0; //key handlers should ONLY set flags. The interpretation of the flags is best left to the game loop
   }      public void keyTyped(KeyEvent ke) {}
 
   public static void main(String [] args) {
      new Game(false);
   }
}


What do u think about it? I think it is working better now.