貪吃蛇系列之十——遊戲地圖

        在上一個項目中,咱們已經有了石塊的對象,可是問題就是咱們只繪製了一塊石頭,這可不是咱們想要的最終結果,因此,在這個版本中,咱們將引入一個新的類,GameMap,一樣的,新建這個類,放在咱們的com.gulang.snake.entity包中。下面呢,就是咱們這個遊戲地圖的代碼,你們請看:

package com.gulang.snake.entity;

import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;

/**
 * 遊戲的地圖
 * @author jiladeyouxiang@qq.com
 *
 */
public class GameMap {
	
	/** 地圖數據 */
	private int[][] mapData = new int[][]{
		{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
		{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
		{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
	};
	/** 裝遊戲中石頭的集合 */
	private List<Stone> stones = new ArrayList<Stone>();
	
	/**
	 * 遊戲地圖的構造方法
	 */
	public GameMap(){
		for(int row = 0; row < mapData.length; row++){
			for(int col = 0; col < mapData[row].length; col++){
				if(mapData[row][col] == 1){
					stones.add(new Stone(col * Stone.SIZE, row * Stone.SIZE));
				}
			}
		}
	}
	
	/**
	 * 繪製遊戲的地圖
	 * @param g
	 */
	public void drawMe(Graphics g){
		for(Stone stone : stones){
			stone.drawMe(g);
		}
	}

	public List<Stone> getStones() {
		return stones;
	}
	
}
        這裏呢,我仍是簡單的來講明一下咱們的遊戲地圖是怎麼一回事。在咱們的遊戲開發中呢,遊戲的地圖是很重要的一部分,一般在咱們的遊戲開發中,咱們的遊戲開發引擎會提供給咱們一個地圖編輯器,我想緣由你們也很清楚了,看了咱們上面的代碼。在咱們的遊戲中,不一樣的素材會有不一樣的特性,就好比說咱們這個遊戲中石頭和食物就是兩種很類似的可是卻擁有不一樣特性的對象。這些對象的特性對於咱們來講是有意義的,可是對於計算機而言,他們是同樣的。因此要想讓計算機知道這是不一樣的兩個對象,咱們就要先制定一些約定,好比說咱們這個地圖對象中,咱們就約定0表示什麼都沒有,1表示的是石頭。所以地圖編輯器就會把咱們遊戲中全部合法的素材都提供給咱們,咱們用這些素材去組拼出一個遊戲的地圖。最後生成的就是一個多維的數組,就是咱們GameMap類中的mapData數組。固然,咱們這裏的環境是很簡單的,所以咱們本身就能夠直接用二維數組的方式寫出來了,在真是的遊戲中地形是能夠設計的很複雜的,那時候再直接用1,2,3,4來構造就比較困難了,所以咱們的遊戲引擎必定會有一個可視化的地圖編輯器提供給咱們使用,有興趣的同窗能夠本身去寫一個咱們貪吃蛇的地圖編輯器,咱們在這裏就再也不深刻的討論這個了。
        好了,這個類也比較簡單,主要就是負責地圖的建立和繪製。惟一須要你們注意的就是咱們在構造地圖的時候,設置石頭的座標的時候要注意row和col的位置噢,這個地方的座標轉換要細心一點。固然,作錯了也沒關係,運行以後發現不是咱們要的效果能夠回來改的嘛。我想你們看這個數組的構造也知道咱們在遊戲窗口的四周布上了石塊,運行後獲得的結果以下圖:

        至於爲何咱們在頂上放了兩排石塊呢,是由於咱們的遊戲窗口上面的一部分被窗口的標題欄遮住了,爲了可以讓你們看到效果,我就設置了兩排。
        那麼有了咱們的遊戲地圖後,咱們就不須要直接去繪製石塊了,所以,咱們去掉GameView中對Stone的引用,改成對GameMap的引用。同時,咱們須要修改Snake類中的isEatStone()方法,修改後的方法以下:
        /**
	 * 判斷蛇是否吃到了石頭
	 * @return		若是蛇吃到了石頭則返回true,不然返回false
	 */
	public boolean isEatStone(){
		Body head = snakeBody.getFirst();
		List<Stone> stones = gameView.getGameMap().getStones();
		for(Stone stone : stones){
			if(head.x == stone.getX() && head.y == stone.getY()){
				return true;
			}
		}
		return false;
	}
        這段代碼我也就不解釋了,我想你們也都看明白了。那麼到這裏,咱們這個版本的貪吃蛇就算完成了,運行看看,嗯,跟咱們記憶中的貪吃蛇遊戲已經比較類似了。可是咱們運行一段時間後就會發現,咱們食物有時候居然會跑到石頭上面去,這顯然是不合理的,所以,咱們在Food類中添加下面的方法,來確保食物在生成的時候不會跑到石頭上面:
        /**
	 * 判斷食物是否出如今石塊上
	 * @return	若是食物出如今石塊上則返回true,不然返回false
	 */
	public boolean isOnStones(){
		List<Stone> stones = gameView.getGameMap().getStones();
		for(Stone stone : stones){
			if(x == stone.getX() && y == stone.getY()){
				return true;
			}
		}
		return false;
	}
        這段代碼呢我想也不用我多作解釋了,而後咱們在Food類中的構造方法中加上對這個方法的調用就能夠了。
do{
	createXY(r, cellsInRow, cellsInCol);
} while (isInSnakeBody(snake) || isOnStones());
        嗯嗯,至此,咱們這個貪吃蛇的項目就基本上完成了,運行一下,基本上已經沒有大問題了。最後呢,還存在一些其餘的問題咱們尚未處理,好比說咱們的蛇如今是能夠穿過本身的身體的,這顯然也是不能夠的,這個問題呢,咱們放在下一個項目中來解決。同時,想一個項目中咱們也對這個小項目來作一下總結,畢竟除了作,咱們更多的是須要反思與總結,這樣才進步的更快。那麼,下個項目再見吧。
        一樣的,這個項目和之前項目的源文件: http://kuai.xunlei.com/d/Ae2cA1x2zAzfUAQA7a7
相關文章
相關標籤/搜索