貪吃蛇系列之五——動起來

      今天這篇文章原本應該早些時候就應該發佈出來的了,可是今天孤狼去參加頒獎典禮去了,耽擱了些時間,呵呵,因此就晚了一些。今天領獎,很高興,仍是說出來跟你們分享一下吧,孤狼參加了移動在學校作的比賽,有幸獲了獎:


固然,姓名和獎金我給P掉了,呵呵,仍是值得高興一下的。這款軟件呢是基於Android平臺的,軟件會在以後公佈源代碼,而且將這個項目的開發過程也挨着挨着分解開給你們探討和學習。那麼說到這裏呢,孤狼仍是簡單的說一下個人一個簡單的計劃吧,由於今天也看到了你們給個人留言,很謝謝你們對個人支持與鼓勵。貪吃蛇呢只是做爲一個引入,或者說是對於J2SE的一個簡單的整合,這個遊戲自己不是重點。在作完這個遊戲的初版以後,孤狼會嘗試着和各位一塊兒進行更深層次的挖掘,方向呢是關於設計模式和軟件架構的,我寫項目這麼長時間以來,仍是以爲這一塊頗有學問也頗有意思,也但願和你們一塊兒探討一下。而後呢,孤狼博客的重點仍是在JavaEE的技術和框架應用上,固然,也會同步更新Android平臺上的相關項目的開發過程。這些咱們須要涉及的話題呢,他們都有一個共同點,就是都使用Java做爲編程語言,這也就是爲何我會選擇一個比較的蹩腳的遊戲開始的緣由。固然,在進行項目的過程當中,孤狼儘量的會從一個軟件代碼開發的各個階段去進行撰文,這裏面也包含了UI設計。我我的雖然比不了那些專業的設計師,可是仍是作過不少項目的UI設計,PhotoShop用的也還比較熟練,所以在這方面個人博文也會有所涉及,但願能夠幫助你們對軟件開發有一個比較全面的認識。
     
好了,下面咱們進入咱們此次的項目。首先咱們要作的固然是在Snake類中添加蛇運動的方法move,下面是該方法的代碼: java

        /**
	 * 蛇移動的方法
	 */
	public void move(){
		//1.去尾。這個很簡單,意思就是說去掉咱們snakeList的最後一個元素
		snakeBody.removeLast();
		 //2.加頭。這個就相對複雜一點,須要咱們根據蛇當前運動的方向來判斷咱們的蛇頭應該加在什麼位置
		Body head = snakeBody.getFirst();//得到當前蛇頭的那個對象
		switch(direction){
		case DIR_UP:
			snakeBody.addFirst(new Body(head.x, head.y - BODY_SIZE));
			break;
		case DIR_DOWN:
			snakeBody.addFirst(new Body(head.x, head.y + BODY_SIZE));
			break;
		case DIR_LEFT:
			snakeBody.addFirst(new Body(head.x - BODY_SIZE, head.y));
			break;
		case DIR_RIGHT:
			snakeBody.addFirst(new Body(head.x + BODY_SIZE, head.y));
			break;
		}
	}
在這個方法中,按照咱們分析的蛇的運動方式的算法,咱們先去掉蛇尾,再在合適的位置加上咱們新的蛇頭。
      接下來呢,咱們就要在線程中來不斷的調用咱們蛇的move方法而且不斷刷新咱們的遊戲窗口,這個原理我想你們都很清楚,和動畫片的實現是一個道理。仍是先看線程部分的代碼:
        /**
	 * 遊戲的主線程
	 * @author jiladeyouxiang@qq.com
	 *
	 */
	class GameThread extends Thread{
		
		/** 控制遊戲開始於暫停的標誌 */
		private boolean isRunning = true;
		
		/**
		 * 設置遊戲的運行狀態,運行或是暫停
		 * @param isRunning	讓遊戲運行則傳入true,讓遊戲中止則傳入false
		 */
		public void setIsRunning(boolean isRunning){
			this.isRunning = isRunning;
		}
		
		/**
		 * 構造一個遊戲的運行線程對象
		 * @param isRunning	讓遊戲運行則傳入true,讓遊戲中止則傳入false
		 */
		public GameThread(boolean isRunning){
			setIsRunning(isRunning);
		}
		
		/**
		 * 線程執行的具體邏輯
		 */
		public void run(){
			//咱們讓線程在循環中每隔1000毫秒執行一次
			while(isRunning){
				//更新遊戲的數據
				updateGame();
				//刷新遊戲界面
				repaint();
				//讓線程休眠100毫秒後繼續執行
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
這個類呢咱們一樣採用內部類的形式來實現,由於咱們的這個線程只須要獲取GameView中的數據,而且其餘的類也不須要調用它。線程的基本概念呢孤狼就不講了,但願不理解線程的同窗本身去查閱相關的資料。在線程中呢,最重要的就是要去重寫run方法,在run方法中去實現咱們本身的邏輯。你們能夠看到,咱們在run方法中作了這麼幾件事情,首先是更新遊戲的數據,而後是讓界面進行重繪。在這裏,孤狼解釋一下repaint()方法,當咱們調用這個方法的時候,咱們的java虛擬機會去調用咱們的paint(Graphics g)這個方法,也就是咱們寫在GameView中的繪製遊戲界面的方法。接着,咱們讓線程休眠1000毫秒,近似於1秒。這個值主要是咱們來模擬遊戲的運行速度,或者說是一個簡單的控制遊戲的幀數。固然,真實的遊戲線程不會這麼簡單,我只是進行了簡單的模擬,在遊戲的線程中這部分要複雜的多,光幀數的控制就有多種方式,感興趣的同窗能夠去查閱和遊戲線程相關的資料,這不是咱們研究的重點。接着呢,你們能夠看到咱們在這個線程中還設置了一個標誌來控制遊戲的暫停和運行。

      接着,咱們在GameView中寫一個新的方法updateGame(),意思就是,咱們全部遊戲的數據更新都在這個方法中去完成,有利於咱們的代碼維護和管理:
算法

        /**
	 * 刷新遊戲的數據
	 */
	public void updateGame(){
		snake.move();
	}

      有了咱們遊戲的主線程,那麼咱們就只須要在GameView中的initGameData()方法中加上關於線程的部分就能夠了,下面是代碼:

        /**
	 * 初始化和遊戲相關的數據
	 */
	private void initGameData() {
		//構造蛇的對象
		snake = new Snake();
		//初始化遊戲的主線程
		gameThread = new GameThread(true);
		//讓遊戲的主線程開始運行
		gameThread.start();
	}
     到這裏呢,基本上咱們的項目已經完成了,最後有一個細節:咱們須要修改paint()方法:

        /**
	 * 繪製界面的方法
	 */
	@Override
	public void paint(Graphics g) {
		//將窗口清空
		g.clearRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
		//繪製蛇的對象
		snake.drawMe(g);
	}
咱們每次繪製以前都須要將窗口清空,要否則你會發現你的蛇會不斷邊長,緣由是什麼呢,就是之前繪製的那些數據沒有被清除。       至此,你就能夠點擊運行試試看了,是否是咱們的蛇就開始運動了,不過貌似咱們的蛇如今一路向東,撞了東牆都不回頭,這個呢,咱們在下一個版本中進行修復,好了,就到這吧。       我把代碼都放在迅雷快傳上了,你們奔走相告吧,這裏給出連接,一篇博文對應一個項目文件,你們直接導入工程就能夠運行: http://kuai.xunlei.com/d/nNdkCUf1HBXTUAQA44e
相關文章
相關標籤/搜索