我决定使用Java重新创建Snake,但我有点陷入困境。目前,我有一个方块,用户可以使用箭头键在屏幕上移动。当您按下LEFT一次时,方块开始使用计时器向左移动。您不需要按住键或继续按下它;当您按下任何其他设置的键(右,上,下)时,它会改变方向。我的目标是使用ArrayList来保存构成蛇的方块。目前,我已经创建了一个只包含一个Snake对象的ArrayList,如果我将第二个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));
}
}
P.S当我在Mac上将相同的代码放在Eclipse中时,我的框架的背景是黑色的,但在Windows上它是浅灰色的......任何人都知道为什么?感谢。
答案 0 :(得分:5)
您的paintComponent(...)
仅绘制一个矩形。相反,如果你想绘制多个矩形或椭圆形,或者其他什么,给你的班级List<Point>
或List<Rectangle2D>
,并在你的Swing Timer中,从列表中删除尾部并添加一个新头。然后让paintComponent()
使用for循环遍历列表,绘制列表中的所有矩形。
此外,您可能希望使用key bindings而不是KeyListener来获取用户的按键,因为当其他组件窃取焦点时,这将更有效。
答案 1 :(得分:5)
要回答您的附言,请设置背景颜色或使用彩绘颜色制作JPanel。
为了推进项目,请考虑将其作为MVC框架中的练习。现在发生的事情是你的模型和视图被链接在同一个类中 - 这使得很难遵循一切背后的逻辑。
你可以做的是首先将你的蛇与视图分开 - 用ArrayList<Integer[]> segmentLocations
或其他东西制作蛇,以代表棋盘上每个分段位置的(x,y)您定义的 - 您可以使用绝对坐标,或者您可以创建任意网格并更改为视图中的绝对坐标(这更好地代表了MVC关系)。 Snake还应该有一个蛇面朝向的方向 - 我会使用enum Direction {N, S, E, W}
,但你有选择,因为你也可以有一个表示方向的整数,或者其他各种方式。
你的Snake也会有自己更新的方法 - move(),根据初始段的当前方向移动所有段的位置,并使所有其他段跟随前一段的移动它(如果你考虑几分钟,这很容易)。
您的视图可能是一个带有GridLayout的JFrame,其中包含JPanels,用于轮询您的Snake实例并查看该位置是否有某个段,如果有,请绘制它或其他众多选项。
您的控制器将是KeyAdapter,当按下箭头键时,它会向Snake发送更新信息。
小提示,让您的生活更轻松:当您添加新细分时,只需将其放在Snake最后一段的位置即可。下次移动时,新段将位于同一位置,其余的Snake应相应移动。
答案 2 :(得分: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);
}
...
}