尝试在简单的游戏中使用KeyListener移动对象

时间:2014-06-08 19:32:15

标签: java applet awt keylistener

我正在尝试创建一个类似于破砖机的简单游戏。我能够弄清楚游戏的一些基本概念(移动球,碰撞检测等)

我正在尝试使用左右箭头键在x方向上移动平台对象。在使用一些println语句测试之后,keyPressed方法的if条件工作,但我无法使用keyListener移动平台对象。是与Platform类中的moveLeft,moveRight方法有关,因为我试图改变dx的值,所以我可能会看到平台中的一些动作。

以下是3个班级。

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);
}

}

2 个答案:

答案 0 :(得分:1)

  1. 致电super.paint或为其他奇怪做好准备
  2. KeyListener只会在注册的组件具有焦点并且具有焦点时才会响应关键事件
  3. 考虑使用Swing API而不是AWT。 AWT组件不是双缓冲的,并且在更新时会闪烁。相反,从JPanel开始,然后将其添加到您想要的内容
  4. 您可以致电setFocusable(true)requestFocusInWindow(),但不能保证它会在100%的时间内正常工作或继续工作。

    相反,更新代码以使用Swing并利用key bindings API,这使您能够控制触发关键事件所需的焦点水平

    <强>更新...

    您还没有更新x的{​​{1}}位置,例如......

    Platform

    现在要求您对public void update(Tennis tg, Ball b) { x += dx; checkForCollosion(b); } 执行范围检查,以查看是否超出了视图的可见范围,如果你有关于这些事情......

    我最后还添加了一个Platform,每次点击都会调用MouseListener,例如......

    requestFocusInWindow

    这就是为什么我不喜欢小程序或addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { requestFocusInWindow(); } }); ,以及大量的内容

答案 1 :(得分:1)

您的第一个问题是,在您的moveRight()moveLeft()方法中,您正在检查dx的值并更新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 } } ,这在您的代码中的任何位置都不会用于绘制平台。

e.g。

x

即使我们更改您的方法以使用dx而不是x,您的第二个问题是增加或减少一个像素也不会移动太多。但是,如果你按住左箭头键足够长的话,平台会慢慢地沿着它移动。当你按下正确的数组(首先)时,由于你的第三个问题:边界检查,什么都不会发生。

移动方法中的边界检查基于 20 的x值,但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; } } 的初始值 275

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 } }

的大小来计算它们
{{1}}