Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (579)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Problem with input events in Java6?  (Read 1907 times)
0 Members and 1 Guest are viewing this topic.
Offline appel

JGO Wizard


Medals: 49
Projects: 5


I always win!


« Posted 2006-12-17 07:32:36 »

I've made a little demo that shows that the input handling in Java 6 seems to freeze at times. Although I'm using a rather perculiar input-handling schema, it is not the source of the problem (works fine in Java 5).

It seems that events get bottlenecked somewhere, and then they start to flow again. As you can see in my application, the ACTIONS text contains a integer defining what keys are currently pressed...they sometimes get "stuck" at some value.

The application ran fine in many cases, but as I kept running it, I kept noticing this "input lag". It's like the application stutters.

(If you don't get it, try running it, close it, and run it again immediatly).

My test application (a basic template for a 4k game):

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Transparency;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.Random;

import javax.swing.JFrame;

public class InputTest extends JFrame {
   static final int W = 1024;
   static final int H = 768;
   
   static int ACTIONS = 0;
   static final int A_LEFT = 1;
   static final int A_RIGHT = 2;
   static final int A_FORWARD = 4;
   static final int A_REVERSE = 8;
   static final int A_MOVERIGHT = 16;
   static final int A_MOVELEFT = 32;
   static final int A_WARP = 64;
   static final int[] GRAP_KEY_TYPES = {A_FORWARD,A_MOVELEFT,A_REVERSE,A_MOVERIGHT,A_WARP};
   static final int[] GRAP_KEY_EVENTS = { KeyEvent.VK_W, KeyEvent.VK_A, KeyEvent.VK_S, KeyEvent.VK_D, KeyEvent.VK_E} ;

   public InputTest() {
     
      setTitle("Input Test");
      setSize(W,H);
      setResizable(false);
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      enableEvents(AWTEvent.KEY_EVENT_MASK|AWTEvent.MOUSE_EVENT_MASK);
      show();

      createBufferStrategy(2);
      BufferStrategy strategy = getBufferStrategy();
      Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
     
      long lastLoopTime = System.nanoTime();
      int frames = 0;
      int acc = 0;
      int fps = 0;
      int MOUSE_X = 0, MOUSE_Y = 0;
      Random rand = new Random(System.nanoTime());
     
      BufferedImage background = new BufferedImage(W,H,Transparency.OPAQUE);
      ((Graphics2D)background.getGraphics()).setBackground(Color.BLACK);
     
      while(true) {
         acc += (System.nanoTime() - lastLoopTime) / 1000000f;
         lastLoopTime = System.nanoTime();
         if(acc >= 1000) {
            acc -= 1000;
            fps = frames;
            frames = 0;
         }
         frames++;
         
         
         try {
            MOUSE_X = getMousePosition().x;
            MOUSE_Y = getMousePosition().y;
         } catch(Exception e) {
         }
         
         g.drawImage(background,0,0,null);

         g.setColor(Color.darkGray);
         for(int i = 0; 100 > i; i++) {
            g.drawRect(rand.nextInt(W),rand.nextInt(H),10,10);
         }
         
         g.setColor(Color.WHITE);
         g.drawString("Actions: " + ACTIONS, 100, 100);
         g.drawString("FPS: " + fps, 250,100);
         g.drawString("Mouse: " + MOUSE_X+","+MOUSE_Y, 450,100);
         
         
         strategy.show();
         
         if (!isVisible()) {
            System.exit(0);
         }
         
         
      }
     
   }
   
   public static void main(String[] args) {
      new InputTest();
   }
   
   protected void processKeyEvent(KeyEvent e) {
      for(int i = 0; GRAP_KEY_EVENTS.length > i; i++) {
         if(e.getKeyCode() == GRAP_KEY_EVENTS[i]) {
            ACTIONS|=(e.getID()==KeyEvent.KEY_PRESSED)?GRAP_KEY_TYPES[i]:0;
            ACTIONS^=(e.getID()==KeyEvent.KEY_RELEASED)?GRAP_KEY_TYPES[i]:0;
            break;
         }
      }
   }
   
   protected void processMouseEvent(MouseEvent e) {
      if(e.getButton() == MouseEvent.BUTTON1) {
         ACTIONS|=(e.getID()==MouseEvent.MOUSE_PRESSED)?A_LEFT:0;
         ACTIONS^=(e.getID()==MouseEvent.MOUSE_RELEASED)?A_LEFT:0;
      }
      else if(e.getButton() == MouseEvent.BUTTON3) {
         ACTIONS|=(e.getID()==MouseEvent.MOUSE_PRESSED)?A_RIGHT:0;
         ACTIONS^=(e.getID()==MouseEvent.MOUSE_RELEASED)?A_RIGHT:0;
      }
   }

}

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline appel

JGO Wizard


Medals: 49
Projects: 5


I always win!


« Reply #1 - Posted 2006-12-17 08:50:19 »

Here is the same application, using boolean flags for the input keys.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Transparency;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.Random;

import javax.swing.JFrame;

public class InputTest2 extends JFrame {
   static final int W = 1024;
   static final int H = 768;
   

   public boolean forward;
   public boolean reverse;
   public boolean right;
   public boolean left;
   

   public InputTest2() {
     
      setTitle("Input Test");
      setSize(W,H);
      setResizable(false);
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      enableEvents(AWTEvent.KEY_EVENT_MASK|AWTEvent.MOUSE_EVENT_MASK);
      show();

      createBufferStrategy(2);
      BufferStrategy strategy = getBufferStrategy();
      Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
     
      long lastLoopTime = System.nanoTime();
      int frames = 0;
      int acc = 0;
      int fps = 0;
      int MOUSE_X = 0, MOUSE_Y = 0;
      Random rand = new Random(System.nanoTime());
     
      BufferedImage background = new BufferedImage(W,H,Transparency.OPAQUE);
      ((Graphics2D)background.getGraphics()).setBackground(Color.BLACK);
     
      while(true) {
         acc += (System.nanoTime() - lastLoopTime) / 1000000f;
         lastLoopTime = System.nanoTime();
         if(acc >= 1000) {
            acc -= 1000;
            fps = frames;
            frames = 0;
         }
         frames++;
         
         
         try {
            MOUSE_X = getMousePosition().x;
            MOUSE_Y = getMousePosition().y;
         } catch(Exception e) {
         }
         
         g.drawImage(background,0,0,null);

         g.setColor(Color.darkGray);
         for(int i = 0; 100 > i; i++) {
            g.drawRect(rand.nextInt(W),rand.nextInt(H),10,10);
         }
         
         g.setColor(Color.WHITE);
         g.drawString("Forward: " + forward, 100, 100);
         g.drawString("Reverse: " + reverse, 100, 120);
         g.drawString("Right: " + right, 100, 140);
         g.drawString("Left: " + left, 100, 160);
         g.drawString("FPS: " + fps, 250,100);
         g.drawString("Mouse: " + MOUSE_X+","+MOUSE_Y, 450,100);
         
         
         strategy.show();
         
         if (!isVisible()) {
            System.exit(0);
         }
         
         
      }
     
   }
   
   public static void main(String[] args) {
      new InputTest2();
   }
   
   protected void processKeyEvent(KeyEvent e) {
     
      if(e.getKeyCode() == KeyEvent.VK_A) {
         if(e.getID() == KeyEvent.KEY_PRESSED) {
            left = true;
         } else if(e.getID() == KeyEvent.KEY_RELEASED) {
            left = false;
         }
      } else if(e.getKeyCode() == KeyEvent.VK_D) {
         if(e.getID() == KeyEvent.KEY_PRESSED) {
            right = true;
         } else if(e.getID() == KeyEvent.KEY_RELEASED) {
            right = false;
         }
      } else if(e.getKeyCode() == KeyEvent.VK_W) {
         if(e.getID() == KeyEvent.KEY_PRESSED) {
            forward = true;
         } else if(e.getID() == KeyEvent.KEY_RELEASED) {
            forward = false;
         }
      } else if(e.getKeyCode() == KeyEvent.VK_S) {
         if(e.getID() == KeyEvent.KEY_PRESSED) {
            reverse = true;
         } else if(e.getID() == KeyEvent.KEY_RELEASED) {
            reverse = false;
         }
      }
     

   }
   
   protected void processMouseEvent(MouseEvent e) {
   }

}

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline CommanderKeith
« Reply #2 - Posted 2006-12-17 19:40:57 »

I'd say you just have a threading issue, but its odd that it doesn't stuff up similarly on Java 5.

Your game loop thread never sleeps so its just hogging processor time so the Event Dispatch Thread (EDT) never has time to process any events.  It will happen with many computers on the java 5 VM too.  You need to call Thread.sleep(1) in every frame (some people get away with Thread.yield() but I've found that some computers don't respond to it), then I guarantee that the events will be processed and won't build up in the EDT  Smiley.

Keith

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Eliwood

Junior Member




Stencyl


« Reply #3 - Posted 2006-12-18 09:58:04 »

I'm experiencing the same problem in my game, but not nearly as bad as what's described here, and it does occur in Java 5 and 6, but moreso in Java 6. Does this Thread wait stuff actually solve it? The problem is that it's so slightly unresponsive that it's hard for me to detect whether it's really there or not.

Edit: Tried it, and I honestly don't notice a difference one way or the other.

Offline Eliwood

Junior Member




Stencyl


« Reply #4 - Posted 2006-12-21 08:51:43 »

Now, the problem is even worse in the J2D version of my project where I see exactly what the original poster was complaining about, but when I use LWJGL, everything is perfect. The fix posted above doesn't work at all. What's going on?

Offline appel

JGO Wizard


Medals: 49
Projects: 5


I always win!


« Reply #5 - Posted 2006-12-21 09:10:32 »

I feel it's kind of a *hack* to use Thread.sleep() ... it just doesn't feel "right". And if the game is running at rather low FPS, then the fps is even going to be worse using Thread.sleep().

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline SluX

Junior Member





« Reply #6 - Posted 2006-12-21 12:02:01 »

Well u definitely have to make the preemption of the rendering thread...u could possibly achieve that by lowering the rendering thread's priority, tho i doubt that any1 has ever used this apporach....yield of sleep would do just fine..

"Intelligence is the most beautiful gift and the greatest temptation which one life can receive from the gods."Me Cheesy
Play strategic football
Offline Jamison

Junior Member




We're all idiots in one way or another.


« Reply #7 - Posted 2007-01-13 17:16:53 »

....yield of sleep would do just fine..
I've come across the same problem appel has, however, it has nothing to do with the key events. It's the rendering Thread (as stated by CommanderKeith). And, SluX, yield() does not do a thing for me here. Thread.sleep(1); works here but causes a considerable large amount of speed drop. In Java 1.6, I can get 2,700+ frames per second, but whening using Thread.sleep() I get about 500 frames per second. However, after doing a couple of speed tests, I can render quite a lot of stuff and still maintain that same framerate. And if you figure it, what game have you ever played on JGF in which had an FPS counter that ran at the maximum, did it ever exceed about 500 FPS? For me, I almost always get between 400-600 frames per second running other people's games (not just on JGF either), with even just a basic window structure with double buffering. The reason I always got that framerate a lot was probally because they had to use Thread.sleep() to prevent problems. It also prevents the CPU from running at 100%, which frees system memory for other applications. One thing that would increase the speed more when using Thread.sleep() is to set your Thread's priority to maximum. On my system, when using max. priority, I can get about 30-40 more frames per second than when using normal Thread priority.

Hope my information helped. (Oh, by the way, sorry for such a late reply...)

I don't like you. Check out my site Smiley www.gamedevforums.com
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (38 views)
2014-04-15 18:08:23

BurntPizza (34 views)
2014-04-15 03:46:01

UprightPath (50 views)
2014-04-14 17:39:50

UprightPath (32 views)
2014-04-14 17:35:47

Porlus (49 views)
2014-04-14 15:48:38

tom_mai78101 (71 views)
2014-04-10 04:04:31

BurntPizza (130 views)
2014-04-08 23:06:04

tom_mai78101 (230 views)
2014-04-05 13:34:39

trollwarrior1 (193 views)
2014-04-04 12:06:45

CJLetsGame (200 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!