Results 1 to 16 of 16
- 08-12-2010, 07:42 PM #1
Member
- Join Date
- Aug 2010
- Posts
- 7
- Rep Power
- 0
Checking for multiple keys pressed
so im very new to java, and i made a program where u can move a little block arround in a little world and "shoot" you move with "WASD" but the movement is very buggy, 1 very important thing is that i cant move 2 directions at the same time, i would like to be able to press both example: A and W and go that > \ way
so here is part of my code:
public void keyPressed( KeyEvent e ) {
// was the easyest way for me to get the ascii of the charather pressed in an int
keyI = e.getKeyCode() + 32;
// speed = 3
for(int i = 0; i < speed; i += 1){
//W
if (keyI == 119 && free(px, py - 1 - rectsize/2) == true){py -= 1;}
//A
if (keyI == 97 && free(px - 1 - rectsize/2, py ) == true){px -= 1;}
//S
if (keyI == 115 && free(px, py + 1 + rectsize/2) == true){py += 1;}
//D
if (keyI == 100 && free(px + 1 + rectsize/2, py ) == true){px += 1;}
}
repaint();
}
so anybody know a good way to make it detect if there is more than 1 key pressed at a time, and which ?
im not sure if this is enough, just tell me if you need the whole code.Last edited by MagnusLarsen; 08-12-2010 at 07:57 PM.
- 08-12-2010, 08:31 PM #2
- Join Date
- Sep 2008
- Location
- Voorschoten, the Netherlands
- Posts
- 11,408
- Blog Entries
- 7
- Rep Power
- 17
You can't do that with just the keyPressed( ... ) method; you need at least one of the other (keyReleased( ... ) and keyTyped( ... )) methods. Read the API documentation for the KeyEvent class for quite a detailed description how and when those events are fired. It also depends on the 'n-key rollover' feature of the keyboard itself.
kind regards,
JosLast edited by JosAH; 08-12-2010 at 08:36 PM.
- 08-12-2010, 08:51 PM #3
If you press and hold key A then press and hold key B while still holding key A you would have two keys pressed at the same time. Use the keyReleased listener method to know when the keys are released.
The listeners would hear: KeyA pressed, KeyB pressed, ..... Key(AorB) released, Key(BorA) released.
Your code would have to remember the state of the keys.
-
I would use key binding, not key listeners, and would create two separate actions for each key, one for press and one for release. I'd then use one boolean for each key to represent the state of the key: pressed or released. I'd then use a game timer to poll the set of booleans and move the sprite accordingly. For example, something like this:
Java Code:import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; import java.util.HashMap; import java.util.Map; import javax.swing.*; public class KeyBindingsGuiTest { private static void createAndShowUI() { KeyBindingsGui guiPanel = new KeyBindingsGui(); JFrame frame = new JFrame("KeyBindingsGuiTest"); frame.getContentPane().add(guiPanel); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public static void main(String[] args) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { createAndShowUI(); } }); } } @SuppressWarnings("serial") class KeyBindingsGui extends JPanel { private static final Dimension SIZE = new Dimension(600, 600); private static final int SPRITE_WIDTH = 26; private static final int SPRITE_HEIGHT = SPRITE_WIDTH; private static final int STROKE_WIDTH = 3; private static final Color SPRITE_COLOR = Color.red; private static final Color GUI_BCKGRD = Color.white; private static final String PRESSED = "Pressed"; private static final String RELEASED = "Released"; public static final int SPRITE_STEP = 8; private static final int SPRITE_STEP_PERIOD = 20; private BufferedImage sprite; private int spriteX = 0; private int spriteY = 0; private Map<Direction, Boolean> directionMap = new HashMap<Direction, Boolean>(); public KeyBindingsGui() { setBackground(GUI_BCKGRD); setPreferredSize(SIZE); sprite = createSprite(); spriteX = (SIZE.width - SPRITE_WIDTH)/2; spriteY = (SIZE.height - SPRITE_HEIGHT)/2; for (Direction direction : Direction.values()) { directionMap.put(direction, Boolean.FALSE); } setBindings(); Timer timer = new Timer(SPRITE_STEP_PERIOD, new GameLoopListener()); timer.start(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (sprite != null) { g.drawImage(sprite, spriteX, spriteY, null); } } private void setBindings() { int context = JComponent.WHEN_IN_FOCUSED_WINDOW; InputMap inputMap = getInputMap(context); ActionMap actionMap = getActionMap(); for (Direction direction : Direction.values()) { inputMap.put(KeyStroke.getKeyStroke(direction.getKeyCode(), 0, false), direction.getName() + PRESSED); inputMap.put(KeyStroke.getKeyStroke(direction.getKeyCode(), 0, true), direction.getName() + RELEASED); // set corresponding actions for the key presses and releases above actionMap.put(direction.getName() + PRESSED, new ArrowKeyAction(true, direction)); actionMap.put(direction.getName() + RELEASED, new ArrowKeyAction(false, direction)); } } private BufferedImage createSprite() { BufferedImage sprite = new BufferedImage(SPRITE_WIDTH, SPRITE_HEIGHT, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = sprite.createGraphics(); g2d.setStroke(new BasicStroke(STROKE_WIDTH)); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setColor(SPRITE_COLOR); g2d.drawOval(STROKE_WIDTH, STROKE_WIDTH, SPRITE_WIDTH - 2 * STROKE_WIDTH, SPRITE_HEIGHT - 2 * STROKE_WIDTH); g2d.dispose(); return sprite; } private class ArrowKeyAction extends AbstractAction { private Boolean pressed; private Direction direction; public ArrowKeyAction(boolean pressed, Direction direction) { this.pressed = Boolean.valueOf(pressed); this.direction = direction; } @Override public void actionPerformed(ActionEvent arg0) { directionMap.put(direction, pressed); } } private class GameLoopListener implements ActionListener { public void actionPerformed(ActionEvent e) { int x0 = spriteX; int y0 = spriteY; for (Direction direction : Direction.values()) { if (directionMap.get(direction)) { spriteX += SPRITE_STEP * direction.getVector().x; spriteY += SPRITE_STEP * direction.getVector().y; } } int x = Math.min(x0, spriteX); int y = Math.min(y0, spriteY); int w = Math.max(x0, spriteX) - x + SPRITE_WIDTH; int h = Math.max(y0, spriteY) - y + SPRITE_HEIGHT; repaint(x, y, w, h); } } } enum Direction { UP("Up", KeyEvent.VK_UP, new Point(0, -1)), DOWN("Down", KeyEvent.VK_DOWN, new Point(0, 1)), LEFT("Left", KeyEvent.VK_LEFT, new Point(-1, 0)), Right("Right", KeyEvent.VK_RIGHT, new Point(1, 0)); private String name; private int keyCode; private Point vector; private Direction(String name, int keyCode, Point vector) { this.name = name; this.keyCode = keyCode; this.vector = vector; } public String getName() { return name; } public int getKeyCode() { return keyCode; } public Point getVector() { return vector; } @Override public String toString() { return name; } }
- 08-16-2010, 09:55 PM #5
Member
- Join Date
- Aug 2010
- Posts
- 7
- Rep Power
- 0
Thanks
thx for the replyes, i made it work and could ( and should ) probally have figgured it out by myself
heres what i changed it to, its still not perfect movement but it works fine :
Java Code:public void keyPressed( KeyEvent e ) { keyI = e.getKeyCode() + 32; if (keyI == 119){ keyW = true; } if (keyI == 97){ keyA = true; } if (keyI == 115){ keyS = true; } if (keyI == 100){ keyD = true; } for(int i = 0; i < speed; i += 1){ //W if (keyW == true && free(px, py - 1 - rectsize/2) == true){py -= 1;} //A if (keyA == true && free(px - 1 - rectsize/2, py ) == true){px -= 1;} //S if (keyS == true && free(px, py + 1 + rectsize/2) == true){py += 1;} //D if (keyD == true && free(px + 1 + rectsize/2, py ) == true){px += 1;} } repaint(); } public void keyReleased( KeyEvent e ) { keyI = e.getKeyCode() + 32; if (keyI == 119){ keyW = false; } if (keyI == 97){ keyA = false; } if (keyI == 115){ keyS = false; } if (keyI == 100){ keyD = false; } }
- 08-16-2010, 10:42 PM #6
Why all the hardcoded decimal literals? what is a 119? Is that the same as 'w'?
'w' is much easier to understand and you'll make fewer mistakes using the char literal than the decimal literal. What if you mistyped 199 or 191? You might not see it?
Also in stead of using 'w' here and another 'w' there, create one final variable and use it in all the places you need to test for the letter w.
final char MoveUpChar = 'w';
If you decided to change the letters used to move the mouse, there would only be one set of variables to change, instead of dozens of decimal values like 119 etc
- 08-17-2010, 01:23 PM #7
Member
- Join Date
- Aug 2010
- Posts
- 7
- Rep Power
- 0
the reason im using 119 for 'w' is because its the ascii number for w, its what i get when i retrieve the key pressed, its easyest just to use it directly from there instead of then making it into a char or w/e
when im learning a new language like java i just like to make the code as short as possible even though it might look messy and hard to understand
- 08-17-2010, 01:29 PM #8
It depends on if you expect to write production code. Good habits formed early will have you writing better code. Your code is not very maintainable with all the hardcode decimal constants. No one can look at the code and understand what 119 means without going to a table to see that its the value for 'w'.like to make the code as short as possible
Plus a self documenting variable like "MoveUpChar"
final char MoveUpChar = 'w';
Makes the code easier for anyone to understand.
When I taught programming and graded students code, usages like yours would merit -10 points for poor documenting and poor maintainability.
- 08-18-2010, 12:57 PM #9
Member
- Join Date
- Aug 2010
- Posts
- 7
- Rep Power
- 0
will consider using more variables instead of writing every number :)
-10 for me on this on though
- 08-19-2010, 02:07 AM #10
Senior Member
- Join Date
- Apr 2010
- Location
- Philippines
- Posts
- 580
- Rep Power
- 4
If I am in your case I will follow fubarable's advice and use KeyBinding instead of keylistener and create an event seperate event for keys "W", "A", "S", "D", "WA", "WD", "AS" and "DS". That will be a lot easier.
- 08-21-2010, 09:11 PM #11
Member
- Join Date
- Aug 2010
- Posts
- 7
- Rep Power
- 0
I will try to find a tutorial on how to use KeyBinding then :)
ty
-
- 08-21-2010, 10:12 PM #13
Member
- Join Date
- Aug 2010
- Posts
- 7
- Rep Power
- 0
im lost
think that was a step too big using KeyBindings, i dont understand half of what that page says, and i cant even get the code u posted working :(
dunno what to do...
- 08-21-2010, 11:26 PM #14
Senior Member
- Join Date
- Apr 2010
- Location
- Belgrade, Serbia
- Posts
- 278
- Rep Power
- 4
If there is something that you don't understand on that page, or in Fubarable's example, you can ask us :cool:think that was a step too big using KeyBindings, i dont understand half of what that page says, and i cant even get the code u posted working
We will help you.
- 08-22-2010, 11:29 AM #15
Member
- Join Date
- Aug 2010
- Posts
- 7
- Rep Power
- 0
at line 30 it says :
The type KeyBindingGui is already defined
don't know what to do about that
-
Similar Threads
-
Checking if a button was pressed in a Window.
By Valkyrie in forum New To JavaReplies: 2Last Post: 12-15-2009, 05:28 AM -
data structure with multiple keys
By jon80 in forum New To JavaReplies: 2Last Post: 06-13-2009, 03:02 PM -
get key pressed
By prashant in forum NetworkingReplies: 1Last Post: 03-26-2009, 09:10 PM -
Multiple types in Vector - type checking
By Excession in forum Advanced JavaReplies: 5Last Post: 07-13-2008, 07:06 PM -
key pressed event
By kavithas in forum New To JavaReplies: 7Last Post: 12-10-2007, 02:01 PM


LinkBack URL
About LinkBacks
Reply With Quote

Bookmarks