package com.gulang.snake.entity;
import java.awt.Color;
import java.awt.Graphics;
import com.gulang.snake.view.GameView;
/**
* 石头
* @author jiladeyouxiang@qq.com
*
*/
public class Stone {
/** 石头的大小 */
private final static int SIZE = Snake.BODY_SIZE;
/** 石头绘制的横坐标 */
private int x;
/** 石头绘制的纵坐标 */
private int y;
/**
* 构造一个石头对象
*/
public Stone(){
//我们在游戏窗口的左下角生成一块石头
x = 0;
y = GameView.WINDOW_HEIGHT - SIZE;
}
/**
* 绘制石块
* @param g
*/
public void drawMe(Graphics g){
Color c = g.getColor();
g.setColor(Color.GRAY);
g.fill3DRect(x, y, SIZE, SIZE, true);
g.setColor(c);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
能够学习到这里的您,我想这个类的意思已经不用我多做解释了,我也就不再解释了。接着,我们在Snake类中照旧添加两个方法,代码如下:
/**
* 判断蛇是否吃到了石头
* @return 如果蛇吃到了石头则返回true,否则返回false
*/
public boolean isEatStone(){
Body head = snakeBody.getFirst();
Stone stone = gameView.getStone();
if(head.x == stone.getX() && head.y == stone.getY()){
return true;
}
return false;
}
/**
* 蛇死亡的方法
*/
public void die(){
gameView.gameOver();
}
这两个方法呢,如果你已经理解了食物的逻辑,那这两个类对你来说已然不是什么大的问题。这两个方法我们在哪里去调用呢?答案还是在蛇的move()方法中,于是,我们在蛇的move()方法前添加下面的代码:
//判断蛇是否吃到了石头
if(isEatStone()){
die();
}
让蛇在每一次移动之前都去检查是否撞到了石头,撞到了就让游戏结束。
下面呢,我们说一下die()方法,如大家所见,我们在蛇的die()方法中,调用了游戏窗口方法的gameOver()方法,因此,我们自然要去实现这个方法,代码如下:
/**
* 游戏结束的方法
*/
public void gameOver(){
//我们在这里让玩家死亡之后立刻重新开始游戏
initGameData();
}
我们在这里处理游戏结束的方式呢是让游戏重新开始,当然,这是我们进行简单的处理。这里呢,为了可以不停止游戏的主线程,我们需要对initGameData()做一点修改,大家看下面的代码:
/**
* 初始化和游戏相关的数据
*/
private void initGameData() {
//构造蛇的对象
snake = new Snake(this);
//初始化食物对象
food = new Food(snake);
//构造石头对象
stone = new Stone();
//初始化游戏的主线程
if(gameThread == null){
gameThread = new GameThread(true);
}
//让游戏的主线程开始运行
if(!gameThread.isAlive()) {
gameThread.start();
}
}
我们主要就是实现了再重置游戏数据的时候不影响游戏主线程,也是很简单,大家一眼就明白了。那么到这里,我们这个版本的贪吃蛇就基本上完成了,运行看看吧,当蛇吃到石头之后我们的游戏就会被重置。在下一个版本中,我们将实现游戏地图的绘制,大家也看到了,在我们这个版本中我们的石头只有一个,显然这是不合理的嘛。所以,下个版本再见吧。
下面是这个版本和之前版本的源代码地址: http://kuai.xunlei.com/d/Ae2cAyx1YfjeUAQAa6e