Snake on a phone——Android開源項目實戰,貪喫蛇遊戲
本文以及後續幾篇文章對貪喫蛇開源項目進行源碼剖析,以此爲切入點對相關知識點進行總結,最後對項目進行擴展,實現可以在手機上操作的遊戲,也就是觸摸操作的Snake遊戲。
https://github.com/lonely917/snake-on-a-phone-fling-version
導入項目
- 新建項目選擇sample工程,有android snake示例項目
- 通過文章給出的github連接下載最終擴展完成的touch版Snake遊戲
項目架構
項目主要文件如下
- Snake.java
- SnakeView.java
- TileView.java
- snake_layout.xml
snake是主activity,對應佈局snake_layout.xml,其中SnakeView是自定義的遊戲主題View,繼承自定義的TileView。
整體項目代碼不多,唯一的佈局文件snake_layout.xml內容如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.android.snake.SnakeView
android:id="@+id/snake"
android:layout_width="match_parent"
android:layout_height="match_parent"
tileSize="24" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:text="@string/snake_layout_text_text"
android:textColor="#ff8888ff"
android:textSize="24sp"
android:visibility="visible" />
</RelativeLayout>
</FrameLayout>
這個很簡單,就是加載了一個自定義View,和一個提示性的text,重點就是我們這個snakeview是如何實現的,其中tilesize是自定義view的自定義屬性,界面是網格型的,它表示每個方形網格的邊長,在snakeview的講解中會重點介紹。
項目啓動流程
Snake主Activity啓動加載layout佈局,然後對SnakeView進行初始化,項目啓動,等待用戶操作,主界面顯示 “press up to start game”,這個時候我們發現如何操作都不能啓動項目,爲什麼呢,因爲這個遊戲試運行在帶手柄的遊戲設備dpad上的,因此手機是無法啓動它的,使用模擬器可以進行適當的設置調出dpad操作鍵,當然我們最終會修改這個項目使得我們能夠通過滑動去操作遊戲,在此之前我們先要明白遊戲是如何運行和控制的,控制接口在哪裏,找到了控制接口我們再用手勢操作去觸發對應接口事件即可,當然重點還是在學習項目的設計邏輯。 下面是snake的oncreate函數,也是snake的主體部分。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.snake_layout);
mSnakeView = (SnakeView) findViewById(R.id.snake);
mSnakeView.setTextView((TextView) findViewById(R.id.text));
if (savedInstanceState == null) {
// We were just launched -- set up a new game
mSnakeView.setMode(SnakeView.READY);
} else {
// We are being restored
Bundle map = savedInstanceState.getBundle(ICICLE_KEY);
if (map != null) {
mSnakeView.restoreState(map);
} else {
mSnakeView.setMode(SnakeView.PAUSE);
}
}
}
我們只看兩個部分
mSnakeView = (SnakeView) findViewById(R.id.snake);
mSnakeView.setMode(SnakeView.READY);
一個是獲取遊戲視圖,一個是設置狀態,savedInstanceState是在此程序意外退出時保存的遊戲狀態,如果保存有狀態,則對應恢復視圖,這裏我們可以先不考慮。由上面代碼可以看出整個程序的控制邏輯都在SnakeView裏面。那麼究竟爲何手機無法控制以及遊戲邏輯實現是什麼樣子,我們往後看。
SnakeView和TileView概覽_爲何無法運行遊戲
本節我們先搞清楚view的結構以及事件響應部分,後續文章會對視圖繪製進行詳細介紹。
SnakeView部分代碼
public class SnakeView extends TileView
TileView是網格視圖基類,自定義了網格的回執,可以理解爲一個棋盤,遊戲就是在上面進行的,SnakeView則是在其上添加了蘋果和蛇,以及遊戲控制邏輯。
public SnakeView(Context context, AttributeSet attrs) {
super(context, attrs);
initSnakeView();
}
構造函數,layout中的加載view的時候會調用,啓動initSnakeView則實現了初始化遊戲視圖的功能。此函數調用完成後視圖也就加載完畢,剩下的就是找事件監聽的部分。
public boolean onKeyDown(int keyCode, KeyEvent msg) {
if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
if (mMode == READY | mMode == LOSE) {
/*
* At the beginning of the game, or the end of a previous one,
* we should start a new game.
*/
initNewGame();
setMode(RUNNING);
update();
return (true);
}
if (mMode == PAUSE) {
/*
* If the game is merely paused, we should just continue where
* we left off.
*/
setMode(RUNNING);
update();
return (true);
}
if (mDirection != SOUTH) {
mNextDirection = NORTH;
}
return (true);
}
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
if (mDirection != NORTH) {
mNextDirection = SOUTH;
}
return (true);
}
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
if (mDirection != EAST) {
mNextDirection = WEST;
}
return (true);
}
if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
if (mDirection != WEST) {
mNextDirection = EAST;
}
return (true);
}
return super.onKeyDown(keyCode, msg);
}
SnakeView重寫了onKeyDown函數,也就是通過方向鍵去控制遊戲進行,比如最初up向上開始遊戲,然後通過方向鍵控制蛇走動的方向。這裏我們看事件監聽的類型
KeyEvent.KEYCODE_DPAD_UP
這是dpad設備的按鍵事件,自然手機沒有了,這也就是我們無法啓動遊戲的原因,我們可以在主界面添加四個方向鍵然後通過他們去控制方向,但是對遊戲界面覆蓋體驗不好,於是我想可以通過滑動手勢去操縱遊戲,於是就有了後文一系列探究。
- 手勢操作的Snake遊戲_拿來主義迅速上手
- SnakeView的控制邏輯_追本溯源一探究竟