Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (475)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (530)
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  
  Can I add an abstract class as a KeyListener?  (Read 4347 times)
0 Members and 1 Guest are viewing this topic.
Offline evilfrenchguy

Junior Member


Medals: 3



« Posted 2012-04-12 18:26:30 »

Hi guys.

Quick question. I want to make an abstract input class so I can poll the mouse and keyboard from a static context wherever, but I am not 100% sure if I can actually add it as a KeyListener since I can't instantiate it. Would Input.class work or is it not possible?
Offline Cruiser

Junior Member


Medals: 1
Projects: 1


Twitter: @totallymorten


« Reply #1 - Posted 2012-04-12 18:47:52 »

Hmmm, couldn't you just create it as either a singleton (a static variable in its own class) or a static variable elsewhere?

something like

1  
2  
3  
4  
class MyKeyListener extends KeyListener
{
  public static MyKeyListener instance = new MyKeyListener();
}


and then

1  
addKeyListener(MyKeyListener.instance);


I know that you should use a "getter" method for a correct singleton pattern, but this is just to show what I mean :-).

Why does it have to be abstract by the way?

Cheers.
Offline evilfrenchguy

Junior Member


Medals: 3



« Reply #2 - Posted 2012-04-12 19:01:45 »

A singleton eh? I'm not sure if that would work or not. I'll go try right now.

I want to have just a class where I can check the input from anywhere with static methods. So in any one game state I can say Input.isKeyDown and it will work. Not even sure if it is doable but I'm gonna try.

Thanks for the idea. 
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Cruiser

Junior Member


Medals: 1
Projects: 1


Twitter: @totallymorten


« Reply #3 - Posted 2012-04-12 19:18:03 »

At least that's how I would go about it, if I needed to access something from different parts of the code (of course there are many ways depending on your design) :-).

Here's a full example of what I'm rambling about:

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  
import java.awt.event.KeyAdapter;


public class MyKeyAdapter extends KeyAdapter
{
   private static MyKeyAdapter inst = null;
   
   private MyKeyAdapter()
   {
     
   }
   
   public static MyKeyAdapter getInst()
   {
      if (MyKeyAdapter.inst == null)
         MyKeyAdapter.inst = new MyKeyAdapter();
     
      return MyKeyAdapter.inst;
   }
   
   public static void main(String[] args)
   {
      // then you access the key adapter like this
     MyKeyAdapter.getInst();
   }

}
Offline evilfrenchguy

Junior Member


Medals: 3



« Reply #4 - Posted 2012-04-12 19:45:37 »

Well I went to go try the singleton idea when I had an epiphany. I made a Keyboard class that implemented KeyListener that held all the key constants and the isKeyDown and isKeyUp methods. Then I can supply Input.keyboard as a listener and when I check inputs.

Unfortunately I think my idea of a static input won't work. I have an array of booleans to represent key states and a list of int constants for each key's spot in the array. Inside keylisteners methods I have a switch statement to check against KeyEvent's constants. Then I can set a certain key in the array to false or true. Finally isKeyDown checks the array for true or false on th key you query it about.

However, it seems there is some lag between the pressing and th query...ill keep at it, i don't think its doable.
Offline sproingie

JGO Kernel


Medals: 201



« Reply #5 - Posted 2012-04-12 19:48:56 »

Why does this all need to be static?
Offline Cruiser

Junior Member


Medals: 1
Projects: 1


Twitter: @totallymorten


« Reply #6 - Posted 2012-04-12 20:02:36 »

Hmm, I would think it would work fine since only one thing is setting the variables so no synchronization problems would occur.

Are you referring "lag" to the delay between key press / poll detection? becuase there will always be a lag when you're polling I guess.

I guess there are so many ways you could design this. I don't think I've ever done polling on key inputs or even polling at all. In cases where I seem to need polling I have used a Thread that does a Object.wait(); and then the code that sets the variable will do a Object.notify();

If you keep having problems with this, I'm sure we can figure something out, I just need to know more about what you are trying to do :-). And then, I'm not the big Java Guru myself :-D.
Offline evilfrenchguy

Junior Member


Medals: 3



« Reply #7 - Posted 2012-04-12 22:47:22 »

@sproingie
Well the goal was to have a system where no matter where I am in the code I can poll the keyboard without passing objects around or having 8 keylisteners. The most obvious solution to me was an abstract class with static methods.

@Cruiser
I'm on my phone so I can't copy paste my code but I'll try to explain it.

I have an abstract class called Input. It doesn't extend anything and it doesn't use any interfaces. In it, I have an instance of a Keyboard class as well as an init and getKeyboard method both of which are public static methods.

Keyboard is a keylistener and has a ton of static int constants for key codes as well as an array of booleans that is the same size as the number of key code constants. Basically each array element represents an individual keys being pressed (true) or normal (false). There is a reset method which just sets all the key states to false, an isKeyDown method which returns true if the element of the provided key code is true, and an isKeyUp method which returns true if the element of the provided key code is false.

In the keyPressed method I have a switch statement for the key event's key code and for each case I will set the array element to true with my key constant. As an example, I might have case KeyEvent.VK_ESCAPE: keyboard[KEY_ESC] = true: where KEY_ESC is my constant for the escape key. I do the same thing for keyReleased but I'll set it to false instead because that means they let go of the key.

So say they press Q. KeyPressed will be called and it will prse the switch statement to find case KeyEvent.VK_Q. In that case, I will use my int constant for Q which might have set to 15 or something. I'll use that as my index for my boolean array and set element 15 (in this case KEY_Q I would have set to 15) to true because VK_Q was pressed. That all happens automatically in the EventDispatchThread. Now in my update method, after adding Input.getKeyboard() as a KeyListener, I can say if (Input.getKeyboard().isKeyDown(Keyboard.KEY_Q)) { ... } to detect if Key Q was pressed.

I hope I explained that well enough. Basically the goal was to be able to poll the keyboard from anywhere without needing object passing or registering more than one key listener.
Offline sproingie

JGO Kernel


Medals: 201



« Reply #8 - Posted 2012-04-12 23:38:04 »

I think you need to refine your sense of object-oriented design.  Throwing everything into a static scope just because it's global is not the way you do it.  You're supposed to pass objects around, but you can collect several onto one object and pass that around.  Worst case is you stick just a few objects into a static scope and use that as the root of your references (see the Gdx class in libgdx for an example of that)

Offline ra4king

JGO Kernel


Medals: 336
Projects: 2
Exp: 5 years


I'm the King!


« Reply #9 - Posted 2012-04-12 23:50:32 »

Maybe you need to look into method delegating, where Input is not abstract but holds an ArrayList of InputHandlers (which would be an interface that extends KeyListener), and then Input delegates the events to all attached InputHandlers.

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

Junior Member


Medals: 1
Projects: 1


Twitter: @totallymorten


« Reply #10 - Posted 2012-04-13 09:12:33 »

@evilfrenchguy I know that using a static object might not be the way to go, but still I think this should work.

I understand what you want to do, but not how you are doing it. Maybe you could post an example about how you are setting the array variable on keyPressed() and how you are polling the array?

Or you could send me the code (my email's in my profile) - I promise not to keep it :-).

@sproingie You're right that this might be the "ideal" way of doing OO, but I find sometimes there's a compromise between "Generic nice code" and "performing flexible code". I agree that "global" variables should be avoided because it's hell to debug, and it's nice to see on a methods definition which data it depends on.

I use a static Game object in my code though, where I keep states like DAY_CYCLE, so the AI and entities can lookup the time of day. Passing all that data around to every method would make a mess :-).
Offline 65K
« Reply #11 - Posted 2012-04-13 09:47:10 »

I use a static Game object in my code though, where I keep states like DAY_CYCLE, so the AI and entities can lookup the time of day. Passing all that data around to every method would make a mess :-).
You could think about object factories, lookups, dependency injection and the like.

Offline ReBirth
« Reply #12 - Posted 2012-04-13 13:36:17 »

Worst case is you stick just a few objects into a static scope and use that as the root of your references (see the Gdx class in libgdx for an example of that)
So Gdx.input is bad?

Offline Danny02
« Reply #13 - Posted 2012-04-13 14:19:51 »

Worst case is you stick just a few objects into a static scope and use that as the root of your references (see the Gdx class in libgdx for an example of that)
So Gdx.input is bad?

yep, the hole gdx lib is really badly coded.
not only does it try to use the Singleton antipattern, it also uses it in a lot more worse way.
Offline ReBirth
« Reply #14 - Posted 2012-04-13 14:37:59 »

Well if singleton is bad than its use will also be bad. We can pool input, display's properties and file from anywhere.
I don't really question about pattern as long it works, but we can't live with no pattern, world said.

Offline sproingie

JGO Kernel


Medals: 201



« Reply #15 - Posted 2012-04-13 17:34:49 »

The libraries Gdx keeps a reference to are naturally singletons.  Input is a natural singleton too (sort of).  I never said singleton is bad by itself, though it's often implemented wrong.  Writing your app in a static scope for the convenience of global references is a different thing entirely.  And do note that singletons are still instances, not static classes.

Offline Danny02
« Reply #16 - Posted 2012-04-13 20:08:02 »

yep, having a single instance and there for a singelton of something is a right approach for some stuff.
What to be carefull about is that keeping this singelton in global space, cause now you have global state which is bad.
Especially in libgdx, were the singoltons aren't even hold in a final reference, but can be changed anytime by any subsystem.
Remember its called Singelton pattern, not Globalton.

A right way of doing it would be dependency injection(which is also a pattern). You don't need necessarily a framework like spring or guice for it. A simple application factory can do the object graph setup at the beginning of the program exactly as well.
Offline evilfrenchguy

Junior Member


Medals: 3



« Reply #17 - Posted 2012-04-13 20:35:16 »

Ok so basically you guys think that this is a bad idea. Can you guys maybe give me some code samples as to what you are suggesting?
Offline Cruiser

Junior Member


Medals: 1
Projects: 1


Twitter: @totallymorten


« Reply #18 - Posted 2012-04-13 20:59:46 »

Ok so basically you guys think that this is a bad idea. Can you guys maybe give me some code samples as to what you are suggesting?

Well, I think you should try to make it work this way. IMHO it should. Then you can change it, and learn something in the process.

I'm still up for helping if you need it, but I need something more. Especially about the "lag", and how you are polling. Maybe a code sample or something? It's up to you :-).
Offline sproingie

JGO Kernel


Medals: 201



« Reply #19 - Posted 2012-04-13 21:11:08 »

A right way of doing it would be dependency injection(which is also a pattern). You don't need necessarily a framework like spring or guice for it. A simple application factory can do the object graph setup at the beginning of the program exactly as well.

DI is another great approach, and IMHO is The Right Way to do Singleton.  I stayed away from it in this conversation because it's not especially popular in game dev circles.  You don't need guice, no, but damn if it isn't handy.  Spring I have far less patience with these days.  Picocontainer is also a viable option.
Offline evilfrenchguy

Junior Member


Medals: 3



« Reply #20 - Posted 2012-04-13 21:25:03 »

Sure. This is what my keyPressed method looks like.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
public void keyPresssd(KeyEvent e)
{
         switch (e.getKeyCode())
         {
               case KeyEvent.VK_ESCAPE:
                      keyboard[KEY_ESC] = true;
               case KeyEvent.VK_ENTER:
                      keyboard[KEY_ENTER] = true;
               ...
          }
}


That's the basic idea. The KEY variables are my own constants.

By the way, what is dependency injection?
Offline tom
« Reply #21 - Posted 2012-04-14 01:02:12 »

Why do you have your own constants?

Offline evilfrenchguy

Junior Member


Medals: 3



« Reply #22 - Posted 2012-04-14 01:07:04 »

Just a simple luxury so I don't need to import or specify java.awt.event.KeyEvent.
Offline ReBirth
« Reply #23 - Posted 2012-04-14 05:45:21 »

I have been comfort with DI on java2d back then. On OP's case I will use an interface that take boolean arrays of key input to be implemented for class that need it.

Offline Cruiser

Junior Member


Medals: 1
Projects: 1


Twitter: @totallymorten


« Reply #24 - Posted 2012-04-14 11:58:14 »

Sure. This is what my keyPressed method looks like.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
public void keyPresssd(KeyEvent e)
{
         switch (e.getKeyCode())
         {
               case KeyEvent.VK_ESCAPE:
                      keyboard[KEY_ESC] = true;
               case KeyEvent.VK_ENTER:
                      keyboard[KEY_ENTER] = true;
               ...
          }
}


That's the basic idea. The KEY variables are my own constants.

By the way, what is dependency injection?

He he, yeah, I think I'm following the basic idea, but I need more information:

1. You are writing about a "lag". How do you measure it, and how does it show itself?
2. How often are you polling the boolean array, and how are you doing this (ex. a while-loop with a sleep??) ?

Cheers :-).
/Morten
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.

ctomni231 (37 views)
2014-07-18 06:55:21

Zero Volt (35 views)
2014-07-17 23:47:54

danieldean (28 views)
2014-07-17 23:41:23

MustardPeter (31 views)
2014-07-16 23:30:00

Cero (46 views)
2014-07-16 00:42:17

Riven (47 views)
2014-07-14 18:02:53

OpenGLShaders (36 views)
2014-07-14 16:23:47

Riven (36 views)
2014-07-14 11:51:35

quew8 (32 views)
2014-07-13 13:57:52

SHC (68 views)
2014-07-12 17:50:04
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
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!