1. 程式人生 > >追逐演算法之--牛鞭的子彈是怎樣練成的(1)--遊戲主框架

追逐演算法之--牛鞭的子彈是怎樣練成的(1)--遊戲主框架

       從小我就知道,我這輩子註定不會有什麼出息,縱觀古今中外大人物的童年,不是像丘吉爾,愛因斯坦這樣的智障腦殘,就是像馬克思,李嘉誠這樣的貧困兒童。而我,從小作為一個公認的神童,幾乎每個見了我的人,都要指著我的鼻子誇個半天。我不禁仰天長嘯,“老天啊,你大爺的為什麼對我這麼不公平!“

    想當年我還是六七歲的小孩,就已經開始了自己創業之旅,每個月都可以有10—200塊以上不等的穩定收入。主要的盈利模式有兩種:第一種模式收益較低,就是每當父母上班之後,把他們所有的衣服口袋挨個翻一遍,一般可以找到一些零星的硬幣,積少成多,一個月也能有至少5塊以上的收益,雖然收益少了一些,但是畢竟風險小,父母不易察覺。(ps:

那時的遊戲幣一塊錢10個,現在的一塊錢至多2個,因此那會的5塊大約相當於現在的25元)。

    第二種盈利模式,收益就很高了,就是直接翻錢包,這個具體的收益要依據個人的風險承擔能力,和個人魄力來決定了,一般收益至少在10元以上,當然這種方式的風險很大,通常都會被發現。而我作為一個公認的膽大心細的神童,主要的收入都是靠後一種方式。

    神童歸神童,被發現的情況還是常事,每當父母板著臉過來質問我錢怎麼沒了,我通常會極其驚訝的大叫起來“我的天!你怎麼又丟了錢!“或者一臉無辜並且莫名其妙的說”What? I Don't Know What Are You Talking About!“,只要表情,語氣夠到位,通常你的父母不會認為自己生了個逆子,而會認為自己提前患上了老年痴呆。我不是一個愛看書的人,但一直有一本書常備我的案頭---

《演員的自我修養》

    ok!下面開始我們今天的第一次遊戲AI的學習之旅,首先我們需要先搭一個簡單的遊戲框架做為AI演示的平臺,這裡我採用javaSwing來搭建基本的框架,這並不是我們教程的重點,實際上你會不會都沒有關係,因為一來這個框架極其簡單,加起來不到200行的程式碼。另一方面,我不希望這些細枝末節影響到我們AI教學的純粹性,當各位碼農兄弟在實際開發的時候,其實是有現成的引擎把這些框架搭好的。如果你非要研究一下,其實也不是什麼問題,因為框架的每一句話我都加上了註釋。不過我建議如果你看不懂,那麼就別看了,反正看著心裡也是病。

    下面我簡單的介紹一下游戲主框架的各個部分,我們今後的每一個AI

教程都是在這個框架上來進行開發,所以原始碼請大家好好的保留。

     在開始講解前我首先要很嚴肅的對整個程式界提出一個鄭重的意見,幾乎我看到的所有有關程式語言的書,或是有關計算機任何方面的書都像著了魔似地,總是在第一課讓讀者列印一句“hello world”,作為一個神童,我對這個極端教條式的教學方式表達強烈的不滿,因此今天,我教大家列印兩句! 

下面的GameFrame類就是遊戲的主入口,如果你要運行遊戲,那麼就在這個類裡面進行

import java.awt.Container;

import javax.swing.JFrame;
public class GameFrame extends JFrame{
	public static GameHandler gameLogical;
	public static GamePanel gamePanel;
	public GameFrame() {
        //設定窗體標題
        setTitle("追蹤AI之牛鞭的子彈該怎麼玩");
  
        //例項化自定義面板
        gamePanel = new GamePanel();
        
        //處理遊戲的主邏輯
        gameLogical= new GameHandler();
        
        //啟動主邏輯執行緒
        new Thread(gameLogical).start();
        
        //獲得當前窗體[容器]的例項,實際上可以直接設定
        Container contentPane = getContentPane();

        //載入自定義的面板到窗體中,就好比在底板上再帖一層畫面。
        //也就是說顯示什麼內容,是由我們載入那個[面板]來決定的,可以輕鬆
        //的實現遊戲中不同畫面間的切換.
        contentPane.add(gamePanel);

        //自動整合窗體
        pack();
    }

	//程式的總入口
	public static void main(String[]args){
		GameFrame gameFrame=new GameFrame();
        
		//令窗體接受關閉[事件]
         gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         
         //讓窗體顯示
         gameFrame.setVisible(true);
	}
}

下面的GamePanel類主要用來設定遊戲視窗面板的一些初始化屬性,對於我們來說,你完全可以忽略掉這個類,因為在後面的學習中,你沒有機會觸碰到它

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JPanel;


public class GamePanel extends JPanel implements KeyListener{
   
    public GamePanel() {
    //設定背景顏色R,G,B引數,
    setBackground(new Color(0,0,0));
    
    //設定面板的預設大小
    setPreferredSize(new Dimension(GameLogical.FRAME_WIDTH, GameLogical.FRAME_HEIGHT));      
   
    //設定焦點在本窗體並付與監聽物件
    setFocusable(true);
    addKeyListener(this);
    }

    /**
     *   Graphics為java.awt下所有類,用以[描繪]圖形介面
     * 大多數Java下的圖形介面開發時,都是以此類為基礎的。
     */
    public void paintComponent(Graphics g) {
    //這裡我們沒有自定義Graphics,而是直接呼叫[父類]的同名方法實現。
        super.paintComponent(g);
        GameFrame.gameLogical.draw(g);
    }
    
	//按下鍵盤事件
	@Override
	public void keyPressed(KeyEvent e) {
		GameFrame.gameLogical.keyPressed(e);
	}
	
	//釋放鍵盤事件
	@Override
	public void keyReleased(KeyEvent e) {
		GameFrame.gameLogical.keyReleased(e);
	}
	
	//字元輸入事件
	@Override
	public void keyTyped(KeyEvent e) {
	}
}

  最後這個類是最最最重要的一個類GameHandler ,我們今後主要打交道的就是它,它是一個執行緒類,每秒讓執行緒休眠25ms,以產生一個類似主迴圈的概念,當然這是一種非常簡陋的做法,但是不影響我們的AI教學,你可以直接修改這裡的FPS值,以達到改變FPS的效果

//遊戲的FPSpublic static final int FPS =40 ;

遊戲中的主迴圈中包含了兩個子迴圈,一個是畫圖迴圈,就是這個

//處理每一幀的畫圖動作public void draw(Graphics g){}  ,

   另一個是邏輯迴圈,就是這個 

//處理每一幀的邏輯處理public void logical(){},

今後我們遊戲中有關繪製圖像的部分都會以這個draw函式為入口,所有有關邏輯處理的部分都放在這個

logical(){}函式中,下面的幾個有關key的函式就很明顯了,是遊戲中的各種鍵盤事件的入口。

這三個類中唯一需要我們關心的就是就是這個類,具體的說,是裡面的draw 函式和logical函式。

另一個需要注意的問題是draw函式中的引數Graphics g 這是個什麼東東,你可以把它簡單的想像成一隻馬良的神奇畫筆,可以畫出各種形狀,可以畫出文字,可以畫出圖片,可以畫出五顏六色的線條等等。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;


public class GameHandler implements Runnable {
    //遊戲的FPS
    public static final int FPS =40 ;
    //定義全域性常量,遊戲視窗的寬度和高度
    public static final int FRAME_WIDTH = 600;
    public static final int FRAME_HEIGHT = 800;
	//處理每一幀的畫圖動作
	public void draw(Graphics g){
		//設定畫筆顏色為白色
		g.setColor(Color.WHITE);
        //在(140,140)座標上,畫出你好 世界!
		g.drawString("hello world!", 140, 140);
		g.drawString("hello world!", 140, 160);
	}
	
	//處理每一幀的邏輯處理
	public void logical(){
		
	}
	
	//按下鍵盤事件
	public void keyPressed(KeyEvent e) {
		//獲得按鍵編號
        int keyCode = e.getKeyCode();
        //後面會新增具體按鍵匹配
        switch (keyCode) {
        }
	}
	
	//釋放鍵盤事件
	public void keyReleased(KeyEvent e) {
		//獲得按鍵編號
        int keyCode = e.getKeyCode();
        //後面會新增具體按鍵匹配
        switch (keyCode) {
        }
}
	
	@Override
	public void run() {
		while(true){
			
			//執行一次邏輯處理函式
			this.logical();
			
			//使面板重繪一次,repaint方法會呼叫GamePanel中的paintComponent方法
			GameFrame.gamePanel.repaint();
			
			try {
				//執行緒每隔25ms休眠一次,即每秒執行40次此函式,即FPS=40
				Thread.sleep(1000/FPS);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

如果你的程式執行之後是下面這樣的,那麼恭喜你,你的智商這輩子都成不了偉人了!

如果你看完了我上面的講解,就像是在聽金剛經,那麼我真得很羨慕你,你可以完全不用理解我上面的這些東西,接著往下學習,因為時間會讓你無師自通!