这个bug出现在我的java程序中似乎没有理由

时间:2013-07-11 20:21:27

标签: java image sprite

出于某种原因,当我的精灵击中左边的边缘时,它不会反弹。该程序运行良好,但后来我改变了一些真正应该对它没有任何影响的东西,它停止了工作。

//Sprite class

public class Sprite {
private String sprite = "sprite-adult.fw.png";

private int speed;
private int dx;
private int dy;
private int x;
private int y;
private Image image;

public Sprite() {
    ImageIcon ii = new ImageIcon(getClass().getResource(sprite));
    image = ii.getImage();

            speed=6;
            dx=speed;
            dy=speed;

    x = 40;
    y = 60;
}
public void move() {
    toggleRebound();

    x += dx;
    y += dy;
}
public void toggleRebound() {
    if(x == 1366) 
        dx = negate(dx);

    if(y == 768) 
        dy = negate(dy);

    if(x == 0) 
        dx = negate(dx);

    if(y == 0) 
        dy = negate(dy);    
}
public int negate(int x) {
    return x*-1;
}
public int getX() {
    return x;
}
public int getY() {
    return y;
}
public Image getImage() {
    return image;
}
}


//SType class

public class SType extends JFrame{
public SType() {
    add(new Board());

    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(1366,768);
    setLocationRelativeTo(null);
    setTitle("S - Type");
    setVisible(true);
    setResizable(false);
}
public static void main(String[] args) {
    new SType();
}
}

//Board class

public class Board extends JPanel implements ActionListener{
private Sprite sprite;
private Timer timer;

public Board() {
    setFocusable(true);
    setBackground(new Color(39,124,36));
    setDoubleBuffered(true);

    sprite = new Sprite();

    timer = new Timer(5,this);
    timer.start();
}
public void paint(Graphics g) {
    super.paint(g);

    Random rand = new Random(5398);
    for(int x=0;x<1000;x++) {
        g.setColor(new Color(22,98,19));
        g.drawOval(rand.nextInt(1368), rand.nextInt(768), 1, 20);
    }

    Graphics2D g2d = (Graphics2D)g;
    g2d.drawImage(sprite.getImage(),sprite.getX(),sprite.getY(),this);

    Toolkit.getDefaultToolkit().sync();
}
public void actionPerformed(ActionEvent arg0) {
    sprite.move();
    repaint();
}
}

2 个答案:

答案 0 :(得分:2)

第一个回答者是正确的,这不应该影响任何事情。虽然它在这个例子中并不真正相关,但是在构造函数中初始化私有实例变量而不是声明它们是一种很好的形式。

private int speed;
private int dx;
private int dy;

public Sprite()
{
    speed=6;
    dx=speed;
    dy=speed;
}

答案 1 :(得分:1)

这里有两课可以学习

首先,您遇到的真正问题是,您正在检查零点的反弹为零(或您的硬编码左/顶尺寸)。这意味着如果您一次移动多个像素(就像在上面的代码中一样),您可能会错过边框并通过它。

一般来说,检查极限等于极限通常是一种好习惯,特别是当有可能一次“移动”多个时。

例如,如果要编写数组类,则不会使用((idx == 0) or (idx == length))进行边界检查。您需要检查((idx <= 0) or (idx >= length))

与精灵位置相同。

其次,检查您的假设总是有用的,特别是当您的期望被违反时。在这种情况下,您确信一个非常简单的更改已经破坏了您的程序。

但事实并非如此。这不可能是真的。在任何情况下都不是这样的:

private int dx = 6;
private int dy = 6;

与此不同:

private int speed = 6
private int dx = speed;
private int dy = speed;

在您的两个测量点(工作,非工作)之间发生了其他变化。这种额外的改变完全有可能以某种方式掩盖了你 - 也许是因为编译错误,或者你只是在看程序的其他方面,而不是让它反弹。但无论出于什么原因,其他一些事情都发生了变化。

在这种特殊情况下,您可能还更改了起点或速度值。

但无论什么原因,当你遇到一个不可能的点时,你必须回去重新检查你的假设。

但无论如何,这就是问题所在:你的精灵“移动”得太快,以至于你目前的反弹无法抓住它。改为小于等于测试,将是我的建议。

你错了。进行此更改,仅进行此更改,不会导致您报告的行为发生更改。

最有可能的是,您实际上进行了多次更改,但仅在此之后测试了反弹行为。