sm15
sm15

Reputation: 85

Trying to move object with KeyListener in simple game

I am trying to create a simple game similar to brick-breaker. I was able to figure out some of the basic concepts of the game (moving the ball, collision detection, etc)

I am trying to move the platform object in an x-direction by using the left and right arrow keys. The if conditions for the keyPressed method work, after testing with some println statements but I am unable to move the platform object using keyListener. Is is something to do with the moveLeft , moveRight methods in the Platform class, because I tried d to changing the values of the dx, so I could maybe see some movement in the platform.

Here are the 3 classes.

import java.applet.*; 
import java.awt.*; 
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;

public class tennisGame extends Applet implements Runnable, KeyListener{ 

Ball b;
Platform p;

public void init() { 

    setSize(640, 480);
    addKeyListener(this);
} 

public void start () { 
    b= new Ball();
    p= new Platform();
    Thread thread = new Thread (this); 
    thread.start (); 
}

public void paint(Graphics g) { 
    b.paint(g);
    p.paint(g);

}
public void run(){
    while (true){
        b.update(this);
        p.update(this,b);
        repaint();
        try {
            Thread.sleep(20);
        }
        catch (InterruptedException e){
            //e.printStackTrace();
        }
    }
}
@Override
public void keyPressed(KeyEvent e) {
    if(e.getKeyCode() == e.VK_RIGHT){
        System.out.println("Pressed RIGHT");
        p.moveRight();
    }
    if(e.getKeyCode() == e.VK_LEFT){
        System.out.println("Pressed LEFT");
        p.moveLeft(); 
    }
}
@Override
public void keyReleased(KeyEvent e) {

}
@Override
public void keyTyped(KeyEvent e) {

}
}


import java.awt.*; 

public class Ball{ 
private int x=0;
private int y=0; 
private double dx=10;
private double dy=10;
private int width=20;
private int height=20;
private int radius=10;

public Ball() {

}

public void update(tennisGame tg){

    if ( x + dx > tg.getWidth()-radius-1){
        x = tg.getWidth()-radius-1;
        dx= -dx;
    }
    else if ( x + dx < 0 + radius ){
        x= 0 + radius;
        dx= -dx;
    }
    else{
        x+=dx;
    }

    if ( y + dy> tg.getHeight()-radius-1){
        y = tg.getHeight()-radius-1;
        dy= -dy;
    }
    else if ( y + dy < 0 + radius ){
        y= 0 + radius;
        dy= -dy;
    }
    else{
        y+=dy;
    }
}

public int getX() {
    return x;
}
public void setX(int x) {
    this.x = x;
}
public int getY() {
    return y;
}
public void setY(int y) {
    this.y = y;
}
public double getDx() {
    return dx;
}
public void setDx(int dx) {
    this.dx = dx;
}
public void setDy(double dy) {
    this.dy = dy;
}
public double getDy() {
    return dy;
}
public int getRadius() {
    return radius;
}

public void paint(Graphics g) { 
    g.setColor(new Color(0,0,250,250));
    g.fillOval(x-radius,y-radius,width, height);
}
}


import java.awt.Color;
import java.awt.Graphics;

public class Platform {

private int x=275;
private int y=400;
int dx=0;
private int width=120;
private int height=20;


public void update(tennisGame tg,Ball b) {
    checkForCollosion(b);
}

private void checkForCollosion(Ball b) {

    int ballX= b.getX();
    int ballY= b.getY();
    int radius= b.getRadius();

    if (ballY + radius > y && ballY + radius < y + height){
        if (ballX > x && ballX < x + width){
            double newDy= b.getDy()* -1 ;
            b.setDy(newDy);
        }
    }
}

public void moveRight() {
    if ( dx + 1 < 20){
        dx+=1;
    }
}
public void moveLeft() {
    if ( dx -1 > -20){
        dx-=1;
    }
}
public void paint(Graphics g){
    g.setColor(Color.red);
    g.fillRect(x , y, width, height);
}

}

Upvotes: 0

Views: 7173

Answers (2)

MadProgrammer
MadProgrammer

Reputation: 347204

  1. Call super.paint or be prepared for additional weirdness
  2. KeyListener will only respond to key events when the component it is registered to is focusable and has focus
  3. Consider using The Swing API instead of AWT. AWT components aren't double buffered and will flicker when updated. Instead, start with something like a JPanel and then add it to what ever you want

You could call, setFocusable(true) and requestFocusInWindow() but there's no guarantee that it will work or continue to work 100% of the time.

Instead, update the code to use Swing and take advantage of the key bindings API, which provides you with ability to control the level of focus required into order to trigger the key events

Updated...

You're also not updating the x position of the Platform, for example...

public void update(Tennis tg, Ball b) {
    x += dx;
    checkForCollosion(b);
}

This will now require you to perform range checking on the Platform to see if passes beyond the visible range of the view, if you about such things...

I also ended up adding a MouseListener which called requestFocusInWindow each time it was clicked, for example...

addMouseListener(new MouseAdapter() {
    @Override
    public void mouseClicked(MouseEvent e) {
        requestFocusInWindow();
    }
});

This is why I don't like applets or KeyListener, to much stuffing about

Upvotes: 1

azurefrog
azurefrog

Reputation: 10945

Your first problem is that in your moveRight() and moveLeft() methods you are checking the value of and updating dx, which isn't used anywhere in your code regarding the painting of the platform.

e.g.

public void moveRight() {
    if (dx + 1 < 20) {
        dx += 1; // updating dx, but x is used to paint
    }
}
public void moveLeft() {
    if (dx - 1 > -20) {
        dx -= 1; // updating dx, but x is used to paint
    }
}

Even if we change your methods to use x instead of dx your second problem is that incrementing or decrementing by one pixel isn't going to move by very much. However, if you hold down the left arrow key long enough you will the platform slowly creeping along. Nothing will happen when you press the right array (at first) because of your third problem: bounds checking.

The bounds checking in your move methods is based off of a value for x of 20, but the initial value of x is 275.

public void moveRight() {
    if (x + 1 < 20) { // can't move very far from the left side of the screen
        x += 1;
    }
}
public void moveLeft() {
    if (x - 1 > -20) { // goes left only a little bit off the screen
        x -= 1;
    }
}

You need to be using values which reflect the size of the applet. This code works, but for time's sake I've just hardcoded the boundary values. You should really calculate them based on the size of the tennisGame:

public void moveRight() {
    if (x < 520) {     // enable moving to the edge of the screen
        x += 10;   // move a little faster
    }
}
public void moveLeft() {
    if (x > 0) {       // enable moving to the edge of the screen
        x -= 10;   // move a little faster
    }
}

Upvotes: 1

Related Questions