Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (481)
Games in Android Showcase (110)
games submitted by our members
Games in WIP (548)
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  
  smooth method to react to keyboard input?  (Read 1717 times)
0 Members and 1 Guest are viewing this topic.
Offline Usul

Senior Newbie




I hunt bugs


« Posted 2005-08-03 14:41:27 »

hi,

what is the smoothest/fastest way of reacting to user keyboard input (in order to move the  player) ?

Right now I'm doing it like this:
-  user presses a key:  the key which is pressed is remembered (for example:  Globals.isMovingForward = true )
-  a Thread which is always running in the backround checks the pressed keys and reacts by moving the player modell

But that approach is not smooth.  It feels slow and its jerking (I tried different Thread priorities).

How do you do it?

Thanx,  Usul


Some relevant examples of the way I do it:

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  
class EventMouseKeyboard
implements KeyListener
{
    public void keyPressed(KeyEvent e)
    {

        switch( e.getKeyCode() )
        {
            case KeyEvent.VK_W :
                Globals.setMoveForward(true);
            break;
            ...
        }
    }
   
    public void keyReleased(KeyEvent e)
    {
        switch( e.getKeyCode() )
        {
            case KeyEvent.VK_W :
                Globals.setMoveForward(false);
            break;
         }
    }
}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
public class Globals
{
    private static boolean isMoveForward = false;
 
   public static synchronized boolean getMoveForward()
    {
        return isMoveForward;
    }

    public static synchronized void setMoveForward(boolean isPressed)
    {
        isMoveForward = isPressed;
    }
}


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  
public class TheThread
extends Thread
{
    private TransformGroup transformGroup;
    private Transform3D transform3D;

    private double moveRate = 0.2;
    private double rotateAmount = Math.PI / 25.0;

    TheThread(TransformGroup transformGroup)
    {
        this.transformGroup = transformGroup;
        transform3D = new Transform3D();
        setPriority(Thread.NORM_PRIORITY + 2);
    }

    public void run()
    {

        while(true)
        {
            try
            {
                Thread.sleep(30);
            } catch (InterruptedException ex)  {}

            if( Globals.getMoveForward() )
            {
                moveForward();
            }
        }
    }
}

It's times like this that I wish I'd listened to what my dad used to tell me.
Yeah? What was that?
I don't know. I never listened. 
- Dr. Venkman and Mr. Zeddemore
Offline anarchotron

Junior Member




...precious bodily fluids.


« Reply #1 - Posted 2005-08-03 15:58:05 »

I would suggest not to seperate the input gathering and input reacting threads.

In my opinion you should handle input gathering and then input reacting immediately afterwards, in the same thread.  That way input is processed as soon as it arrives, in the same frame that it arrives.
Offline Usul

Senior Newbie




I hunt bugs


« Reply #2 - Posted 2005-08-03 16:13:05 »

I would suggest not to seperate the input gathering and input reacting threads.

In my opinion you should handle input gathering and then input reacting immediately afterwards, in the same thread.  That way input is processed as soon as it arrives, in the same frame that it arrives.

That doesnt work.  Try the following:  type "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".  If you hold down the "A" key, you'll notice that the first "A" is written immediately.  Then there is a short pause before the other "A"'s are written.
And thats the problem with handling the key input immediately.  It doesnt behave natural then.

But I found the workaround:
I'm saving the system time when the key was pressed.  Then I'm computing the way which was left behind by multiplying the speed with the time since the key was pressed.  That way I'm independent of when the Thread is called.  And it works perfectly, the figur now moves smoothly as it should.

But is there any other way?  I dont think that my method is the perfect solution.  So again:  How do you do it?

It's times like this that I wish I'd listened to what my dad used to tell me.
Yeah? What was that?
I don't know. I never listened. 
- Dr. Venkman and Mr. Zeddemore
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline rdcarvallo

Senior Member


Projects: 5
Exp: 15 years


2D Java games forever!


« Reply #3 - Posted 2005-08-03 16:38:21 »

You must not use Threads to do this in Java3D. To change the graph you must use behaviors.
You can set the triggers for it to be time elapsed, frames elapsed, AWT Events (Key, mouse, others), ad others.
Here is a behavior example :
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
public class MoveBehavior extends Behavior{
  TransformGroup target;
  Transform3D t3d;
  WakeupOnElapsedTime trigger; //This time it will be triggered by time
 public MoveBehavior(TransformGroup target){
    this.target = target;
    t3d = new Transform3D();
    trigger = new WakeupOnElapsedTime(1000 / 60);
  }
  public void initialize() {
    this.wakeupOn(trigger);
  }
  public void processStimulus(Enumeration criteria) {
    //the enumeration has all the triggers that meet its condition,
   //In this case is only one, so no iteration to define the response
   //Do the transforms
   t3d.rotX();
    //Set the transform
   target.setTransform(t3d);
     //Set the trigger for the nest time
   this.wakeupOn(trigger);
  }
}


To put the behavior in the scenegraph you use something like this:
1  
2  
3  
4  
5  
  //In the graph creation
 branchGroup.addChild(groupToChange);
  MoveBahavior mv = new MoveBehavior(groupToChange); //The group you want to move
 mv.setSchedulingBounds(new BoundingSphere(new Point3d(),100.0f));
  branchgroup.addChild(mv);


To receive the keyboard events you may use:
1  
    trigger = new WakeupOnAWTEvent(AWTEvent.KEY_EVENT_MASK);


  Read the Javadocs!
  If you have troubles just ask!

  Hope it helps,
      Rafael.-

   
Offline Usul

Senior Newbie




I hunt bugs


« Reply #4 - Posted 2005-08-03 16:42:07 »

Thank you rdcarvallo.

I have no trouble using behaviors.  But you said "you must not use threads".

Whats so wrong with threads?  What disadvantages/risks do they have?

It's times like this that I wish I'd listened to what my dad used to tell me.
Yeah? What was that?
I don't know. I never listened. 
- Dr. Venkman and Mr. Zeddemore
Offline rdcarvallo

Senior Member


Projects: 5
Exp: 15 years


2D Java games forever!


« Reply #5 - Posted 2005-08-03 17:45:54 »

Java3D uses its own threads to run behaviors and rendering. It's not a good idea to change things in middle of their work.
Example:
 Your player object is a Tank(with two shapes Body and Turret)
 The J3D Render Thread begins to draw your Tank, trasnforms the body and draw the polygons
  You change the Transform to move forward
 The J3D Render Thread continues to draw your Tank, trasnforms the turret and draw the polygons
  Now you have a mutant Tank with the turret moved forward!

Other cases could be to change the camera rotation in the middle of the rendering of your scene , etc.

Using behaviors you wil update the transform always in a synchronized way  with the rendering.

   Rafael.-

Offline Usul

Senior Newbie




I hunt bugs


« Reply #6 - Posted 2005-08-03 18:56:08 »

Thats a good point Rafael!

OK, so now I use Behaviors. 

I use a KeyBehavior which reacts on the user pressing or releasing a key.  When he does this, the state of the key is safed along with the time of the action.  But when the Behavioris called because a key is pressed which is already pressed then the time is not safed (because it was already safed).

Then I have a second Behaviorwhich uses WakeupOnElapsedTime in order to act like a thread.  It checks if a key is pressed and then moves the player accordingly.

So, for example, when the user presses the key "w" in order to move forward these things happen:

-  the KeyBehavior class is called and it sets the boolean isMoveForward to true and the long timeMoveForward to the current time
-  the KeyBehaviour class is called again, because the user did not yet release the "w" key:  nothing happens
-  the ThreadBehavior awakes and checkes if isMoveForward is true
-  the ThreadBehavior gets  timeMoveForward and moves the player. 
-  the ThreadBehavior sets timeMoveForward  to the current time
-  all this is repeated until the user releases the "w" key
-  the user releases the "w" key:  KeyBehavior sets isMoveForward to false

It works as smoothly as my previous approach (It feels perfect). 

Does that sound like the right way to do it now?

It's times like this that I wish I'd listened to what my dad used to tell me.
Yeah? What was that?
I don't know. I never listened. 
- Dr. Venkman and Mr. Zeddemore
Offline rdcarvallo

Senior Member


Projects: 5
Exp: 15 years


2D Java games forever!


« Reply #7 - Posted 2005-08-03 20:15:32 »

It seems OK,

     I have an Input object shared for the two behaviors, then the InputBehavior sets the input flags (up,down,left,right,fire, etc) and the ShipMovementBehavior reads them and acts as needed.

     I dont't understand very well your time keeping, but if that gives you fine  smooth results, use it Wink

     Rafael.-
Offline Usul

Senior Newbie




I hunt bugs


« Reply #8 - Posted 2005-08-03 20:43:55 »

Thanx a lot Rafael!

So one problem is solved, lets find out what the future brings.

It's times like this that I wish I'd listened to what my dad used to tell me.
Yeah? What was that?
I don't know. I never listened. 
- Dr. Venkman and Mr. Zeddemore
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.

atombrot (26 views)
2014-08-19 09:29:53

Tekkerue (24 views)
2014-08-16 06:45:27

Tekkerue (23 views)
2014-08-16 06:22:17

Tekkerue (14 views)
2014-08-16 06:20:21

Tekkerue (21 views)
2014-08-16 06:12:11

Rayexar (59 views)
2014-08-11 02:49:23

BurntPizza (38 views)
2014-08-09 21:09:32

BurntPizza (30 views)
2014-08-08 02:01:56

Norakomi (37 views)
2014-08-06 19:49:38

BurntPizza (67 views)
2014-08-03 02:57:17
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
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!