Java:Space Invaders游戏中KeyListener的问题

时间:2016-02-16 11:14:27

标签: java swing keylistener actionevent

我试图在Java中的Space Invaders游戏中实现KeyListener来移动船(现在,它只是一个红色矩形)。

我觉得它实现得很好,但我不能让它发挥作用。

这是船的一个:

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

public class Nave{

int x, y;
int AnchoNave = 40, AltoNave = 40;  // WIDTH_SHIP and HIGH_SHIP
Finestra f;                         // WINDOW
int velocidad = 4, v = 0;           // VELOCITY
Joc j;

Nave(Finestra f, int x, int y){
    this.f = f;
    this.x = x;
    this.y = y;
}

void pintaNave(Graphics g){

    g.setColor(Color.RED);
    g.drawRect(x, y, AnchoNave, AltoNave);
    g.setColor(Color.RED);
    g.fillRect(x, y, AnchoNave, AltoNave);

}

void movimiento(){  // this is not in the loop now.

    x+=velocidad;
    if (x>f.AMPLE-AnchoNave-10){
        x=0;
    }  

}  

}

这是Window的一个:

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.*;
import javax.swing.JFrame;

public class Finestra extends JFrame implements ActionListener,  KeyListener{

Image im;
Graphics g;
int AMPLE=600,ALT=500;     // WIDTH and HIGH
Joc j;

Nave nave;                 // Nave = SHIP
int velocidad = 10;        // VELOCITY

public static void main(String[] args) {
    new Finestra();        // Finestra = WINDOW
}

Finestra(){

    super("-+- Space Invaders -+-");
    setVisible(true);
    setSize(AMPLE,ALT);
    im=this.createImage(AMPLE, ALT);
    g=im.getGraphics();
    j=new Joc(this);
    j.playing();
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setResizable(false);

    addKeyListener(this);
    setFocusable(true);
    setFocusTraversalKeysEnabled(false);
}

public void update(Graphics g) {
    paint(g);
}

public void paint(Graphics g) { 
    g.drawImage(im, 0,0, null); 
}


@Override
public void actionPerformed(ActionEvent e) {
    j.nave.x =j.nave.x + j.nave.v;
    repaint();  
}  

@Override
public void keyPressed(KeyEvent e) {
    int tecla = e.getKeyCode();
    if (tecla == KeyEvent.VK_RIGHT)
        j.nave.v = +10;
    if (tecla == KeyEvent.VK_LEFT)
        j.nave.v = -10;
    }

@Override
public void keyReleased(KeyEvent e) {
    j.nave.v = 0;
}

@Override
public void keyTyped(KeyEvent e) {}

}

最后这是包含游戏循环的类:

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

public class Joc{


Finestra f;                 // WINDOW
Enemigos c1[];              // ENEMIES
Nave nave;                  // SHIP

Joc(Finestra f){            // JOC = GAME
    this.f=f;
}
void playing() {
    initicalitzaJoc();
    do {
        moviments();           // MOVEMENTS
        detectaColisions();    // COLLISION DETECTION
        pintarPantalla(f.g);   // PAINT SCREEN
        f.repaint();

        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }           
    }while(true);
}

private void detectaColisions() { 
} 

private void moviments() {  
    for(int i=0;i<c1.length;i++)
        c1[i].movimiento(); 
}

private void initicalitzaJoc() {        

    c1 = new Enemigos[15];                 // ENEMIES

    for (int i=0; i<5; i++)
        c1[i] = new Enemigos(f, 100+i*80, 100, 5);
    for (int i=5; i<10; i++)
        c1[i] = new Enemigos(f, 100+(i-5)*80, 150, 5);
    for (int i=10; i<15; i++)
        c1[i] = new Enemigos(f, 100+(i-10)*80, 200, 5);

    // Nave del jugador:                    // PLAYER'S SHIP
    nave = new Nave(f,300-40/2, 500-40-5);

}

void pintarPantalla(Graphics g) {   

    g.setColor(Color.WHITE);
    g.fillRect(0, 0, 600,500);

    for (int i=0; i<5; i++)         
        c1[i].pinta(g,1);;
    for (int i=5; i<10; i++)
        c1[i].pinta(g,3);
    for (int i=10; i<15; i++)
        c1[i].pinta(g,6);       

    nave.pintaNave(g);

}

}

我不知道错误可能在哪里,也许是在循环中......我不知道。

问题是我如何修理它可以使用键盘移动船? 这个太空入侵者是一个家庭作业,我有义务使用KeyListener ......我怎样才能使它有效?

2 个答案:

答案 0 :(得分:1)

我找到了答案。

问题是“Finestra”类在读取键之前会执行“播放”功能(因此循环开始)。

足以追逐订单:

Finestra(){

    super("-+- Space Invaders -+-");
    setVisible(true);
    setSize(AMPLE,ALT);
    im=this.createImage(AMPLE, ALT);
    g=im.getGraphics();
    j=new Joc(this);

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setResizable(false);

    addKeyListener(this);
    setFocusable(true);
    setFocusTraversalKeysEnabled(false);
    System.out.println("hola");
    j.playing();  // enter the loop after reading the keys.
}

答案 1 :(得分:0)

查看您的关键事件处理程序:

@Override
public void keyPressed(KeyEvent e) {
  int tecla = e.getKeyCode();
  if (tecla == KeyEvent.VK_RIGHT)
    j.nave.v = +10;
  if (tecla == KeyEvent.VK_LEFT)
    j.nave.v = -10;
}

它改变你船上的一个名为'v'的变量(中殿)。

然后,您船上的movimiento(可能是“移动”)方法使用另一个变量velocidad。它完全忽略了v!

删除变量v并使用velocidad

此外,你只能在你的敌舰上召唤movimiento,而不是在你的玩家的船上!很自然,它永远不会移动。