Java游戲編程初步(2)
發表于:2007-07-14來源:作者:點擊數:
標簽:
四、多媒體 使用多媒體聲音 多媒體功能在 游戲 中是必不少的一部分,優美的音樂,漂亮的界面往往是一個成功游戲必需具備的條件。 在開始之前我們先了解一下主要的小型聲音文件類型: AU - (擴展名為AU或SND)適用于短的聲音文件,為Solaris和下一代機器的通用
四、多媒體
使用多媒體聲音
多媒體功能在
游戲中是必不少的一部分,優美的音樂,漂亮的界面往往是一個成功游戲必需具備的條件。
在開始之前我們先了解一下主要的小型聲音文件類型:
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:當打擊鍵時發生
由于在后面我們設計的游戲中我們不會使用到鍵盤操作,鍵盤事件處理我們就交給大家自己去實現。
現在我們來回顧一下我們能做什么了?移動一個物體,加載聲音和圖片,用鼠標對游戲進行一定的控制。哦,我的天,我們已經可以做自己的很簡單的游戲了。是的,你可以了,我認為在此,大家可以放下教程,把自己小時候一直想玩的游戲,把自己學程序時一直想做的游戲自己進行設計實現,這對你的幫助將是非常大的。對你的編程水平也是一個很大的提高。
當然如果你仍然認為自己認識還不是很深,下面讓我們來設計一個完整的游戲。這將是一個很有意思的過程。
第一個游戲-"保衛者"
主線思路:
真正做自己的游戲是總是很興奮。在開始任何事情之前,我們都要有個好的設計,游戲更不例外。下面我們就以上面的例子為本。設計一個”保衛者”的游戲。游戲思路本身很簡單,從屏幕的頂端不斷的有炸彈落下來,而我們這些”保衛者” 要在它們著地之前,用鼠標點擊讓它反彈回去,不讓它落到地面上來,但是球在上升過程中我們也要注意不讓它撞到頂上。如果撞到頂上或地畫,你的生命點數都會減少。每點中一個炸彈你的分數就會增加。當你的生命點數為零?!盙ame 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
測試的內定值設定。
原文轉自:http://www.anti-gravitydesign.com