小飛機遊戲

手機遊戲-飛機大戰外星蜘蛛
遊戲玩法:利用手機的重力加速度感測器來進行飛機的移動,飛機本身會自行發射子彈,目標是摧毀外星蜘蛛即可過關。
說明:此範例使用類似XNA架構編寫手機遊戲,其中應用到手機重力感應。此範例的特色為,利用重力加速度感測器來進行飛機的移動,如上下左右時,須擺動手機才能進行移動,功能類似iPhone上的電子水平儀遊戲。
下圖為遊戲程式執行畫面、程式的狀態圖、架構圖及流程圖。
%E5%B0%8F%E9%A3%9B%E6%A9%9F.PNG
圖一-遊戲程式執行畫面

Aircraft%28%E6%95%B5%E6%A9%9F%29%E7%8B%80%E6%85%8B%E5%9C%96.png
圖二-敵機狀態圖


spider%E7%8B%80%E6%85%8B%E5%9C%96.png
圖三-關卡魔王狀態圖]


%E4%B8%BB%E6%9E%B6%E6%A7%8B%E5%9C%96.png
圖四-主架構圖


%E5%9F%B7%E8%A1%8C%E7%B7%92.png
圖五-執行緒架構圖


%E5%B0%8F%E9%A3%9B%E6%A9%9F%E6%B5%81%E7%A8%8B%E5%9C%96.png
圖3六-繼承類別圖


%E7%B9%BC%E6%89%BF%E9%A1%9E%E5%88%A5%E5%9C%96.png
圖七-小飛機流程圖


以下為飛機大戰外星蜘蛛的程式碼:
專案下載:Bee.rar
主程式:Bee.java

package Bee.main;
import Bee.Object.Music;
import Bee.Role.F16;
import Bee.main.GameStateClass.GameState;
import Bee.scene.Game1;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.Vibrator;
import android.os.PowerManager.WakeLock;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
 
public class Bee extends Activity {
    private PowerManager powerManager;
    private WakeLock wakeLock;
 
    // 重力加速度感測器
    private SensorManager sensorMgr;  
    private Sensor sensor;
 
    // 遊戲選單
    public Game1 game;
 
    // 程式進入點
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        // 初始化
        Initialize();
 
        // 載入資源
        LoadContent();
    }
 
    // 初始化
    private void Initialize() {
        GV.res = getResources();
 
        // 取得震動系統服務
        GV.vibrator = (Vibrator) getApplication().getSystemService(
                Service.VIBRATOR_SERVICE);
 
        // 無標題列
        requestWindowFeature(Window.FEATURE_NO_TITLE);
 
        // 全螢幕設定
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
 
        // 螢幕固定成垂直方向
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
 
        // 取得螢幕大小
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        GV.scaleWidth = dm.widthPixels;
        GV.scaleHeight = dm.heightPixels;
        GV.halfWidth = GV.scaleWidth >> 1;
        GV.halfHeight = GV.scaleHeight >> 1;
 
        // 取得螢幕恆亮服務
        powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "BackLight");
 
        // 取得重力加速度感測器服務
        sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
        sensor = sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    }
 
    // 載入資源
    public void LoadContent() {
 
        // 遊戲狀態初始化
        GameStateClass.currentState = GameState.op;
        GameStateClass.oldState = GameState.None;
 
        // 背景音樂
        GV.music = new Music(this, R.raw.stage1, 3);
 
        // 初始化遊戲
        game = new Game1(this);
 
        // 初始化影片播放器
        GV.videoPlayer = new VideoPlayer(this);
 
        // 載入開頭動畫
        GV.videoPlayer.Load(R.raw.op);
 
        // 播放開頭動畫
        GV.videoPlayer.Play();
    }
 
    // 釋放資源
    public void UnloadContent()
    {
        GV.snd.release();
        GV.snd = null;
 
        finish();
    }
 
    // 回復程式
    @Override
    protected void onResume() {
        wakeLock.acquire();
 
        // 加速度計註冊
        sensorMgr.registerListener(lsn, sensor, SensorManager.SENSOR_DELAY_GAME);
 
        // 繼續播放影片
        if (GV.videoPlayer.isRuningVideo)
            GV.videoPlayer.Resume();
 
        super.onResume();
 
        // 會切到surfaceCreated
    }
 
    // 暫停程式
    @Override
    protected void onPause() {
        GV.vibrator.cancel();
        wakeLock.release();
 
        // 加速度計解註冊
        sensorMgr.unregisterListener(lsn);
 
        // 暫停影片播放
        if (GV.videoPlayer.isRuningVideo)
            GV.videoPlayer.Pause();
 
        if (game != null)
        {
            // 暫停音樂播放
            if (GameStateClass.currentState != GameState.Menu)
            {
                if (GV.music != null)
                    GV.music.Pause();
            }
 
            // 停止遊戲迴圈
 
            game.Exit();
        }
 
        super.onPause();
    }
 
    // 觸控事件
    public boolean onTouchEvent(MotionEvent event) 
    {
        // 按下
        if (event.getAction() == MotionEvent.ACTION_DOWN)
        {
            switch(GameStateClass.currentState)
            {
                case op:
                    GV.videoPlayer.Destroy();
 
                    break;
                case Menu:
                    // 如果正在播放影片則停止播放
                    if (!GV.videoPlayer.isRuningVideo)
                    {
                        // 停止遊戲執行緒
                        game.Exit();
 
                        // 載入並播放F16起飛動畫
                        GV.videoPlayer.Load(R.raw.f16);
                        GV.videoPlayer.Play();
                    }else
                    {
                        GV.videoPlayer.Destroy();
                    }
 
                    break;
                case Stage1:
 
                    // 大絕招
                    if (F16.bigBoom > 0)
                    {
                        if ((int)game.totalFrames - F16.startBigBoomFrame > F16.bigBoomDelayFrame)
                        {
                            F16.startBigBoomFrame = (int)game.totalFrames;
 
                            F16.isTouchBoom = true;
                            F16.bigBoom--;
                        }
                    }
 
                    break;
            }
        }
 
        return super.onTouchEvent(event);
    }
 
    // 鍵盤事件
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
 
        switch(keyCode)
        {
            case KeyEvent.KEYCODE_DPAD_LEFT:
                GV.x -=10;
                break;
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                GV.x +=10;
                break;
            case KeyEvent.KEYCODE_DPAD_UP:
                GV.y -=10;
                break;
            case KeyEvent.KEYCODE_DPAD_DOWN:
                GV.y +=10;
                break;
        }
 
        return super.onKeyDown(keyCode, event);
    }
 
    // 重力加速度感測器
    private SensorEventListener lsn = new SensorEventListener() {  
        public void onSensorChanged(SensorEvent e) {
 
            GV.x += (int) -e.values[SensorManager.DATA_X] << 2;
            GV.y += (int) e.values[SensorManager.DATA_Y] << 2;
 
            if (GV.y > GV.scaleHeight)
            {
                GV.y = GV.scaleHeight;
            }
 
//            GV.z = (int)e.values[SensorManager.DATA_Z];    
        }  
 
        public void onAccuracyChanged(Sensor s, int accuracy) {  
        }  
    };  
}

程式:GameStateClass.java

package Bee.main;
 
import XNA.lbs.DrawableGameComponent;
import XNA.lbs.Game;
 
public class GameStateClass {
    // 遊戲狀態
    public enum GameState
    {
        None,
        op,
        Menu,
        Stage1,
        Stage2,
    }
 
    public static GameState currentState;   // 目前遊戲狀態
    public static GameState oldState;       // 上一次的遊戲狀態
 
    // 切換關卡
    public static void changeState(GameState newState,DrawableGameComponent nowGameClass,Game game)
    {
        // 從Game1元件中移除
        game.Components.remove(nowGameClass);
 
        // 釋放Class
        nowGameClass.Dispose();
 
        currentState = newState;
    }
}

程式:GV.java

package Bee.main;
 
import Bee.Object.Music;
import android.content.res.Resources;
import android.graphics.Rect;
import android.media.SoundPool;
import android.os.Vibrator;
 
// 所有類別共用變數
public class GV {
    public enum Sound{
        boom,
        alert,
    }
 
    // 影片播放
    public static VideoPlayer videoPlayer = null;
 
    // 播放音樂
    public static Music music = null;
 
    // 播放遊戲音效
    public static SoundPool snd = null;
 
    // 音效ID
    public static int soundIDBoom = 0;
 
    // 音效ID
    public static int soundIDAlert = 0;
 
    // 螢幕大小
    public static int scaleWidth = 0;
    public static int scaleHeight = 0;
    public static int halfWidth = 0;
    public static int halfHeight = 0;
 
    // 螢幕範圍
    public static Rect screenRect = null;
 
    // 震動
    public static Vibrator vibrator = null;
 
    // 資源
    public static Resources res = null;
 
    // 自機的位置
    public static int x , y; 
 
    // 畫布
    public static Surface surface = null;
 
    // 碰撞偵測
    public static boolean isCollision(Rect a, Rect b)
    {
        if (a.left < b.right)
            if (a.right > b.left)
                if (a.top < b.bottom)
                    if (a.bottom > b.top)
                        return true;
 
        return false;
    }
 
    // 是否在螢幕內
    public static boolean isInScreen(Rect obj)
    {
        return isCollision(obj, screenRect);
    }
 
    // 三角函數
    public static float[] Cosine = new float[360];
    public static float[] Sine = new float[360];
 
    // 求角度
    public static int getTheta(double XDistance, double YDistance)
    {
        // 不可除以0
        if (XDistance == 0) XDistance = 1;
 
        // 角度
        int theta = (int)(Math.atan(YDistance / XDistance) * 180 / Math.PI);
 
        // 象限轉換
        if (XDistance >= 0 && theta <= 0)
            theta += 360;
        else if (XDistance <= 0)
            theta += 180;
 
        return theta;
    }
 
    // 播放音效
    public static void playSound(Sound sound)
    {
        switch(sound)
        {
        case boom:
            snd.play(soundIDBoom, 1, 1, 0, 0, 1);
            break;
        case alert:
            snd.play(soundIDAlert, 1, 1, 0, 0, 1);
            break;
        }
 
    }
}

程式:Surface.java

package Bee.main;
 
import android.view.SurfaceHolder;
import android.view.SurfaceView;
 
public class Surface extends SurfaceView implements SurfaceHolder.Callback
{
    public SurfaceHolder mHolder;
    private Bee bee;
 
    public Surface(Bee context) {
        super(context);
 
        bee = context;
 
        mHolder = this.getHolder();
        mHolder.addCallback(this);
    }
 
    public void surfaceCreated(SurfaceHolder arg0) {
        // 如果影片不是播放的狀態才執行遊戲執行緒
        if (!GV.videoPlayer.isRuningVideo)
        {
            // 以新的執行緒執行
            bee.game.Run();
 
            switch(GameStateClass.currentState)
            {
                case Menu:
 
                    break;
                case Stage1:
                    // 播放音樂
                    GV.music.Play();
 
                    break;
            }
        }
    }
 
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { }
 
    public void surfaceDestroyed(SurfaceHolder arg0) { }
}

程式:VideoPlayer.java

package Bee.main;
 
import Bee.main.R;
import Bee.main.GameStateClass.GameState;
import android.content.Context;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.view.MotionEvent;
import android.widget.VideoView;
 
public class VideoPlayer
{
    private myVideo video;
    private int videoPosition = 0;
    private Bee bee;
    public boolean isRuningVideo;
 
    public VideoPlayer(Bee bee) {
        this.bee = bee;
 
        video = new myVideo(bee);
 
        Load(R.raw.f16);
 
        video.setOnCompletionListener(new OnCompletionListener() {
 
            public void onCompletion(MediaPlayer arg0) {
                Destroy();
            }
        });
    }
 
    public void Load(int movie)
    {
        Uri uri = Uri.parse("android.resource://" + bee.getPackageName() + "/" + movie);
        video.setVideoURI(uri);
    }
 
    public void Play()
    {
        isRuningVideo = true;
 
        bee.setContentView(video);
        video.requestFocus();
 
        video.start();
    }
 
    public void Resume() {
        video.seekTo(videoPosition);
        video.start();
    }
 
    public void Pause() {
        video.pause();
        videoPosition = video.getCurrentPosition();
    }
 
    public void Stop()
    {
        isRuningVideo = false;
        video.stopPlayback();
    }
 
    public void Destroy() {
        Stop();
 
        video.destroyDrawingCache();
        video.clearAnimation();
        video.clearFocus();
 
        // 切換關卡
        switch(GameStateClass.currentState)
        {
            case op:
 
                // 初始化畫布View
                GameStateClass.currentState = GameState.Menu;
                GV.surface = new Surface(bee);
 
                break;
            case Menu:
                GameStateClass.changeState(GameState.Stage1, bee.game.menu, bee.game);
 
                break;
            case Stage1:
 
                break;
        }
 
        bee.setContentView(GV.surface);
    }
 
    class myVideo extends VideoView
    {
        public myVideo(Context context) {
            super(context);
        }
 
        // 將影片設定為全螢幕
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            setMeasuredDimension(GV.scaleWidth, GV.scaleHeight);
        }
 
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
 
            return false;
        }
    }
}

程式:Music.java

package Bee.Object;
 
import Bee.main.R;
import android.content.Context;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
 
public class Music{
    public MediaPlayer player;
    public boolean isComplete;
 
    public Music(Context context,int music,int volume) {
        player = MediaPlayer.create(context, music);
 
        // 音量大小(0~10)
        player.setVolume(volume, volume);
 
        isComplete = false;
 
        player.setOnCompletionListener(new OnCompletionListener() 
        {            
            public void onCompletion(MediaPlayer arg0) 
            {
                isComplete = true;
            }
        });
    }
 
    public void Play()
    {
        if (!isComplete)
            if (!player.isPlaying())
                player.start();
    }
 
    public void Stop()
    {
        player.stop();
        isComplete = false;
    }
 
    public void Pause()
    {
        player.pause();
    }
}

程式:Object2D.java

package Bee.Object;
 
import Bee.main.R;
import android.content.Context;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
 
public class Music{
    public MediaPlayer player;
    public boolean isComplete;
 
    public Music(Context context,int music,int volume) {
        player = MediaPlayer.create(context, music);
 
        // 音量大小(0~10)
        player.setVolume(volume, volume);
 
        isComplete = false;
 
        player.setOnCompletionListener(new OnCompletionListener() 
        {            
            public void onCompletion(MediaPlayer arg0) 
            {
                isComplete = true;
            }
        });
    }
 
    public void Play()
    {
        if (!isComplete)
            if (!player.isPlaying())
                player.start();
    }
 
    public void Stop()
    {
        player.stop();
        isComplete = false;
    }
 
    public void Pause()
    {
        player.pause();
    }
}

程式:Plane.java

package Bee.Object;
 
import java.util.ArrayList;
import android.graphics.Color;
import android.graphics.Rect;
import Bee.Role.Boom;
import Bee.Role.Bullet1;
import Bee.Role.ShootEffect;
import Bee.main.GV;
import Bee.main.GV.Sound;
 
public class Plane extends Object2D{
    public class Barrel extends Object2D
    {
        // 開始射擊時間
        public int startShootFrame = 0;
 
        // 再度發射延遲時間
        public int bulletDelayFrame;
 
        // 炮管的角度
        public int barrelTheta;
 
        // 子彈
        public ArrayList<Bullet1> bullet;
 
        public Barrel(int length,int barrelTheta,int theta, int speed, int bulletDelayFrame) {
            super(length, theta, speed);
 
            bullet = new ArrayList<Bullet1>();
 
            // 炮管在機身中位置的角度
            this.barrelTheta = barrelTheta;
 
            // 再度發射延遲時間
            this.bulletDelayFrame = bulletDelayFrame;
        }
 
        public void addBarrelTheta(int speed)
        {
            barrelTheta = (barrelTheta + speed) % 360;
            if (barrelTheta < 0)
                barrelTheta += 360;
        }
    }
 
    // 多個炮管
    public ArrayList<Barrel> barrel = new ArrayList<Barrel>();
 
    // 影格欄數
    private static final int col = 4; 
 
    // 動畫最大索引
    private int maxIndex = 18;
 
    // 迴圈變數
    private int f,j,k;
 
    // 子彈暫存用
    private Bullet1 bullet;
 
    // 增加或減少畫格
    protected int offset;
 
    // 生命
    public int life;
 
    // 血量
    public int blood;
 
    // 子彈位置
    private int x;
    private int y;
 
    // 透明回復開始時間
    private int startRestoreAlphaFrame;
 
    // 透明回復延遲時間
    private static int resotreAlphaDelayFrame = 5;
 
    public Plane(int destX,int destY,int destWidth,int destHeight,int srcX,int srcY,int srcWidth,int srcHeight,int speed,int color,int theta) {
        super(destX, destY, destWidth, destHeight, srcX, srcY, srcWidth, srcHeight, speed, color,theta);
 
    }
 
    // 檢查飛機碰撞
    public static void CheckPlaneCollision(int frameTime,ArrayList<Plane> planeA,ArrayList<Plane> planeB,ArrayList<Boom> boom)
    {
        for (int f = planeA.size() - 1; f >= 0; f--)
        {
            if (planeA.get(f).isAlive)
            {
                for (int j = planeB.size() - 1; j >= 0; j--)
                {
                    if (planeB.get(j).isAlive)
                    {
                        if (GV.isCollision(planeA.get(f).destRect, planeB.get(j).destRect))
                        {
                            planeA.get(f).Collisioned(frameTime,boom);
                            planeB.get(j).Collisioned(frameTime,boom);
 
                            break;
                        }
                    }
                }
            }
        }
    }
 
    // 檢查子彈與飛機是否碰撞
    public void CheckBulletCollision(int frameTime,ArrayList<Plane> plane,ArrayList<Boom> boom)
    {
        // 炮管
        for (f = barrel.size() - 1; f >= 0; f--)
        {
            // 子彈
            for (j = barrel.get(f).bullet.size() - 1; j >= 0; j--)
            {
                // 被碰撞的飛機
                for (k = plane.size() - 1; k >= 0; k--)
                {
                    if (plane.get(k).isAlive)
                    {
                        // 暫存子彈
                        bullet = barrel.get(f).bullet.get(j);
 
                        // 檢查是否碰撞
                        if (GV.isCollision(bullet.destRect, plane.get(k).destRect))
                        {
                            // 子彈消失
                            barrel.get(f).bullet.remove(j);
 
                            // 發生碰撞
                            plane.get(k).Collisioned(frameTime,boom);
 
                            break;
                        }
                    }
                }
            }
        }
    }
 
    // 碰撞發生
    public void Collisioned(int frameTime,ArrayList<Boom> boom)
    {
        blood--;
 
        if (blood > 0)
        {
            paint.setAlpha(128);
            startRestoreAlphaFrame = frameTime;
        }
        else
        {
            // 新增爆炸
            boom.add(new Boom(getX() + halfWidth - Boom.halfSize,
                                 getY() + halfHeight - Boom.halfSize,
                              Boom.size, Boom.size));
 
            // 爆炸音效
            GV.playSound(Sound.boom);
 
            // 飛機消失
            isAlive = false;
 
            life--;
            if (life > 0)
                Rebirth();
        }
    }
 
    // 重生
    protected void Rebirth()
    {
 
    }
 
    // 敵機行動
    public void Action(int frameTime, Plane plane, ArrayList<ShootEffect> shootEffect)
    {
        ActionCommon(frameTime);
    }
 
    // 自機行動
    public void Action(int frameTime,ArrayList<ShootEffect> shootEffect)
    {
        ActionCommon(frameTime);
    }
 
    // 行動共用
    private void ActionCommon(int frameTime)
    {
        if (frameTime - startRestoreAlphaFrame > resotreAlphaDelayFrame)
        {
            paint.setAlpha(255);
        }
    }
 
    // 子彈移動
    public void AllBulletMove()
    {
        // 走訪炮管
        for (f = barrel.size() - 1;  f >= 0; f--)
        {
            // 走訪子彈
            for (j = barrel.get(f).bullet.size() - 1 ; j>=0 ;j--)
            {
                if (barrel.get(f).bullet.get(j).bulletMove())
                    barrel.get(f).bullet.remove(j);
            }
        }
    }
 
    // 子彈射擊
    public void Shoot(int frameTime,ArrayList<ShootEffect> shootEffect) 
    {        
 
        // 走訪炮管
        for (f = barrel.size() - 1; f >= 0; f--)
        {
            if (frameTime - barrel.get(f).startShootFrame > barrel.get(f).bulletDelayFrame)
            {
                // 儲存開始發射時間
                barrel.get(f).startShootFrame = frameTime;
 
                x = getX() + halfWidth  + (int)(barrel.get(f).destHeight * GV.Cosine[barrel.get(f).barrelTheta]);
                y = getY() + halfHeight + (int)(barrel.get(f).destHeight * GV.Sine[barrel.get(f).barrelTheta]);
 
                // 新增子彈
                barrel.get(f).bullet.add(new Bullet1(x - Bullet1.halfSize, y - Bullet1.halfSize, barrel.get(f).speed, Color.WHITE, barrel.get(f).theta));
 
                // 新增特效
                shootEffect.add(new ShootEffect(x - ShootEffect.halfWidth, y - ShootEffect.halfHeight));
            }
        }
    }
 
    // 民航機向下移動
    protected boolean moveDown(int destY)
    {
 
        // 遞增
        addY(speed);
 
        // 是否到達目的地
        if (getY() + halfHeight > destY)
        {
            setY(destY - halfHeight);
            return true;
        }
        else
            return false;
    }
 
    // 民航機向上移動
    protected boolean moveUp(int destY)
    {
        // 遞減
        addY(-speed);
 
        // 是否到達目的地
        if (getY() + halfHeight < destY)
        {
            setY(destY - halfHeight);
            return true;
        }
        else
            return false;
    }
 
    // 向左移動
    protected boolean moveLeft(int destX)
    {
        addX(-speed);
 
        if (getX() + halfWidth < destX)
        {
            setX(destX - halfWidth);
 
            return true;
        }
        else
            return false;
    }
 
    // 向右移動
    protected boolean moveRight(int destX)
    {
        addX(speed);
 
        if (getX() + halfWidth > destX)
        {
            setX(destX - halfWidth);
 
            return true;
        }
        else
            return false;
    }
 
    // 自轉
    protected boolean rotationPlane(int destTheta)
    {
        int value = destTheta - theta;
        int speed = 0;
 
        if (value != 0)
        {
            if (value > 0)
            {
                if (Math.abs(value)>=180)
                {
                     // 逆轉
                    speed = -1;
                }
                else
                {
                    // 順轉
                    speed = 1;
                }
            }
            else if (value < 0)
            {
                if (Math.abs(value)>=180)
                {
                    // 順轉
                    speed = 1;
                }
                else
                {
                    // 逆轉
                    speed = -1;                    
                }
            }
 
            addTheta(speed);
 
            // 炮管與機身同步旋轉
            for (f = barrel.size() - 1; f >= 0; f--)
            {
                barrel.get(f).addTheta(speed);
                barrel.get(f).barrelTheta = barrel.get(f).theta;
            }
        }
 
        if (theta == destTheta)
            return true;
        else            
            return false;
    }
 
    // 播放動畫
    protected void planeAnimation()
    {
 
        // 設定影格
        setAnimationIndex(col);
 
        // 慢慢回復成正面,offset對畫格做增減
        if (offset == 0)
        {
            if (index > 10)
                index--;
            else if (index < 10)
                index++;
        }
        else
            index += offset;
 
        // 歸零
        offset = 0;
 
        // 防止動畫索引超出範圍
        if (index < 0)
            index = 0;
        else if (index > maxIndex)
            index = maxIndex;
    }
}

程式:Text.java

package Bee.Object;
 
import android.graphics.Paint;
import android.graphics.Typeface;
 
public class Text {
    public int x;
    public int y;
    public int size;
    public String message;
    public Paint paint;
    public boolean isVisible;
    public int startFrame;
    public int delayFrame;
 
    public Text(int x, int y, int size, String message, int color) {
        this.x = x;
        this.y = y;
        this.size = size;
        this.message = message;
 
        paint = new Paint();
        paint.setColor(color);
        paint.setTextSize(size);
        paint.setTypeface(Typeface.MONOSPACE);
    }
}

程式:Aircraft.java

package Bee.Role;
 
import java.util.ArrayList;
 
import android.util.StateSet;
import Bee.Object.Object2D;
import Bee.Object.Plane;
import Bee.main.GV;
 
public class Aircraft extends Plane{
 
    // 狀態種類
    private State kind = State.step1;
 
    // 長
    public static int width = 0;
 
    // 寬
    public static int height = 0;
 
    public static int halfWidth = 0;
    public static int halfHeight = 0;
 
    // 瞄準目標時間
    private int startTargetFrame = 0;
 
    // 切換到射擊狀態的時間
    private static final int switchShootDelayFrame = 60;
 
    // 開始結束狀態時間
    private int startEndFrame = 0;
 
    // 切換到結束狀態的時間
    private static final int switchEndDelayFrame = 300; 
 
    // 用來判斷左右
    private int tempX;
 
    // 向下移動到目的位置
    private int movDestY;
 
    // 暫存角度
    private int tempTheta;
 
    public Aircraft(int destX,int destY,int destWidth,int destHeight,int srcX,int srcY,int srcWidth,int srcHeight,int speed,int color,int theta,State kind) {
        super( destX, destY, destWidth, destHeight, srcX, srcY, srcWidth, srcHeight,speed, color,theta);
 
        // Action的狀態圈
        this.kind = kind;
 
        switch(kind)
        {
            case step1:
 
                // 新增炮管
                barrel.add(new Barrel(halfHeight, theta, theta, 5, 60));
 
                blood = 4;
 
                break;
            case step2:
                blood = 4;
 
                break;
            case step3:
            case step4:
                tempTheta = theta;
                setTheta(90);
 
                blood = 3;
 
                break;
        }
 
        // 設為已存活
        isAlive = true;
 
        // 動畫正面
        index = 10;
 
        // 向下移動到目的位置
        movDestY = destY + GV.scaleHeight;
    }
 
    @Override
    public void Action(int frameTime, Plane myPlane,ArrayList<ShootEffect> shootEffect) 
    {
        tempX = getX();
 
        switch(kind)
        {
            case step1:
                switch(state)
                {
                    case step1:
 
                        // 向下移動
                        if (moveDown(movDestY))
                        {
                            state = State.step2;
 
                            startTargetFrame = frameTime;
                            startEndFrame = frameTime;
                        }
 
                        break;
                    case step2:
 
                        // 瞄準目標
                        rotationPlane(getTargetTheta(myPlane.destRect,this.destRect));
 
                        // 切換下一個狀態
                        if (frameTime - startTargetFrame > switchShootDelayFrame)
                        {
                            state = State.step3;
                        }
 
                        break;
                    case step3:
 
                        // 射擊
                        Shoot(frameTime,shootEffect);
 
                        // 切換成瞄準狀態
                        startTargetFrame = frameTime;
                        state = State.step2;
 
                        // 切換成結束狀態
                        if (frameTime - startEndFrame > switchEndDelayFrame)
                        {
                            state = State.step4;
                        }
 
                        break;
                    case step4:
                        if (moveUp(-destHeight))
                            isAlive = false;
 
                        break;
                }
                break;
            case step2:
                switch(state)
                {
                    case step1:
 
                        // 移動到螢幕四分之一的高度
                        if (moveDown(GV.halfHeight >> 1))
                        {
                            state = State.step2;
                        }
 
                        break;
                    case step2:
 
                        // 向F16衝撞
                        setTheta(getTargetTheta(myPlane.destRect,this.destRect));
                        move();
 
                        if (frameTime - startEndFrame > switchEndDelayFrame)
                        {
                            state = State.step3;
                        }
 
                        break;
                    case step3:
                        move();
                        if (!GV.isInScreen(destRect))
                        {
                            isAlive = false;
                        }
 
                        break;
                }
 
                break;
            case step3:
                switch(state)
                {
                    case step1:
                        if (moveDown(movDestY))
                        {
                            theta = tempTheta;
                            state = State.step2;
                        }
 
                        break;
 
                    case step2:
                        move();
                        if (!GV.isInScreen(destRect))
                        {
                            isAlive = false;
                        }
 
                        break;
                }
                break;
            case step4:
                switch(state)
                {
                    case step1:
                        if (moveDown(destHeight << 2))
                        {
                            theta = tempTheta;
                            state = State.step2;
                        }
 
                        break;
                    case step2:                    
                        move();
                        if (!GV.isInScreen(destRect))
                        {
                            isAlive = false;
                        }
 
                        break;
                }
 
                break;
        }
 
        tempX = getX() - tempX;
 
        if (tempX > 0)
            offset = 1;
        else if (tempX < 0)
            offset = -1;
 
        // 自機動畫
        planeAnimation();
 
        super.Action(frameTime, myPlane,shootEffect);
    }
}

程式:Boom.java

package Bee.Role;
 
import android.graphics.Color;
import Bee.Object.Object2D;
 
public class Boom extends Object2D{
    public static int size = 0;
    public static int halfSize = 0;
    public static int col = 5;
    public static int maxIndex = 24;
 
    public Boom(int destX,int destY,int destWidth,int destHeight) {
        super(destX, destY, destWidth, destHeight, 0, 0, size, size, 0, Color.WHITE,0);
 
        isAlive = true;
    }
 
    public void Animation()
    {
        setAnimationIndex(col);
 
        if (index < maxIndex)
            index++;
        else
            isAlive = false;
 
    }
}

程式:Bullet1.java

package Bee.Role;
 
import java.util.ArrayList;
 
import Bee.Object.Object2D;
import Bee.main.GV;
 
// 子彈
public class Bullet1 extends Object2D{
 
    // 子彈的大小
    public static int size = 15;
    public static int halfSize = size >> 1;
 
    public Bullet1(int destX,int destY,int speed,int color, int theta) {
        super( destX, destY, size, size, 0, 0, size, size,speed, color,theta);
 
        isAlive = true;
    }
 
    // 子彈移動
    public boolean bulletMove()
    {
        move();
 
        // 是否超出螢幕
        if (!GV.isInScreen(destRect))
            return true;
        else
            return false;
    }
}

程式:F16.java

package Bee.Role;
 
import java.util.ArrayList;
 
import Bee.Object.Plane;
import Bee.main.GV;
 
public class F16 extends Plane {
 
    // 大絕招
    public static int bigBoom = 3;
 
    // 使用大絕招
    public static boolean isTouchBoom;
 
    // 開始使用大絕招的時間
    public static int startBigBoomFrame = 0;
 
    // 再度使用大絕招的延遲時間
    public static int bigBoomDelayFrame = 30; // 一秒後
 
    // 大絕招的破壞力
    public static int bigBoomPower = 10;
 
    public F16(int destX, int destY, int destWidth, int destHeight, int srcX, int srcY, int srcWidth, int srcHeight,int speed, int color,int theta) {
        super(destX, destY, destWidth, destHeight, srcX, srcY, srcWidth, srcHeight, speed, color,theta);
 
        // 新增炮管(距離飛機中心的距離,距離飛機中心的絕對距離)
        barrel.add(new Barrel(halfHeight, theta, theta, 10, 10));
        barrel.add(new Barrel(halfHeight, theta - 20, theta - 15, 10, 12));
        barrel.add(new Barrel(halfHeight, theta + 20, theta + 15, 10, 12));
        barrel.add(new Barrel(halfHeight, theta - 45, theta - 30, 10, 12));
        barrel.add(new Barrel(halfHeight, theta + 45, theta + 30, 10, 12));
 
        // 設定大絕招的數量
        bigBoom = 3;
 
        // 大絕開始使用時間歸零
        startBigBoomFrame = 0;
 
        // 生命
        life = 5;
 
        lifeInitialize();
    }
 
    private void lifeInitialize()
    {
 
        // 可使用大絕的次數
        bigBoom = 3;
 
        // 動畫正面
        index = 10;
 
        // 設為已存活
        isAlive = true;
 
        // 血量
        blood = 10;
    }
 
    // 自機行動
    @Override
    public void Action(int frameTime, ArrayList<ShootEffect> shootEffect) 
    {
 
        if (GV.x - (getX() + halfWidth) > 5)
        {
            offset = 1;
            addX(speed);
        }
        else if (GV.x - (getX() + halfWidth) < -5)
        {
            offset = -1;
            addX(-speed);
        }
 
        if (GV.y - (getY() + halfHeight) > 5)
            addY(speed);
        else if (GV.y - (getY() + halfHeight) < -5)
            addY(-speed);
 
        // 防止超出邊界
        if (getX() < 0)
        {
            offset = 0;
            GV.x = halfWidth;
            setX(0);
        }
        else if (getX() + destWidth > GV.scaleWidth)
        {
            offset = 0;
            GV.x = GV.scaleWidth - halfWidth;
            setX(GV.scaleWidth - destWidth);
        }
 
        if (getY() < 0)
        {
            GV.y = halfHeight;
            setY(0);
        }
        else if (getY() + destHeight > GV.scaleHeight)
        {
            if (GV.y > GV.scaleHeight - halfHeight)
                GV.y = GV.scaleHeight - halfHeight;
 
            setY(GV.scaleHeight - destHeight);
        }
 
        // 自動發射子彈
        Shoot(frameTime,shootEffect);
 
        // 自機動畫
        planeAnimation();
 
        super.Action(frameTime,shootEffect);
    }
 
    // 被撞擊後
    @Override
    public void Collisioned(int frameTime,ArrayList<Boom> boom) {
 
        // 震動0.1秒
        GV.vibrator.vibrate(100);
 
        super.Collisioned(frameTime, boom);
    }
 
    // 重生
    @Override
    protected void Rebirth() {
 
        GV.x = GV.halfWidth;
        GV.y = GV.halfHeight + destHeight;
        setX(GV.halfWidth - halfWidth);
        setY(GV.scaleHeight << 1);
 
        lifeInitialize();
    }    
}

程式:RedMask.java

package Bee.Role;
 
import android.graphics.Color;
import Bee.Object.Object2D;
import Bee.Object.Text;
import Bee.main.GV;
import Bee.main.GV.Sound;
 
public class RedMask extends Object2D{
 
    private int startFrame;
    private int delayFrame = 300;
    public Text warningText;
 
    public RedMask(int color,int alpha) {
        super(0, 0, GV.scaleWidth, GV.scaleHeight, color, alpha);
 
        warningText = new Text(50, GV.halfHeight, 36, "Warning", Color.BLACK);
    }
 
    public void Action(int frameTime)
    {
        switch(state)
        {
            case step1:
                startFrame = frameTime;
                state = State.step2;
 
                break;
            case step2:
                if (FadeIn())
                    state = State.step3;
 
                break;
            case step3:
                if (FadeOut())
                    state = State.step2;
 
                if (frameTime - startFrame > delayFrame)
                {
                    isAlive = false;
                }
 
                break;
        }
    }
 
    public boolean FadeIn()
    {
        alpha+=5;
        if (alpha > 192)
        {
            alpha = 192;
            GV.playSound(Sound.alert);
            return true;
        }
 
        paint.setAlpha(alpha);
        return false;
    }
 
    public boolean FadeOut()
    {
        alpha-=5;
        if (alpha < 0)
        {
            alpha = 0;
            return true;
        }
 
        paint.setAlpha(alpha);
        return false;
    }
}

程式:ShootEffect.java

package Bee.Role;
 
import android.graphics.Color;
import Bee.Object.Object2D;
import Bee.Object.Object2D.State;
 
public class ShootEffect extends Object2D{
 
    public static int width;
    public static int height;
    public static int halfWidth;
    public static int halfHeight;
 
    public ShootEffect(int destX,int destY) {
        super( destX, destY, width, height, 0, 0, width, height,0, Color.WHITE,0);
 
        alpha = 255;
    }
 
    public boolean Animation()
    {
        destRect.left++;
        destRect.top++;
        destRect.right--;
        destRect.bottom--;
 
        alpha-=5;
        paint.setAlpha(alpha);
 
        if (destWidth <= 0 || destHeight <= 0 || alpha <= 0)
            return true;
        else
            return false;
 
    }
}

程式:Spider.java

package Bee.Role;
 
import java.util.ArrayList;
 
import Bee.Object.Object2D;
import Bee.Object.Plane;
import Bee.main.GV;
import Bee.main.GV.Sound;
import android.graphics.Color;
 
public class Spider extends Plane{
 
    public static int width;
    public static int height;
 
    // 切換成炮管左右來回旋轉的延遲時間
    private int startSwitchStep4Frame;
    private int switchStep4DelayFrame = 300;
 
    // 切換到stpe6的延遲時間 
    private int startSwitchStep6Frame;
    private int switchStep6DelayFrame = 300;
 
    // 切換到stpe8的延遲時間 
    private int startSwitchStep8Frame;
    private int switchStep8DelayFrame = 300;
 
    // 血條物件
    public Object2D bloodObj;
 
    // 最大血量
    private static final int maxBlood = 500;
 
    // 迴圈變數
    private int f;
 
    public Spider(int destX,int destY,int destWidth,int destHeight,int srcX,int srcY,int srcWidth,int srcHeight, int speed,int color, int theta) {
        super( destX, destY, destWidth, destHeight, srcX, srcY, srcWidth, srcHeight, speed, color, theta);
 
        barrel.add(new Barrel(halfHeight,theta, theta, 5, 5));
        barrel.add(new Barrel(halfHeight,theta, theta - 45, 5, 5));
        barrel.add(new Barrel(halfHeight,theta, theta + 45, 5, 5));
 
        // 初始化血條
        bloodObj = new Object2D(20, 20, GV.scaleWidth - 40, 10, Color.RED, 128);
 
        // 設為存活
        isAlive = true;
 
        // 血量
        blood = maxBlood;
    }
 
    @Override
    public void Action(int frameTime, Plane plane,ArrayList<ShootEffect> shootEffect) {
 
        switch(state)
        {
            case step1:
 
                // 移進螢幕
                if (moveDown(20))
                {
                    state = State.step2;
 
                    // 切換到 step 4 計時
                    startSwitchStep4Frame = frameTime;
                }
 
                break;
            case step2:
 
                // 向右移動並發射子彈
                if (moveRight(GV.scaleWidth - halfWidth))
                {
                    state = State.step3;
                }
 
                Shoot(frameTime, shootEffect);
 
                // 時間到則切換step4
                if (frameTime - startSwitchStep4Frame > switchStep4DelayFrame)
                {
                    state = State.step4;
 
                    // 增加子彈再度發射的延遲時間
                    for (f = barrel.size() -1 ;f>=0;f--)
                    {
                        barrel.get(f).bulletDelayFrame = 15;
                    }
 
                    // 切換到step6計時
                    startSwitchStep6Frame = frameTime;
                }
 
                break;
            case step3:
 
                // 向左移動並發射子彈
                if (moveLeft(halfWidth))
                {
                    state = State.step2;
                }
 
                Shoot(frameTime, shootEffect);
 
                break;
            case step4:
 
                Shoot(frameTime, shootEffect);
 
                // 順轉炮管
                for (f = barrel.size() - 1; f >= 0; f--)
                {
                    rotationBarrel(barrel.get(f), 1);
 
                    // 旋轉次數
                    if (barrel.get(f).theta > 180)
                    {
                        state = State.step5;
                        break;
                    }
                }
 
                break;
            case step5:
 
                Shoot(frameTime, shootEffect);
 
                // 逆轉炮管
                for (f = barrel.size() - 1; f >= 0; f--)
                {
                    rotationBarrel(barrel.get(f), -1);
 
                    // 旋轉角度
                    if (barrel.get(f).theta > 350)
                    {
                        state = State.step4;
                        break;
                    }
                }
 
                // 時間到就切換到state6
                if (frameTime - startSwitchStep6Frame > switchStep6DelayFrame)
                {
                    state = State.step6;
                }
 
                break;
            case step6:
 
                // 蜘蛛旋轉
                rotationBarrel(this, 1);
                if (theta > 270)
                {
                    state = State.step7;
 
                    // 移除所有炮管
                    barrel.removeAll(barrel);
 
                    // 新增炮管
                    for (f = 0; f < 360; f += 15)
                    {
                        barrel.add(new Barrel(halfHeight >> 2,f, f, 10, 5));
                    }
 
                    startSwitchStep8Frame = frameTime;
                }
 
                break;
            case step7:
 
                Shoot(frameTime, shootEffect);
 
                // 時間到就切到狀態8
                if (frameTime - startSwitchStep8Frame > switchStep8DelayFrame)
                {    
                    state = State.step8;
                }
 
                break;
            case step8:
 
                // 旋轉蜘蛛
                rotationBarrel(this, 1);
                if (theta == 90)
                {    
                    // 移除所有炮管
                    barrel.removeAll(barrel);
 
                    // 還原初始炮管
                    barrel.add(new Barrel(halfHeight,theta, theta, 5, 5));
                    barrel.add(new Barrel(halfHeight,theta, theta - 45, 5, 5));
                    barrel.add(new Barrel(halfHeight,theta, theta + 45, 5, 5));
 
                    state = State.step1;
                }
 
                break;
        }
 
        super.Action(frameTime, plane, shootEffect);
    }
 
    @Override
    public void Collisioned(int frameTime, ArrayList<Boom> boom) {
        bloodObj.destRect.right = (int)((float)blood / maxBlood * (GV.scaleWidth - 20)); 
 
        // 新增爆炸
        if (blood < 2)
        {
            boom.add(new Boom(getX() + halfWidth - GV.halfWidth,
                                 getY() + halfHeight - GV.halfHeight,
                              GV.halfWidth, GV.halfHeight));
        }
 
        super.Collisioned(frameTime, boom);
    }
 
    // 旋轉炮管
    private void rotationBarrel(Object2D obj, int speed)
    {
        obj.addTheta(speed);
    }
}

程式:Game1.java

package Bee.scene;
 
import Bee.Object.Music;
import Bee.Role.F16;
import Bee.main.Bee;
import Bee.main.GV;
import Bee.main.GameStateClass;
import Bee.main.R;
import XNA.lbs.Game;
import android.graphics.Color;
import android.media.AudioManager;
import android.media.SoundPool;
 
public class Game1 extends Game {
    public Menu menu;
    public Stage1 stage1;
    public Bee bee;
 
    public Game1(Bee bee) {
        this.bee = bee;
    }
 
    @Override
    protected void Initialize() {
 
        // 設定靜態變數的初值
        F16.bigBoom = 1;
        F16.startBigBoomFrame = 0;
 
        super.Initialize();
    }
 
    @Override
    protected void LoadContent() {
 
        // 遊戲音效
        GV.snd = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
 
        // 爆炸
        GV.soundIDBoom = GV.snd.load(bee, R.raw.explosion, 0);
 
        // 警告
        GV.soundIDAlert = GV.snd.load(bee, R.raw.sysalert, 0);
 
        super.LoadContent();
    }
 
    @Override
    protected void UnloadContent() {
 
        super.UnloadContent();
    }
 
    @Override
    protected void Update() {
 
        if (GameStateClass.currentState != GameStateClass.oldState) {
            switch (GameStateClass.currentState) {
            case None:
                bee.UnloadContent();
 
                break;
            case Menu:
                menu = new Menu(this);
                Components.add(menu);
 
                break;
            case Stage1:
 
                // 新增第一關
                stage1 = new Stage1(this);
                Components.add(stage1);
 
                // 播放背景音樂
                if (!GV.music.player.isPlaying()) {
                    GV.music.player.release();
                    GV.music = new Music(bee, R.raw.stage1,2);
                    GV.music.Play();
                }
 
                break;
            }
 
            GameStateClass.oldState = GameStateClass.currentState;
        }
 
        super.Update();
    }
 
    @Override
    protected void Draw() {
 
        canvas = GV.surface.mHolder.lockCanvas(null);
 
        // 清空
        canvas.drawColor(Color.BLACK);
 
        super.Draw();
    }
}

程式:Menu.java

package Bee.scene;
 
import Bee.Object.Object2D;
import Bee.Object.Text;
import Bee.main.GV;
import XNA.lbs.DrawableGameComponent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
 
public class Menu extends DrawableGameComponent{
    private Game1 game;
    private Canvas subCanvas;
 
    // 畫格時間
    private int frameTime;
 
    // 背景
    private Bitmap menuBitmap;
    private Object2D menuObj;
 
    // "Touch"文字
    private Text menuText;
    private Text menuShadow;
 
    // 標題文字
    private Text menuTitleText;
    private Text menuTitleShadow;
 
    public Menu(Game1 game) {
        this.game = game;
    }
 
    @Override
    protected void Initialize() {
 
        // 標題文字
        menuTitleText = new Text(65, 50, 36, "小飛機", Color.YELLOW);
 
        menuTitleShadow = new Text(menuTitleText.x + 10, menuTitleText.y - 5, menuTitleText.size, menuTitleText.message, Color.BLACK);
 
        // "Touch"文字
        menuText = new Text(50, GV.scaleHeight - 70, 12, "Touch screen to start", Color.YELLOW);
        menuText.delayFrame = 20;
 
        menuShadow = new Text(menuText.x + 10, menuText.y - 5, menuText.size, menuText.message, Color.BLACK);
 
        // 載入背景
        menuBitmap = BitmapFactory.decodeResource(GV.res, Bee.main.R.drawable.menu);
 
        // 初始化背景物件
        menuObj = new Object2D(0, 0, GV.scaleWidth, GV.scaleHeight, 0, 0, menuBitmap.getWidth(), menuBitmap.getHeight(), 0, Color.WHITE, 0);
        menuObj.paint.setAlpha(170);
 
        super.Initialize();
    }
 
    @Override
    protected void UnloadContent() {
 
        super.UnloadContent();
    }
 
    @Override
    protected void Update() {
 
        // 取得目前的畫格時間
        frameTime = (int)game.totalFrames;
 
        // 閃礫"Touch"文字
        if (frameTime - menuText.startFrame > menuText.delayFrame)
        {
            menuText.startFrame = frameTime;
 
            menuText.isVisible = !menuText.isVisible;
        }
 
        super.Update();
    }
 
    @Override
    protected void Draw() {
 
        subCanvas = game.canvas;
 
        // 畫出背景
        subCanvas.drawBitmap(menuBitmap, menuObj.srcRect, menuObj.destRect, menuObj.paint);
 
        // 畫出標題陰影
        subCanvas.drawText(menuTitleShadow.message, menuTitleShadow.x, menuTitleShadow.y, menuTitleShadow.paint);
 
        // 畫出標題
        subCanvas.drawText(menuTitleText.message, menuTitleText.x, menuTitleText.y, menuTitleText.paint);
 
        // 閃礫
        if (menuText.isVisible)
        {
            // 畫出"Touch"陰影
            subCanvas.drawText(menuShadow.message, menuShadow.x, menuShadow.y, menuShadow.paint);
 
            // 畫出"Touch"文字
            subCanvas.drawText(menuText.message, menuText.x, menuText.y, menuText.paint);
        }
 
        super.Draw();
    }
}

程式:Stage1.java

package Bee.scene;
 
import java.util.ArrayList;
import Bee.Object.Music;
import Bee.Object.Object2D;
import Bee.Object.Plane;
import Bee.Object.Text;
import Bee.Object.Object2D.State;
import Bee.Role.Aircraft;
import Bee.Role.Boom;
import Bee.Role.Bullet1;
import Bee.Role.F16;
import Bee.Role.RedMask;
import Bee.Role.ShootEffect;
import Bee.Role.Spider;
import Bee.main.GV;
import Bee.main.GameStateClass;
import Bee.main.R;
import Bee.main.GameStateClass.GameState;
import XNA.lbs.DrawableGameComponent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
 
public class Stage1 extends DrawableGameComponent {
 
    private Game1 game;
 
    private Canvas subCanvas;
 
    // 顯示FPS文字
    private Text fpsText;
 
    // 自機圖片
    private Bitmap f16Bitmap;
 
    // 自機物件
    private ArrayList<Plane> myPlane;
 
    // 民航機圖片
    private Bitmap aircraftBitmap;
 
    // 民航機物件
    private ArrayList<Plane> aircraft;
 
    // 子彈圖片
    private Bitmap bulletBitmap1;
 
    // 一般背景圖片
    private Bitmap backGroundImage;
 
    // 一般背景物件
    private Object2D backGroundObj;
 
    // 爆炸圖片
    private Bitmap boomBitmap;
 
    // 爆炸
    private ArrayList<Boom> boom = new ArrayList<Boom>();
 
    // 子彈暫存用物件
    private Bullet1 bullet;
 
    // 爆炸暫存
    private Boom subBoom;
 
    // 飛機暫存
    private Plane plane;
 
    // 迴圈變數
    private int f, j, k;
 
    // 發射特效圖片
    private Bitmap shootEffectBitmap;
 
    // 發射特效物件
    public ArrayList<ShootEffect> shootEffect = new ArrayList<ShootEffect>();
 
    // 是否啟用黑色遮罩
    private boolean isBlackMask;
    private Object2D blackMask;
 
    // 是否啟用紅色遮罩
    private RedMask redMask;
 
    // 黑色遮罩開始啟用時間
    private int startBlackMaskFrame;
 
    // 從黑色遮罩到重新遊戲的時間
    private int restartDelayFrame = 150;
 
    // 顯示GameOver文字
    private Text gameOverText;
 
    // 蜘蛛
    private Bitmap spiderBitmap;
    private ArrayList<Plane> spiderObj;
 
    // 畫格總數
    private int frameTime;
 
    // 蜘蛛背景
    private Bitmap spiderBackGroundBitmap;
 
    // 蜘蛛背景物件
    private Object2D spiderBackGroundObj;
 
    // 破關
    private boolean breakOff;
 
    public Stage1(Game1 game) {
        this.game = game;
    }
 
    @Override
    protected void Initialize() {
 
        // 預先算好三角函數
        for (int f = 0; f < 360; f++) {
            GV.Cosine[f] = (float) Math.cos(f * Math.PI / 180);
            GV.Sine[f] = (float) Math.sin(f * Math.PI / 180);
        }
 
        GV.screenRect = new Rect(0, 0, GV.scaleWidth, GV.scaleHeight);
 
        // 歸零
        game.totalFrames = 0;
 
        super.Initialize();
    }
 
    @Override
    protected void LoadContent() {
 
        // 取得單一影格的寬高
        int width, height;
 
        // 民航機
        aircraftBitmap = (Bitmap) BitmapFactory.decodeResource(GV.res,
                R.drawable.aircraft);
 
        width = aircraftBitmap.getWidth() / 4;
        height = aircraftBitmap.getHeight() / 5;
 
        aircraft = new ArrayList<Plane>();
        Aircraft.width = width;
        Aircraft.height = height;
        Aircraft.halfWidth = width >> 1;
        Aircraft.halfHeight = height >> 1;
 
        // 自機
        f16Bitmap = (Bitmap) BitmapFactory.decodeResource(GV.res,
                R.drawable.f16);
 
        width = f16Bitmap.getWidth() / 4;
        height = f16Bitmap.getHeight() / 5;
 
        myPlane = new ArrayList<Plane>();
        myPlane.add(new F16(GV.halfWidth - (width >> 1), GV.scaleHeight, width,
                height, 0, 0, width, height, 5, Color.WHITE, 270));
 
        // 設定觸控位置在中下方
        GV.x = GV.halfWidth;
        GV.y = GV.scaleHeight - height;
 
        // 子彈
        bulletBitmap1 = BitmapFactory
                .decodeResource(GV.res, R.drawable.bullet1);
 
        // 背景
        backGroundImage = (Bitmap) BitmapFactory.decodeResource(GV.res,
                R.drawable.water);
 
        // 背景物件
        backGroundObj = new Object2D(0, 0, GV.scaleWidth / backGroundImage.getWidth(), GV.scaleHeight / backGroundImage.getHeight(), 0, 0, 0, 0, 0, 0, 0);
        backGroundObj.isAlive = true;
 
        // 文字
        fpsText = new Text(GV.halfWidth, 20, 12, "FPS", Color.YELLOW);
 
        // 爆炸
        boomBitmap = BitmapFactory.decodeResource(GV.res, R.drawable.boom2);
        Boom.size = boomBitmap.getWidth() / Boom.col;
        Boom.halfSize = Boom.size >> 1;
 
        // 發射的特效
        shootEffectBitmap = BitmapFactory.decodeResource(GV.res,
                R.drawable.effect);
 
        ShootEffect.width = shootEffectBitmap.getWidth();
        ShootEffect.height = shootEffectBitmap.getHeight();
        ShootEffect.halfWidth = ShootEffect.width >> 1;
        ShootEffect.halfHeight = ShootEffect.height >> 1;
 
        // 紅色Mask
        redMask = new RedMask(Color.RED, 0);
 
        // 黑色Mask
        blackMask = new Object2D(0, 0, GV.scaleWidth, GV.scaleHeight,
                Color.BLACK, 128);
 
        gameOverText = new Text(20, GV.halfHeight-18, 36, "Game Over", Color.WHITE);
 
        // 蜘蛛
        spiderBitmap = BitmapFactory.decodeResource(GV.res, R.drawable.spider);
 
        Spider.width = spiderBitmap.getWidth();
        Spider.height = spiderBitmap.getHeight();
 
        spiderObj = new ArrayList<Plane>();
 
        // 蜘蛛背景
        spiderBackGroundBitmap = BitmapFactory.decodeResource(GV.res, R.drawable.spider_scene);
 
        // 蜘蛛背景物件
        spiderBackGroundObj = new Object2D(0,-GV.scaleHeight,GV.scaleWidth,GV.scaleHeight,0, 0, spiderBackGroundBitmap.getWidth(), spiderBackGroundBitmap.getHeight(),0,Color.WHITE,0);
 
        super.LoadContent();
    }
 
    @Override
    protected void UnloadContent() {
 
        super.UnloadContent();
    }
 
    @Override
    protected void Update() {
 
        frameTime = (int)game.totalFrames;
 
        // 在遊戲中初始化飛機(對映到下方的Action)
        switch ((int) game.totalFrames) {
        case 150: // 5秒
            aircraft.add(new Aircraft(GV.halfWidth - Aircraft.halfWidth,
                    -Aircraft.height, Aircraft.width, Aircraft.height, 0, 0,
                    Aircraft.width, Aircraft.height, 5, Color.WHITE, 90,
                    State.step2));
            break;
        case 240: // 8秒
            aircraft.add(new Aircraft(20, -Aircraft.height, Aircraft.width,
                    Aircraft.height, 0, 0, Aircraft.width, Aircraft.height, 5,
                    Color.WHITE, 90, State.step2));
            break;
        case 330: // 11秒
            aircraft.add(new Aircraft(GV.scaleWidth - Aircraft.width - 20,
                    -Aircraft.height, Aircraft.width, Aircraft.height, 0, 0,
                    Aircraft.width, Aircraft.height, 5, Color.WHITE, 90,
                    State.step1));
 
            aircraft.add(new Aircraft(30, -Aircraft.height, Aircraft.width,
                    Aircraft.height, 0, 0, Aircraft.width, Aircraft.height, 5,
                    Color.WHITE, 90, State.step2));
 
            aircraft.add(new Aircraft(GV.scaleWidth - Aircraft.width - 20,
                    -Aircraft.height, Aircraft.width, Aircraft.height, 0, 0,
                    Aircraft.width, Aircraft.height, 5, Color.GREEN, 90,
                    State.step1));
 
            aircraft.add(new Aircraft(GV.scaleWidth - Aircraft.width - 30,
                    -Aircraft.height, Aircraft.width, Aircraft.height, 0, 0,
                    Aircraft.width, Aircraft.height, 5, Color.GREEN, 90,
                    State.step2));
 
            break;
        case 450: // 15秒 左邊連續出現
            for (f = 0; f < 5; f++) {
                aircraft.add(new Aircraft(20, (-Aircraft.halfHeight - 20)
                        * (f + 1), Aircraft.width, Aircraft.height, 0, 0,
                        Aircraft.width, Aircraft.height, 5, Color.RED, 90,
                        State.step1));
            }
 
            break;
        case 540: // 18秒 中間連續出現
            for (f = 0; f < 5; f++) {
                aircraft.add(new Aircraft(GV.halfWidth - Aircraft.halfWidth,
                        (-Aircraft.halfHeight - 20) * (f + 1), Aircraft.width,
                        Aircraft.height, 0, 0, Aircraft.width, Aircraft.height,
                        5, Color.BLUE, 90, State.step2));
            }
 
            break;
        case 630: // 21秒 右邊連續出現
            for (f = 0; f < 5; f++) {
                aircraft.add(new Aircraft(GV.scaleWidth - Aircraft.width - 20,
                        (-Aircraft.halfHeight - 20) * (f + 1), Aircraft.width,
                        Aircraft.height, 0, 0, Aircraft.width, Aircraft.height,
                        5, Color.GRAY, 90, State.step1));
            }
 
            break;
 
        case 750: // 25秒 左跟右連續出現
            for (f = 0; f < 5; f++) {
                aircraft.add(new Aircraft(20, (-Aircraft.halfHeight - 20)
                        * (f + 1), Aircraft.width, Aircraft.height, 0, 0,
                        Aircraft.width, Aircraft.height, 5, Color.WHITE, 90,
                        State.step2));
            }
 
            for (f = 0; f < 5; f++) {
                aircraft.add(new Aircraft(GV.scaleWidth - Aircraft.width - 20,
                        (-Aircraft.halfHeight - 20) * (f + 1), Aircraft.width,
                        Aircraft.height, 0, 0, Aircraft.width, Aircraft.height,
                        5, Color.YELLOW, 90, State.step2));
            }
 
            break;
        case 930: // 31秒
            for (f = 0; f < 5; f++) {
                aircraft.add(new Aircraft(GV.halfWidth - Aircraft.halfWidth,
                        (-Aircraft.halfHeight - 20) * (f + 1), Aircraft.width,
                        Aircraft.height, 0, 0, Aircraft.width, Aircraft.height,
                        5, Color.BLACK, 90, State.step1));
            }
 
            break;
        case 1020: // 34
            for (f = 0; f < 3; f++) {
                aircraft.add(new Aircraft(-Aircraft.width,
                        (-Aircraft.halfHeight - 20) * (f + 1), Aircraft.width,
                        Aircraft.height, 0, 0, Aircraft.width, Aircraft.height,
                        5, Color.WHITE, 45, State.step3));
            }
 
            break;
        case 1110: // 37
            for (f = 0; f < 3; f++) {
                aircraft.add(new Aircraft(GV.scaleWidth - Aircraft.width - 20,
                        (-Aircraft.halfHeight - 20) * (f + 1), Aircraft.width,
                        Aircraft.height, 0, 0, Aircraft.width, Aircraft.height,
                        5, Color.WHITE, 135, State.step4));
            }
 
            for (f = 0; f < 3; f++) {
                aircraft.add(new Aircraft(20, (-Aircraft.halfHeight - 20)
                        * (f + 1), Aircraft.width, Aircraft.height, 0, 0,
                        Aircraft.width, Aircraft.height, 5, Color.WHITE, 45,
                        State.step4));
            }
 
            break;
        case 1200: // 40
            for (f = 0; f < 3; f++) {
                aircraft.add(new Aircraft(GV.scaleWidth - Aircraft.width - 20,
                        (-Aircraft.halfHeight - 20) * (f + 1), Aircraft.width,
                        Aircraft.height, 0, 0, Aircraft.width, Aircraft.height,
                        5, Color.WHITE, 135, State.step4));
            }
 
            for (f = 0; f < 3; f++) {
                aircraft.add(new Aircraft(20, (-Aircraft.halfHeight - 20)
                        * (f + 1), Aircraft.width, Aircraft.height, 0, 0,
                        Aircraft.width, Aircraft.height, 5, Color.WHITE, 45,
                        State.step4));
            }
 
            break;
        case 1290: // 43
            for (f = 0; f < 3; f++) {
                aircraft.add(new Aircraft(GV.scaleWidth - Aircraft.width - 20,
                        (-Aircraft.halfHeight - 20) * (f + 1), Aircraft.width,
                        Aircraft.height, 0, 0, Aircraft.width, Aircraft.height,
                        5, Color.WHITE, 135, State.step4));
            }
 
            for (f = 0; f < 3; f++) {
                aircraft.add(new Aircraft(20, (-Aircraft.halfHeight - 20)
                        * (f + 1), Aircraft.width, Aircraft.height, 0, 0,
                        Aircraft.width, Aircraft.height, 5, Color.WHITE, 45,
                        State.step4));
            }
 
            break;
        case 1380: // 46
            for (f = 0; f < 3; f++) {
                aircraft.add(new Aircraft(20, -GV.halfHeight
                        + (-Aircraft.halfHeight - 20) * (f + 1),
                        Aircraft.width, Aircraft.height, 0, 0, Aircraft.width,
                        Aircraft.height, 5, Color.WHITE, 45, State.step3));
            }
 
            for (f = 0; f < 3; f++) {
                aircraft.add(new Aircraft(GV.scaleWidth - Aircraft.width - 20,
                        -GV.halfHeight + (-Aircraft.halfHeight - 20) * (f + 1),
                        Aircraft.width, Aircraft.height, 0, 0, Aircraft.width,
                        Aircraft.height, 5, Color.WHITE, 135, State.step3));
            }
 
            break;
        case 1470: // 49
            for (f = 0; f < 3; f++) {
                aircraft.add(new Aircraft(20, -GV.halfHeight
                        + (-Aircraft.halfHeight - 20) * (f + 1),
                        Aircraft.width, Aircraft.height, 0, 0, Aircraft.width,
                        Aircraft.height, 5, Color.WHITE, 45, State.step3));
            }
 
            for (f = 0; f < 3; f++) {
                aircraft.add(new Aircraft(GV.scaleWidth - Aircraft.width - 20,
                        -GV.halfHeight + (-Aircraft.halfHeight - 20) * (f + 1),
                        Aircraft.width, Aircraft.height, 0, 0, Aircraft.width,
                        Aircraft.height, 5, Color.WHITE, 135, State.step3));
            }
 
            break;
        case 1560: // 52
            for (f = 0; f < 3; f++) {
                aircraft.add(new Aircraft(20, -GV.halfHeight
                        + (-Aircraft.halfHeight - 20) * (f + 1),
                        Aircraft.width, Aircraft.height, 0, 0, Aircraft.width,
                        Aircraft.height, 5, Color.WHITE, 45, State.step3));
            }
            for (f = 0; f < 3; f++) {
                aircraft.add(new Aircraft(20, -GV.halfHeight
                        + (-Aircraft.halfHeight - 20) * (f + 1),
                        Aircraft.width, Aircraft.height, 0, 0, Aircraft.width,
                        Aircraft.height, 5, Color.WHITE, 45, State.step3));
            }
 
            break;
        case 1650: // 55
 
            aircraft.add(new Aircraft(GV.halfWidth - Aircraft.width,
                    -Aircraft.halfHeight - 20, Aircraft.width, Aircraft.height,
                    0, 0, Aircraft.width, Aircraft.height, 5, Color.WHITE, 90,
                    State.step1));
 
            aircraft.add(new Aircraft(GV.halfWidth + Aircraft.width,
                    -Aircraft.halfHeight - 20, Aircraft.width, Aircraft.height,
                    0, 0, Aircraft.width, Aircraft.height, 5, Color.WHITE, 90,
                    State.step1));
 
            aircraft.add(new Aircraft(GV.halfWidth - (Aircraft.width << 1),
                    -(Aircraft.halfHeight << 1), Aircraft.width,
                    Aircraft.height, 0, 0, Aircraft.width, Aircraft.height, 5,
                    Color.WHITE, 90, State.step2));
 
            aircraft.add(new Aircraft(GV.halfWidth + (Aircraft.width << 1),
                    -(Aircraft.halfHeight << 1), Aircraft.width,
                    Aircraft.height, 0, 0, Aircraft.width, Aircraft.height, 5,
                    Color.WHITE, 90, State.step2));
 
            aircraft.add(new Aircraft(GV.halfWidth + Aircraft.width * 3,
                    -(Aircraft.halfHeight * 3), Aircraft.width,
                    Aircraft.height, 0, 0, Aircraft.width, Aircraft.height, 5,
                    Color.WHITE, 135, State.step3));
 
            aircraft.add(new Aircraft(GV.halfWidth - (Aircraft.width * 3),
                    -(Aircraft.halfHeight * 3), Aircraft.width,
                    Aircraft.height, 0, 0, Aircraft.width, Aircraft.height, 5,
                    Color.WHITE, 45, State.step3));
 
            aircraft.add(new Aircraft(20, -(Aircraft.halfHeight << 2),
                    Aircraft.width, Aircraft.height, 0, 0, Aircraft.width,
                    Aircraft.height, 5, Color.WHITE, 45, State.step4));
 
            aircraft.add(new Aircraft(GV.scaleWidth - Aircraft.width - 20,
                    -(Aircraft.halfHeight << 2), Aircraft.width,
                    Aircraft.height, 0, 0, Aircraft.width, Aircraft.height, 5,
                    Color.WHITE, 135, State.step4));
 
            break;
        case 1800: // 60
            redMask.isAlive = true;
 
            break;
        case 1950: // 65
 
            // 蜘蛛背景音樂
            GV.music.player.release();
            GV.music = new Music(game.bee, R.raw.spidermusic, 1);
            GV.music.Play();
 
            spiderObj.add(new Spider(GV.halfWidth - (Spider.width >> 1), -Spider.height , Spider.width, Spider.height, 0, 0, spiderBitmap.getWidth(),spiderBitmap.getHeight() , 5, Color.WHITE, 90));
 
            break;
        }
 
        // 蜘蛛
        for (f = spiderObj.size() - 1; f >= 0; f--)
        {
            plane = spiderObj.get(f);
 
            // 子彈移動
            plane.AllBulletMove();
 
            if (plane.isAlive)
            {
                // 被大絕打到
                if (F16.isTouchBoom)
                {
                    // 損血
                    plane.blood -= F16.bigBoomPower;
 
                    // 直接進行碰撞
                    plane.Collisioned(frameTime, boom);
                }
 
                // 蜘蛛行動
                plane.Action(frameTime, myPlane.get(0), shootEffect);
            }
            else
            {
                // 破關
                breakOff = true;
 
                // 蜘蛛炮管
                for (j = plane.barrel.size() - 1; j >= 0; j--) 
                {
                    // 子彈數量
                    if (plane.barrel.get(j).bullet.size() != 0)
                        break;
                }
 
                // 所有子彈消失後移除蜘蛛
                if (j == -1)
                    spiderObj.remove(f);
            }
 
            // 檢查子彈與F16碰撞
            plane.CheckBulletCollision(frameTime, myPlane, boom);
        }
 
        // 檢查蜘蛛與自機碰撞
        Plane.CheckPlaneCollision((int) game.totalFrames, spiderObj, myPlane,boom);
 
        // 檢查民航機與自機碰撞
        Plane.CheckPlaneCollision((int) game.totalFrames, aircraft, myPlane, boom);
 
        // aircraft民航機行動
        for (f = aircraft.size() - 1; f >= 0; f--) {
            plane = aircraft.get(f);
 
            // 被大絕招打到
            if (F16.isTouchBoom)
            {
                // 損血
                plane.blood -= F16.bigBoomPower;
 
                // 直接進行碰撞
                plane.Collisioned(frameTime, boom);
            }
 
            // 子彈移動
            plane.AllBulletMove();
 
            if (plane.isAlive)
                plane.Action((int) game.totalFrames, myPlane.get(0), shootEffect);
            else 
            {
                // 民航機炮管
                for (j = plane.barrel.size() - 1; j >= 0; j--) 
                {
                    // 子彈數量
                    if (plane.barrel.get(j).bullet.size() != 0)
                        break;
                }
 
                // 所有子彈消失後移除民航機
                if (j == -1)
                    aircraft.remove(f);
            }
        }
 
        // 自機
        for (f = myPlane.size() - 1; f >= 0; f--) {
            plane = myPlane.get(f);
 
            // 子彈移動
            plane.AllBulletMove();
 
            // 自機行動
            if (plane.isAlive)
                plane.Action((int) game.totalFrames, shootEffect);
 
            // 檢查自機子彈與民航機碰撞
            plane.CheckBulletCollision((int) game.totalFrames, aircraft, boom);
 
            // 檢查自機子彈與蜘蛛碰撞
            plane.CheckBulletCollision(frameTime, spiderObj, boom);
        }
 
        // 檢查民航機子彈與自機的碰撞
        for (f = aircraft.size() - 1; f >= 0; f--) {
            aircraft.get(f).CheckBulletCollision((int) game.totalFrames,
                    myPlane, boom);
        }
 
        // 大絕招
        if (F16.isTouchBoom) {
 
            // 新增爆炸
            boom.add(new Boom(0, 0, GV.scaleWidth, GV.scaleHeight));
            F16.isTouchBoom = false;
        }
 
        // 爆炸動畫
        for (f = boom.size() - 1; f >= 0; f--) {
            subBoom = boom.get(f);
 
            subBoom.Animation();
 
            if (!subBoom.isAlive)
                boom.remove(f);
        }
 
        // 發射特效
        for (f = shootEffect.size() - 1; f >= 0; f--) {
            if (shootEffect.get(f).Animation()) {
                shootEffect.remove(f);
            }
        }
 
        // 紅色遮罩淡入淡出
        if (redMask.isAlive)
        {
            redMask.Action(frameTime);
 
            // 設為切換背景
            spiderBackGroundObj.isAlive = true;
        }
 
        // 一般背景捲動
        if (backGroundObj.isAlive)
        {
            backGroundObj.addY(1);
 
            // 不斷循環
            backGroundObj.setY(backGroundObj.getY() % backGroundImage.getHeight());
        }
 
        // 如果是一般背景狀態
        if (spiderBackGroundObj.isAlive)
        {
            // 蜘蛛背景捲動
            if (spiderBackGroundObj.getY() < 0)
            {
                spiderBackGroundObj.addY(1);
            }
            else
                backGroundObj.isAlive = false;
        }
 
        // 更新fps顯示
        fpsText.message = (int) game.actualFPS + " FPS (" + (int) game.fps
                + ") " + (int) game.totalFrames;
 
        // 重新初始化
        if (myPlane.get(0).life == 0 || breakOff) {
            if (!isBlackMask)
            {
                isBlackMask = true;
                gameOverText.isVisible = true;
                startBlackMaskFrame = frameTime;
            }
 
            // 重新遊戲
            if (frameTime - startBlackMaskFrame > restartDelayFrame)
            {
                GV.music.Stop();
                GameStateClass.changeState(GameState.Menu, this, game);
            }
        }
 
        // 10ms後震動100ms
        // vibrator.vibrate(new long[]{10,100},-1);
 
        super.Update();
    }
 
    @Override
    protected void Draw() {
 
        // 取得canvas
        subCanvas = game.canvas;
 
        // 一般背景
        if (backGroundObj.isAlive)
        {
            for (f = 0; f <= backGroundObj.destWidth; f++) 
            {
                for (j = -1; j <= backGroundObj.destHeight; j++) 
                {
                    subCanvas.drawBitmap(backGroundImage,
                                         f * backGroundImage.getWidth() + backGroundObj.destRect.left,
                                         j * backGroundImage.getHeight() + backGroundObj.destRect.top,
                                         null);
                }
            }
        }
 
        // 蜘蛛背景
        if (spiderBackGroundObj.isAlive)
        {
            subCanvas.drawBitmap(spiderBackGroundBitmap, spiderBackGroundObj.srcRect,spiderBackGroundObj.destRect,null);
        }
 
        // 蜘蛛
        for (f = spiderObj.size() - 1; f >= 0; f--)
        {
            plane = spiderObj.get(f);
 
            if (plane.isAlive)
            {
                subCanvas.save();
 
                subCanvas.rotate(plane.theta - 90, plane.getX() + plane.halfWidth, plane.getY() + plane.halfHeight);
                subCanvas.drawBitmap(spiderBitmap, plane.srcRect, plane.destRect, plane.paint);
 
                subCanvas.restore();
 
                subCanvas.drawRect(((Spider)plane).bloodObj.destRect,((Spider)plane).bloodObj.paint);
            }
 
            // 子彈
            for (j = plane.barrel.size() - 1; j >= 0; j--)
            {
                for (k = plane.barrel.get(j).bullet.size() - 1; k >= 0 ;k--)
                {
                    bullet = plane.barrel.get(j).bullet.get(k);
                    subCanvas.drawBitmap(bulletBitmap1, bullet.getX(), bullet.getY(),bullet.paint);
                }
            }
        }
 
        // 民航機
        for (f = aircraft.size() - 1; f >= 0; f--) {
            plane = aircraft.get(f);
 
            if (plane.isAlive) {
                subCanvas.save();
 
                subCanvas.rotate(plane.theta - 90, plane.getX()
                        + Aircraft.halfWidth, plane.getY()
                        + Aircraft.halfHeight);
                subCanvas.drawBitmap(aircraftBitmap, plane.srcRect,
                        plane.destRect, plane.paint);
 
                subCanvas.restore();
            }
 
            // 民航機子彈
            for (j = plane.barrel.size() - 1; j >= 0; j--) {
                for (k = plane.barrel.get(j).bullet.size() - 1; k >= 0; k--) {
                    bullet = plane.barrel.get(j).bullet.get(k);
                    subCanvas.drawBitmap(bulletBitmap1, bullet.getX(), bullet
                            .getY(), bullet.paint);
                }
            }
        }
 
        // 自機
        for (f = myPlane.size() - 1; f >= 0; f--) {
            plane = myPlane.get(f);
 
            if (plane.isAlive)
                subCanvas.drawBitmap(f16Bitmap, plane.srcRect, plane.destRect,
                        plane.paint);
 
            // 自機炮管
            for (j = plane.barrel.size() - 1; j >= 0; j--) {
                // 自機子彈
                for (k = plane.barrel.get(j).bullet.size() - 1; k >= 0; k--) {
                    bullet = plane.barrel.get(j).bullet.get(k);
                    subCanvas.drawBitmap(bulletBitmap1, bullet.getX(), bullet
                            .getY(), bullet.paint);
                }
            }
        }
 
        // 爆炸
        for (f = 0; f < boom.size(); f++) {
            subBoom = boom.get(f);
            subCanvas.drawBitmap(boomBitmap, subBoom.srcRect, subBoom.destRect,
                    subBoom.paint);
        }
 
        // 發射特效
        for (f = shootEffect.size() - 1; f >= 0; f--) {
            subCanvas.drawBitmap(shootEffectBitmap, shootEffect.get(f).srcRect,
                    shootEffect.get(f).destRect, shootEffect.get(f).paint);
        }
 
        // FPS文字
        subCanvas.drawText(fpsText.message, fpsText.x, fpsText.y, fpsText.paint);
 
        // 紅色遮罩
        if (redMask.isAlive)
        {
            subCanvas.drawRect(redMask.destRect, redMask.paint);
 
            // 警告訊息
            subCanvas.drawText(redMask.warningText.message, redMask.warningText.x, redMask.warningText.y, redMask.warningText.paint);
        }
 
        // 黑色遮罩
        if (isBlackMask)
            subCanvas.drawRect(blackMask.destRect, blackMask.paint);
 
        // gameover
        if (gameOverText.isVisible)
            subCanvas.drawText(gameOverText.message, gameOverText.x, gameOverText.y, gameOverText.paint);
 
        super.Draw();
    }
}

程式:DrawableGameComponent.java

package XNA.lbs;
 
public class DrawableGameComponent {
 
    public DrawableGameComponent() {
 
    }
 
    public void Dispose() {
        UnloadContent();
    }
 
    protected void Initialize() {
    }
 
    protected void LoadContent(){
    }
 
    protected void UnloadContent() {
 
    }
 
    protected void Update() {
 
    }
 
    protected void Draw() {
 
    }
}

程式:Game.java

package XNA.lbs;
 
import android.graphics.Canvas;
import Bee.main.GV;
 
public class Game {
 
    // 是否為第一次跑 
    private boolean isRun;
    public GameComponentCollection Components = new GameComponentCollection();
    public Canvas canvas = null;
    public long totalFrames;
    public int fps;
    public int actualFPS;
    public int setFPS = 30;
    private int fpsInterval = 1000 / setFPS;
 
    private Thread gameLoop;
    private int f;
 
    public Game()
    {
 
    }
 
    // 開始遊戲
    public void Run()
    {
        // 如果是第一次跑則進行初始化並載入資源
        if (!isRun)
        {
            Initialize();
            LoadContent();
 
            // 設為已跑過
            isRun = true;
        }
 
        gameLoop = new Thread(new GameLoop());
        gameLoop.setDaemon(true);
        gameLoop.start();
    }
 
    // 離開遊戲
    public void Exit()
    {
        if (gameLoop != null)
        {
            gameLoop.interrupt();
        }
    }
 
    class GameLoop implements Runnable
    {
 
        // 遊戲主迴圈
        public void run() {
            long startTime;
            int delayTime;
            int sleepTime;
 
            while(!Thread.interrupted())
            {            
                startTime = System.currentTimeMillis(); 
 
                // 動作更新
                Update();
 
                // 畫面更新
                Draw();
 
                delayTime = (int)(System.currentTimeMillis() - startTime);
 
                if (delayTime == 0) delayTime = 1;
                fps = 1000 / delayTime;
 
                // 如果太快就延遲
                sleepTime = fpsInterval - delayTime;
                if (sleepTime > 0) {
                    actualFPS = 1000 / fpsInterval;
                    try {
                        Thread.sleep(sleepTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        Thread.currentThread().interrupt();
                    }
                }else
                {
                    actualFPS = 1000 / delayTime;
                }
            }
        }
    }
 
    protected void Initialize() {
 
    }
 
    protected void LoadContent(){
 
    }
 
    protected void UnloadContent() {
        Exit();
    }
 
    protected void Update() {
        for (f = Components.size() -1 ; f >= 0; f--)
            Components.get(f).Update();
    }
 
    protected void Draw() {
        for (f = Components.size() -1 ; f >= 0; f--)
            Components.get(f).Draw();
 
        // 解除鎖定
        GV.surface.mHolder.unlockCanvasAndPost(canvas);
 
        totalFrames++;
    }    
}

程式:GameComponentCollection.java

package XNA.lbs;
 
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
 
public class GameComponentCollection implements Collection<DrawableGameComponent>{
 
    protected List<DrawableGameComponent> componse = new ArrayList<DrawableGameComponent>();
 
    public boolean add(DrawableGameComponent arg0) {
        arg0.Initialize();
        arg0.LoadContent();
 
        return componse.add(arg0);
    }
 
    public DrawableGameComponent get(int arg0) {
        return componse.get(arg0);
    }
 
    public void add(int arg0,DrawableGameComponent arg1)
    {
        componse.add(arg0, arg1);
    }
 
    public boolean addAll(Collection<? extends DrawableGameComponent> arg0) {
        // TODO Auto-generated method stub
        return componse.addAll(arg0);
    }
 
    public void clear() {
        componse.clear();
    }
 
    public boolean contains(Object arg0) {
        // TODO Auto-generated method stub
        return componse.contains(arg0);
    }
 
    public boolean containsAll(Collection<?> arg0) {
        // TODO Auto-generated method stub
        return componse.containsAll(arg0);
    }
 
    public boolean isEmpty() {
        // TODO Auto-generated method stub
        return componse.isEmpty();
    }
 
    public Iterator<DrawableGameComponent> iterator() {
        // TODO Auto-generated method stub
        return componse.iterator();
    }
 
    public boolean remove(Object arg0) {
        return componse.remove(arg0);
    }
 
    public boolean removeAll(Collection<?> arg0) {
        // TODO Auto-generated method stub
        return componse.removeAll(arg0);
    }
 
    public boolean retainAll(Collection<?> arg0) {
        // TODO Auto-generated method stub
        return componse.retainAll(arg0);
    }
 
    public int size() {
        // TODO Auto-generated method stub
        return componse.size();
    }
 
    public Object[] toArray() {
        // TODO Auto-generated method stub
        return componse.toArray();
    }
 
    public <T> T[] toArray(T[] arg0) {
        // TODO Auto-generated method stub
        return componse.toArray(arg0);
    }
}

AndroidManifest.xml為使用權限:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="Bee.main"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true" android:name="@string/app_name">
 
        <activity android:name=".Bee"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>                                
        </activity>
 
    </application>
 
    <uses-sdk android:minSdkVersion="4" />
 
    <!-- 震動權限 -->
    <uses-permission android:name="android.permission.VIBRATE"/>
 
    <!-- 恆亮權限 -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
 
</manifest>

程式影片解說

程式手機執行影片