0

I'm working on a game in Java. In the game, the player will be able to control a tank that moves on the screen using Key Bindings. Each arrow-button moves the tank in a different direction.

I'd like to know, if the way I used Key Bindings in the program, is correct and isn't supposed to cause problems with the EDT or with anything else later on.

I will explain in short the structure of the program, and how I used Key Bindings.

  • There's a Board class, a class that extends JPanel and has most of the game logic. It also displays the graphics.

  • There's a KeyBindingsRunnabel class, a class that implements Runnable. This class has all the KeyBindings code.

  • Board contains the game-loop. The game loop happens inside a thread. In the thread, but before the game loop, a new thread is created and started, that thread runs KeyBindingsRunnabel.

(There's also a Main class that extends JFrame and creates an instance of Board, but that's irrelevant).

I'll demonstrate all of this in short:

Here is the code for the KeyBindingsRunnabel class:

public class KeyBindingsRunnable implements Runnable {

    Board b;

    Action upAction,leftAction;
    InputMap inputMap;
    ActionMap actionMap;

    public KeyBindingsRunnable (Board b){

        this.b = b;
        inputMap = b.getInputMap();
        actionMap = b.getActionMap();

    public void run() {

        leftAction = new AbstractAction(){
            public void actionPerformed(ActionEvent e){
                // Code to move tank left.
            }
        };

        rightAction = new AbstractAction(){
            public void actionPerformed(ActionEvent e){
                // Code to move tank right.
            }
        };

        inputMap.put(KeyStroke.getKeyStroke("LEFT"),"leftAction");
        inputMap.put(KeyStroke.getKeyStroke("RIGHT"),"rightAction");

        actionMap.put("leftAction",leftAction);
        actionMap.put("rightAction",rightAction);

    }

}

The way the Board class uses KeyBindingsRunnable is as follows:

The Board class also implements Runnable. It contains a thread declaration in it's constructor:

Thread gameloop = new Thread(this);
gameloop.start();

In Board's run() method, there are two thing: a game-loop, and before the loop, the creation of a new thread that runs KeyBindingRunnable.

The run() method of Board looks like this:

public void run(){

    Thread keyBindingsThread = new Thread(new KeyBindingRunnable(this));
    keyBindingsThread.start();

         while(gameIsRunning){
         // The loop.
         // .....
         }

}

My question is: Is this the correct way to use Key Bindings without interupting with the EDT, and in general the correct way?

Is there a more effecient/safer/shorter way of using Key Bindings in a 2D game?

Thanks a lot :)

user3150201
  • 1,901
  • 5
  • 26
  • 29
  • please why is there Runnable instead of Swing Timer – mKorbel Jan 03 '14 at 11:33
  • 1
    for better help sooner post an SSCCE, short, runnable, compilable – mKorbel Jan 03 '14 at 11:34
  • Swing Timer doesn't allow me to use a type of game-loop that has proven to run the game at constant speed without problems. Does it matter in this situation specifically? (About the key bindings?) – user3150201 Jan 03 '14 at 11:35
  • any Thread.sleep(int) to block an execution of Swing methods, you can to lost those events (nothing is repainted on the screen) – mKorbel Jan 03 '14 at 11:35
  • Swing Timer doesn't allow me to use a type of game-loop - you are wrong logics is the same, only chars representing code are different, I'm out of this thread – mKorbel Jan 03 '14 at 11:36
  • Sorry didn't understand what you mean or what you're trying to say. – user3150201 Jan 03 '14 at 11:37
  • Maybe I'm wrong, and indeed it won't matter for the game-loop if I used a Swing timer. But do you think it's a better choice? – user3150201 Jan 03 '14 at 11:39
  • The problem is the Swing Timer, the problem is the fact that Swing uses a passive rendering algorithm. This would almost immediately discount using Key Bindings, as the only way to get into a active painting mechanism is restricted to AWT. Take a look at [this](http://stackoverflow.com/questions/14886232/swing-animation-running-extremely-slow/14902184#14902184) example, which animates 4500 separate objects simultaniously – MadProgrammer Jan 03 '14 at 11:41
  • Sorry how is this relevant? I mean I didn't use Swing timers in the program described above. – user3150201 Jan 03 '14 at 11:42
  • We don't understand why you key bindings are wrapped in Runnables. If you only problem with using a Swing Timer is trying to keep a constant frame rate, then you need to be using an active painting approach, which can only be achieved by using AWT based components (`Canvas`) which does not support key bindings... – MadProgrammer Jan 03 '14 at 11:44
  • Also need to remember, that all key bindings are processed within the context of the EDT, so the use of a `Thread` or `Runnable` in this means is basically...wasteful...Any time you deal with ANY swing component, you are going to have to deal with the EDT... – MadProgrammer Jan 03 '14 at 11:46
  • A lot of times on this site I had question about programs such as the one above: A JPanel-extending class where most of the game logic is, and where the graphics are drawn, and KeyListener used to move things on the screen. And almost everytime somebody told me to use Key Bindings instead of Key Listener. So now you're telling me that Key Bindings can't be used with Swing? I'm pretty much a beginner to game-making in Java, so a lot of what you said doesn't make much sense to me. Could you try and explaing again? – user3150201 Jan 03 '14 at 11:52
  • I'm pretty much a beginner to game-making in Java, so a lot of what you said doesn't make much sense to me. - post an SSCCE, otherwise rest is desribed in official Oracle tutorial, we may not suply those tutorials with our explanations here – mKorbel Jan 03 '14 at 11:58
  • I'll post an SSCCE, but based on what I wrote above - would you say that that structure should work in the game? Or is the thread/swing-timer thing critical? – user3150201 Jan 03 '14 at 12:01
  • You should use `@someonesName` to notify them of a comment. If they are not on this page anymore, they may not get your comment. the @ notifies the person. – Paul Samsotha Jan 03 '14 at 12:03
  • @MadProgrammer A lot of times on this site I had question about programs such as the one above: A JPanel-extending class where most of the game logic is, and where the graphics are drawn, and KeyListener used to move things on the screen. And almost everytime somebody told me to use Key Bindings instead of Key Listener. So now you're telling me that Key Bindings can't be used with Swing? I'm pretty much a beginner to game-making in Java, so a lot of what you said doesn't make much sense to me. Could you try and explaing again? – user3150201 Jan 03 '14 at 12:05
  • @mKorbel I'll post an SSCCE, but based on what I wrote above - would you say that that structure should work in the game? Or is the thread/swing-timer thing critical? – user3150201 Jan 03 '14 at 12:05
  • No, I'm trying to say that key bindings is a Swing based API. In order to achieve active painting, you can only do this with AWT, which precludes using Swing components due to the differences in the way that they work. So if you want "control" over how the painting is done, you are restricted to using AWT. If you want things like key bindings and other features out of Swing (transparent controls), you have to contend with Swing's passive painting approach. – MadProgrammer Jan 03 '14 at 12:07
  • Or is the thread/swing-timer thing critical? - yes you can to lost repainting on the screen or animations/events aren't natural/smooth, to try to avoiding to use incomplete code (and outdated) sucked from www sites, here is (especially in posts by @MadProgrammer) everything – mKorbel Jan 03 '14 at 12:08
  • For a simple game, Swing based on a Swing Timer update is perfectly suitable. If you think that you can use a `Thread` and simply call `repaint` and it will give you better performance, than you are mistaken, it's still using Swing's passive painting algorithm. Forgive me, just trying to understand why you think putting the key bindings in a `Runnable` will make any difference... – MadProgrammer Jan 03 '14 at 12:10
  • @MadProgrammer could you direct me to a tutorial that explains what active painting and passive painting is? All I need, is a game where the screen gets updated every 10 milliseconds, and buttons get pushed to move object on the screen - and all of this in constant FPS. What do you think is the best way to do that? – user3150201 Jan 03 '14 at 12:15
  • It's pretty basic, but you could take a look at [Passive vs. Active Rendering](http://docs.oracle.com/javase/tutorial/extra/fullscreen/rendering.html). Depending on the complexity of your problem, personally, I'd start with a Swing Timer. This is a very simple approach. Once you have the basics of this, you could explore a more complex update engine using a `Thread` and then on to active rendering, where you have absolute complete control... – MadProgrammer Jan 03 '14 at 12:17
  • [All I need, is a game where the screen gets updated every 10 milliseconds](http://stackoverflow.com/questions/20901770/about-the-edt-java) you can't do that on stadard PC with stadard Operating System, and without two GPUs in SLI mode – mKorbel Jan 03 '14 at 12:26
  • @mKorbel I already did exactly that with a simple Pong clone..? – user3150201 Jan 03 '14 at 13:22
  • @MadProgrammer So what you are saying, is that the structure I described above is fine, except for one thing - the game loop needs to be a Swing timer actionPerformed(), and not a loop inside a thread. Am I right? – user3150201 Jan 03 '14 at 13:23
  • exactly, you are right, thats correct – mKorbel Jan 03 '14 at 13:44
  • @mKorbel, are you reffering to what I asked MadProgrammer? (just making sure) – user3150201 Jan 03 '14 at 13:51
  • @user3150201 the game loop needs to be invoked from Swing Timer's actionPerformed() (from Swing Action/ActionListener) – mKorbel Jan 03 '14 at 13:59
  • No, what I'm saying, is there's no reason to use a separate thread to register your keybindings. It increases the complexity of your program for zero benefit – MadProgrammer Jan 03 '14 at 20:39
  • So just register them in the existing thread in the Board class? – user3150201 Jan 03 '14 at 23:57

1 Answers1

0

Too many comments for me to read so I don't know if I'm saying anything new or just repeating something.

The way I see it. KeyBindings are just used to indicate the state of keys on the keyboard.

Take a look at KeyboardAnimtion.java from Motion Using the Keyboard. In that example wen the key is pressed the key is added to the Map and when the key is released the key is removed from the map. That is the sole function of the key bindings, to track the keys that are pressed and the associated movement of that key.

The example then uses a Timer to schedule the animation of the object. When the Timer fires the move() method is invoked and the object is moved based on the keys in the Map.

Swing Timer doesn't allow me to use a type of game-loop that has proven to run the game at constant speed without problems.

There is no reason to use the Timer. If your game does its own looping then you should be able to invoke the move() method directly. However, all this does is control that the repaint request is made at a constant time, it does not guarantee that the painting is done immediately, although normally painting requests should be handled right away unless the system is really busy.

I would start by using the Timer an see what happens.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • This all good advice. What is concerning us is whether or not the OP is using active (BufferStrategy) or passive rendering (Swing) – MadProgrammer Jan 03 '14 at 20:41