贪吃蛇系列之七——有吃的啦

      在上一个小项目中,咱们遗留了一个小问题,就是咱们的蛇能够反向运动,这是不被容许的,所以呢,咱们先来修复这么一个小BUG。其实问题很简单,咱们只要保证蛇在向上的时候不能向下就是了,天然,咱们想到的最广泛的就是经过if语句来进行判断。没错,这样咱们确实能够达到目的,可是咱们的代码却很臃肿,很差。所以,咱们有更优雅的解决方案,仍是来看代码:
        /** 蛇前进的方向,向上 */
	public static final int DIR_UP = -1;
	/** 蛇前进的方向,向下 */
	public static final int DIR_DOWN = 1;
	/** 蛇前进的方向,向左 */
	public static final int DIR_LEFT = -2;
	/** 蛇前进的方向,想右 */
	public static final int DIR_RIGHT = 2;

        /**
         * 改变蛇的运动方向
         * @param direction	蛇的新的运动方向
         */
         public void changeDirection(int direction){
             if(this.direction + direction != 0){
                 this.direction = direction;
             }
         } 
我想各位聪明的看官已经很清楚了,咱们作了什么,这里运用了一点技巧,咱们把相反方向上的两个方向的值设置为一正一负,那么咱们的问题就解决了,也很优雅。嗯嗯,好了,再次运行你的程序,就算你把键盘戳烂了都不会出现那种状况了,呵呵。

      解决了一点小问题,咱们继续咱们的贪吃蛇。咱们的蛇到目前为止已经基本上OK了,接下来咱们将要开始对蛇的食物进行编码,咱们有吃的啦!!固然,咱们新建一个叫Food的类,放在com.gulang.snake.entity包下面。下面就是咱们编写的Food类,请看代码:
java

package com.gulang.snake.entity;

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;

import com.gulang.snake.view.GameView;

/**
 * 食物对象
 * @author jiladeyouxiang@qq.com
 *
 */
public class Food {
	
	/** 食物的大小,咱们这里是和蛇的一个身体节点同样大 */
	public static final int FOOD_SIZE = Snake.BODY_SIZE;
	
	/** 食物的位置,横坐标 */
	private int x;
	/** 食物的位置,纵坐标 */
	private int y;
	
	/**
	 * 构造一个食物对象,而且设置食物出现的位置在游戏的窗口上的任何一个有效的地方
	 * 1.不能出如今窗口外;
	 * 2.不能出如今有蛇的位置;
	 * 3.不能出如今有石块的地方
	 * 
	 * @param	游戏中的蛇的对象
	 */
	public Food(Snake snake){
		//咱们先将咱们的游戏窗口网格化,并计算出每一行有多少个单元格,每一列有多少个单元格
		int cellsInRow = GameView.WINDOW_WIDTH / Snake.BODY_SIZE;
		int cellsInCol = GameView.WINDOW_HEIGHT / Snake.BODY_SIZE;
		//咱们用随机数类来产生咱们的食物的横坐标和纵坐标,而且保证食物的坐标不产生在蛇的身体上
		Random r = new Random();
		do{
			createXY(r, cellsInRow, cellsInCol);
		} while (isInSnakeBody(snake));
	}
	
	/**
	 * 生成新的食物的坐标
	 * @param r				随机数对象
	 * @param cellsInRow	一行中的单元格个数
	 * @param cellsInCol	一列中的单元格个数
	 */
	private void createXY(Random r, int cellsInRow, int cellsInCol){
		x = r.nextInt(cellsInRow) * Snake.BODY_SIZE;
		y = r.nextInt(cellsInCol) * Snake.BODY_SIZE;
	}
	
	/**
	 * 判断当前食物的位置是否在蛇的身体上
	 * @param snake	蛇
	 * @return		若是当前的食物在蛇的身体上则返回true,不然返回false
	 */
	public boolean isInSnakeBody(Snake snake){
		for(Snake.Body body : snake.getSnakeBody()){
			if(this.x == body.getX() && this.y == body.getY()){
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 将食物绘制出来
	 * @param g
	 */
	public void drawMe(Graphics g){
		//得到画笔原来的颜色
		Color c = g.getColor();
		//将画笔的颜色设置为绿色
		g.setColor(Color.GREEN);
		//绘制一个3D的绿色方块做为食物
		g.fill3DRect(x, y, FOOD_SIZE, FOOD_SIZE, true);
		//将画笔的颜色还原回去
		g.setColor(c);
	}
	
}
      咱们如今已经有了Snake类的经验,所以我想你们对于该类的理解应该不存在什么有困难的地方。固然,有几点关于游戏的细节仍是须要注意的,好比咱们Food的构造方法,咱们食物的产生地必须知足几个条件,这些我都写在注释上了,你们应该也看到了。接着呢,为了看到效果,咱们只须要在GameView中添加关于Food类的代码就能够了,我想可以看到这里的你也应该没有什么问题了,固然,惯例孤狼仍是贴一下代码,请看:
        /**
	 * 绘制界面的方法
	 */
	@Override
	public void paint(Graphics g) {
		//将窗口清空
		g.clearRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
		//绘制蛇的对象
		snake.drawMe(g);
		//绘制食物
		food.drawMe(g);
	}
      到这里呢,还有一点小问题,是咱们以前在写Snake类时留下来的,你们回想一下咱们在写Snake类时设置的蛇的边长是30,可是咱们的游戏的窗口的边长是800,这在咱们将窗口网格化的时候就会出现问题,致使咱们蛇的位置和食物的位置对不齐,所以呢咱们首先将蛇的身体的大小改成20,而后再将蛇的初始化位置修正。咱们原来是让蛇在窗口的正中央,可是网格化之后咱们须要的实际上是在最中间的那一个,所以咱们修改蛇的构造方法,看代码:
        /**
	 * 初始化一条蛇
	 */
	public Snake(){
		//初始化蛇最开始前进的方向为向右
		direction = DIR_RIGHT;
		//咱们将蛇的第一节身体初始化在游戏窗口的中央
		int cellsInRow = GameView.WINDOW_WIDTH / BODY_SIZE;
		int cellsInCol = GameView.WINDOW_HEIGHT / BODY_SIZE;
		int startX = cellsInRow / 2 * BODY_SIZE;
		int startY = cellsInCol / 2 * BODY_SIZE;
		//初始化蛇的身体,即向body链表中添加数据,咱们初始化蛇的初始节点为3个
		for(int i = 0; i < 3; i++){
			//逐个的计算出蛇的每个节点的位置
			Body body = new Body(startX - i * BODY_SIZE, startY);
			snakeBody.add(body);
		}
	}
      那么到这里呢,咱们的这个小项目就作完了,运行一下看看吧,是否是感受已经有一点贪吃蛇游戏的雏形了,仍是小有成就感的吧,呵呵。咱们如今能够控制咱们的蛇去吃食物了,可是遗憾的是蛇如今通过食物的时候还不能吃掉食物,这个咱们将在下一次的项目中来完成这个功能。那今天就到这里吧,晚安啦,各位,但愿天亮之后我还有机会完成后面的博文,呵呵,芥末日快乐啦。

我把代码都放在迅雷快传上了,你们奔走相告吧,这里给出连接,一篇博文对应一个项目文件,你们直接导入工程就能够运行: 
http://kuai.xunlei.com/d/nNdkCSP3vUXTUAQAa50
相关文章
相关标签/搜索