貪吃蛇大作戰JavaFx版完整原始碼
貪吃蛇大作戰 Java版
(記得點star啊,收藏一個專案最好的方式是star而不是fork)
遊戲截圖:
幾句話:
這個遊戲是去年寫的,用來交資料結構作業的,本來在大一暑假時我就開始寫,那時老師還沒提具體要求,我就用unity3d配合C#寫了個高仿貪吃蛇大作戰,自認為效果不錯,如下圖:
結果等到開學了老師佈置了一下具體要求,只能用Java或者C++來寫,沒辦法重新寫就重新寫吧,剛好新學期學Java,書上介紹的圖形介面程式設計庫是Javafx,於是就趕工寫了上面的遊戲交上去,程式碼質量肯定是有點不足,不過還是想分享出來給大家看一下。至於unity3d版的貪吃蛇大作戰,專案打包下載:點選開啟連結
遊戲說明:
專案結構如上圖,程式碼全都在src資料夾,有兩個包,第一個是core包,稱之為核心,程式碼抄襲自點選開啟連結還有點選開啟連結。
第二個是snake包,主要的內容和操作都在這裡面,時間隔了太久也記不清具體的實現細節了,所以就直接把當時交的實驗報告裡的內容複製上來,因為交作業嘛,大家都懂,瞎扯的內容居多,閱讀體驗肯定比不上自己寫的部落格,還請各位看官多加包涵。
---------------------------------------------------分割線---------------------------------------------------
實驗報告部分內容如下:
2.1 確定技術路線
我們選擇Java作為此次開發的語言,同時選用JavaFx庫來進行圖形化介面程式設計。開發平臺為windows + eclipse。
JavaFX是Java的下一代圖形使用者介面工具包。JavaFX是一組圖形和媒體API,我們可以用它們來建立和部署富客戶端應用程式。
2.2 遊戲整體架構
遊戲的主要執行介面是基於JavaFx提供的canvas(畫布)API來實現的,為了編寫方便,同時也為了使程式更加簡潔高效,我們先編寫了一個基礎的遊戲框架,再以此框架為基礎,進行遊戲功能的開發。通過對要實現的遊戲功能進行初步討論確定,以及對各項功能進行技術可行性驗證後,我們最終確定瞭如下圖所示的整體架構:
2.3 程式開發分工
......
2.4 基礎框架編寫
基礎框架的編寫基於Javafx庫,Javafx已經內建在我們使用的jdk8環境中,因此直接匯入即可。編寫的第一步便是建立程式入口,在Javafx中,Application類是程式的入口點,該類中的launch用於啟動一個獨立的Javafx應用,也就是說,程式的主類要繼承Application類,並且重寫 (Overriding)其start方法,然後在main方法中呼叫其launch方法來啟動程式。
public abstract class SApplication extends Application {
private Group mGroup;
private Scene mScene;
@Override
public void start(Stage primaryStage) throws Exception {
before();
mGroup = new Group();
mScene = new Scene(mGroup, SContants.WIDTH, SContants.HEIGHT);
after();
showStage(primaryStage);
}
}
以上為SApplication類程式碼片段(如無說明下文程式碼均為選取片段),該類start方法中引數Stage物件是Javafx中的一個窗體,類似舞臺,而Scene物件表示在舞臺下的一個場景,Group用於儲存場景中各種Object。當該類啟動時,JVM便建立該類的一個例項,同時呼叫其start方法。start方法一般用於將UI元件放入一個場景,並且在舞臺中顯示該場景。
有了主類後,接下來我們需要在這個舞臺、場景上進行表演,Javafx提供的Canvas(畫布)便是表演的組織形式,這裡我們引人遊戲程式設計中的幾個概念,一個是時間線,一個是幀,一個遊戲可以看成是一個無限迴圈執行的程式,亦即一條長長的時間線,在這個迴圈中每次迴圈便是一幀,我們定義一個SScreen類繼承自Canvas類,在每一幀中均重繪場景中的物件,便形成了一個動態執行的遊戲畫面。
public abstract class SScreen extends Canvas implements SEvent {
public SScreen(double width, double height) {
super(width, height);
initTimeLine();
}
private void initTimeLine() {
timeline = new Timeline();
timeline.setCycleCount(Timeline.INDEFINITE);
keyFrame=newKeyFrame(Duration.millis(duration),newEventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent arg0) {
draw(getGraphicsContext2D());
update();
}
});
timeline.getKeyFrames().add(keyFrame);
}
}
如上,我們初始化時間線,並且在時間線上新增關鍵幀,在每一幀中我們都呼叫draw()方法和update()方法,這兩個方法主要是渲染圖形和重新整理圖形。
在這個程式中,我們把所有遊戲物件都抽象成一個基類SObject,這個類主要是物件的各種屬性,如長度、寬度等,同時也有一個檢測是否兩個Object是否接觸的方法用來檢測貪吃蛇是否發生碰撞。
public abstract class SObject implements SEvent {
protected DoubleProperty widthProperty = new SimpleDoubleProperty(0);
protected DoubleProperty heightProperty = new SimpleDoubleProperty(0);
protected DoubleProperty xProperty = new SimpleDoubleProperty(0);
protected DoubleProperty yProperty = new SimpleDoubleProperty(0);
protected BooleanProperty updateProperty = new SimpleBooleanProperty(true);
protected BooleanProperty visibleProperty = new SimpleBooleanProperty(true);
}
有了以上三個基礎類後整個遊戲框架就基本建立起來了,再來就是配置類SCcontants用來管理視窗的大小,蛇的大小等,事件類SEvent表示鍵盤滑鼠事件。
2.5 蛇相關類編寫
蛇相關類是整個程式最重要的一部分,首先對於一條蛇,我們將其看作是由一個蛇頭和蛇身組成的,分別對應BaseSnake類和BaseBody類,前者負責控制蛇頭按照其Direction(方向)變數移動,後者則控制蛇身移動。這裡蛇身的移動策略是這樣的,首先它的建構函式有一個引數為BaseSnake類,這裡將兩者位置屬性繫結在一起,蛇身是由一個個圓形排列在一起形成的,使用類似雙端佇列的結構(list)儲存,每次移動時,就將這一串圓形的最後一個刪除,同時新增一個新的圓形到蛇頭的位置,因為蛇頭也在這段時間內向前移動了,這樣就形成了前進的效果,當然如果是吃到了食物的話,那就只新增圓形而不刪除。如下圖所示:
有了這兩個基礎類組成蛇之後,我們還需要分別設計兩個類來繼承BaseSnake類,一個作為被玩家使用鍵盤控制的蛇UserSanke類,另一個為電腦控制的蛇AISnake類。對於玩家來說,主要是通過方向鍵來控制蛇,蛇的移動有八個方位,玩家使用方向鍵可改變基類中的Direction變數,然後基類通過計算該方向在x軸、y軸的移動量來往這個方向移動。而電腦蛇的移動策略也比較簡單,每個一段時間檢測一次食物在哪個方位,然後更新方向變數即可。
2.6 介面UI
介面UI比較簡單,主要是呼叫Canvas的渲染影象api把圖形畫出來,包括兩個類,一個是Info類,負責顯示遊戲進行中的各種資訊,如當前得分、剩餘時間等,另一個是GameOver類,負責顯示遊戲結束時的提示畫面。
2.7 食物類與時間類
食物類主要是隨機選取一個位置生成食物,當食物被吃了之後,就繼續生成一個。
時間類,其實就是提供給介面UI的倒計時,這個類單獨開了一個執行緒,在這個執行緒上設定遞減計數,每計一次執行緒就休眠一秒,再把計數器宣告一個方法暴露出去,這樣就形成了按秒的倒計時。
2.8 主遊戲場景
這個GameScreen類繼承自SScreen類,是遊戲的主要執行場景,這裡要引人一個層的概念,即遊戲畫面是由一層層的物件疊加而成的,在這個類中,我們將UI層放在最上面,將蛇(包括user蛇和AI蛇)放在中間層,最底層是食物,這樣疊加起來就形成我們看到的遊戲畫面了。
同時在這個類中,我們進行大部分的操作,如呼叫UI更新資訊的方法,檢測是否吃到食物,是否發生碰撞等。
另外,這裡還設定了一個功能,就是蛇的穿牆操作,當蛇前進到邊界後,它會從邊界的映象方向出現,形成了穿牆,其實就是當蛇頭進入邊界外後,更新蛇的位置座標到相反方向。
2.9 程式入口
MainEnter類既是程式的入口,也是程式的流程控制器,當進入程式後,它先顯示出開始介面以及開始遊戲的按鈕,點選按鈕後,程式會把主遊戲場景掛載在該類下,也就是顯示了主遊戲場景,開始了遊戲,當遊戲結束或者點選返回按鈕後,程式會把主遊戲場景刪除掉,繼而回到開始介面,形成一個完整的遊戲邏輯。