昨天的代码
昨天的贪吃蛇已经做到了可以基本显示界面的状态,所以今天的主要任务就是使我们的蛇动起来,并且能够根据你的键盘操作来控制蛇的移动。
一.使蛇动起来。
// 刷新线程
class FlashThread implements Runnable {
// 核心代码写到这里
@Override
public void run() {
// TODO Auto-generated method stub
// 一直刷新
while (true) {
// 核心函数,每次执行就执行paint重画JFrame
repaint();
try {
// 通过线程睡眠可以控制刷新时间,也就表现为蛇的速度
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
然后就是可以在 startGame()方法中将线程开启new Thread(flashThread).start();
但是在写完后运行你会发现蛇并没有移动,这是为什么呢,是因为尽管你一直在调用刷新线程,并且同时一直在调用paint方法,但是在调用蛇的draw时,蛇的位置并没有发生改变,所以体现出来便为蛇静止不动,此时你可以在蛇的draw中加一个move()方法,作为测试加深印象,
// 将蛇显示出来
public void draw(Graphics g) {
// TODO Auto-generated method stub
move();
// 显示所有节点
for (Node n = head; n != null; n = n.next) {
n.draw(g);
}
}
// 蛇的移动
private void move() {
// TODO Auto-generated method stub
head.x++;//先模拟一下
}
现在再运行你会发现蛇就会动了,所以此时的问题就是蛇的移动怎么实现,上面的只是在只有一个头的情况下才能执行,但是当蛇是一条很多的点构成的话其移动式怎么回事呢?其实蛇的移动你可以把它看作是将尾巴放到了头上,就是蛇的移动(及前面加一个,后面少一个),所以现在问题就是怎么把蛇前面加一个节点与后面少一个节点呢?其实删除很简单就把tail向前挪一下就可(想一下数据结构中的链表)代码如下
// 蛇的运动主要是删尾 加头
private void deleteTail() {
tail = tail.pre;
tail.next = null;
}
但是加头就稍微麻烦一点,主要是因为头还要控制整条蛇的方向所以在加头的时候要把方向也要考虑进去,不同的方向,头的位置增加的数不一样,比如像左的时候,则y不变,x减一,。。所以加头代码如下
// 在头的位置加一个节点
private void addHead() {
Node n = null;
// 根据头的方向确定位置
switch (head.dir) {
case LEFT:
n = new Node(head.x - 1, head.y, head.dir);
;
break;
case UP:
n = new Node(head.x, head.y - 1, head.dir);
break;
case RIGHT:
n = new Node(head.x + 1, head.y, head.dir);
;
break;
case DOWN:
n = new Node(head.x, head.y + 1, head.dir);
;
break;
}
// n变为新头
n.next = head;
head.pre = n;
// 重新给头赋值
head = n;
}
在写完这两个方法后move方法也就完成了所以重新写move
// 蛇的移动
private void move() {
// TODO Auto-generated method stub
// head.x++;// 先模拟一下
// 实际代码
addHead();
deleteTail();
}
此时工作已完成了一大半。
二.使蛇受控制
- 控制蛇则主要是写键盘监听算法,同样监听可以用内部类,也可以用外部类这里采用内部类,其中内容主要就是获取事件源,然后根据事件做出响应,主要就是响应键盘的方向键,当你按下上下左右时,就意味着对蛇的方向做出了改变,此时需要对蛇头方向进行更改,并且要注意如果蛇本身朝左走,则不能更改为右,代码如下
// 键盘监听
class KeyListen extends KeyAdapter {
// 重写见键盘按下的方法
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
// key临时储存事件源的标识
int key = e.getKeyCode();
// 根据不同事件做不同操作
switch (key) {
case KeyEvent.VK_LEFT:
if (snake.head.dir != Dir.RIGHT)
snake.head.dir = Dir.LEFT;
break;
case KeyEvent.VK_UP:
if (snake.head.dir != Dir.DOWN)
snake.head.dir = Dir.UP;
break;
case KeyEvent.VK_RIGHT:
if (snake.head.dir != Dir.LEFT)
snake.head.dir = Dir.RIGHT;
break;
case KeyEvent.VK_DOWN:
if (snake.head.dir != Dir.UP)
snake.head.dir = Dir.DOWN;
break;
}
}
}
写完监听,则只需要将其加到JFrame中即可,所以先声明一个对象KeyListen listen = new KeyListen();
然后再构造函索或者startGame函数中增加事件监听
this.addKeyListener(listen);
此时几乎就接近尾声了,主体功能就差一个能够吃食物了。
留做明天的任务。
因为这个明天有点久所以放个链接
明天的内容