田如柏 符傳銳 王瑞婷
摘要:近年來,JAVA以其簡單性,可移植性和平臺無關等特點,廣泛應用于Android應用、金融業(yè)應用、網(wǎng)站、嵌入式領域等,所以JAVA成了許多編程者的主要選擇。像炮臺打飛機、貪吃蛇,五子棋等一些小游戲是初學者實戰(zhàn)的很好例子。
關鍵詞:JAVA;炮臺打飛機;編程;游戲
炮臺打飛機的游戲我們經(jīng)常玩,所以對大家來說都不陌生,對于初學者來說確實是一個不錯的選擇。但是對初學者來說確實會遇到很多問題,所以我們在這里做一些簡單的介紹。
1 游戲世界
現(xiàn)在的游戲,能夠在正確的位置繪制出正確的圖形,使用屏幕空間和游戲空間是必不可少的。我們需要一個空間,用來保存整個游戲世界里面的數(shù)據(jù),在每一次游戲更新畫面的時候,取出要進行更新的那一部份數(shù)據(jù),將其繪制在屏幕上。在游戲世界中一般使用笛卡兒坐標系,而在繪制圖像中一般使用屏幕坐標系。在游戲世界中使用笛卡兒坐標系是因為處理方便。而繪制圖像使用屏幕坐標系是因為很多的標準繪圖函數(shù)提供的接口都是使用屏幕坐標系,包括C,JAVA,OPENGL和DIRECTX。所以,這項代碼的編程難度,就是坐標空間的轉(zhuǎn)換。具體的實現(xiàn)方式有很多,也有很多前輩封裝好的轉(zhuǎn)換函數(shù),大都用矩陣的乘法來進行運算。我們自己寫了一套平移,旋轉(zhuǎn),翻轉(zhuǎn)和縮放的代碼。這個CLASS的實現(xiàn),方便了我對于坐標的理解,有了這個CLASS的幫助,只需要在笛卡爾坐標系下對游戲中運動的物體進行每幀位置的更新即可,而不需要把使用屏幕坐標系進行位置更新。這樣不僅代碼簡單,也利于游戲的移植。
2 飛機刷新
游戲之所以有趣,就在于其變數(shù),俗稱隨機性。每一次開始游戲,都可以遇到不同的事件,這會引起玩家不斷挑戰(zhàn)的欲望。一般的游戲,都會配備一個地圖編輯器,就像魔獸爭霸的世界編輯器。這些東西的存在很好的劃分的了游戲引擎和游戲內(nèi)容,而且允許玩家創(chuàng)建屬于自己的游戲世界也會讓游戲能存活得更久。說來慚愧,我們只是創(chuàng)建了一種生成飛機的方式。具體的做法是:用一個值timePass保存已經(jīng)逝去的時間,當然他的初始值為0。在每一次游戲循環(huán)中,不斷的讀取當前的時間time,讓timePass+=time。在每一關里面,都有一個生成飛機的控制:當當前時間大于x秒的時候,消耗y秒,生成一個z類型飛機,每一次生成飛機之后,timePass=y。這樣做主要是防止出現(xiàn)不斷的刷新飛機的情況。
3 主動刷屏
FPS是每個即時游戲的基礎,也是游戲和軟件最大的不同之處。軟件傾向于被動刷新,即等待系統(tǒng)的REPAINT消息,而游戲則要求主動刷新。由于人眼睛每秒鐘最多捕捉24張畫面和滯留效應,電視的制作得以成為可能。而電子游戲的成功也離不開。對于一般的智益類游戲來說,F(xiàn)PS大于24即可,這也是老式DOS游戲的標準刷新頻率。而對于動作類游戲來說,要求FPS達到60甚至更高?,F(xiàn)在的機器的性能都非常的高,如果不加入SLEEP,那么一秒鐘內(nèi)可以進行過百甚至過千次的游戲循環(huán)。雖然可以不加入SLEEP讓游戲以全速的方式運行下去,但是,這樣只會造成不必要的資源浪費,CPU使用也會出現(xiàn)居高不下的情況。以FPS60為例,SLEEP具體的算法是:當本畫面開始更新時,記錄一次當前的時間。然后,通過不停的等待,檢測下一次更新的時間(1/60秒)是否到來。如果到來,就紀錄當前的時間,然后對畫面進行更新,繼續(xù)檢測下一次更新的時間。我們寫了一個比較完美的代碼在TIMER.JAVA中。
4 鍵盤響應
游戲必須要的就是和玩家的交互??上У氖牵琖INDOWS系統(tǒng)提供的鍵盤消息,根本滿足不了游戲每秒60FPS的要求。所以,必須主動獲取當前鍵盤的狀態(tài)。在老式的DOS平臺上,軟件可以直接讀取鍵盤的緩沖區(qū),然后對緩沖區(qū)中的信息進行分析,提取出所需的數(shù)據(jù)。使用C語言WIN32編程,主要是通過調(diào)用GetKeyState和GetSynsKeyState這兩個比較底層的函數(shù)查詢當前鍵盤中某個游戲感興趣的按鍵的狀態(tài)。不過,JAVA沒有直接讀取鍵盤緩沖區(qū)的方法,也沒有檢測鍵盤狀態(tài)的函數(shù)。不過,最后我還是找到了一個解決方案。具體的原理是:開一個THREAD,這個THREAD不斷監(jiān)聽鍵盤消息,將所有的鍵盤消息保存到一個STACK中。每當游戲循環(huán)一次的時候,游戲引擎復制一份THREAD中STACK中的數(shù)據(jù),不斷的訪問他們,以獲取當前鍵盤的狀態(tài)。這樣也不會發(fā)生在一秒鐘內(nèi),快速點擊鍵盤而發(fā)生漏掉消息的情況。而游戲引擎還要為每個KEY保存一份他們上一次的狀態(tài)。如果這一次STACK中,某個KEY沒有KeyUp的消息,而上一次這個KEY狀態(tài)中是KeyDown的,那么,引擎要告訴游戲,這個KEY連續(xù)一直被按下且沒有被釋放過。
5 粒子效果
雖然我讀過相關的知識,也曾經(jīng)在魔獸爭霸3的平臺上使用T語言進行過粒子效果的編寫,不過在C,C++,JAVA平臺上,我都沒有嘗試過制作這樣子的效果。所以我對我能否制作出這樣子的效果是帶有疑問的。不過我嘗試著去做了,最后我發(fā)現(xiàn)自己做得也可以。我在飛機的爆炸,戰(zhàn)艦移動的波浪,子彈的彈道都使用了粒子效果都使用了自己寫的粒子效果。雖然它只是一個簡單的點的繪制,在生命周期結束之后自動釋放。具體的時間方法是:創(chuàng)建一個粒子(Particle)對象,里面有粒子當前的坐標,已經(jīng)存活的時間,移動的方向,還有粒子的顏色。然后用一個粒子表(ParticleList)來管理所有的粒子。每一次游戲循環(huán),更新所有粒子的位置,然后減少粒子的生命。如果粒子此時的剩余生命小于0,則從粒子表中刪除之。否則,在粒子當前所在的位置,用粒子顏色的筆繪制一個點。后來,我還使用了Graphics中的透明度,繪制的粒子還擁有透明度效果,讓粒子效果更加的逼真。具體的做法是,檢測粒子當前的生命值(cur)和最大的生命(max),設置創(chuàng)建的筆的透明度為cur/max。