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

      在上一個小項目中,咱們遺留了一個小問題,就是咱們的蛇能夠反向運動,這是不被容許的,所以呢,咱們先來修復這麼一個小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
相關文章
相關標籤/搜索