4

我决定使用 Java 重新创建 Snake,但我有点卡住了。目前,我有一个正方形,用户可以使用箭头键在屏幕上移动。当您按一次 LEFT 时,方块开始使用计时器向左移动。您无需按住键或一直按住它;当您按下任何其他设置的键(右,上,下)时,它会改变方向。我的目标是使用 ArrayList 来保存构成蛇的方块。目前,我已经创建了一个 ArrayList,其中只有一个 Snake 对象,如果我将第二个 Snake 对象添加到列表中并将其添加到框架(第一个),则只有一个 Snake 对象是可见的并且键移动它不起作用。我正在寻找一些关于如何推进这个项目的想法 - 请不要给我完整的答案,因为我 我想自己解决大部分问题;我只是需要一些方向。在此先感谢 - 代码如下。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Snake extends JPanel implements KeyListener, ActionListener
{
int x = 0, y = 0, velx = 0, vely = 0;
Timer t = new Timer(250, this);


public Snake(int num1, int num2)
{
    t.start();
    addKeyListener(this);
    setFocusable(true);
    setFocusTraversalKeysEnabled(true);
    x = num1;
    y = num2;
}
public void paintComponent(Graphics g)
{   
    super.paintComponent(g);

    g.setColor(Color.blue);
    g.fillRect(x, y, 20, 20);
}
public void actionPerformed(ActionEvent e)
{
    repaint();
    x += velx;
    y += vely;
}
public void up()
{
    vely = -20;
    velx = 0;
}
public void down()
{
    vely = 20;
    velx = 0;
}
public void left()
{
    vely = 0;
    velx = -20;
}
public void right()
{
    vely = 0;
    velx = 20;
}
public void keyPressed(KeyEvent e)
{
    int code = e.getKeyCode();

    if(code == KeyEvent.VK_UP)
        up();
    else if(code == KeyEvent.VK_DOWN)
        down();
    else if(code == KeyEvent.VK_RIGHT)
        right();
    else if(code == KeyEvent.VK_LEFT)
        left();

}
public void keyReleased(KeyEvent e)
{

}
public void keyTyped(KeyEvent e)
{

}
}
//Driver Class
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class UserClass
{
private static JFrame frame = new JFrame("Snake");
private static ArrayList<Snake> mySnake = new ArrayList<Snake>();

public static void main(String[] args)
{
    frame.setSize(500,500);
    frame.setBackground(Color.black);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    mySnake.add(new Snake(20,20));
    frame.add(mySnake.get(0));
}
}

PS当我在Mac上的Eclipse中输入相同的代码时,我的框架背景是黑色的,但在Windows上它是浅灰色的......有人知道为什么吗?谢谢。

4

3 回答 3

5

paintComponent(...)只画了一个矩形。相反,如果你想绘制多个矩形或椭圆形,或者其他什么,给你的类一个List<Point>or List<Rectangle2D>,然后在你的 Swing Timer 中,从列表中删除尾部并添加一个新的头部。然后paintComponent()使用 for 循环遍历列表,绘制列表中的所有矩形。

此外,您可能希望使用键绑定而不是 KeyListener 来获取用户的按键,因为当其他组件窃取焦点时,这会更好地工作。

于 2012-06-09T22:10:17.947 回答
5

要回答您的后记,请设置背景颜色或在其他所有内容后面制作一个 JPanel,并涂上颜色。

要推进项目,请考虑将其作为 MVC 框架中的练习。现在发生的事情是您的模型和视图链接在同一个类中 - 这使得很难遵循所有内容背后的逻辑。

您可以做的是首先将您的 Snake 与与视图有关的任何事情分开 - 用 anArrayList<Integer[]> segmentLocations或其他东西制作一条蛇,以表示您定义的板上每个段位置的 (x,y) - 您可以使用绝对坐标,或者您可以在视图中创建任意网格并更改为绝对坐标(这更好地代表了 MVC 关系)。Snake 还应该有一个表示蛇所面对方向的字段——我会使用enum Direction {N, S, E, W},但你可以选择,因为你也可以有一个表示方向的整数,或各种其他方式。

然后,您的 Snake 也将有方法进行自我更新 - move(),根据初始段的当前方向移动所有段的位置,并导致所有其他段跟随它之前的移动(这如果您考虑几分钟,这很容易)。

您的视图可能是一个 JFrame,其 GridLayout 由 JPanel 组成,这些 JPanel 轮询您的 Snake 实例并查看该位置是否有一个段,如果有,则绘制它,或许多其他选项。

您的控制器将是 KeyAdapter,当按下箭头键时,它会向您的 Snake 发送更新。

小提示,让您的生活更轻松:当您添加新段时,只需将其放在 Snake 的最后一段的位置即可。下次它移动时,新的段将在相同的位置,并且 Snake 的其余部分应该相应地移动。

于 2012-06-09T22:12:01.460 回答
4

给定一个定义段几何的类,

class Segment {
    private int x, y, d;

    public Segment(int x, int y, int r) {
        this.x = x - r;
        this.y = y - r;
        this.d = 2 * r;
    }
}

考虑一个段队列,

Queue<Segment> snake = new LinkedList<Segment>();

然后每次迭代都很简单

snake.remove();
snake.add(new Segment(...));

paintComponent()包括这个循环

@Override
public void paintComponent(Graphics g) {
    ...
    for (Segment s : snake) {
        g.fillXxxx(s.x, s.y, s.d, s.d);
    }
    ...
}
于 2012-06-09T23:18:19.977 回答