游戲策劃咨訊
          做一個游戲并不難,難的是做一個好游戲;完美在于積累!
          Java游戲編程初步
                一、現在流行的游戲似乎都是用C或C++來開發的。在java平臺上幾乎沒有很大型及可玩的流行游戲。由于java是個新生語言,他的許多特性還有待大家的發掘,但是我們不能否認Java在游戲編程方面的強大性。本文將帶領大家一步一步學習編寫Java游戲。最終打造屬于自己的Java游戲。

            在開始之前我們得確認你已經安裝了Java JDK,并已經安裝了瀏覽器軟件如IE。本章是以Internet為開發對象,一步一步教大家認識Java的Thread、Applets….以及游戲編程要注意的一些方方面面。并在每一小部分附上了相應的源代碼以供大家參考,最后我們還會對我們的游戲程序進行指導性的提示。在文章中我們還穿插了很多建設性的問題,讓讀者參與到我們的開發中來。但是由于本章指在帶領大家進入這個門檻,大部分知識并不會很詳細說明,有興趣的讀者可查閱相關的資料補充。在開始之前我們還得確認你已經知道類,繼承和java語言的一些基本屬性了。

            基本applet

            Applets是一種Web瀏覽器上的小程序,由于applet對系統而言絕對安全,所以它做的事比aaplication有限,但是對于客戶端的程序,applets仍然是個很強大的工具。為了瀏覽和運行方便,我們就以applet為開發對象。

            開發Applets程序,我們得繼承Applet類,并覆寫必要的函數,下面幾個函數控制了Web頁面上的applet生成與執行。

          函數 作用 
          Init() 這個函數會被自動調用,執行applet的初始化動作—包括組件在版面上的分配,你一定得覆寫它 
          Start() 每當瀏覽器顯示applet內容時,都會調用它,讓applet開啟其正規工作(尤其是那些被stop()關閉的工作),調用init()之后也會調用這個函數 
          Stop() 每當瀏覽器不顯示內容時,都會調用它。讓applet關閉某些耗資源的工作,調用destory()之后也會調用這個函數 
          Destroy() 瀏覽器將applet自網頁移除之際,便會調用它,以執行”applet不再被使用”應該做的最后釋放資源等動作 
          Paint() 讓你在Applet界面上進行相應的繪畫動作,每次刷新時都會重畫 

            所有的applet文件源文件名和java應用程序一樣都是.java為擴展名,編譯后的執行文件擴展名為.class,由于在applet中已經沒有了main()函數,它是和html自動集成,所以我們要執行applet,要在html源文件中放入一特定的標簽(tag),才能告訴網頁如何裝載并執行這個applet,這里有一點要注意,我們執行的網頁必須能執行java程序。

            普通Html 源碼格式

          <HTML>

          <APPLET CODE="HelloWorld.class" WIDTH=300 HEIGHT=500>

          </APPLET>

          </HTML
           


            <applet code ="HelloWorld.class" width=300 height=500>這行即applet的執行處。

            applet 執行文檔為 ="HelloWorld.class" 告訴網頁”applet ”擴展文件為HelloWorld.class

            width 和 height 告訴瀏覽器這個顯示的applet的大小 

            有關標簽(tag)的說明,大家可在網上找到很多相關的說明文檔。


            線程

            由于apllet,java應用程序的執行都和線程有關。我們來大概了解一下線程的概念。

            線程也稱為輕型進程 (LWP)。每個線程只能在單個進程的作用域內活動、協作和數據交換,并且在計算資源方面非常廉價。線程需要操作系統的支持,因此不是所有的機器都提供線程。Java 編程語言,作為相當新的一種語言,已將線程支持與語言本身合為一體,這樣就對線程提供了強健的支持。

            Thread 類是一個具體的類,即不是抽象類,該類封裝了線程的行為。要創建一個線程,程序員必須創建一個從 Thread 類導出的新類。程序員必須覆蓋 Thread 的 run() 函數來完成有用的工作。用戶并不直接調用此函數;而是必須調用 Thread 的 start() 函數,該函數再調用 run()。

            但是使用Thread類實現線程,增加了程序的類層次,所以一般程序員都由另一個java線程接口Runnable接口來實現,Runnable接口只有一個函數run(),此函數必須由實現了此接口的類實現。

            線程中有幾個重要的方法是我們得了解:

             Thread.start(): 啟動一個線程

             Thread.stop(): 停止一個線程

             Thread.sleep(time in milliseconds): 暫停線程在一個等待時間內。

          二、動畫技術 

            自由降落動畫

            了解了一些基本概念后,下面我們就開始我們的實質性的工作。我們設計一個球從屏幕頂上降落到屏幕下面,程序實現比較簡單,但是這是游戲動畫中不可少的一部分。在開始之前我們來看看我們的applet開始語句。

          import java.awt.*;
          import java.applet.*; 

          public class Ball 

          extends Applet implements Runnable 

          public void init() { }

          public void start() { }

          public void stop() { }

          public void destroy() { }

          public void run () { }

          public void paint (Graphics g) { } 


           

            在開始函數中我們要新建程序的主線程,并啟動這個線程。一旦做好這些準備工作以后,當applet第一次被顯示時,就會創建線程對象的一個實例,并把this對象作為建構方法的參數,之后就可以啟動動畫了

          public void start ()
          {

          // 定義一個新的線程
          Thread th = new Thread (this);
          // 啟動線程
          th.start ();


           

            現在我們來看看線程的run方法,它在循環while(),中每隔20毫秒重畫動畫場景。sleep這個方法很重要,如果在run循環中沒有這部分,圓的重畫動作將執行得很快,其他方法將得不到有效執行,也即我們在屏幕上將看不到球的顯示。

          public void run ()
          {

          //
          while (true)
          {

          // 重畫applet畫面
          repaint();

          try
          {

          // 暫停線程20毫秒
          Thread.sleep (20);

          }
          catch (InterruptedException ex)
          {

          }

          }

          }

           

            我們接著讀下去之前,有幾個問題需要回答。你也許會問,瀏覽器調用Java小程序的start和stop方法嗎? run 方法是如何被調用的? 情況是這樣的,當瀏覽器啟動了一個內部線程時,就相應地啟動了applet 的運行。當網頁顯示時,就啟動了applet的start 方法。Start方法創建一個線程對象,并把applet自身傳送給線程,以實現run方法。

            此時,兩個線程在運行:由瀏覽器啟動的初始線程,以及處理動畫的線程。快速查看applet的start方法,可以知道它創建了線程,并啟動了它。類似地,當網頁被隱藏后,applet的stop方法就調用了線程的stop方法。

            注意:在Applets和Threads中的 start/stop子程序

            在Applet 和Thread 兩個類中都有start和stop方法,但它們的功能不同。一旦Applet 顯示時,就調用applet的start方法,一旦applet 隱藏時,就調用applet的stop 方法。相反,線程的start方法將調用run方法,線程的stop方法將停止正在執行的線程。

          public void paint(Graphics g); 

            paint() 方法所傳入的參數—— java.awt.Graphics 對象將是一個經裁剪的相關顯示區的圖像代表(而不會是整個顯示區)。我們對圓球圖形元素的繪制就是在通過重寫 paint()方法,在其中對傳入的Graphics 對象g進行操作完成的。 

            當我們應用程序的邏輯要對系統界面進行更新時,調用 repaint() 方法來通知AWT線程進行刷新操作。repaint() 方法實際會讓 AWT線程去調用另外一個方法,update。update方法在默認情況下會做兩件事,一是清除當前區域內容,二是調用其 paint()方法完成實際繪制工作。paint、repaint、update 三個方法關系如圖所示:

          此主題相關圖片如下:

          但是如何讓我們的圓運動呢?這里我們利用函數Graphics 類的fillOval函數來設置了圓的起始位置x,y。現在我們只要在線程run方法中每單位時間增大y的值,線程將在每一個單位時間內重畫圓的位置。每單位時間y值越大,下降的速度就會越快。在屏幕上我們就將看到這個圓球做自由降落運動。 如下代碼所示:

          while (true) 

          // 設置動畫移動速度 

          y +=1;
          }

          public void paint (Graphics g)
          {

          //設置球的顏色
          g.setColor (Color.blue);

          // 從x,y位置處畫一個實心的圓
          g.fillOval (x , y, 2 * r, 2 * r);

          }
           

            在這之前我們需要在開始處設置一些變量,定義好x,y的默認位置值。r 在此處是我們畫的圓的半徑大小。

          int x = 100;
          int y = 20;
          int r = 10;  

            我們的自由降落的動畫就完了。是不是很簡單,如果還有地方不明白,大家可在此處下載完整的代碼及應用程序。看看真實的演示效果和代碼。下面每一部分我們也將在最后附上相應的源代碼及應用程序下載。如果大家有興趣,可改變y的值,及x的值,你會得到不同的下降效果。

          三、雙緩沖,消除閃爍

            大家可能注意到了上面例子中的我們下降的圓看起來不是很清晰,帶著很嚴重的閃爍。這種現象在寫游戲程序中是普遍存在的現象。這是由于我們的repaint()函數導致的結果,由于它在調用paint()函數前會自動清除屏幕,所以在一個毫秒內我們會看到一個空白的屏幕,在快速的變換操作中就出現了閃爍現象。

            解決這種閃爍現象有幾種方法,下面是兩種方法的列舉說明,其他的方式大家可以自己嘗試。

            第一種:我們始終不清除屏幕顯示,但是這個方法會帶來個附作用,我們下降的圓不在是一個圓了,而是一條直線,因為它的下降過程中沒有了斷點,保留了所有的圓球的影象。我們只要在Ball.java內加上如下代碼update(Graphics g) {paint(g)},你就會看到一條很長的線拉出來。有興趣的朋友可以試試。

            第二種:使用雙緩沖機制(Double buffering)

            現在大部分的游戲都是采用雙緩沖機制來解決屏幕的閃爍現象,我們就以此為例來進行說明,有關緩沖區及相關緩沖機制的概念,大家可參考附錄的緩沖說明。

            而我們的程序中簡單的說就是在顯示我們想要的圖畫之前,把所有的圖畫先在后臺繪制好并存放到相應的圖像變量中去。當需要顯示時直接復制到前臺屏幕就可以了。

            具體實現:

             1.首先我們用createImage方法新建一后臺圖像類變量

             2.然后使用getGraphics()方法得到當前圖像的圖形關聯

             3.在后臺處理所有相關的處理,如清除屏幕,后臺繪畫等等

            當完成所有的后臺工作后,復制已經繪制好的圖像到前臺,并覆蓋前臺的存在圖像。這樣我們的所有操作都是在后臺前行,在屏幕顯示新的圖像前,這些內容都已經存在于后臺了。所以你也將在任何時刻都看不到空屏幕的存在。也即代表閃爍消除了。

            下面我們來看看相關的代碼說明: 

            在開始之前我們得先在程序的開始部分聲明兩個實例變量用來存儲后臺圖畫。如下:

          private Image bgImage;
          private Graphics bg;  

            然后我們利用update()方法來實現雙緩沖機制。

            Update()方法要實現下面三個步驟:

             1.清除屏幕上的組件

             2.設置相關聯組件的前景色

             3.調用paint方法重畫屏幕

          public void update (Graphics g)
          {

          // 初始化buffer
          if (bgImage == null)
          {

          bgImage = createImage (this.getSize().width, this.getSize().height);
          bg = bgImage.getGraphics ();

          }

          // 后臺清屏,即設置圓球組件和后臺一樣的顏色,大小
          bg.setColor (getBackground ());
          bg.fillRect (0, 0, this.getSize().width, this.getSize().height);

          // 繪制相應的元素組件
          bg.setColor (getForeground());
          paint (bg);

          // 在屏幕上重畫已經繪制好的圓
          g.drawImage (bgImage, 0, 0, this);

          }
           

            此處g 為屏幕圖形,bg為g的后臺關聯。而bgimage包含了bg圖形。請于此處來看看我們的源代碼例子及演示效果。


            改變運動方向

            我們已經解決了動畫的兩個很重要的問題,移動動畫和閃爍消除。但是我們很快會發現一個問題,球從屏幕頂上落下來后,就不見了。這可不是我們所需要的。我們要的是一個生動的畫面。如何讓我們的球不穿過屏幕而始終在屏幕上活動呢?在開始之前,我建議大家自己想辦法解決,如果你能自己處理好了。你的水平將會有一個很大的提高。如果沒有想出好辦法,沒關系,下面我們將很詳細的說明球的方向改變的技術。

            不知道大家注意了沒有,在上面我們說到球的移動時,我們是通過增加y的值,讓線程重畫新的圓位置和圖形。如果改變y的值的大小球的下降速度也會改變。不錯,這就是我們的解決方法 ,我們只要用一個變量來存儲這個速度的大小而不用固定的值。在線程執行也即run方法處我們用代碼改變速度的方向,球的方向也會改變。即設置這個變量”speed”為”-1”。當然在設置值前我們要進行判斷,你是想讓球穿過屏幕從別一邊開始顯示,還是來回反彈呢!如果想來回反彈,我們只要不讓球的半徑值超過applet屏幕顯示區域就可以了。此處我們用r/2來表示球的半徑。

          //反彈下落球
          if (y > appletsize_y – r/2)
          {

          // 改變方向
          x_speed = -1;

          }
          // 反彈上升球
          else if ( < r/2)
          {

          // 改變方向
          x_speed = +1;

          }
           

            至于如何讓球穿過從屏幕頂上重新下降,我們在此沒有說明,也不會說明了。留給大家自己去想想,已經很簡單了。在下面我們附上了兩種方式的源代碼和執行文件。如果大家運行程序,大家可能會發現,我們的球的大小和速度有一些改變。這里是為了更好的反應演示效果。 

          四、多媒體

            使用多媒體聲音

            多媒體功能在游戲中是必不少的一部分,優美的音樂,漂亮的界面往往是一個成功游戲必需具備的條件。

            在開始之前我們先了解一下主要的小型聲音文件類型:

            AU - (擴展名為AU或SND)適用于短的聲音文件,為Solaris和下一代機器的通用文件格式,也是JAVA平臺的標準的音頻格式。AU類型文件使用的三種典型音頻格式為: 8位μ-law類型(通常采樣頻率為8kHz), 8位線性類型,以及16位線性類型。


            WAV - (擴展名為WAV)由 Microsoft和 IBM共同開發,對WAV的支持已經被加進Windows 95并且被延伸到Windows 98. WAV文件能存儲各種格式包括μ-law,a-law和 PCM (線性)數據。他們幾乎能被所有支持聲音的Windows應用程序播放。

            AIFF - (擴展名為AIF或IEF)音頻互換文件格式是為Macintosh計算機和Silicon Graphics (SGI)計算機所共用的標準音頻文件格式。AIFF和 AIFF-C幾乎是相同的,除了后者支持例如μ-law和 IMA ADPCM類型的壓縮。

            MIDI - (擴展名為MID)樂器數字接口MIDI是為音樂制造業所認可的標準,主要用于控制諸如合成器和聲卡之類的設備。

            在JDK1.0上,java只支持*.au格式的聲音文件,但是java2的API以及聲音包提供了很強大的對聲音技術的支持。而此部分為了讓大家快速掌握游戲編程的基本知識,我們僅使用了AudioClip接口類來實現播放"*.wav"。如果大家有興趣可參考sun java網站的聲音sapmle,上面提供了完備的實例和教程說明。

            使用AudioClip接口比較簡單,我們只要實例對象,加載聲音文件后,再在任何地方播放即可。恢復和播放聲音最簡單的方法是通過Applet類的play()方法。

            AudioClip接口

             1.播放 play
             2.循環 loop
             3.停止 stop

            啟動和停止聲音文件,或循環播放,你必須用 applet的 getAudioClip方法把它裝載進入 AudioClip對象,getAudioClip方法要用一個或兩個參數,當作播放的指示。第一個或唯一的一個參數是 URL參數,用來指示聲音文件的位置,第二參數是文件夾路徑指針。

            下列代碼行舉例說明加載聲音文件進入剪貼對象: 下面的"gun.wav"是指當前目錄下的聲音文件。我們也可用*.au格式的文件代替。

          AudioClip co = getAudioClip(getCodeBase(), "gun.wav");  

            getAudioClip()方法僅僅能被applet內調用。隨著JAVA2的引入,應用程序也能用Applet類的newAudioClip方法裝入聲音文件。前一例子可以改寫如下以用于Java應用程序:

          AudioClip co = newAudioClip(“gun.wav”) 

            我們現在可在任何地方使用方法play()播放我們的聲音了。play()一旦被調用立刻開始恢復和播放聲音。但這有一點要注意:如果聲音文件不能被查找,將不會有出錯信息,僅僅是沉默。
          源代碼及應用程序請于此處下載.


            圖片處理技術

            圖片的處理和聲音的處理在一樣簡單。設置圖片變量,得到圖形,最后繪制圖形。我們就直接從代碼來分析。在此我們繪制一幅applet的背景圖。開始繪制前,我們先要聲明圖形變量,用來存放圖形文件。

          Image backImage; 

          // 加載圖片文件
          backImgage = getImage (getCodeBase (), "black.gif");
           

            下面在我們的paint()方法中利用函數drawImage繪制我們圖形。

          g.drawImage (backImage, 0, 0, this); 

            DrawImage參數中的blackImage即我們得到的圖形,而后面的0,0分別代表圖形的x坐標和y坐標.this:為圖形代表的類,這里指的即picture類。在這里建議大家使用*.gif格式的圖片文件。因為如果是internet網上,文件的大小也決定了你的applet加載時的快慢,沒有人很愿意等很長時間來玩你的游戲,即使你的游戲比較出色。源代碼及演示程序下載.

            大家在玩游戲時是不是見過人物圖像行走?動物來回跑動的動畫?這些都是基于圖形技術來實現的。我們只要把上面的代碼稍微修改,用數組變量來存儲我們得到的圖形文件組,再利用drawImage()方法播放出來就可實現動畫圖片的播放.

          Image[ ] backImage; 

          // 加載圖片文件

          for (int i=4,i<backImage.length,i++)

          {
          backImgage[i] = getImage (getCodeBase (), "t1"+i+".gif");

          }

           

            大家可參考JDK包中的Animation例子,它就是一個很好的播放一組圖片文件的例子。

          五、事件處理 

            鼠標監聽技術

            玩游戲時,不管是小型的撲克牌和大型的RPG游戲,都要參與者溶入到游戲的角色當中。不錯,交互,游戲有了交互的功能才可以說是一個完整的游戲。即使是編程游戲如機器人足球,Robocode都要程序員參與編寫代碼,觀察比賽。有兩種主流方法可實現游戲的交互:鼠標和鍵盤。當然還包括手操桿等,但現在大部分Pc機上使用的還是鼠標和鍵盤。我們就以這兩項為基礎來說明游戲中事件的響應過程。

            要判斷相應的鼠標所進行的動作:是點擊,還是移動。我們必須對我們鼠標進行監聽。要監聽鼠標事件就必須調用這些接口之一,或擴展一個鼠標適配器(mouse adapters) 類. AWT 提供了兩種監聽接口(listener interface): java.awt.event.MouseListener 和 java.awt.event.MouseMotionListener.

            現在我設計一個鼠標事件,當點擊applet屏幕時,下降的球向反方向運動。以實現了對游戲的簡單控制。

            MouseListener一共有5個方法,主要用來實現鼠標的點擊事件。這里要注意一點:由于MouseListener是接口我們要在實現的類中重載它的所有方法. 

            Mouse點擊事件

             · mousePressed() 當用戶按下鼠標按鈕時發生.

             · mouseReleased() 當用戶松開鼠標按鈕時發生.

             · mouseClicked() 當用戶按下并松開鼠標按鈕時發生. 用戶在選擇或雙擊圖標的時候通常會點擊鼠標按鈕. 用戶如果在松開鼠標之前移動鼠標,點擊不會導致鼠標相應事件出現.

             · 因為點擊鼠標是按下鼠標和松開鼠標的結合, 在事件分配給 mouseClicked() 方法之前, mousePressed() 和 mouseReleased() 方法已同時被調用.

            鼠標狀態處理:

             mouseEntered() 當鼠標離開當前組件并進入你所監聽的組件時激活事件.

             mouseExited() 當鼠標離開你所監聽的組件時發生.

            Mouse 移動事件

            鼠標移動主要通過接口MouseMotionListener來實現:

             mouseDragged() 當用戶按下鼠標按鈕并在松開之前進行移動時發生.在mouseDragged() 后松開鼠標不會導致mouseClicked().

             mouseMoved() 當鼠標在組件上移動而 不時拖動時發生.

            依據我們的游戲設計,我們在這要使用到MouseListener接口。實現接口后。我們要在init()函數加入監聽器addMouseLisener(),來監聽對applet的響應事件。

            知道了鼠標事件的處理,我們再來回顧一下上面提到的球反彈設計,現在我們要如何處理了球的控制呢?讓我們想一想,不錯,可能你已經發現了,我們照樣可通過改變speed方向來實現回彈控制操作。在mousePressed(){}事件中加入下面的代碼,我們的回彈控制就設計完成。

          speed = -4


            記得在釋放applet資源時,我們要釋放mouseListener資源。在destory()中加入

          removeMouseListener(this);

            可能有些朋友會使用mouseDown()方法,mouseDown()在此我建議大家不要再使用這個方法了,它已經是被淘汰的產品。是為了兼容JDK1.0而帶到JDK1.4中來的。

           六、鍵盤監聽技術


            知道了鼠標的操作處理,鍵盤的操作處理就很簡單了。我們只要實現keyListener接口,并在相應的事件中加入我們要實現的代碼。

             KeyPressed: 當按鍵時發生

             KeyReleased:當翻譯鍵時發生

             KeyTyped:當打擊鍵時發生


            由于在后面我們設計的游戲中我們不會使用到鍵盤操作,鍵盤事件處理我們就交給大家自己去實現。


            現在我們來回顧一下我們能做什么了?移動一個物體,加載聲音和圖片,用鼠標對游戲進行一定的控制。哦,我的天,我們已經可以做自己的很簡單的游戲了。是的,你可以了,我認為在此,大家可以放下教程,把自己小時候一直想玩的游戲,把自己學程序時一直想做的游戲自己進行設計實現,這對你的幫助將是非常大的。對你的編程水平也是一個很大的提高。

            當然如果你仍然認為自己認識還不是很深,下面讓我們來設計一個完整的游戲。這將是一個很有意思的過程。


            第一個游戲-"保衛者"

            主線思路:

            真正做自己的游戲是總是很興奮。在開始任何事情之前,我們都要有個好的設計,游戲更不例外。下面我們就以上面的例子為本。設計一個”保衛者”的游戲。游戲思路本身很簡單,從屏幕的頂端不斷的有炸彈落下來,而我們這些”保衛者” 要在它們著地之前,用鼠標點擊讓它反彈回去,不讓它落到地面上來,但是球在上升過程中我們也要注意不讓它撞到頂上。如果撞到頂上或地畫,你的生命點數都會減少。每點中一個炸彈你的分數就會增加。當你的生命點數為零。”Game Over”。

            設計結構:

            1.模塊設計:

            游戲的結構很簡單,由三個模塊組成。

            Denfen類:Denfen類控制整個游戲主線程,初始化炸彈類,并繪制屏幕上的炸彈數量及處理炸彈的移動,并監聽鼠標事件

            Bomb類:主要是判斷炸彈的速度,方向,是否撞到地面和點擊事件

            Denfense類:主要用來處理游戲者的記分和生命點數


            2.方法實現:

            Denfen:

            init(): 初始化所有對象,包括聲音文件的加載,Bomb類的生成

            run(): 處理炸彈的下降運動

            paint(...):繪制炸彈及相關的數據記錄顯示

            update(...): 實現屏幕圖像的雙緩沖,消除閃爍

            mouseProcess (...): 利用mouseEvent事件監聽來處理鼠標按下事件,并根據鼠標當時的x坐標和y坐標判斷是否點中炸彈。

            addBomb():利用默認值來動態實現bomb的生成,這里我們利用了數組來記錄的。默認值是3,大家可依據自己的愛好增加或減少記錄。

            Denfenser:

            Score:積分

            Life:生命點

            AddScore():增加游戲者的積分

            Death():減少游戲者的生命點數

            getScore():獲得當前的積分數

            getLife():獲得當前的生命點數

            Bomb:

            Bomb(...): 構造函數,初始化炸彈的位置,聲音,顏色等相關變量的值.

            down():處理bomb的下降

            isRebound ():反向回彈炸彈的方向,并根據積分來加快炸彈的下降速度

            userHit (int x, int y):游戲者是否點中炸彈。

            wasHitEarth(): 判斷炸彈是否撞擊到地面或頂面,如果是生命點將減少。

            DrawBomb(Graphics g): 繪制Bomb圖象。

            3.工作原理:

            首先我們在init()方法中加載所有游戲必要的資源,包括聲音,鼠標事件的監聽、背景等相關設置。利用addBomb()方法增加bomb的數量、初始位置及初始化顏色。再利用start()啟動線程。線程調用run()方法,處理炸彈下降運動down()。Repaint()會在每一個單位時間調用paint()方法不斷的刷新屏幕,paint()調用Bomb.addBomb()繪制炸彈。當游戲者按下鼠標,mousePress()事件激活,判斷是否點中了炸彈。如果點中addScore()自動加1分。如果沒有點中炸彈,炸彈繼續下降,當撞到屏幕wasHitEarth()方法激活,其內調用death()方法,減少Denfenser.life生命點,同時audio.play()處理聲音的播放,用以提示游戲者。當你的生命點數小于0時”Game Over”。

            這個游戲并不是很完善。下面提到一些改進方法,大家可以動手試試。做出適合自己的游戲風格來。具體的源代碼及實現過程請大家從這里下載.

            4.游戲的改進:

            背景的替換,本例的背景用的是函數setBackground(),大家可用相應的圖形來代替。

            炸彈數量的增加,為了減少復雜度,例子用到的炸彈數量是固定值3,我們可根據積分的多少,在游戲中動態的增加炸彈的數量。

            等級的設置,本游戲中沒有等級的功能。如果大家在游戲中加入等級,依據不同的等級不斷的變換游戲的模式,這將是很有意思的過程。

            模式改變。我們可以在游戲中實現自己的模式。如消滅炸彈。點一個炸彈,就讓炸彈從屏幕上消滅。

            我們還可以增加一個游戲者,加大游戲的可玩性。增加鍵盤的處理功能。加大游戲的靈活性。

            還有很多很多的處理和玩法,這都等著你去發掘。相信java 游戲編程將會是一個很有意思的學習過程。

          七、附錄:緩沖機制

            . 緩沖區 緩沖區用來儲存著色的像素(影像)在視頻內存中的區域。緩沖區的大小由解析度和色深決定,例如800x600,16bit色的緩沖區就占用800x600x2(16bit=2bytes)的內存區域。

            (1) 前置Buffer是當前顯示在螢幕上的緩沖區,后置Buffer是尚未顯示在螢幕上的緩沖區。

            (2) Single Buffering使用一個前置緩沖區,在著色的同時影像立即顯示在螢幕上。因此當螢幕更新影像時會出現閃爍的現象。Single Buffering在目前的程序中已很少使用。

            (3) Double Buffering則使用兩個緩沖區,一個前置Buffer,一個后置Buffer。所謂前置和后置是相對而言的。前置緩存的像素在屏幕上顯示的同時,顯卡正在緊張地著色后置緩存中的像素。

            后置緩存的像素上色完畢后是以Vsync信號的形式等待。在前置緩存和后置緩存交換后,新一輪的著色工作又重新開始。這正如舞臺話劇中前臺和后臺的演員一般。在前臺演員表演時,后臺的演員仍在進行最后的排練。前臺的演員下場時正是后臺演員登場的時間。唯一不同的是前置和后置緩存是循環輪番上陣,而演員表演完畢一般都不再出場。目前大多數游戲內定都使用Double Buffering。

            (4) Triple Buffering使用一個前置緩存和兩個后置緩存。在著色完第一個后置緩沖區的數據后,立即開始處理第二個后置緩沖區。今天,不少新游戲都采用的是Triple Buffering,Trible Buffering正逐漸成為發展的趨勢,因為它沒有Vsync(螢幕的垂直刷新頻率)等待的時間,游戲也將更加流暢。Triple Buffering也是3Dmark2000測試的內定值設定。

          JAVA游戲編程初步源代碼

          posted on 2005-02-17 18:49 藍色雪焰 閱讀(239) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
           
          主站蜘蛛池模板: 乌苏市| 宾川县| 革吉县| 沾化县| 五大连池市| 郓城县| 宜昌市| 安丘市| 建平县| 东台市| 芜湖县| 尚义县| 敦化市| 景谷| 明光市| 平阳县| 赫章县| 玛沁县| 青川县| 隆回县| 舞钢市| 东台市| 舟山市| 梁山县| 池州市| 句容市| 台东县| 五家渠市| 长武县| 济源市| 铜山县| 忻城县| 株洲市| 东港市| 阜平县| 璧山县| 桃园市| 灌南县| 贺州市| 惠东县| 宁武县|