android開發學習之路——連連看之游戲Activity(四)


    前面連連看之游戲界面(一)中已設計出游戲界面的布局文件,該布局文件需要使用一個Activity來負責顯示,除此以外,Activity還需要為游戲界面的按鈕、GameView組件的事件提供事件監聽器。

    尤其是對於GameView組件,程序需要監聽用戶的觸碰動作,當用戶觸碰屏幕時,程序需要獲取用戶觸碰的是哪個方塊,並判斷是否需要“消除”該方塊。為了判斷能否消除該方塊,程序需要進行如下判斷:

    ·如果程序之前已經選中了某個方塊,就判斷當前觸碰多的方塊是否能與之前的方塊“相連”,如果可以相連,則消除兩個方塊;如果兩個方塊不可以相連,則把當前方塊設置為選中方塊。

    ·如果程序之前沒有選中方塊,直接將當前方塊設置為選中方塊。

    Activity的代碼如下:src\org\crazyit\link\Link.java

  1 public class Link extends Activity
  2 {
  3     // 游戲配置對象
  4     private GameConf config;
  5     // 游戲業務邏輯接口
  6     private GameService gameService;
  7     // 游戲界面
  8     private GameView gameView;
  9     // 開始按鈕
 10     private Button startButton;
 11     // 記錄剩余時間的TextView
 12     private TextView timeTextView;
 13     // 失敗后彈出的對話框
 14     private AlertDialog.Builder lostDialog;
 15     // 游戲勝利后的對話框
 16     private AlertDialog.Builder successDialog;
 17     // 定時器
 18     private Timer timer = new Timer();
 19     // 記錄游戲的剩余時間
 20     private int gameTime;
 21     // 記錄是否處於游戲狀態
 22     private boolean isPlaying;
 23     // 振動處理類
 24     private Vibrator vibrator;
 25     // 記錄已經選中的方塊
 26     private Piece selected = null;
 27     private Handler handler = new Handler()
 28     {
 29         public void handleMessage(Message msg)
 30         {
 31             switch (msg.what)
 32             {
 33                 case 0x123:
 34                     timeTextView.setText("剩余時間: " + gameTime);
 35                     gameTime--;
 36                     // 時間小於0, 游戲失敗
 37                     if (gameTime < 0)
 38                     {
 39                         stopTimer();
 40                         // 更改游戲的狀態
 41                         isPlaying = false;
 42                         lostDialog.show();
 43                         return;
 44                     }
 45                     break;
 46             }
 47         }
 48     };
 49 
 50     @Override
 51     public void onCreate(Bundle savedInstanceState)
 52     {
 53         super.onCreate(savedInstanceState);
 54         setContentView(R.layout.main);
 55         // 初始化界面
 56         init();
 57     }
 58 
 59     // 初始化游戲的方法
 60     private void init()
 61     {
 62         config = new GameConf(8, 9, 2, 10 , 100000, this);
 63         // 得到游戲區域對象
 64         gameView = (GameView) findViewById(R.id.gameView);
 65         // 獲取顯示剩余時間的文本框
 66         timeTextView = (TextView) findViewById(R.id.timeText);
 67         // 獲取開始按鈕
 68         startButton = (Button) this.findViewById(R.id.startButton);
 69         // 獲取振動器
 70         vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
 71         gameService = new GameServiceImpl(this.config);
 72         gameView.setGameService(gameService);
 73         // 為開始按鈕的單擊事件綁定事件監聽器
 74         startButton.setOnClickListener(new View.OnClickListener()
 75         {
 76             @Override
 77             public void onClick(View source)
 78             {
 79                 startGame(GameConf.DEFAULT_TIME);
 80             }
 81         });
 82         // 為游戲區域的觸碰事件綁定監聽器
 83         this.gameView.setOnTouchListener(new View.OnTouchListener()
 84         {
 85             public boolean onTouch(View view, MotionEvent e)
 86             {
 87                 if (e.getAction() == MotionEvent.ACTION_DOWN)
 88                 {
 89                     gameViewTouchDown(e);
 90                 }
 91                 if (e.getAction() == MotionEvent.ACTION_UP)
 92                 {
 93                     gameViewTouchUp(e);
 94                 }
 95                 return true;
 96             }
 97         });
 98         // 初始化游戲失敗的對話框
 99         lostDialog = createDialog("Lost", "游戲失敗! 重新開始", R.drawable.lost)
100             .setPositiveButton("確定", new DialogInterface.OnClickListener()
101             {
102                 public void onClick(DialogInterface dialog, int which)
103                 {
104                     startGame(GameConf.DEFAULT_TIME);
105                 }
106             });
107         // 初始化游戲勝利的對話框
108         successDialog = createDialog("Success", "游戲勝利! 重新開始",
109             R.drawable.success).setPositiveButton("確定",
110             new DialogInterface.OnClickListener()
111             {
112                 public void onClick(DialogInterface dialog, int which)
113                 {
114                     startGame(GameConf.DEFAULT_TIME);
115                 }
116             });
117     }
118     @Override
119     protected void onPause()
120     {
121         // 暫停游戲
122         stopTimer();
123         super.onPause();
124     }
125     @Override
126     protected void onResume()
127     {
128         // 如果處於游戲狀態中
129         if (isPlaying)
130         {
131             // 以剩余時間重寫開始游戲
132             startGame(gameTime);
133         }
134         super.onResume();
135     }
136 
137     // 觸碰游戲區域的處理方法
138     private void gameViewTouchDown(MotionEvent event)
139     {
140         // 獲取GameServiceImpl中的Piece[][]數組
141         Piece[][] pieces = gameService.getPieces();
142         // 獲取用戶點擊的x座標
143         float touchX = event.getX();
144         // 獲取用戶點擊的y座標
145         float touchY = event.getY();
146         // 根據用戶觸碰的座標得到對應的Piece對象
147         Piece currentPiece = gameService.findPiece(touchX, touchY);
148         // 如果沒有選中任何Piece對象(即鼠標點擊的地方沒有圖片), 不再往下執行
149         if (currentPiece == null)
150             return;
151         // 將gameView中的選中方塊設為當前方塊
152         this.gameView.setSelectedPiece(currentPiece);
153         // 表示之前沒有選中任何一個Piece
154         if (this.selected == null)
155         {
156             // 將當前方塊設為已選中的方塊, 重新將GamePanel繪制, 並不再往下執行
157             this.selected = currentPiece;
158             this.gameView.postInvalidate();
159             return;
160         }
161         // 表示之前已經選擇了一個
162         if (this.selected != null)
163         {
164             // 在這里就要對currentPiece和prePiece進行判斷並進行連接
165             LinkInfo linkInfo = this.gameService.link(this.selected,
166                 currentPiece);
167             // 兩個Piece不可連, linkInfo為null
168             if (linkInfo == null)
169             {
170                 // 如果連接不成功, 將當前方塊設為選中方塊
171                 this.selected = currentPiece;
172                 this.gameView.postInvalidate();
173             }
174             else
175             {
176                 // 處理成功連接
177                 handleSuccessLink(linkInfo, this.selected
178                     , currentPiece, pieces);
179             }
180         }
181     }
182     // 觸碰游戲區域的處理方法
183     private void gameViewTouchUp(MotionEvent e)
184     {
185         this.gameView.postInvalidate();
186     }
187     
188     // 以gameTime作為剩余時間開始或恢復游戲
189     private void startGame(int gameTime)
190     {
191         // 如果之前的timer還未取消,取消timer
192         if (this.timer != null)
193         {
194             stopTimer();
195         }
196         // 重新設置游戲時間
197         this.gameTime = gameTime;        
198         // 如果游戲剩余時間與總游戲時間相等,即為重新開始新游戲
199         if(gameTime == GameConf.DEFAULT_TIME)
200         {
201             // 開始新的游戲游戲
202             gameView.startGame();
203         }
204         isPlaying = true;    
205         this.timer = new Timer();
206         // 啟動計時器 , 每隔1秒發送一次消息
207         this.timer.schedule(new TimerTask()
208         {
209             public void run()
210             {
211                 handler.sendEmptyMessage(0x123);
212             }
213         }, 0, 1000);
214         // 將選中方塊設為null。
215         this.selected = null;
216     }    
217 
218     /**
219      * 成功連接后處理
220      * 
221      * @param linkInfo 連接信息
222      * @param prePiece 前一個選中方塊
223      * @param currentPiece 當前選擇方塊
224      * @param pieces 系統中還剩的全部方塊
225      */
226     private void handleSuccessLink(LinkInfo linkInfo, Piece prePiece,
227         Piece currentPiece, Piece[][] pieces)
228     {
229         // 它們可以相連, 讓GamePanel處理LinkInfo
230         this.gameView.setLinkInfo(linkInfo);
231         // 將gameView中的選中方塊設為null
232         this.gameView.setSelectedPiece(null);
233         this.gameView.postInvalidate();
234         // 將兩個Piece對象從數組中刪除
235         pieces[prePiece.getIndexX()][prePiece.getIndexY()] = null;
236         pieces[currentPiece.getIndexX()][currentPiece.getIndexY()] = null;
237         // 將選中的方塊設置null。
238         this.selected = null;
239         // 手機振動(100毫秒)
240         this.vibrator.vibrate(100);
241         // 判斷是否還有剩下的方塊, 如果沒有, 游戲勝利
242         if (!this.gameService.hasPieces())
243         {
244             // 游戲勝利
245             this.successDialog.show();
246             // 停止定時器
247             stopTimer();
248             // 更改游戲狀態
249             isPlaying = false;
250         }
251     }
252 
253     // 創建對話框的工具方法
254     private AlertDialog.Builder createDialog(String title, String message,
255         int imageResource)
256     {
257         return new AlertDialog.Builder(this).setTitle(title)
258             .setMessage(message).setIcon(imageResource);
259     }
260     private void stopTimer()
261     {
262         // 停止定時器
263         this.timer.cancel();
264         this.timer = null;
265     }
266 }

    上面代碼中的gameViewTouchDown()方法負責處理觸碰事件。它會先根據觸碰點計算出觸碰的方法。接下來該方法會判斷是否之前已有選中的方塊,如果沒有,直接將當前方塊設為選中方塊,如果有,判斷兩個方塊是否可以相連。

    如果兩個方塊可以相連,程序將會從Piece[][]數組中刪除這兩個方塊,該邏輯由handleSuccessLink()方法完成。

    除此之外,該程序為了控制時間流失,定義了一個計時器,該計時器每隔1秒發送一條消息,程序將會根據該消息減少游戲剩余的時間。

    該Link Activity用的兩個類如下:

    ·GameConf:負責管理游戲的初始化設置信息。

    ·GameService:負責游戲的邏輯實現。

    上面兩個工具類中GameConf只是一個簡單的設置類,代碼如下:

 1 public class GameConf
 2 {
 3     // 設置連連看的每個方塊的圖片的寬、高
 4     public static final int PIECE_WIDTH = 40;
 5     public static final int PIECE_HEIGHT = 40;
 6     // 記錄游戲的總事件(100秒).
 7     public static int DEFAULT_TIME = 100;    
 8     // Piece[][]數組第一維的長度
 9     private int xSize;
10     // Piece[][]數組第二維的長度
11     private int ySize;
12     // Board中第一張圖片出現的x座標
13     private int beginImageX;
14     // Board中第一張圖片出現的y座標
15     private int beginImageY;
16     // 記錄游戲的總時間, 單位是秒
17     private long gameTime;
18     private Context context;
19 
20     /**
21      * 提供一個參數構造器
22      * 
23      * @param xSize Piece[][]數組第一維長度
24      * @param ySize Piece[][]數組第二維長度
25      * @param beginImageX Board中第一張圖片出現的x座標
26      * @param beginImageY Board中第一張圖片出現的y座標
27      * @param gameTime 設置每局的時間, 單位是秒
28      * @param context 應用上下文
29      */
30     public GameConf(int xSize, int ySize, int beginImageX,
31         int beginImageY, long gameTime, Context context)
32     {
33         this.xSize = xSize;
34         this.ySize = ySize;
35         this.beginImageX = beginImageX;
36         this.beginImageY = beginImageY;
37         this.gameTime = gameTime;
38         this.context = context;
39     }
40 
41     public long getGameTime()
42     {
43         return gameTime;
44     }
45 
46     public int getXSize()
47     {
48         return xSize;
49     }
50 
51     public int getYSize()
52     {
53         return ySize;
54     }
55 
56     public int getBeginImageX()
57     {
58         return beginImageX;
59     }
60 
61     public int getBeginImageY()
62     {
63         return beginImageY;
64     }
65 
66     public Context getContext()
67     {
68         return context;
69     }
70 }

 

具體實現步驟連接:

android開發學習之路——連連看之游戲界面(一)

android開發學習之路——連連看之數據模型(二)

android開發學習之路——連連看之加載圖片(三)

android開發學習之路——連連看之游戲Activity(四)

android開發學習之路——連連看之游戲邏輯(五)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM