Skip to main content
gamedev.net
🔒 Locked

Java Game-Problem with KeyListener

Started by Big Cheez Mar 1, 2004 at 3:51 PM 15 replies 3.1k views
Original Post
Big Cheez
Big Cheez
I'm having a problem with a KeyListener in Java, it's for my Swarm game, the problem is that the ship won't move. When I put
playerX+=1  
in ActionPerformed it moves, so it must be the KeyListener. What's wrong?
/**
 * <p>Title: Swarm</p>
 * <p>Description: Shoot any ship that isn't yours.</p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: Hot Metal Software</p>
 * @author Matthew Dyck a.k.a. Big Cheez
 * @version 1.0
 */

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class Swarm extends JPanel implements KeyListener, ActionListener{
  Image player;
  Timer gameTimer;
  boolean frozen=false;
  int playerX=0;
  final int WIND_X=800;
  final int WIND_Y=600;
  boolean rapidFire=false;
  boolean doubleBlasters=false;
  boolean syncBlasters=false;
  final int SHOT_DELAY=20;
  final int SYNC_SHOT_DELAY=10;
  boolean lastFired=false;
  final int RAPID_SHOT_DELAY=5;
  boolean laser=false;

  public static void main(String args[]){
    JFrame mainFrame=new JFrame();
    Swarm mainPanel=new Swarm();
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.getContentPane().add(mainPanel);
    mainFrame.pack();
    mainFrame.show();
  }
  Swarm(){
    initGraphics();
    initKey();
    iniTimer();
    gameTimer.start();
  }
  void initGraphics(){
    player=getToolkit().getImage("img/player.gif");
  }
  void initKey(){
    addKeyListener(this);
  }
  void iniTimer(){
    gameTimer=new Timer(1,this);
    gameTimer.setInitialDelay(1);
    gameTimer.setCoalesce(true);
  }
  public void keyTyped(KeyEvent k){
  }
  public void keyPressed(KeyEvent k){
    if(k.getKeyCode()==k.VK_RIGHT){
      playerX+=1;
      System.out.println("Right");
    }
    if(k.getKeyCode()==k.VK_LEFT){
      playerX-=1;
      System.out.println("Left");
    }
    if(k.getKeyCode()==k.VK_X){
      frozen=!frozen;
      System.out.println("X");
      if(frozen){
        gameTimer.stop();
      }else{
        gameTimer.start();
      }
    }
  }
  public void keyReleased(KeyEvent k){
    if(k.getKeyCode()==k.VK_RIGHT){
      playerX+=1;
      System.out.println("Right-Released");
    }
    if(k.getKeyCode()==k.VK_LEFT){
      playerX-=1;
      System.out.println("Left-Released");
    }
  }
  public void actionPerformed(ActionEvent a){
    playerX+=1;
    repaint();
  }
  public void paintComponent(Graphics gOrig){
    Graphics2D g=(Graphics2D)gOrig;
    g.drawImage(player,playerX,WIND_Y-32,this);
  }
}
[edited by - Big Cheez on March 3, 2004 6:31:45 AM]
"That MSMAGNET program trashed my hard drive!"
Mr_Ridd
Mr_Ridd
I''m not sure if it is the key listener, try getKeyChar() and see if tht works. If it doesn''t, put a System.out.println() in the key listener to see if it is getting there. It might be that playerX is incrementing but the panel isn''t updating it.

I wouldn''t do it the way you are doing it though. If you look at the Java examples they give you sample 2D stuff. Take classes, something like Surface and AnimatingSurface and put them into your app. That''s what I did until I found LWJGL. Why use normal graphics when you can have OpenGL.
The ability to succeed is the ability to adapt
paulecoyote
paulecoyote
You need to do a few things

1. You need to keep track of when the key is pressed, and when it is released. You get 1 message when it''s pressed, and 1 when it''s released. You would probably have better luck with the way you are doing it by using Typed. Be nice if you created a game action class or something.

2. You should consume the event so nothing else tries to handle it

Tip: If you want to make sure the ship stays in bounds, a simple way is using the modulus operator on the playerx+=1 line and the bounds - eg playerx+=1 % WIND_X

3. Use your timer so your game updates per clock cycle rather then per event recieved. Use a float for this - so if a user manages to move a little bit but not a whole pixel, you don''t loose that little bit each time. Your velocity while moving might be something like 1 pixel / sec - so if a user holds the key for half a second, stops for a second, then presses it for another half second it will move the whole pixel.
Anything posted is personal opinion which does not in anyway reflect or represent my employer. Any code and opinion is expressed “as is” and used at your own risk – it does not constitute a legal relationship of any kind.
Big Cheez
Big Cheez
to Mr_Ridd: What's the KeyChar for the left and right arrows? Once I find out, I'll try getKeyChar() once I can get my application to register keyPresses and keyReleases-currently, it doesn't pay them any attention. And how can you implement OpenGL in Java?

to paulsdsrubbish: 1.I did that and found out that my application didn't register keyPresses or keyReleases.
2.Sorry, I'm not that advanced in java, what's "consume" mean? And I'll make the boundaries later, I need to get the left/right movement working.
3.I don't get how you'd use a float to track timer events- do you mean to store the character's position?

[edited by - Big Cheez on March 2, 2004 6:21:44 AM]
"That MSMAGNET program trashed my hard drive!"
paulecoyote
paulecoyote
consume is is in the KeyEvent interface - and yes storing a position in a float.

Find out how long it was since the last time the screen was updated, and move it accordingly to your pixels/sec speed.

I don't think your actionlistener is ever going to be fired - you could do well to repaint on a timer in the code you have yourself at the moment.

This is a simple game loop taken from a book (http://www.amazon.co.uk/exec/obidos/ASIN/1592730051/qid%3D1078229077/202-3486186-4223843 I recommended in another thread (this won't compile unless you have more of the source from the book, but you get the idea):

/**
Runs through the game loop until stop() is called.
*/

public void gameLoop() {
long startTime = System.currentTimeMillis();
long currTime = startTime;

while (isRunning) {
long elapsedTime =
System.currentTimeMillis() - currTime;
currTime += elapsedTime;

// update

update(elapsedTime);

// draw the screen

Graphics2D g = screen.getGraphics();
draw(g);
g.dispose();
screen.update();

// don't take a nap! run as fast as possible

/*try {
Thread.sleep(20);
}
catch (InterruptedException ex) { }*/

}

EDIT: embedded source properly

[edited by - paulsdsrubbish on March 2, 2004 7:09:52 AM]
Anything posted is personal opinion which does not in anyway reflect or represent my employer. Any code and opinion is expressed “as is” and used at your own risk – it does not constitute a legal relationship of any kind.
Big Cheez
Big Cheez
Yes, ActionListener is fired- I tried it. It''s just the KeyListener.
"That MSMAGNET program trashed my hard drive!"
paulecoyote
paulecoyote
You tried different keys? Like VK_Z and VK_X just in case?

Your tried implementing only KeyListener rather then both?
Anything posted is personal opinion which does not in anyway reflect or represent my employer. Any code and opinion is expressed “as is” and used at your own risk – it does not constitute a legal relationship of any kind.
Big Cheez
Big Cheez
Neither of them worked.

[edited by - Big Cheez on March 2, 2004 7:52:28 AM]
"That MSMAGNET program trashed my hard drive!"
Raghar
Raghar
First use the BufferedImage.
second
volatile boolean left
KeyPressed(...){
...
if key=left (left=true);


You could use OpenGL from Java by LWJGL. So look at sourceforge and try to find it.

BTW set ignoreRepaint(true);


[edited by - raghar on March 2, 2004 6:06:59 PM]
yaroslavd
yaroslavd
I think the Javadoc comments have to be immediately before the class. Meaning you can''t put import statements in between the comments and the class.
Big Cheez
Big Cheez
to yaroslavd: It works. I''ve done stuff before like that and it worked.
to Raghar: what''s setIgnoreRepaint(true) do? And Image worked fine... what''s the advantage to using a BufferedImage? And I tried using
boolean left; 
and
boolean right; 
, it didn''t work.
"That MSMAGNET program trashed my hard drive!"
Zahlman
Zahlman
actionPerformed() contains a repaint(), and when you put some code in there to update the model, you saw a change on the screen.

keyPressed() does not contain a repaint(), and when you put in the same code there to update the model, you didn''t see a change on the screen.

HMM...
Big Cheez
Big Cheez
But wouldn''t the KeyListener update playerX, and then ActionPerformed be called right after the Timer fired and update the actual image?
"That MSMAGNET program trashed my hard drive!"
Raghar
Raghar
What about registering your keyListener? mainFrame.getContentPane().add(mainPanel);
mainFrame.addKeyListener(mainPanel);
JFrame seems to be nice target.
If you have own timer you should do drawind independently on JFrame, so you''d rather disable automatic refresh to prevent unnecessary colisions.
BufferedImage is nicer to Graphics2D, and of course it''s more easily loaded by Java.ImageIO.
Big Cheez
Big Cheez
Thanx everyone, it works now!
"That MSMAGNET program trashed my hard drive!"
paulecoyote
paulecoyote
Post the working code then!
Anything posted is personal opinion which does not in anyway reflect or represent my employer. Any code and opinion is expressed “as is” and used at your own risk – it does not constitute a legal relationship of any kind.
Big Cheez
Big Cheez

/**
* <p>Title: Swarm</p>
* <p>Description: Shoot any ship that isn''t yours.</p>
* <p>Copyright: Copyright (c) 2004</p>
* <p>Company: Hot Metal Software</p>
* @author Matthew Dyck a.k.a. Big Cheez
* @version 1.0
*/


import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class Swarm extends JPanel implements KeyListener, ActionListener{
Image player;
Timer gameTimer;
int playerX=0;
final int WIND_X=800;
final int WIND_Y=600;
boolean rapidFire=false;
boolean doubleBlasters=false;
boolean syncBlasters=false;
final int SHOT_DELAY=20;
final int SYNC_SHOT_DELAY=10;
boolean lastFired=false;
final int RAPID_SHOT_DELAY=5;
boolean laser=false;
short direction;

public static void main(String args[]){
JFrame mainFrame=new JFrame();
Swarm mainPanel=new Swarm();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.getContentPane().add(mainPanel);
mainFrame.addKeyListener(mainPanel);
mainFrame.pack();
mainFrame.show();
}
Swarm(){
initGraphics();
initKey();
iniTimer();
gameTimer.start();
}
void initGraphics(){
player=getToolkit().getImage("img/player.gif");
}
void initKey(){
addKeyListener(this);
}
void iniTimer(){
gameTimer=new Timer(1,this);
gameTimer.setInitialDelay(1);
gameTimer.setCoalesce(true);
}
public void keyTyped(KeyEvent k){
}
public void keyPressed(KeyEvent k){
if (k.getKeyCode() == k.VK_RIGHT) {
direction=1;
System.out.println("Right");
}
if (k.getKeyCode() == k.VK_LEFT) {
direction=-1;
System.out.println("Left");
}
}
public void keyReleased(KeyEvent k){
direction=0;
}
public void actionPerformed(ActionEvent a){
if(direction==1){
playerX+=2;
}
if(direction==-1){
playerX-=2;
}
repaint();
}
public void paintComponent(Graphics gOrig){
Graphics2D g=(Graphics2D)gOrig;
g.drawImage(player,playerX,WIND_Y-32,this);
}
}
"That MSMAGNET program trashed my hard drive!"

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.