【android遊戲】海底世界
阿新 • • 發佈:2018-12-05
轉載請註明出處:https://blog.csdn.net/u011038298/article/details/84334699
目錄
1.遊戲的執行視窗主類
import android.app.Activity; import android.app.ActivityManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.Display; import android.view.Window; import android.view.WindowManager; import android.content.pm.ActivityInfo; public class MainActivity extends Activity { public static int SCREEN_WIDTH; //螢幕的寬度 public static int SCREEN_HEIGHT; //螢幕的高度 private int message ; //定義一個整型變數,用於獲取訊息 public Handler gameHandler = null; //定義Handler物件 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); //請求把螢幕設定成橫屏 requestWindowFeature(Window.FEATURE_NO_TITLE); //請求隱藏標題,設定全屏狀態 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); WindowManager wm = getWindowManager(); //獲取WindowManager物件 Display display = wm.getDefaultDisplay(); //例項化Display物件 SCREEN_WIDTH = display.getWidth(); //獲取螢幕的寬度 SCREEN_HEIGHT = display.getHeight(); //獲取螢幕的高度 switchContentView(GameConstant.START_CARTOON); //每次當程式啟動的時候,執行開機動畫 gameHandler = new Handler(){ @Override public void handleMessage(Message msg) { message = msg.what; //把訊息賦值給message switchContentView(message); //根據message選擇程式執行的檢視 } }; } /** * 選擇檢視 * @param gameState */ public void switchContentView(int gameState) { switch(gameState) { case GameConstant.START_CARTOON: //開機動畫 setContentView(new StartCartoonView(this)); break; case GameConstant.GAME_MENU: //選單介面 setContentView(new MenuView(this)); break; case GameConstant.START_GAME: //開始遊戲 setContentView(new GameView(this)); break; case GameConstant.ABOUT_GAME: //關於遊戲 setContentView(new AboutView(this)); break; case GameConstant.EXIT_GAME: //退出遊戲 finish(); break; } } /** * 返回到選單介面 */ private void returnMenuView() { Message msg = new Message(); //例項化Message物件 msg.what = GameConstant.GAME_MENU; //把選單介面的常量賦值給msg.what gameHandler.sendMessage(msg); //給Handler傳送訊息 } @Override public void onBackPressed() { switch(message) { case GameConstant.GAME_MENU : //當介面顯示的是MenuView的時候 finish(); //結束程式 break; case GameConstant.START_GAME: //當介面顯示的是GameView的時候 returnMenuView(); //返回選單介面 break; case GameConstant.ABOUT_GAME : //當介面顯示的是AboutView的時候 returnMenuView(); //返回選單介面 break; } } }
2.遊戲的開機動畫類
import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.os.Message; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.SurfaceHolder.Callback; public class StartCartoonView extends SurfaceView implements Runnable, Callback { private Main main; //定義Main物件 private int count=0; //開機動畫的持續時間 private Thread subThread = null; //定義一個執行緒 private boolean subThreadFlag = true; //標誌子執行緒迴圈執行 private SurfaceHolder myHolder = null; //定義SurfaceHolder物件 private Bitmap img_start_cartoon = null; //定義Bitmap物件 public StartCartoonView(Context context) { super(context); //呼叫父類構造方法 main = (Main)context; //例項化Main物件 subThread = new Thread(this); //例項化子執行緒 myHolder = getHolder(); //獲取SurfaceHolder物件例項 myHolder.addCallback(this); //新增Callback介面 } /** * 執行子執行緒 */ public void run() { while(subThreadFlag) { count += 1; //開機動畫的持續時間自增 Canvas canvas = myHolder.lockCanvas(); //鎖定畫布 if(canvas != null) { //判斷畫布不為空 canvas.drawBitmap(img_start_cartoon, 0, 0, null); //繪製開機動畫圖 myHolder.unlockCanvasAndPost(canvas); //解除畫布鎖定 } if(count>3) { //判斷開機動畫的持續時間大於5 Message msg = new Message(); //例項化Message物件 msg.what = GameConstant.GAME_MENU; //把表示選單介面的常量給msg.what賦值 main.gameHandler.sendMessage(msg); //給Handler傳送訊息 } try { Thread.sleep(1000); //執行緒每隔1秒執行一次 } catch (InterruptedException e) {} } } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { //當SurfaceView例項尺寸改變時呼叫 } public void surfaceCreated(SurfaceHolder holder) { //當SurfaceView例項建立時呼叫 img_start_cartoon = BitmapFactory.decodeResource(getResources(), R.drawable.start_cartoon); //初始化背景圖片 subThread.start(); //啟動子執行緒 } public void surfaceDestroyed(SurfaceHolder holder) { //當SurfaceView例項銷燬時呼叫 subThreadFlag = false; //停止子執行緒迴圈 count = 0; //開機動畫時間清零 } }
3.遊戲的選單類
import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.os.Message; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.SurfaceHolder.Callback; public class MenuView extends SurfaceView implements Runnable, Callback { private Main main; //定義Main物件 private Thread subThread = null; //定義一個執行緒 private boolean subThreadFlag = true; //標誌子執行緒迴圈執行 private SurfaceHolder holder = null; //定義SurfaceHolder物件 private Bitmap imgMenu = null; //定義Bitmap物件 public MenuView(Context context) { super(context); //呼叫父類構造方法 main = (Main)context; //例項化Main物件 subThread = new Thread(this); //例項化子執行緒 holder = getHolder(); //獲取SurfaceHolder物件例項 holder.addCallback(this); //新增Callback介面 } /** * 繪製選單介面 */ private void drawGameMenu() { Canvas canvas = holder.lockCanvas(); //鎖定畫布 if(canvas != null) { //判斷畫布不為空 canvas.drawBitmap(imgMenu, 0, 0, null); //繪製選單背景圖 holder.unlockCanvasAndPost(canvas); //解除畫布鎖定 } } /** * 執行子執行緒 */ public void run() { while(subThreadFlag) { drawGameMenu(); //繪製選單介面 } } @Override public boolean onTouchEvent(MotionEvent event) { float touchX = event.getX(); //獲取使用者點選螢幕的X座標 float touchY = event.getY(); //獲取使用者點選螢幕的Y座標 System.out.println("touchX:" +touchX + "touchY" +touchY); //先判斷點選的事件是使用者點選螢幕鬆口手的那一瞬間,再判斷觸控的X座標是否滿足條件 if(event.getAction() == MotionEvent.ACTION_DOWN && imgMenu.getWidth()*0.63 <= touchX && touchX <= imgMenu.getWidth()*0.9) { if(imgMenu.getHeight()*0.28 <= touchY && touchY <= imgMenu.getHeight()*0.42) { //開始遊戲 Message msg = new Message(); //例項化Message物件 msg.what = GameConstant.START_GAME; //把開始遊戲的常量給msg.what賦值 main.gameHandler.sendMessage(msg); //給Handler傳送訊息 } else if(imgMenu.getHeight()*0.48 <= touchY && touchY <= imgMenu.getHeight()*0.62) { //關於遊戲 Message msg = new Message(); //例項化Message物件 msg.what = GameConstant.ABOUT_GAME; //把關於遊戲的常量給msg.what賦值 main.gameHandler.sendMessage(msg); //給Handler傳送訊息 } else if(imgMenu.getHeight()*0.68 <= touchY && touchY <= imgMenu.getHeight()*0.82) { //退出遊戲 Message msg = new Message(); //例項化Message物件 msg.what = GameConstant.EXIT_GAME; //把退出遊戲的常量給msg.what賦值 main.gameHandler.sendMessage(msg); //給Handler傳送訊息 } } return super.onTouchEvent(event); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { //當SurfaceView例項尺寸改變時呼叫 } public void surfaceCreated(SurfaceHolder holder) { //當SurfaceView例項建立時呼叫 imgMenu = BitmapFactory.decodeResource(getResources(), R.drawable.menu); //初始化背景圖片 subThread.start(); //啟動子執行緒 } public void surfaceDestroyed(SurfaceHolder holder) { //當SurfaceView例項銷燬時呼叫 subThreadFlag = false; //停止子執行緒迴圈 } }
4.遊戲的關於介面
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
import android.graphics.BitmapFactory;
import android.view.SurfaceHolder.Callback;
public class AboutView extends SurfaceView implements Runnable, Callback {
private Thread subThread = null; //定義一個執行緒
private boolean subThreadFlag = true; //標誌子執行緒迴圈執行
private SurfaceHolder myHolder = null; //定義SurfaceHolder物件
private Bitmap img_about = null; //定義Bitmap物件
public AboutView(Context context) {
super(context); //呼叫父類構造方法
subThread = new Thread(this); //例項化子執行緒
myHolder = getHolder(); //獲取SurfaceHolder物件例項
myHolder.addCallback(this); //新增Callback介面
}
/**
* 執行子執行緒
*/
public void run() {
while(subThreadFlag) {
Canvas canvas = myHolder.lockCanvas(); //鎖定畫布
if(canvas != null) { //判斷畫布不為空
canvas.drawBitmap(img_about, 0, 0, null); //繪製開機動畫圖
myHolder.unlockCanvasAndPost(canvas); //解除畫布鎖定
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
//當SurfaceView例項尺寸改變時呼叫
}
public void surfaceCreated(SurfaceHolder holder) {
//當SurfaceView例項建立時呼叫
img_about = BitmapFactory.decodeResource(getResources(),
R.drawable.about); //初始化背景圖片
subThread.start(); //啟動子執行緒
}
public void surfaceDestroyed(SurfaceHolder holder) {
//當SurfaceView例項銷燬時呼叫
subThreadFlag = false; //停止子執行緒迴圈
}
}
5.遊戲的主介面
import java.util.ArrayList;
import java.util.Iterator;
import android.app.Service;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;
public class GameView extends SurfaceView implements Runnable, Callback {
private Thread subThread = null; // 定義一個執行緒
private boolean subThreadFlag = true; // 標誌子執行緒迴圈執行
private SurfaceHolder myHolder = null; // 定義SurfaceHolder物件
private Bitmap imgBackground = null; // 背景圖片
private int backgroundX; // 背景圖片的X座標
public int gameCustom = 1; // 遊戲關卡,開始時預設第一關
private int time = 0; // 定義一個時間來控制畫怪獸魚
private int bossTime = 0; // 定義出現BOSS的時間
private int customTime = 30; // 根據不同的關卡來控制出怪物的時間,開始的時候預設第一關
private int customBossTime = 5000; // 出現BOSS的時間
private int customBossTime2; // 出BOSS的時間
private int coolingTime = 0; // 技能冷卻時間
private int bossBulletTime = 0; // 定義BOSS出子彈的時間
private Player player; // 定義玩家物件
private int orientation = 1; // BOSS的方向, 1往下走,2往上走
private Bitmap imgPlayerBullet; // 玩家子彈圖
private Bitmap imgFish1; // 第一關的怪獸魚
private Bitmap imgFish2; // 第二關的怪獸魚
private Bitmap imgFish3; // 第三關的怪獸魚
private Bitmap imgBoss1; // 第一關的BOSS
private Bitmap imgBoss2; // 第二關的BOSS
private Bitmap imgBossBullet; // BOSS的子彈
private Bitmap imgBossBullet2; // BOSS的子彈
private Bitmap imgBossHP; // 血條
private Bitmap imgBossHP1; // 空血條
private Bitmap imgGameOver; // 遊戲結束圖
private Bitmap imgGameWin; // 遊戲勝利圖
private int boss1X; // BOSS的X座標
private int boss1Y; // BOSS的Y座標
private int boss1HP; // BOSS1血條
private int boss2HP; // BOSS2血條
private int boss2X; // BOSS2的X座標
private int boss2Y; // BOSS2的Y座標
private ArrayList<PlayerBullet> playerBulletList = new ArrayList<PlayerBullet>(); // 玩家子彈集合
private ArrayList<Fish> fishList = new ArrayList<Fish>(); // 怪獸魚的集合
private ArrayList<BossBullet> bossBulletList = new ArrayList<BossBullet>(); // BOSS子彈集合
private boolean bossFlag = false; // 標誌出現BOSS的時候
private boolean gameoverFlag = false; // 標誌遊戲結束
private boolean gameCustom2Flag = false; // 進入下一關遊戲
private Sensor sensor; // 定義一個感測器
private SensorManager sensorManager; // 定義感測器物件
private SensorEventListener smListener; // 定義感測器監聽物件
public GameView(Context context) {
super(context);
initResourceImg(); // 初始化資源圖片
initData(); // 初始化資料
sensorMethod(); // 感測器方法
subThread = new Thread(this); // 例項化子執行緒
myHolder = getHolder(); // 獲取SurfaceHolder物件例項
myHolder.addCallback(this); // 新增Callback介面
}
/**
* 初始化圖片資源
*/
private void initResourceImg() {
imgBackground = BitmapFactory.decodeResource(getResources(),
R.drawable.background); // 初始化背景圖片
imgPlayerBullet = BitmapFactory.decodeResource(getResources(),
R.drawable.player_bullet); // 初始化玩家子彈
imgFish1 = BitmapFactory.decodeResource(getResources(),
R.drawable.fish1); // 初始化怪獸魚1號
imgFish2 = BitmapFactory.decodeResource(getResources(),
R.drawable.fish2); // 初始化怪獸魚2號
imgFish3 = BitmapFactory.decodeResource(getResources(),
R.drawable.fish3); // 初始化怪獸魚3號
imgBoss1 = BitmapFactory.decodeResource(getResources(),
R.drawable.boss1); // 初始化Boss1
imgBossBullet = BitmapFactory.decodeResource(getResources(),
R.drawable.boss_bullet); // 初始化BOSS子彈
imgBossBullet2 = BitmapFactory.decodeResource(getResources(),
R.drawable.boss2_bullet); // 初始化BOSS子彈
imgBossHP = BitmapFactory.decodeResource(getResources(),
R.drawable.boss_hp); // 初始化BOSS血條
imgBossHP1 = BitmapFactory.decodeResource(getResources(),
R.drawable.boss_hp1); // 初始化BOSS空血條
imgBoss2 = BitmapFactory.decodeResource(getResources(),
R.drawable.longwang); // 初始化Boss2圖
imgGameOver = BitmapFactory.decodeResource(getResources(),
R.drawable.gameover); // 初始化遊戲結束圖
imgGameWin = BitmapFactory.decodeResource(getResources(),
R.drawable.passgame);
}
/**
* 初始化資料
*/
private void initData() {
player = new Player(getContext()); // 例項化玩家物件
boss1X = (int) (Main.SCREEN_WIDTH - imgBoss1.getWidth()); // 初始化BOSS的X座標
boss1Y = (int) Main.SCREEN_HEIGHT / 2; // 初始化BOSS的Y座標
boss1HP = 1000; // 初始化BOSS滿血
}
/**
* 感測器方法
*/
private void sensorMethod() {
sensorManager = (SensorManager) getContext().getSystemService(
Service.SENSOR_SERVICE); // 獲取SensorManager物件
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); // 獲取加速感測器
smListener = new SensorEventListener() { // 監聽感測器事件
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// 感測器精度發生變化的時候呼叫
}
public void onSensorChanged(SensorEvent event) {
// 感測器發生加速度分量值發生改變時呼叫
float[] values = event.values;
float sensorX = values[0];
float sensorY = values[1];
// 判斷X軸方向的加速度是否大於Y軸方向的加速
if (Math.abs(sensorX) > Math.abs(sensorY)) {
if (sensorX > 0) { // 如果X軸感測加速度為正數
player.playerY += 10;
if (player.playerY + player.imgPlayerH >= Main.SCREEN_HEIGHT) {
player.playerY -= 10;
}
} else if (sensorX < 0) { // 如果X軸感測加速度為負數
player.playerY -= 10;
if (player.playerY <= 0) {
player.playerY += 10;
}
}
} else {
if (sensorY > 0) { // 如果Y軸感測加速度為正
player.playerX += 10;
if (player.playerX + player.imgPlayerW >= Main.SCREEN_WIDTH) {
player.playerX -= 10;
}
} else if (sensorY < 0) { // 如果Y軸感測加速度為負
player.playerX -= 10;
if (player.playerX <= 0) {
player.playerX += 10;
}
}
}
}
};
sensorManager.registerListener(smListener, sensor,
SensorManager.SENSOR_DELAY_FASTEST); // 註冊加速感測器的監聽
}
/**
* 玩家發子彈
*/
private void playerSendBullet() {
synchronized (playerBulletList) { // 同步把玩家子彈放進集合中,保證執行緒的安全性
if(player.fraction<10000) { //當玩家分數少於一萬時
PlayerBullet playerBullet = new PlayerBullet(imgPlayerBullet,
(int) (player.playerX + player.imgPlayerW),
player.playerY, 5, 0);// 子彈水平方向
playerBulletList.add(playerBullet); // 把子彈新增到集合中去
}else {
PlayerBullet playerBullet1 = new PlayerBullet(imgPlayerBullet,
(int) (player.playerX + player.imgPlayerW),
player.playerY, 5, -4);// 子彈向上方向
PlayerBullet playerBullet2 = new PlayerBullet(imgPlayerBullet,
(int) (player.playerX + player.imgPlayerW),
player.playerY, 5, 0);// 子彈水平方向
PlayerBullet playerBullet3 = new PlayerBullet(imgPlayerBullet,
(int) (player.playerX + player.imgPlayerW),
player.playerY, 5, 4);// 子彈向下方向
playerBulletList.add(playerBullet1); // 把第一顆子彈新增到集合中去
playerBulletList.add(playerBullet2); // 把第二顆子彈新增到集合中去
playerBulletList.add(playerBullet3); // 把第三顆子彈新增到集合中去
}
}
}
/**
* 把集合中的子彈繪製在螢幕上
*/
private void drawPlayerBulletOnScreen(Canvas canvas) {
synchronized (playerBulletList) { // 同步把玩家子彈放進集合中,保證執行緒的安全性
for (Iterator<PlayerBullet> iterator = playerBulletList.iterator(); iterator
.hasNext();) {
PlayerBullet bullet = iterator.next(); // 用迭代的方法把子彈從集合中取出來
bullet.drawPlayerBullet(canvas); // 繪製玩家子彈
}
}
}
/**
* 往集合中不斷的新增怪獸魚
*/
private void addFishToList() {
time++; // 讓時間累加
if (time > customTime) { // 判斷時間是否大於關卡時間
time = 0; // 重新計時
synchronized (fishList) {
switch (gameCustom) {
case GameConstant.GAME_CUSTOM1: // 遊戲的第一關
Fish oneF1 = new Fish(imgFish1, getWidth(),
(int) ((float) getHeight() / 4));
Fish oneF2 = new Fish(imgFish1, getWidth(),
(int) ((float) getHeight() / 2));
Fish oneF3 = new Fish(imgFish1, getWidth(),
(int) ((float) getHeight() / 1.2));
fishList.add(oneF1); // 把第一條魚新增到集合中去
fishList.add(oneF2); // 把第二條魚新增到集合中去
fishList.add(oneF3); // 把第三條魚新增到集合中去
break;
case GameConstant.GAME_CUSTOM2: // 遊戲的第二關
Fish twoF1 = new Fish(imgFish2, getWidth(),
(int) ((float) getHeight() / 5));
Fish twoF2 = new Fish(imgFish3, getWidth(),
(int) ((float) getHeight() / 3.5));
Fish threeF1 = new Fish(imgFish2, getWidth(),
(int) ((float) getHeight() / 1.8));
Fish threeF2 = new Fish(imgFish3, getWidth(),
(int) ((float) getHeight() / 1.2));
fishList.add(twoF1); // 把第一條魚新增到集合中去
fishList.add(threeF1); // 把第三條魚新增到集合中去
fishList.add(twoF2); // 把第二條魚新增到集合中去
fishList.add(threeF2); // 把第四條魚新增到集合中去
break;
}
}
}
}
/**
* 把集合中的魚繪製在螢幕上
*/
private void drawFishOnScreen(Canvas canvas) {
addFishToList(); // 先把怪獸魚新增到集合中來
synchronized (fishList) { // 同步怪獸魚的執行緒
for (Iterator<Fish> iterator = fishList.iterator(); iterator
.hasNext();) {
Fish fish = iterator.next(); // 用迭代的方法把怪獸魚逐個的從集合中取出
int random = (int) (Math.random() * 10); // 產生一個隨機數
fish.fishX -= random; // 隨機移動怪獸魚的X座標
if (random > 6) {
fish.fishY += random; // 隨機移動怪獸魚的Y座標
if (fish.fishY + imgFish1.getHeight() >= getHeight()) {
fish.fishY -= random;
}
} else {
fish.fishY -= random; // 隨機移動怪獸魚的Y座標
if (fish.fishY <= 0) {
fish.fishY += random;
}
}
fish.drawFish(canvas); // 畫怪獸魚
}
}
}
/**
* 把集合中的魚繪製在螢幕上2
*/
private void drawFishOnScreen2(Canvas canvas) {
addFishToList(); // 先把怪獸魚新增到集合中來
synchronized (fishList) {
for (Iterator<Fish> iterator = fishList.iterator(); iterator
.hasNext();) {
Fish fish = iterator.next(); // 用迭代的方法把怪獸魚逐個的從集合中取出
int random = (int) (Math.random() * 10); // 產生一個隨機數
fish.fishX -= random; // 隨機移動怪獸魚的X座標
if (random > 6) {
fish.fishY += random; // 隨機移動怪獸魚的Y座標
if (fish.fishY + imgFish1.getHeight() >= getHeight()) {
fish.fishY -= random;
}
} else {
fish.fishY -= random; // 隨機移動怪獸魚的Y座標
if (fish.fishY <= 0) {
fish.fishY += random;
}
}
fish.drawFish(canvas); // 畫怪獸魚
}
}
}
/**
* 判斷子彈是否打中怪獸魚
*/
private void bulletHitFish() {
synchronized (playerBulletList) { // 同步子彈執行緒
synchronized (fishList) { // 同步怪獸魚執行緒
PlayerBullet playerBullet = null;
Fish fish = null;
for (PlayerBullet bullet : playerBulletList) {
int bulletX = bullet.playerBulletX; // 獲取該子彈物件的X座標
int bulletY = bullet.playerBulletY; // 獲取該子彈物件的Y座標
for (Fish fishs : fishList) {
int fishX = fishs.fishX; // 獲取該怪獸魚物件的X座標
int fishY = fishs.fishY; // 獲取該怪獸魚物件的Y座標
if (Math.abs(bulletX - fishX) <= 10
&& Math.abs(bulletY - fishY) <= 10) { // 判斷是否相撞
playerBullet = bullet; // 把相撞的子彈物件賦值出去
fish = fishs; // 把相撞的怪獸魚物件賦值出去
player.fraction += 100; // 將分數值自增100
}
}
}
playerBulletList.remove(playerBullet); // 把子彈從集合中移除
fishList.remove(fish); // 把怪獸魚從集合中移除
}
}
}
/**
* 判斷怪獸魚是否碰撞到了玩家
*/
private void fishCollidePlayer() {
synchronized (fishList) {
Fish fish = null;
for (Fish f : fishList) {
int fishX = f.fishX;
int fishY = f.fishY;
if (Math.abs(fishX - player.playerX - player.imgPlayerW) <= 10
&& Math.abs(fishY + (imgFish1.getHeight() / 2)
- player.playerY - (player.imgPlayerH / 2)) <= 10) {
fish = f;
player.playerHP -= 30;
}
}
fishList.remove(fish);
}
}
/**
* 判斷BOSS1子彈是否打中玩家
*/
private void bossBulletHitPlayer() {
synchronized (bossBulletList) {
BossBullet bossBullet = null;
for (BossBullet bb : bossBulletList) {
int bossBulletX = bb.bossBulletX;
int bossBulletY = bb.bossBulletY;
if (Math.abs(bossBulletX - player.playerX - player.imgPlayerW) <= 10
&& Math.abs(bossBulletY
+ (bb.imgBullet.getHeight() / 2)
- player.playerY - (player.imgPlayerH / 2)) <= 10) {
bossBullet = bb;
switch (gameCustom) {
case GameConstant.GAME_CUSTOM1:
player.playerHP -= 50; //玩家減血
break;
case GameConstant.GAME_CUSTOM2:
player.playerHP -= 50; //玩家減血
break;
}
}
}
bossBulletList.remove(bossBullet);
}
}
/**
* 判斷玩家子彈是否打中BOSS
*/
private void playerBulletHitBoss() {
synchronized (playerBulletList) {
PlayerBullet playerBullet = null;
for (PlayerBullet pb : playerBulletList) {
int playerBulletX = pb.playerBulletX;
int playerBulletY = pb.playerBulletY;
switch (gameCustom) {
case GameConstant.GAME_CUSTOM1:
if (playerBulletX > boss1X && playerBulletX < getWidth()
&& playerBulletY > boss1Y
&& playerBulletY < boss1Y + imgBoss1.getHeight()) {
playerBullet = pb; // 傳遞玩家子彈物件
player.fraction += 200; // 玩家加分
boss1HP -= 10; // BOSS減血
}
break;
case GameConstant.GAME_CUSTOM2:
if (playerBulletX > boss2X && playerBulletX < getWidth()
&& playerBulletY > boss2Y
&& playerBulletY < boss2Y + imgBoss2.getHeight()) {
playerBullet = pb; // 傳遞玩家子彈物件
player.fraction += 500; // 玩家加分
boss2HP -= 20; // BOSS減血
}
break;
}
}
playerBulletList.remove(playerBullet); // 移除玩家子彈
}
}
/**
* 往BOSS子彈集合中新增子彈
*/
private void addBossBulletToList() {
switch (gameCustom) {
case GameConstant.GAME_CUSTOM1:
bossBulletTime++; // 發子彈的時間累加
if (bossBulletTime > 30) { // 判斷髮子彈的時間是否大於10
synchronized (bossBulletList) {
BossBullet bossBullet1 = new BossBullet(imgBossBullet,
boss1X,
(int) (boss1Y + (imgBoss1.getHeight() / 2)), -5, -3);
BossBullet bossBullet2 = new BossBullet(imgBossBullet,
boss1X,
(int) (boss1Y + (imgBoss1.getHeight() / 2)), -5, 0);
BossBullet bossBullet3 = new BossBullet(imgBossBullet,
boss1X,
(int) (boss1Y + (imgBoss1.getHeight() / 2)), -5, 3);
bossBulletList.add(bossBullet1);
bossBulletList.add(bossBullet2);
bossBulletList.add(bossBullet3);
}
bossBulletTime = 0; // 重新計時
}
break;
case GameConstant.GAME_CUSTOM2:
bossBulletTime++; // 發子彈的時間累加
if (bossBulletTime > 10) {
synchronized (bossBulletList) {
BossBullet bossBullet2 = new BossBullet(imgBossBullet2,
boss1X,
(int) (boss2Y + (imgBoss2.getHeight() / 2)), -5, -4);
BossBullet bossBullet1 = new BossBullet(imgBossBullet2,
boss1X,
(int) (boss2Y + (imgBoss2.getHeight() / 2)), -5, -2);
BossBullet bossBullet3 = new BossBullet(imgBossBullet2,
boss1X,
(int) (boss2Y + (imgBoss2.getHeight() / 2)), -5, 0);
BossBullet bossBullet4 = new BossBullet(imgBossBullet2,
boss1X,
(int) (boss2Y + (imgBoss2.getHeight() / 2)), -5, 2);
BossBullet bossBullet5 = new BossBullet(imgBossBullet2,
boss1X,
(int) (boss2Y + (imgBoss2.getHeight() / 2)), -5, 4);
bossBulletList.add(bossBullet1);
bossBulletList.add(bossBullet2);
bossBulletList.add(bossBullet3);
bossBulletList.add(bossBullet4);
bossBulletList.add(bossBullet5);
}
bossBulletTime = 0; // 重新計時
}
break;
}
}
/**
* BOSS1發子彈
*/
private void sendBossBullet(Canvas canvas) {
addBossBulletToList(); // 先往集合中裝子彈
synchronized (bossBulletList) {
for (Iterator<BossBullet> iterator = bossBulletList.iterator(); iterator
.hasNext();) {
BossBullet bossBullet = iterator.next();
bossBullet.drawBossBullet(canvas);
}
}
}
/**
* 繪製BOSS
*/
private void drawBoss(Canvas canvas) {
switch (gameCustom) { // 判斷關卡
case GameConstant.GAME_CUSTOM1: // 遊戲的第一關
canvas.drawBitmap(imgBoss1, boss1X, boss1Y, null); // 繪製BOSS
if (orientation == 1) { // 判斷BOSS的方向
boss1Y++; // 移動BOSS的Y座標向下走
} else if (orientation == 2) { // 判斷BOSS的方向
boss1Y--; // 移動BOSS的Y座標向上走
}
if (boss1Y <= 0) { // 判斷BOS的Y座標是否小於等於0
orientation = 1; // 改變BOSS的方向,往下走
} else if (boss1Y + imgBoss1.getHeight() >= getHeight()) {
orientation = 2; // 改變BOSS的方向,往上走
}
sendBossBullet(canvas); // BOSS發子彈
int width = imgBossHP.getWidth() + 10;
canvas.drawBitmap(imgBossHP1, getWidth() - width, 10, null); // 繪製空血條
canvas.save(); // 先儲存畫布
canvas.clipRect(getWidth() - width, 10,
((getWidth() - width) + ((float) boss1HP / 1000)
* imgBossHP.getWidth()), 10 + imgBossHP.getHeight()); // 剪切出一個矩形
canvas.drawBitmap(imgBossHP, getWidth() - width, 10, null); // 畫血條HP
canvas.restore(); // 恢復畫布
break;
case GameConstant.GAME_CUSTOM2: // 遊戲的第二關
canvas.drawBitmap(imgBoss2, boss2X, boss2Y, null); // 繪製BOSS
if (orientation == 1) { // 判斷BOSS的方向
boss2Y++; // 移動BOSS的Y座標向下走
} else if (orientation == 2) { // 判斷BOSS的方向
boss2Y--; // 移動BOSS的Y座標向上走
}
if (boss2Y <= 0) { // 判斷BOS的Y座標是否小於等於0
orientation = 1; // 改變BOSS的方向,往下走
} else if (boss2Y + imgBoss2.getHeight() >= getHeight()) {
orientation = 2; // 改變BOSS的方向,往上走
}
sendBossBullet(canvas); // BOSS發子彈
int width2 = imgBossHP.getWidth() + 10;
canvas.drawBitmap(imgBossHP1, getWidth() - width2, 10, null); // 繪製空血條
canvas.save(); // 先儲存畫布
canvas.clipRect(getWidth() - width2, 10,
((getWidth() - width2) + ((float) boss2HP / 1000)
* imgBossHP.getWidth()), 10 + imgBossHP.getHeight()); // 剪切出一個矩形
canvas.drawBitmap(imgBossHP, getWidth() - width2, 10, null); // 畫血條HP
canvas.restore(); // 恢復畫布
break;
}
}
/**
* 判斷BOSS1是否出現了
*/
private void judgeBossAppear() {
if (bossTime > customBossTime) { // 判斷是否到了出BOSS時間
bossFlag = true; // 標誌著BOSS已經出現
fishList.clear(); // 清空怪獸魚集合
}
}
/**
* 判斷BOSS2是否出現了
*/
private void judgeBoss2Appear() {
if (bossTime > customBossTime2 || player.fraction>=100000) { // 判斷是否到了出BOSS2的時間
bossFlag = true; // 標誌著BOSS已經出現
fishList.clear(); // 清空怪獸魚集合
}
}
/**
* 根據BOSS的血條判斷通過遊戲
*/
private void judgeGamePass(Canvas canvas) {
if (boss1HP <= 0) { // 判斷BOSS的血是否小於等於零,
gameCustom = GameConstant.GAME_CUSTOM2; // 遊戲進入第二關
gameCustom2Flag = true; // 標誌著進入下一關遊戲
bossFlag = false; // BOSS出現為假
player.playerHP = 1000; // 讓玩家滿血
player.fraction += 3000; //打死BOSS玩家加三千分
time = 0; // 把控制出怪物的冷卻時間清零
customTime = 10; // 出怪物的時間間隔
bossTime = 0; // 把計算出BOSS的時間清零
customBossTime2 = 6000; // 出第二關BOSS的時間
boss2HP = 1000; // 初始化第二關BOSS的血
boss2X = (int) (Main.SCREEN_WIDTH - imgBoss2.getWidth()); // 初始化BOSS2的X座標
boss2Y = (int) (Main.SCREEN_HEIGHT / 2); // 初始化BOSS2的Y座標
bossBulletList.clear(); // BOSS子彈集合清零
bossBulletTime = 0; // BOSS發子彈累加清零
}
}
/**
* 根據玩家血條判斷遊戲結束
*/
private void judgeGameOver(Canvas canvas) {
if (player.playerHP <= 0) { // 判斷玩家的血是否小於等於零
canvas.drawBitmap(imgGameOver, 50, getHeight() / 3, null); // 畫遊戲結束圖
canvas.save(); // 儲存畫布
gameoverFlag = true; // 標誌遊戲結束
}
}
/**
* 移動背景圖片
*/
private void moveImgBackground() {
// 判斷背景圖的X座標是否小於背景圖的寬度減去檢視的寬度再減去5個畫素
if (backgroundX < imgBackground.getWidth() - getWidth() - 5) {
backgroundX += 5; // 背景圖的X自增5個畫素
if (backgroundX >= imgBackground.getWidth() - getWidth() - 5) {
backgroundX = 0; // 重新定位背景圖的X座標
}
} else {
backgroundX = 0; // 重新定位背景圖的X座標
}
}
/**
* 繪製遊戲介面
*/
private void drawGameView() {
if (!gameoverFlag) { // 如果遊戲結束不為真
Canvas canvas = myHolder.lockCanvas(); // 鎖定畫布
if (canvas != null) { // 判斷畫布不為空
Bitmap imgBackgrounds = Bitmap.createBitmap(imgBackground,
backgroundX, 0, getWidth(), getHeight()); // 建立新的背景圖片
canvas.drawBitmap(imgBackgrounds, 0, 0, null); // 繪製遊戲介面的背景圖片
moveImgBackground(); // 移動背景圖片
player.drawPlayer(canvas); // 畫出玩家
drawPlayerBulletOnScreen(canvas); // 畫出子彈
if (!gameCustom2Flag) { // 判斷進入下一關是否為假
judgeBossAppear(); // 判斷BOSS是否出現
if (!bossFlag) { // 判斷如果BOSS沒有出現
drawFishOnScreen(canvas); // 畫出怪獸魚
bulletHitFish(); // 判斷子彈是否擊中怪獸魚
fishCollidePlayer(); // 判斷怪獸魚是否碰撞到玩家
} else if (bossFlag) {
if (boss1HP > 0) {
drawBoss(canvas); // 繪製BOSS
bossBulletHitPlayer(); // 判斷BOSS子彈是否打中玩家
playerBulletHitBoss(); // 判斷玩家子彈是否打中BOS
}
}
judgeGamePass(canvas); // 判斷遊戲是否進入下一關
} else { // 繪製第二關遊戲介面
judgeBoss2Appear();
if (!bossFlag) {
drawFishOnScreen2(canvas); // 繪製怪物魚
bulletHitFish(); // 判斷子彈是否打中怪獸魚
fishCollidePlayer(); // 判斷怪獸魚是否碰撞到玩家
} else if (bossFlag) {
if (boss2HP > 0) {
drawBoss(canvas); // 繪製BOSS2
bossBulletHitPlayer(); // 判斷BOSS子彈是否打中玩家
playerBulletHitBoss(); // 判斷玩家子彈是否打中BOS
} else {
canvas.drawBitmap(imgGameWin, 50, 100, null); // 畫出遊戲勝利
canvas.save(); // 儲存畫布
gameoverFlag = true; // 結束遊戲
}
}
}
bossTime++; // 出現BOSS的時間自增
coolingTime++; // 玩家技能冷卻時間自增
player.drawPlayerHP(canvas); // 畫出玩家血條和分數值
judgeGameOver(canvas); // 判斷遊戲是否結束
myHolder.unlockCanvasAndPost(canvas); // 解除畫布鎖定
}
}
}
/**
* 執行子執行緒
*/
public void run() {
while (subThreadFlag) {
drawGameView(); // 繪製遊戲介面
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() == MotionEvent.ACTION_DOWN) {
switch (gameCustom) {
case GameConstant.GAME_CUSTOM1: // 遊戲第一關
if (coolingTime > 12) { // 判斷冷卻時間是否大於12
playerSendBullet(); // 玩家發子彈
player.playerState = GameConstant.PLAYER_STATE1; // 把玩家發子彈時的狀態賦值給玩家狀態
coolingTime = 0; // 重置技能冷卻時間
}
break;
case GameConstant.GAME_CUSTOM2: // 遊戲第二關
if (coolingTime > 8) { // 判斷冷卻時間是否大於8
playerSendBullet(); // 玩家發子彈
player.playerState = GameConstant.PLAYER_STATE1; // 把玩家發子彈時的狀態賦值給玩家狀態
coolingTime = 0; // 重置技能冷卻時間
}
break;
}
}
return super.onTouchEvent(event);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// 當SurfaceView例項尺寸改變時呼叫
}
public void surfaceCreated(SurfaceHolder holder) {
// 當SurfaceView例項建立時呼叫
backgroundX = 0; // 初始化背景圖的X座標
subThread.start(); // 啟動子執行緒
}
public void surfaceDestroyed(SurfaceHolder holder) {
// 當SurfaceView例項銷燬時呼叫
subThreadFlag = false; // 停止子執行緒迴圈
sensorManager.unregisterListener(smListener); // 取消感測器的註冊監聽
}
}
6.遊戲的常量類
public class GameConstant {
/** 開機動畫、選單的常量 */
public final static int START_CARTOON = 110;
public final static int GAME_MENU = 120;
/** 開始遊戲、關於遊戲和退出遊戲的常量 */
public final static int START_GAME = 0;
public final static int ABOUT_GAME = 1;
public final static int EXIT_GAME = 2;
/**玩家發子彈時候的狀態*/
public final static int PLAYER_STATE = 0;
public final static int PLAYER_STATE1 = 1;
/**遊戲的關卡*/
public final static int GAME_CUSTOM1 = 1;
public final static int GAME_CUSTOM2 = 2;
}
7.遊戲的玩家類
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
public class Player {
private Context context; //定義一個上下文
public Bitmap imgPlayer; //玩家正常狀態
public Bitmap imgPlayer1; //玩家發子彈時的狀態
public Bitmap imgPlayerHP; //玩家血條
public Bitmap imgPlayerHP1; //玩家空血條
public int imgPlayerW; //玩家圖片的寬度
public int imgPlayerH; //玩家圖片的高度
public int playerX; //玩家的X座標
public int playerY; //玩家的Y座標
public int playerState; //玩家的狀態
public int playerHP; //玩家的血條
public int fraction = 0; //玩家的分數值
public Paint paint; //定義畫筆物件
public Player(Context c) {
context = c; //傳遞上下文給當前玩家類
imgPlayer = BitmapFactory.decodeResource
(context.getResources(), R.drawable.player); //初始化玩家圖片
imgPlayer1 = BitmapFactory.decodeResource
(context.getResources(), R.drawable.player1); //初始化玩家圖片
imgPlayerHP = BitmapFactory.decodeResource
(context.getResources(), R.drawable.player_hp); //初始化玩家血條圖片
imgPlayerHP1 = BitmapFactory.decodeResource
(context.getResources(), R.drawable.player_hp1); //初始化玩家空血條圖片
imgPlayerW = imgPlayer.getWidth(); //獲取玩家圖片寬度
imgPlayerH = imgPlayer.getHeight(); //獲取玩家圖片的高度
playerX = 100; //初始化玩家的X座標
playerY = 100; //初始化玩家的Y座標
playerState = 0; //初始化玩家狀態
playerHP = 1000; //初始化玩家的血條
paint = new Paint(); //例項化畫筆
}
/**
* 繪製玩家
* @param canvas
*/
public void drawPlayer(Canvas canvas) {
switch(playerState) {
case GameConstant.PLAYER_STATE: //玩家正常狀態
canvas.drawBitmap(imgPlayer, playerX, playerY, null); //根據X,Y座標繪製玩家
break;
case GameConstant.PLAYER_STATE1: //玩家發子彈時的狀態
canvas.drawBitmap(imgPlayer1, playerX, playerY, null); //根據X,Y座標繪製玩家
playerState = GameConstant.PLAYER_STATE; //把玩家正常時的狀態賦值給玩家狀態
break;
}
}
/**
* 繪製玩家血條和分數值
* @param canvas
*/
public void drawPlayerHP(Canvas canvas) {
paint.setColor(Color.YELLOW); //設定字型顏色
paint.setTextSize(15); //設定字型大小
paint.setAntiAlias(true); //消除鋸齒
canvas.drawText("HP ", 10 , 10 + imgPlayerHP.getHeight(), paint);
canvas.drawBitmap(imgPlayerHP1, 35, 10, null); //繪製空血條
canvas.save(); //先儲存畫布
canvas.clipRect(35, 10, (35+((float)playerHP/1000)*imgPlayerHP.getWidth()),
10 + imgPlayerHP.getHeight()); //剪切出一個矩形,大小為血條值的百分比乘以血條圖的寬度
canvas.drawBitmap(imgPlayerHP, 35, 10, null); //畫血條HP
canvas.restore(); //恢復畫布
canvas.drawText("分數值:"+fraction, (40+imgPlayerHP.getWidth()),
10 + imgPlayerHP.getHeight(), paint); //畫出分數值
}
}
8.遊戲的玩家子彈類
import android.graphics.Bitmap;
import android.graphics.Canvas;
public class PlayerBullet {
public Bitmap imgBullet; //玩家子彈
public int playerBulletX; //玩家子彈的X座標
public int playerBulletY; //玩家子彈的Y座標
public int bulletSpeedX; //玩家子彈的X加速度
public int bulletSpeedY; //玩家子彈的Y加速度
public PlayerBullet(Bitmap bitmap, int x, int y, int speedX, int speedY) {
imgBullet = bitmap; //把傳遞過來的圖片賦值給子彈圖片
playerBulletX = x; //把傳遞過來的X座標賦值給子彈X座標
playerBulletY = y; //把傳遞過來的Y座標賦值給子彈Y座標
bulletSpeedX = speedX; //把傳遞過來的值賦值給子彈X加速度
bulletSpeedY = speedY; //把傳遞過來的值賦值給子彈Y加速度
}
/**
* 繪製玩家子彈
* @param canvas
*/
public void drawPlayerBullet(Canvas canvas) {
playerBulletX += bulletSpeedX; //把當前玩家子彈的X座標加上傳遞過來的加速度再賦值給玩家的X座標
playerBulletY += bulletSpeedY; //把當前玩家子彈的Y座標加上傳遞過來的加速度再賦值給玩家的Y座標
canvas.drawBitmap(imgBullet, playerBulletX, playerBulletY, null); //繪製玩家子彈
}
}
9.遊戲的怪獸類
import android.graphics.Bitmap;
import android.graphics.Canvas;
public class Fish {
private Bitmap imgFish; //怪獸魚
public int fishX; //怪獸魚的X座標
public int fishY; //怪獸魚的Y坐 標
public Fish(Bitmap bitmap, int x, int y) {
imgFish = bitmap; //把傳遞過來的圖片賦值給怪獸魚
fishX = x; //把傳遞過來的X座標賦值給怪獸魚的X座標
fishY = y; //把傳遞過來的Y座標賦值給怪獸魚的Y座標
}
/**
* 繪製怪獸魚
* @param canvas
*/
public void drawFish(Canvas canvas) {
canvas.drawBitmap(imgFish, fishX, fishY, null); //畫怪獸魚
}
}
10.遊戲的BOSS子彈類
import android.graphics.Bitmap;
import android.graphics.Canvas;
public class BossBullet {
public Bitmap imgBullet;
public int bossBulletX;
public int bossBulletY;
public int bossBulletSpeedX;
public int bossBulletSpeedY;
public BossBullet (Bitmap bitmap, int x, int y, int speedX, int speedY) {
imgBullet = bitmap;
bossBulletX = x;
bossBulletY = y;
bossBulletSpeedX = speedX;
bossBulletSpeedY = speedY;
}
/**
* 繪製BOSS子彈
* @param canvas
*/
public void drawBossBullet(Canvas canvas) {
bossBulletX += bossBulletSpeedX;
bossBulletY += bossBulletSpeedY;
canvas.drawBitmap(imgBullet, bossBulletX, bossBulletY, null);
}
}
11.遊戲執行截圖