Java Swing中的贪吃蛇游戏 - 我的蛇只能变长

3

我正在尝试使用Swing做经典的贪吃蛇游戏,并且我成功让贪吃蛇移动了,但是当它移动时,它会变得无限长,因为它永远不会擦掉它的尾巴。

我一直在使用validate()repaint(),但是没有任何作用。

问题截图

这是我的代码:

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;

public class controls extends JPanel implements KeyListener, ActionListener { // Amb aquestes dues implementacions, fem que el programa pugui rebre per teclat

// Mida serp
private int[] longXserp = new int[750];
private int[] longYserp = new int[750];

// Longitut inicial de la serp
private int serplong = 3;

// Moviments que fem
private int moviments = 0;

// Controls
private boolean esquerra = false;
private boolean dreta = false;
private boolean amunt = false;
private boolean avall = false;

// Gràfics de moviment
private ImageIcon serpesquerra;
private ImageIcon serpdreta;
private ImageIcon serpamunt;
private ImageIcon serpavall;

private Timer timer;
private int velocitatserp = 100;
private ImageIcon serp;

public controls() {
    addKeyListener(this);
    setFocusable(true);
    setFocusTraversalKeysEnabled(false);
    timer = new Timer(velocitatserp, this);
    timer.start();
}

public void paint(Graphics g) { // Mètode amb el que imprimim per pantalla. Ha d'anomenar-se "paint", o si no, no funcionarà

    if(moviments == 0) {

        longXserp[2] = 50;
        longXserp[1] = 75;
        longXserp[0] = 100;

        longYserp[2] = 100;
        longYserp[1] = 100;
        longYserp[0] = 100;
    }


    serpdreta = new ImageIcon("src/grafics/serpdreta.png");
    serpdreta.paintIcon(this, g, longXserp[0], longYserp[0]);

    for(int a = 0; a < serplong; a++) {

        if(a == 0 && esquerra) {

            serpesquerra = new ImageIcon("src/grafics/serpesquerra.png");
            serpesquerra.paintIcon(this, g, longXserp[a], longYserp[a]);
        }

        if(a == 0 && dreta) {

            serpdreta = new ImageIcon("src/grafics/serpdreta.png");
            serpdreta.paintIcon(this, g, longXserp[a], longYserp[a]);
        }

        if(a == 0 && amunt) {

            serpamunt = new ImageIcon("src/grafics/serpamunt.png");
            serpamunt.paintIcon(this, g, longXserp[a], longYserp[a]);
        }

        if(a == 0 && avall) {

            serpavall = new ImageIcon("src/grafics/serpavall.png");
            serpavall.paintIcon(this, g, longXserp[a], longYserp[a]);
        }

        if(a != 0) {
            serp = new ImageIcon("src/grafics/serp.png");
            serp.paintIcon(this, g, longXserp[a], longYserp[a]);
        }

    }

    g.dispose();
}


@Override
public void keyPressed(KeyEvent ke) {

    if(ke.getKeyCode() == KeyEvent.VK_RIGHT){ // Si polses la tecla X, la seva variable boolean es posa en true
        moviments++;
        dreta = true;

        if(!esquerra) {
            dreta = true;
        }

        else {
            dreta = false;
            esquerra = true;
        }

        amunt = false;
        avall = false;
    }

    if(ke.getKeyCode() == KeyEvent.VK_LEFT){
        moviments++;
        esquerra = true;

        if(!dreta) {
            esquerra = true;
        }

        else {
            esquerra = false;
            dreta = true;
        }

        amunt = false;
        avall = false;
    }

    if(ke.getKeyCode() == KeyEvent.VK_UP){
        moviments++;
        amunt = true;

        if(!avall) {
            amunt = true;
        }

        else {
            amunt = false;
            avall = true;
        }

        esquerra = false;
        dreta = false;
    }

    if(ke.getKeyCode() == KeyEvent.VK_DOWN){
        moviments++;
        avall = true;

        if(!amunt) {
            avall = true;
        }

        else {
            amunt = true;
            avall = false;
        }

        esquerra = false;
        dreta = false;
    }

}
@Override
public void keyReleased(KeyEvent ke) {
    // TODO Auto-generated method stub

}
@Override
public void keyTyped(KeyEvent ke) {
    // TODO Auto-generated method stub

}
@Override
public void actionPerformed(ActionEvent ae) {

    timer.start();

    if(dreta) {

        for(int d = serplong-1; d>=0; d--) {
            longYserp[d+1] = longYserp[d];
        }

        for(int e = serplong; e>= 0; e--) {
            if(e==0) {
                longXserp[e] = longXserp[e] + 25;
            }

            else {
                longXserp[e] = longXserp[e-1];
            }

            if(longXserp[e] > 850) {
                longXserp[e] = 25;

            }
        }

        repaint(); // Mètode per refrescar els gràfics tornant a cridar al mètode paint(). Es usa quan es realitzan canvis sobre els gràfics
    }

    if(esquerra) {

        for(int d = serplong-1; d>=0; d--) {
            longYserp[d+1] = longYserp[d];
        }

        for(int d = serplong; d>= 0; d--) {
            if(d==0) {
                longXserp[d] = longXserp[d] - 25;
            }

            else {
                longXserp[d] = longXserp[d-1];
            }

            if(longXserp[d] < 25) {
                longXserp[d] = 850;

            }
        }

        repaint();
    }

    if(amunt) {

        for(int d = serplong-1; d>=0; d--) {
            longXserp[d+1] = longXserp[d];
        }

        for(int d = serplong; d>= 0; d--) {
            if(d==0) {
                longYserp[d] = longYserp[d] - 25;
            }

            else {
                longYserp[d] = longYserp[d-1];
            }

            if(longYserp[d] < 75) {
                longYserp[d] = 625;

            }
        }

        repaint();
    }

    if(avall) {

        for(int d = serplong-1; d>=0; d--) {
            longXserp[d+1] = longXserp[d];
        }

        for(int d = serplong; d>= 0; d--) {
            if(d==0) {
                longYserp[d] = longYserp[d] + 25;
            }

            else {
                longYserp[d] = longYserp[d-1];
            }

            if(longYserp[d] > 625) {
                longYserp[d] = 75;

            }
        }

        repaint();
    }
}   
}

我已经试图弄清楚出了什么问题好几天了。上述代码有什么问题?

1个回答

3
public void paint(Graphics g) { ..

这应该是:

public void paintComponent(Graphics g) { 
    super.paintComponent(g); ..

请注意两个重要区别:
  1. 覆盖任何类或扩展JComponentpaintComponent 方法。
  2. 在自定义绘图时调用超类方法以擦除先前的绘图

现在我更仔细地查看代码,还有其他提示:

  1. serpdreta = new ImageIcon("src/grafics/serpdreta.png"); 这种类型的资源加载不应该在绘图方法中完成,因为期望这些方法尽可能快地完成。相反,在类构造时加载图像并将它们存储为类的字段,以便在需要时使用。
  2. 但是当应用程序转换为Jar文件时,该路径很可能会失败。通常不包括src目录。
  3. 应用程序资源将在部署时成为嵌入式资源,因此现在开始访问它们就像它们已经是嵌入式资源一样是明智的。必须通过URL而不是文件来访问。有关如何形成URL,请参见嵌入式资源信息页
  4. 如果应用程序需要绘制图像,请创建Image而不是ImageIcon
  5. 为了更好地反馈加载图像的情况,请使用ImageIO.read(..)而不是创建ImageIcon,因为后者会在出现问题时默默失败,而ImageIO会提供有关任何问题原因的有用信息。
  6. 对于Swing,我们通常使用键绑定而不是较低级别的KeyListener

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接