#apply
#include "../_include.txt"
#include "../../define/_vector2.txt"

cev[CEV_AGUGA] .name("mg_AGUGA") {

    def {
        NUM_OF_VAR = 720
        NUM_OF_STR = 1
        NUM_OF_PIC = 220

        BASE_LAYER = 6

        PATH_FRAME    = "ag\fr"
        PATH_BACK     = "ag\ba"
        PATH_EPILOGUE = "ag\ep"
        PATH_SCREEN   = "cm\da"
        PATH_WINDOW   = "ag\wi"
        PATH_COUNT    = "ag\co"
        PATH_HAND     = "ag\ha"
        PATH_FACE     = "ag\fa"
        PATH_RADER    = "ag\ra"
        PATH_MAP      = "ag\ma"
        PATH_WALL     = "ag\wa"
        PATH_SPRITE   = "ag\sp"
        PATH_CROSSHAIR= "ag\cr"

        //ピクチャID
        PIC_HEAD       = 1
        PIC_SORTED     = 10//+0_+88
        PIC_BACK       = 99
        PIC_SPRITE     = 100//+0_+88
        PIC_HAND       = 199
        PIC_CROSSHAIR  = 200
        PIC_SCREEN     = 201
        PIC_WINDOW     = 202
        PIC_MAP        = 203
        PIC_FACE       = 204
        PIC_RADER      = 205
        PIC_ENEMY_CNT  = 206//+0_+1
        PIC_FLOOR_CNT  = 208//+0_+1
        PIC_HEALTH_CNT = 210//+0_+1
        PIC_EPILOGUE   = 212
        PIC_TEXT       = 213
        PIC_FRAME      = 214
        PIC_TIMER_CNT  = 215

        //実績
        ACHIEVE_TIME = UNIT_FPS * 60 * 11//11分

        //シーン
        SCENE_START = 0
        SCENE_GAME
        SCENE_DEFEAT
        SCENE_GOAL
        SCENE_EPILOGUE
        SCENE_CHOICE

        //シーンに応じた判定処理
        CHK_UPDATE_CHARA  = sceneState == SCENE_GAME//主人公を制御できる
        CHK_UPDATE_SPRITE = between(sceneState, SCENE_START, SCENE_DEFEAT)//スプライトを更新する

        //トリガー
        TR_BIT_FACE       = 1 << 0
        TR_BIT_MAP        = 1 << 1
        TR_BIT_ENEMY_CNT  = 1 << 2
        TR_BIT_FLOOR_CNT  = 1 << 3
        TR_BIT_HEALTH_CNT = 1 << 4
        TR_BIT_TIMER_CNT  = 1 << 5

        //操作方法
        CTRL_TYPE_KEY = 0
        CTRL_TYPE_MOUSE

        //顔
        FACE_STATE_NORMAL1 = 0
        FACE_STATE_NORMAL2
        FACE_STATE_NORMAL3
        FACE_STATE_DEFEAT
        FACE_STATE_DAMAGE
        FACE_STATE_POWERUP

        //手
        HAND_STATE_INIT = 0
        HAND_STATE_BOTH
        HAND_STATE_SHOOT
        HAND_STATE_BOTH_SHOOT
        HAND_STATE_SMOKE

        //視覚判定
        VISION_NONE = 0
        VISION_OUTRANGE
        VISION_WALL
        VISION_PLAYER

        //表示
        OUT_RANGE  = -320
        REF_X = 32
        REF_Y = 24
        REF_HUD_X = REF_X + HUD_X
        REF_HUD_Y = REF_Y + HUD_Y
        REF_SCR_WIDTH  = REF_X + SCR_WIDTH  / 2
        REF_SCR_HEIGHT = REF_Y + SCR_HEIGHT / 2
        HUD_X  = 0
        HUD_Y  = 144
        HAND_X = 130
        HAND_Y = 144
        FACE_X = 109
        FACE_Y = 5
        ENEMY_CNT_X  = 98
        ENEMY_CNT_Y  = 14
        FLOOR_CNT_X  = 46
        FLOOR_CNT_Y  = 14
        HEALTH_CNT_X = 196
        HEALTH_CNT_Y = 14
        TIMER_CNT_X  = 42
        TIMER_CNT_Y  = 4
        RADER_X  = 232
        RADER_Y  = 24
        RADER_SIZE = 32
        SCR_WIDTH  = 256
        SCR_HEIGHT = 192
        SCR_CENTER_X = 128
        SCR_CENTER_Y = 72
        SCR_FOV = UNIT_ANG * 60//度数 * 単位
        SCR_HALF_FOV = SCR_FOV / 2
        SCR_DIST = 225//width / 2 / tan(fov / 2)
        SCR_MIN_DEPTH = UNIT_POS//距離 * 単位
        SCR_MAX_DEPTH = 80 * UNIT_POS
        CHARA_SCALE_BASE = 20//拡大率の基準値
        CHARA_HIT_RADIUS = 4 * UNIT_POS//弾との衝突判定
        CHARA_OFFSET_Z = 1 * UNIT_POS//表示位置を少し下げる
        ROUND_ANGLE = 360 * UNIT_ANG
        COUNTER_WIDTH = 16
        COUNTER_DIGIT = 2

        //マップ
        MAP_SIZE = 16
        MAP_COLOR_GOAL = 0x01

        //単位
        UNIT_POS = 100
        UNIT_ANG = 100
        UNIT_TRI = 1000
        UNIT_MAPPOS = (UNIT_POS * 10)//ゲーム内の座標単位に応じたマスの大きさ

        //壁
        WALL_GRID_X   = 16
        WALL_PATTERN  = 4
        WALL_TYPE_NUM = 4
        WALL_SCALE_X   = 250
        WALL_SCALE_Y   = 35
        WALL_MAX_SCALE = 4000

        //ゲーム
        FLOOR_MAX = 16
        HEALTH_MAX = 99
        TIMER_MAX  = 60 * 59 * UNIT_FPS//59分

        //プレイヤー
        PLAYER_SPEED      = UNIT_POS * 8 / 10
        PLAYER_MAX_ROTATE = 45 * UNIT_ANG
        PLAYER_RADIUS     = 2 * UNIT_POS
        PLAYER_HIT_RADIUS = 3 * UNIT_POS
        PLAYER_GOAL_LEN   = 6 * UNIT_POS
        PLAYER_SHOOT_WAIT = 8
        PLAYER_SHOOT_VEL  = 4 * UNIT_POS

        //アイテム
        ITEM_HIT_RADIUS = 4 * UNIT_POS

        //敵
        ENEMY_VISION_INT = 12
        ENEMY_GIVEUP_INT = UNIT_FPS * 3

        //文字列
        EPILOGUE_MESSAGE = __str("",
"要塞の中枢、光り輝く心臓は
外界の太陽のように君を照らす。
無礼な来客たちを丁重にもてなし、
地獄へ追い返してやったのだ！

十字手裏剣と黒魔術めいた妖術を操る
謎のおっさんも、君の吐き出す業火の前では
まるで子犬のようだったな。

悪の巣窟と化したホワイトハウスは、
隅々まで清められた。
地獄への門は二度と開かれる事はないだろう。
我々がこの過ちを忘れない限り…

ところでアグネ。
タオル持ってない？")

        //----------------------------
        //キャラクターのタイプや状態
        ITEM_TYPE_NUM  = 1
        ATK_TYPE_NUM   = 7
        ENEMY_TYPE_NUM = 5

        CHARA_TYPE_NONE = 0
        CHARA_TYPE_ITEM
        CHARA_TYPE_PL_ATK_NORMAL
        CHARA_TYPE_PL_ATK_STRONG
        CHARA_TYPE_PL_ATK_SMOKE
        CHARA_TYPE_PL_ATK_TOBACCO
        CHARA_TYPE_EN_ATK_NORMAL
        CHARA_TYPE_EN_ATK_CROSS
        CHARA_TYPE_EN_ATK_CHASE
        CHARA_TYPE_EN_ZOMBIE
        CHARA_TYPE_EN_BEAR
        CHARA_TYPE_EN_PLANT
        CHARA_TYPE_EN_BEETLE
        CHARA_TYPE_EN_FURY

        CHARA_STATE_NONE = 0
        CHARA_STATE_DELETE
        CHARA_STATE_CREATE
        CHARA_STATE_ENABLE

        ITEM_STATE_ENABLE = 3//=CHARA_STATE_ENABLE

        ATK_STATE_ENABLE = 3
        ATK_STATE_HIT

        ENEMY_STATE_ENABLE = 3
        ENEMY_STATE_ATTACK
        ENEMY_STATE_SPECIAL
        ENEMY_STATE_WAIT
        ENEMY_STATE_DEAD
        ENEMY_STATE_DOWN

        //----------------------------
        //スプライト/キャラクタ
        SPRITE_NUM = 80//wall + chara
        WALL_NUM   = 54
        CHARA_NUM  = 26

        //スプライトIDの割り当て
        SPR_ID_WALL  = 0
        SPR_ID_CHARA = 54

        //スプライトの構造とサイズ
        MEM_SPR_PID = 0
        MEM_SPR_DEPTH
        SIZE_OF_SPR

        //スプライトのメンバー変数へのアクセス(A,B)
        A_mSprPId   = v[ptrSprA + MEM_SPR_PID]
        A_mSprDepth = v[ptrSprA + MEM_SPR_DEPTH]

        B_mSprPId   = v[ptrSprB + MEM_SPR_PID]
        B_mSprDepth = v[ptrSprB + MEM_SPR_DEPTH]

        //キャラクタの構造とサイズ
        //MC_SPRID//スプライトIDはインデックス番号で固定
        MC_STATE = 0
        MC_TIMER
        MC_TYPE
        MC_POINT
        MC_CELL
        MC_SCALE
        MC_ANGLE
        MC_PARAM_1
        MC_PARAM_2
        MC_X
        MC_Y
        SIZE_OF_CHARA

        //キャラクタのメンバー変数へのアクセス(A,B)
        A_mChState   = v[ptrCharaA + MC_STATE]
        A_mChTimer   = v[ptrCharaA + MC_TIMER]
        A_mChType    = v[ptrCharaA + MC_TYPE]
        A_mChPoint   = v[ptrCharaA + MC_POINT]
        A_mChCell    = v[ptrCharaA + MC_CELL]
        A_mChScale   = v[ptrCharaA + MC_SCALE]
        A_mChAngle   = v[ptrCharaA + MC_ANGLE]
        A_mChParam_1 = v[ptrCharaA + MC_PARAM_1]
        A_mChParam_2 = v[ptrCharaA + MC_PARAM_2]
        A_mChX       = v[ptrCharaA + MC_X]
        A_mChY       = v[ptrCharaA + MC_Y]

        B_mChState   = v[ptrCharaB + MC_STATE]
        B_mChTimer   = v[ptrCharaB + MC_TIMER]
        B_mChType    = v[ptrCharaB + MC_TYPE]
        B_mChPoint   = v[ptrCharaB + MC_POINT]
        B_mChCell    = v[ptrCharaB + MC_CELL]
        B_mChScale   = v[ptrCharaB + MC_SCALE]
        B_mChAngle   = v[ptrCharaB + MC_ANGLE]
        B_mChParam_1 = v[ptrCharaB + MC_PARAM_1]
        B_mChParam_2 = v[ptrCharaB + MC_PARAM_2]
        B_mChX       = v[ptrCharaB + MC_X]
        B_mChY       = v[ptrCharaB + MC_Y]

    }

    //ピクチャの共通コマンド
    def {
        //共通コマンドの共通部分
        basePicCmd = bl {
            .chromakey(1)
            .mapLayer(BASE_LAYER)
            .eraseWhenTransfer
            .affectedByTint
            .affectedByFlash
            .affectedByShake
        }

        //エピローグ
        epiloguePicCmd = bl {
            PATH_EPILOGUE
            basePicCmd
        }

        //マップ
        mapPicCmd = bl {
            PATH_MAP
            .grid(4, 4)
            basePicCmd
        }

        //カウンタ
        countPicCmd = bl {
            PATH_COUNT
            .grid(10, 1)
            basePicCmd
        }

        //顔
        facePicCmd = bl {
            PATH_FACE
            .grid(6, 1)
            basePicCmd
        }

        //手
        handPicCmd = bl {
            PATH_HAND
            .grid(1, 4)
            basePicCmd
        }

        //手
        crosshairPicCmd = bl {
            PATH_CROSSHAIR
            .add
            basePicCmd
        }

        //壁
        wallPicCmd = bl {
            PATH_WALL
            .grid(WALL_GRID_X * WALL_PATTERN, 1)
            basePicCmd
        }

        //キャラクター
        charaPicCmd = bl {
            PATH_SPRITE
            .grid(8, 5)
            basePicCmd
        }

        //文字列
        largeTextPicCmd = bl {
            .size(0, 0)
            .trans(0)
            .font("", 24)
            .spacing(0, 4)
            .skin "" .nobg .noframe .noPadding
            basePicCmd
        }

        smallTextPicCmd = bl {
            .size(0, 0)
            .trans(0)
            .font("", 12)
            .spacing(0, 4)
            .skin "" .nobg .noframe .noPadding
            basePicCmd
        }
    }

    //変数定義
    defv {
        varHead = TV_MINIGAME

        //初期化の対象にならない
        sensitivity

        //初期化の範囲の頭
        initHead

        idxA
        idxB
        ptrSprA
        ptrSprB
        ptrCharaA
        ptrCharaB

        ftA
        ftB

        input
        loopNum
        pix
        pid
        cell

        state
        timer
        type
        hit

        atkType
        atkPoint
        atkScale
        atkAng
        atkSpeed

        alpha
        beta
        gamma
        delta
        theta
        depth
        rayCos
        raySin
        sigX
        sigY
        adjX
        adjY
        vx
        vy
        sx
        sy
        ex
        ey
        ax
        ay
        bx
        by
        cx
        cy

        sceneState
        sceneTimer
        triggerFlg

        gameTimer
        floorTimer
        enemyNum
        enemyCnt
        floor

        faceState
        faceTimer
        handState
        handTimer

        camX
        camY
        camZ
        camAng
        camCos
        camSin

        plHealth
        plDamage
        plPower

        //初期化の範囲の尾
        initFoot

        charaHead
        sprHead   = (__id(charaHead) + CHARA_NUM  * SIZE_OF_CHARA)
        sortDepth = (__id(sprHead)   + SPRITE_NUM * SIZE_OF_SPR )//ソート用配列
        sortSprId = (__id(sortDepth) + SPRITE_NUM)

        varFoot = (__id(sortSprId) + SPRITE_NUM)
    }

    deft {
        strLine = TS_MINIGAME
    }

    commentRangeOfVariables(varFoot, TV_MINIGAME, NUM_OF_VAR, NUM_OF_STR, NUM_OF_PIC)

    //----------------------------
    //スプライトを全て非表示にし、奥に追いやる
    //ピクチャIDはそのまま
    __fn _initAllSprite bl {
        @loop SPRITE_NUM .dst(ftA) bl {
            _getSprPtr(ftB, ftA)
            v[ftB + MEM_SPR_DEPTH] = SCR_MAX_DEPTH
            pid = v[ftB + MEM_SPR_PID]
            hidePicture(pid)
        }
    }

    //スプライトごとに処理を行う
    __fn _forEachSprites $dvPtr $dvIdx $loopNum $sprHead $block bl {
        @loop $loopNum .dst($dvIdx) {
            v[__id($dvIdx)] = $sprHead + $dvIdx
            _getSprPtr($dvPtr, $dvIdx)
            $block
        }
    }

    //スプライトのポインタを取得する
    __fn _getSprPtr $dvDst $idx bl {
        v[__id($dvDst)] = __id(sprHead) + SIZE_OF_SPR * ($idx)
    }

    //キャラクタIDに対応したスプライトのポインタを取得する
    __fn _getSprPtrFromChId $dvDst $idx bl {
        v[__id($dvDst)] = __id(sprHead) + SIZE_OF_SPR * (SPR_ID_CHARA + $idx)
    }

    //スプライトのメンバ変数を初期化する
    __fn _setSprMembers $ptr $arr bl {
        v[$ptr..$ptr + SIZE_OF_SPR - 1] = $arr
    }

    //----------------------------
    //キャラクタを全て初期化する
    //スプライトは残る
    __fn _initAllChara bl {
        @loop CHARA_NUM .dst(ftA) {
            _getCharaPtr(ftB, ftA)
            _initCharaMembers(ftB)
        }
    }

    //空いているキャラクタのポインタを探す
    //見つからなかった場合は0を渡す
    //0番目はプレイヤーの弾で固定されている為、選ばれない
    __fn _getEmptyCharaPtr $dvPtr bl {
        v[__id($dvPtr)] = 0
        @loop CHARA_NUM .dst(ftA) bl {
            _getCharaPtr(ftB, ftA)
            @if `ftA > 0 && v[ftB + MC_TYPE] == CHARA_TYPE_NONE bl {
                v[__id($dvPtr)] = ftB
                @break
            }
        }
    }

    //キャラクタのポインタを取得する
    __fn _getCharaPtr $dvDst $idx bl {
        v[__id($dvDst)] = __id(charaHead) + SIZE_OF_CHARA * ($idx)
    }

    //キャラクタのメンバ変数を初期化する
    __fn _setCharaMembers $ptr $arr bl {
        v[$ptr..$ptr + SIZE_OF_CHARA - 1] = $arr
    }

    //キャラクタのメンバ変数を初期値で初期化する
    __fn _initCharaMembers $ptr bl {
        v[$ptr..$ptr + SIZE_OF_CHARA - 1] = [CHARA_STATE_NONE, -1, CHARA_TYPE_NONE, 0, 0, 0, 0, 0, 0, 0, 0]
    }

    //キャラクタの状態を変える
    __fn _changeCharaState $ptr $state bl {
        v[$ptr + MC_STATE..$ptr + MC_TIMER] = [$state, -1]
    }

    //----------------------------
    //シーンの状態を変える
    __fn _changeSceneState $state bl {
        v[__id(sceneState)..__id(sceneTimer)] = [$state, -1]
    }

    //手の状態を変える
    __fn _changeHandState $state bl {
        v[__id(handState)..__id(handTimer)] = [$state, -1]
    }

    //顔の状態を変える
    __fn _changeFaceState $state $time bl {
        v[__id(faceState)..__id(faceTimer)] = [$state, $time]
    }

    //数値を表示する
    //sx. ex. pid, cellを使用する
    __fn _showCounter $num $pid $dig $x $y bl {
        ey = 1
        @loop $dig .dst(ex) bl {
            v[__id(sx)..__id(sy)] = [($x) - ex * COUNTER_WIDTH, ($y)]

            pid  = ($pid) + ex
            cell = (($num) < ey && ey != 1) ? (0) : (1 + ($num) % (ey * 10) / ey)
            @pic.show [pid] .pos(sx, sy) .topRight .scale(100) .cell(cell) countPicCmd

            //次の桁
            ey *= 10
        }
    }

    //フェードアウト/フラッシュ
    __fn _screenColor $red $green $blue $transS $transE $time bl {
        $SCALE_X = SCR_WIDTH  * 100 / 16
        $SCALE_Y = SCR_HEIGHT * 100 / 16
        @pic.show [PIC_SCREEN] PATH_SCREEN .pos(REF_SCR_WIDTH, REF_SCR_HEIGHT) .scale2($SCALE_X, $SCALE_Y) .trans($transS) .rgbs($red, $green, $blue, 100) basePicCmd
        @pic.move [PIC_SCREEN] .relative .pos(0, 0) .scale2(0, 0) .trans($transE - $transS) .time($time) .keepRgbs 
    }

    //地形用ピクチャからピクセルを取得する
    //範囲外である場合は0が入力される
    __fn _getPixelFromMap $dvPixel $x $y bl {
        v[__id($dvPixel)] = 0x0
        @if `between($x, 0, MAP_SIZE - 1) && between($y, 0, MAP_SIZE - 1) bl {
            @pic.getInfo [PIC_MAP] .pixel($x, $y, 1, 1) .dst($dvPixel) .ignoreA .static
        }
    }

    //地形用ピクチャとの衝突判定を行う
    __fn _checkCollFromMap $dvFlag $x $y bl {
        v[__id($dvFlag)] = FALSE
        @if `between($x, 0, MAP_SIZE - 1) && between($y, 0, MAP_SIZE - 1) bl {
            @pic.getInfo [PIC_MAP] .pixel($x, $y, 1, 1) .dst(ftA) .ignoreA .static
            @if `between(ftA & 0xff, 1, WALL_TYPE_NUM) bl {
                v[__id($dvFlag)] = TRUE
            } 
        }
    }

    //ハイスコアを更新する
    //クリア時間なので少ない方を取る
    __fn _updateHighScore bl {
        agugaScore = agugaScore <= 0 ? gameTimer : min(agugaScore, gameTimer)
    }

    //----------------------------
    //開始処理
    bl {
        initPicturesAndVariables(PIC_HEAD, NUM_OF_PIC, TV_MINIGAME, NUM_OF_VAR, TS_MINIGAME, NUM_OF_STR)
        storeAndStopBGM()
        msgBottom()
        
        @pic.show [PIC_FRAME]  PATH_FRAME  .pos(0, 0) .topLeft basePicCmd
        @pic.show [PIC_BACK]   PATH_BACK   .pos(REF_X + SCR_CENTER_X, REF_Y + SCR_CENTER_Y) .scale2(SCR_WIDTH * 100 / 16, SCR_HEIGHT * 100 / 16) .center basePicCmd
        @pic.show [PIC_SCREEN] PATH_SCREEN .pos(OUT_RANGE, OUT_RANGE) .center .trans(100) basePicCmd
        @pic.show [PIC_WINDOW] PATH_WINDOW .pos(REF_X + HUD_X, REF_Y + HUD_Y) .topLeft .trans(0) basePicCmd
        @pic.show [PIC_RADER]  PATH_RADER  .pos(OUT_RANGE, OUT_RANGE) .center .trans(100) basePicCmd
        @pic.show [PIC_MAP]    PATH_MAP    .pos(OUT_RANGE, OUT_RANGE) .center .cell(0) .trans(100) .cell(0) basePicCmd
        @pic.show [PIC_FACE]      .pos(OUT_RANGE, OUT_RANGE) .center .trans(100) .cell(0) facePicCmd
        @pic.show [PIC_CROSSHAIR] .pos(REF_X + SCR_CENTER_X, REF_Y + SCR_CENTER_Y) .center crosshairPicCmd
        @pic.show [PIC_HAND]      .pos(OUT_RANGE, OUT_RANGE) .trans(100) .cell(0) handPicCmd

        //スプライトを初期化する
        _forEachSprites(ptrSprA, idxA, WALL_NUM, SPR_ID_WALL,
            bl {
                pid = PIC_SPRITE + idxA
                A_mSprPId = pid
                @pic.show [pid] .pos(OUT_RANGE, OUT_RANGE) .cell(0) wallPicCmd
            }
        )

        _forEachSprites(ptrSprA, idxA, CHARA_NUM, SPR_ID_CHARA,
            bl {
                pid = PIC_SPRITE + idxA
                A_mSprPId = pid
                @pic.show [pid] .pos(OUT_RANGE, OUT_RANGE) .cell(0) charaPicCmd
            }
        )

        //初期感度
        sensitivity = 200

        //暗転
        fastFadeInTintOnly(1)

        @label.jump "gameLoop"
    }

    //----------------------------
    //ゲーム処理
    @label.set "gameLoop"
    bl {
        //変数を一括で初期化する
        assignVarUsingDeclared(initHead, initFoot, 0)
        //ピクチャを隠す
        hidePicturesForEach( [ PIC_EPILOGUE, PIC_TEXT ] )
        //初期シーン
        _changeSceneState(SCENE_START)
        //初期状態
        gameTimer = 0
        floor = 1
        //floor = FLOOR_MAX - 1//最終ステージ手前から
        plHealth = HEALTH_MAX
        //BGM
        startBGM("battle_gyokuro_aguneVer", TRUE, 0, 90, 80, 50)
        //----------------------------
        //ループ
        @loop bl {
            @wait(0)

            //----------------------------
            //シーン
            bl {
                //カウンタ
                sceneTimer += 1

                //----------------------------
                //ゲーム中
                @if sceneState == SCENE_GAME bl {
                    @if gameTimer < TIMER_MAX bl {
                        gameTimer += 1
                        //1秒ごとに時間を表示する
                        @if `!(gameTimer % UNIT_FPS) bl {
                            bitOn(triggerFlg, TR_BIT_TIMER_CNT)
                        }
                    }
                    
                    //体力がゼロになるとゲームオーバー
                    @if plHealth <= 0 bl {
                        _changeSceneState(SCENE_DEFEAT)
                    }

                    //最初に表示される文字列を消す
                    @if floorTimer > 0 bl {
                        floorTimer -= 1

                        @if floorTimer <= 0 bl {
                            hidePicture(PIC_TEXT)
                        }
                    }

                    //ゴール判定
                    //敵を全滅させている
                    @if enemyCnt <= 0 bl {
                        //プレイヤーの前方
                        V2_set(cx,
                            (camX + camCos * PLAYER_GOAL_LEN / UNIT_TRI) / UNIT_MAPPOS,
                            (camY + camSin * PLAYER_GOAL_LEN / UNIT_TRI) / UNIT_MAPPOS
                        )

                        //ピクセルを取得する
                        _getPixelFromMap(pix, cx, cy)
                        pix &= 0xff

                        //ゴール
                        @if pix == MAP_COLOR_GOAL bl {
                            _changeSceneState(SCENE_GOAL)
                        }
                    }

                    //メニュー
                    @key.input .dst(input) .cancel
                    @if `input bl {
                        @se.play "Cancel2" .opt(100, 100, 50)

                        @label.set "pause"
                        @msg.choice bl {
                            .cancel(0)
                            .case "\>つづける" bl {
                                @wait(3)
                            }
                            .case "\>\c[2]感度設定\c[0]" bl {
                                @msg.choice bl {
                                    .case "\>100%" {
                                        sensitivity = 100
                                    }
                                    .case "\>200%(デフォルト)" {
                                        sensitivity = 200
                                    }
                                    .case "\>300%" {
                                        sensitivity = 300
                                    }
                                    .case "\>400%" {
                                        sensitivity = 400
                                    }
                                    .cancel {
                                        @se.play "Cancel2" .opt(100, 100, 50)
                                    }
                                }

                                @label.jump "pause"
                            }
                            .case "\>\c[2]クロスヘア表示\c[0]" bl {
                                @msg.choice bl {
                                    .case "\>表示する" {
                                        @pic.move [PIC_CROSSHAIR] .pos(REF_X + SCR_CENTER_X, REF_Y + SCR_CENTER_Y) .center .trans(0) .keepBlend
                                    }
                                    .case "\>表示しない" {
                                        @pic.move [PIC_CROSSHAIR] .pos(REF_X + SCR_CENTER_X, REF_Y + SCR_CENTER_Y) .center .trans(100) .keepBlend
                                    }
                                    .cancel {
                                        @se.play "Cancel2" .opt(100, 100, 50)
                                    }
                                }
                                @label.jump "pause"
                            }
                            .case "\>やめる" bl {
                                @label.jump "gameEnd"
                            }
                        }
                    }

                //----------------------------
                //開始
                } .elif sceneState == SCENE_START bl {

                    @if sceneTimer == 0 bl {
                        //暗転
                        _screenColor(0, 0, 0, 0, 100, 2)
                        //階層表示
                        @pic.strpic [PIC_TEXT] __str("Floor \c[7]\", floor) .pos(REF_SCR_WIDTH, REF_SCR_HEIGHT + 120) .center .scale(100) .bold largeTextPicCmd
                        @pic.move [PIC_TEXT] .relative .pos(0, -120 - 32) .scale(0) .trans(0) .time(2)
                        //HUD更新
                        bitOn(triggerFlg, TR_BIT_TIMER_CNT | TR_BIT_FACE | TR_BIT_MAP | TR_BIT_ENEMY_CNT | TR_BIT_FLOOR_CNT | TR_BIT_HEALTH_CNT )
                        //キャラクタを初期化する
                        _initAllChara()
                        _initAllSprite()
                        //初期化
                        floorTimer = 60
                        enemyNum = 0
                        enemyCnt = 0
                        _changeFaceState(FACE_STATE_NORMAL1, 1)
                        //手の状態
                        state = plPower > 0 ? HAND_STATE_BOTH : HAND_STATE_INIT
                        _changeHandState(state)
                        //ステージ
                        @pic.show [PIC_MAP] .pos(OUT_RANGE, OUT_RANGE) .trans(100) .cell(floor) mapPicCmd
                        //ステージ読み込み
                        @loop MAP_SIZE .dst(sy) bl {
                            @loop MAP_SIZE .dst(sx) bl {
                                //ピクチャをステージデータとして扱う
                                @pic.getInfo [PIC_MAP] .pixel(sx, sy, 1, 1) .dst(pix)
                                //青色成分で分岐する
                                pix &= 0xff
                                //設置するキャラクタのタイプ
                                type  = 0
                                //ノルマの増加数
                                alpha = 0

                                //地形
                                @if `between(pix, 1, 8) bl {
                                    //何もしない
                                    @continue
                                //プレイヤー
                                } .elif `between(pix, 16, 19) bl {
                                    pix -= 16
                                    //向き
                                    camAng = pix * 90 * UNIT_ANG
                                    V2_getCosSin(camCos, camAng, UNIT_ANG, UNIT_TRI)
                                    //位置
                                    V2_mulScalar(camX, sx, UNIT_MAPPOS)
                                    V2_asAddScalar(camX, UNIT_MAPPOS / 2)

                                //アイテム
                                } .elif `between(pix, 24, 26) bl {
                                    pix -= 24
                                    type = CHARA_TYPE_ITEM + pix

                                //敵
                                } .elif `between(pix, 32, 48) bl {
                                    pix -= 32
                                    type = CHARA_TYPE_EN_ZOMBIE + pix
                                    alpha = 1
                                }

                                //キャラクターを設置する
                                @if type > 0 bl {
                                    //空きを探す
                                    _getEmptyCharaPtr(ptrCharaA)
                                    @if ptrCharaA > 0 bl {
                                        //キャラクタを設置する
                                        V2_set(ex,
                                            sx * UNIT_MAPPOS + UNIT_MAPPOS / 2,
                                            sy * UNIT_MAPPOS + UNIT_MAPPOS / 2
                                        )
                                        _setCharaMembers(ptrCharaA, [CHARA_STATE_CREATE, -1, type, 0, 0, CHARA_SCALE_BASE, 0, 0, 0, ex, ey] )
                                        //ノルマをカウント
                                        enemyNum += alpha
                                        enemyCnt += alpha
                                    }
                                }
                            }
                        }
                    }
                    //次のシーンへ移る
                    @if sceneTimer >= 8 bl {
                        _changeSceneState(SCENE_GAME)
                    }

                //----------------------------
                //フロアクリア
                } .elif sceneState == SCENE_GOAL bl {
                    //@waitを使用する

                    //最終ステージだった場合、光る
                    @if floor >= FLOOR_MAX bl {
                        _screenColor(200, 200, 200, 40, 100, 2)
                        @pic.strpic [PIC_TEXT] __str("\c[7]Complete!") .pos(REF_SCR_WIDTH, REF_SCR_HEIGHT - 32) .center .scale(100) .bold largeTextPicCmd
                        @se.play "Flash2" .opt(90, 80, 50)
                        @wait(15)

                    } .else bl {
                        @se.play "Move" .opt(90, 120, 50)
                    }

                    //手を隠す
                    @pic.move [PIC_HAND] .pos(REF_X + HAND_X, REF_Y + HAND_Y + 96)
                    //背景を暗くする
                    @pic.move [PIC_BACK] .relative .pos(0, 0) .scale(0) .trans(0) .rgbs(0, 0, 0, 100)
                    //壁以外のスプライトを透明にする
                    _forEachSprites(ptrSprA, idxA, CHARA_NUM, SPR_ID_CHARA,
                        bl {
                            pid = A_mSprPId
                            hidePicture(pid)
                        } )
                    //壁のピクチャをランダムに下に移動させる
                    _forEachSprites(ptrSprA, idxA, SPRITE_NUM, SPR_ID_WALL,
                        bl {
                            pid = A_mSprPId
                            input = -30 - rnd(0, 10)
                            @pic.move [pid] .relative .pos(0, SCR_HEIGHT) .rgbs(0, 0, 0, 100) .time(input)
                        } )
                    @wait(4)

                    //暗転
                    _screenColor(0, 0, 0, 100, 0, 2)
                    @wait(4)

                    //ピクチャを隠す
                    hidePicture(PIC_TEXT)
                    //背景の色を戻す
                    @pic.move [PIC_BACK] .relative .pos(0, 0) .scale(0) .trans(0) .rgbs(100, 100, 100, 100)

                    //ステージ数が最大だった場合、エピローグに移る
                    @if floor >= FLOOR_MAX bl {
                        input = SCENE_EPILOGUE

                    } .else bl {
                        floor += 1
                        input = SCENE_START
                    }

                    //次のシーンに移る
                    _changeSceneState(input)

                //----------------------------
                //ゲームオーバー
                } .elif sceneState == SCENE_DEFEAT bl {
                    //画面が徐々に赤くなる
                    @if sceneTimer == 0 bl {
                        _screenColor(200, 60, 0, 0, 80, 10)
                    }

                    //視点が下がる
                    $SPEED  = 10
                    $LENGTH = 350
                    @if camZ > -$LENGTH bl {
                        camZ -= $SPEED
                    }

                    //選択肢へ
                    $WAIT = 180
                    @if sceneTimer == $WAIT bl {
                        _changeSceneState(SCENE_CHOICE)
                    }

                //----------------------------
                //エピローグ
                } .elif sceneState == SCENE_EPILOGUE bl {
                    //入力も表示もしないのでwaitを使う

                    //ハイスコアを更新する
                    _updateHighScore()

                    //実績
                    checkSetAchievement(achievedAguga, gameTimer <= ACHIEVE_TIME)

                    //一枚絵で暗転させる
                    @pic.show [PIC_EPILOGUE] .pos(REF_X, REF_Y) .topLeft .rgbs(0, 0, 0, 100) epiloguePicCmd
                    @wait(10)

                    //BGM
                    startBGM("PHRASE_6", FALSE, 0, 100, 100, 50)
                    
                    @pic.move [PIC_EPILOGUE] .relative .pos(0, 0) .scale(0) .rgbs(100, 100, 100, 100) .time(2)
                    @wait(10)
                    @pic.move [PIC_EPILOGUE] .relative .pos(0, 0) .scale(0) .rgbs(50, 50, 50, 100) .time(4)
                    @wait(5)
                    //エピローグをスライドさせる
                    $SLIDE = -320
                    @pic.strpic [PIC_TEXT] EPILOGUE_MESSAGE .pos(REF_X + 8, REF_Y + SCR_HEIGHT) .topLeft smallTextPicCmd
                    @pic.move [PIC_TEXT] .relative .pos(0, $SLIDE) .scale(0) .trans(0) .time(150)

                    //ボタン入力で待ち時間を省略できる
                    $WAIT = 960//16秒
                    @loop $WAIT bl {
                        @wait(0)
                        getAnyKey(input, FALSE)
                        @if `input bl {
                            @break
                        }
                    }

                    //選択肢へ移る
                    _changeSceneState(SCENE_CHOICE)

                //----------------------------
                //選択肢
                } .elif sceneState == SCENE_CHOICE bl {
                    replayProcess("gameLoop", "gameEnd")
                }
            }

            //----------------------------
            //ゲームの状態を更新する
            @if `CHK_UPDATE_CHARA bl {

                //----------------------------
                //プレイヤーを更新する
                bl {
                    //----------------------------
                    //入力を取得する
                    //ax:移動方向 theta:旋回 alpha:射撃スイッチ gamma:煙草
                    V2_set(ax, 0, 0)
                    theta = 0
                    alpha = 0
                    gamma = 0

                    //キーボード操作
                    @if gameMode == CTRL_TYPE_KEY bl {
                        //矢印キーで移動
                        V2_getInput(sx)
                        //Zで射撃
                        @key.input .dst(alpha) .decision
                        //SHIFTで平行移動
                        @key.input .dst(beta) .shift
                        //左クリックで煙草
                        @key.input .dst(gamma) .lclick
                        //前後移動
                        @if `sy bl {
                            ay = -1 * sy * PLAYER_SPEED
                        }

                        @if `sx bl {
                            //横移動
                            @if `beta bl {
                                ax = sx * PLAYER_SPEED
                            //左右旋回
                            } .else bl {
                                theta = sx * sensitivity
                            }

                        }

                    //マウス操作
                    } .else bl {
                        //カーソル移動量
                        @mouse.getPos(beta, 0)
                        beta -= WINDOW_WIDTH / 2
                        //カーソル位置を拘束する
                        @mouse.setPos(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2)
                        //矢印キーで移動
                        V2_getInput(sx)
                        //左クリックで射撃
                        @key.input .dst(alpha) .lclick
                        //Shiftで煙草
                        @key.input .dst(gamma) .shift
                        //前後移動
                        @if `sy bl {
                            ay = -1 * sy * PLAYER_SPEED
                        }

                        //横移動
                        @if `sx bl {
                            ax = sx * PLAYER_SPEED
                        }

                        //旋回
                        //ブレを防ぐ為、最初のフレームのみ入力を受け付けない
                        @if `beta && sceneTimer > 0 bl {
                            theta = beta * sensitivity / 10
                        }
                    }

                    //----------------------------
                    //移動する
                    @if `ax || ay || theta bl {
                        //左右旋回
                        @if `theta bl {
                            //旋回速度に制限を設ける
                            theta = clamp(theta, -PLAYER_MAX_ROTATE, PLAYER_MAX_ROTATE)
                            camAng = (camAng + theta + ROUND_ANGLE) % ROUND_ANGLE
                            V2_getCosSin(camCos, camAng, UNIT_ANG, UNIT_TRI)
                        }

                        //移動量
                        V2_set(vx, 0, 0)
                        //90度回す
                        V2_set(bx, -camSin, camCos)
                        //左右移動
                        @if `ax bl {
                            V2_asAddMuldiv(vx, bx, ax, UNIT_TRI)
                        }
                        //前後移動
                        @if `ay bl {
                            V2_asAddMuldiv(vx, camCos, ay, UNIT_TRI)
                        }
                        //移動量を拘束する
                        V2_clampMag(vx, PLAYER_SPEED)
                        //移動と衝突判定
                        @if `vx || vy bl {
                            //移動後の座標
                            V2_add(ex, camX, vx)
                            //移動方向
                            V2_set(sigX,
                                vx > 0 ? 1 : -1,
                                vy > 0 ? 1 : -1
                            )
                            //4つの隅の内、2か所のピクセルを調べる
                            //X軸について調べた後、Y軸について調べる
                            @loop 4 .dst(idxA) bl {
                                //ループごとに判定座標が変わる
                                V2_set(cx,
                                    ((idxA <= 1 ? (sigX) : (idxA % 2 * 2 - 1)) * PLAYER_RADIUS + ex) / UNIT_MAPPOS,
                                    ((idxA >  1 ? (sigY) : (idxA % 2 * 2 - 1)) * PLAYER_RADIUS + (idxA <= 1 ? (camY) : (ey))) / UNIT_MAPPOS
                                )
                                //ピクセルを取得する
                                _checkCollFromMap(pix, cx, cy)
                                //壁と衝突している
                                @if `pix bl {
                                    //移動後の位置とマップタイルの中央を比較して、修正方向を決める
                                    @if `idxA <= 1  bl {
                                        ex = (ex - (cx * UNIT_MAPPOS + UNIT_MAPPOS / 2)) < 0 ? (cx * UNIT_MAPPOS - PLAYER_RADIUS - 1) : ((cx + 1) * UNIT_MAPPOS + PLAYER_RADIUS + 1)
                                    } .else bl {
                                        ey = (ey - (cy * UNIT_MAPPOS + UNIT_MAPPOS / 2)) < 0 ? (cy * UNIT_MAPPOS - PLAYER_RADIUS - 1) : ((cy + 1) * UNIT_MAPPOS + PLAYER_RADIUS + 1)
                                    }
                                }
                            }
                            //エラー防止の為、移動後の座標を拘束する
                            $A = UNIT_MAPPOS * MAP_SIZE 
                            V2_clampPointInsideRect2(ex, 0, 0, $A, $A )
                            //移動後の座標を適用する
                            V2_copy(camX, ex)
                        }
                    }

                    //----------------------------
                    //射撃
                    @if handState != HAND_STATE_SMOKE bl {
                        //煙草
                        @if `gamma bl {
                            _changeHandState(HAND_STATE_SMOKE)
                        }

                        //弾が存在しない時に撃てる
                        _getCharaPtr(ptrCharaA, 0)
                        @if `alpha && A_mChType == CHARA_TYPE_NONE bl {
                            //弾の位置
                            V2_set(ex,
                                camX + camCos * 4 * UNIT_POS / UNIT_TRI,
                                camY + camSin * 4 * UNIT_POS / UNIT_TRI
                            )
                            //強化弾
                            @if plPower > 0 bl {
                                _setCharaMembers(ptrCharaA, [CHARA_STATE_CREATE, -1, CHARA_TYPE_PL_ATK_STRONG, 1, 0, CHARA_SCALE_BASE / 2, 0, camAng, PLAYER_SHOOT_VEL, ex, ey] )
                                _changeHandState(HAND_STATE_BOTH_SHOOT)
                                plPower = 0

                                @se.play "Fire3" .opt(100, 100, 50)

                            //通常弾
                            } .else bl {
                                _setCharaMembers(ptrCharaA, [CHARA_STATE_CREATE, -1, CHARA_TYPE_PL_ATK_NORMAL, 1, 0, CHARA_SCALE_BASE / 3, 0, camAng, PLAYER_SHOOT_VEL, ex, ey] )

                                //手をかざす
                                @if handState == HAND_STATE_SHOOT bl {
                                    handTimer = 1

                                } .else bl {
                                    _changeHandState(HAND_STATE_SHOOT)


                                }

                                @se.play "Fire3" .opt(60, 150, 50)
                            }
                        }
                    }
                }

                //----------------------------
                //キャラクターを更新する
                @loop CHARA_NUM .dst(idxA) bl {
                    //ポインタ
                    _getCharaPtr(ptrCharaA, idxA)
                    //状態
                    state = A_mChState
                    //存在しない
                    @if state == CHARA_STATE_NONE bl {
                        @continue
                    }
                    //消去予定
                    @if state == CHARA_STATE_DELETE bl {
                        //スプライト
                        _getSprPtrFromChId(ptrSprA, idxA)
                        //ピクチャID
                        pid = A_mSprPId
                        //ピクチャを非表示にする
                        @pic.show [pid] .pos(OUT_RANGE, OUT_RANGE) .center .cell(0) charaPicCmd
                        //スプライトは画面奥に持っていく
                        A_mSprDepth = SCR_MAX_DEPTH
                        //キャラクタの変数を初期化
                        _initCharaMembers( ptrCharaA )

                        @continue
                    }

                    //カウンタ
                    A_mChTimer += 1

                    //一時変数
                    timer = A_mChTimer
                    type  = A_mChType

                    //長すぎるのでラベルを使ってみる
                    //アイテム
                    @if `between(type, CHARA_TYPE_ITEM, CHARA_TYPE_ITEM + ITEM_TYPE_NUM - 1) bl {
                        @label.jump "updateItem"
                    //弾
                    } .elif `between(type, CHARA_TYPE_PL_ATK_NORMAL, CHARA_TYPE_PL_ATK_NORMAL + ATK_TYPE_NUM - 1) bl {
                        @label.jump "updateAttack"
                    //敵
                    } .elif `between(type, CHARA_TYPE_EN_ZOMBIE, CHARA_TYPE_EN_ZOMBIE + ENEMY_TYPE_NUM - 1) bl {
                        @label.jump "updateEnemy"
                    //例外
                    } .else bl {
                        @continue
                    }

                    //----------------------------
                    //アイテム
                    @label.set "updateItem"
                    bl {
                        //----------------------------
                        //アイテムの共通処理

                        //衝突フラグ
                        hit = 0

                        //----------------------------
                        //プレイヤーとの衝突判定
                        V2_set(vx,
                            camX - A_mChX,
                            camY - A_mChY
                        )

                        ex = ITEM_HIT_RADIUS + PLAYER_HIT_RADIUS
                        @if `abs(vx) < ex && abs(vy) < ex && vx * vx + vy * vy < ex * ex bl {
                            hit = 1

                        }

                        //種類ごとの処理
                        //----------------------------
                        //パワーアップ+回復
                        @if type == CHARA_TYPE_ITEM bl {
                            @if state == CHARA_STATE_ENABLE bl {
                                $CELL = 8
                                $ATTACK = 30

                                //取得時
                                @if `hit bl {
                                    //消去する
                                    _changeCharaState(ptrCharaA, CHARA_STATE_DELETE)
                                    //パワーアップ
                                    @if plPower <= 0 bl {
                                        plPower = 1
                                        bitOn(triggerFlg, TR_BIT_FACE)
                                        _changeFaceState(FACE_STATE_POWERUP, 180)
                                        _changeHandState(HAND_STATE_BOTH)
                                    }
                                    //回復
                                    @if `plHealth < HEALTH_MAX bl {
                                        plDamage += $ATTACK
                                    }
                                    //画面を光らせる
                                    _screenColor(150, 200, 150, 50, 100, 4)
                                    @se.play "Buff" .opt(100, 100, 50)
                                }
                            //初期化
                            } .elif state == CHARA_STATE_CREATE bl {
                                A_mChCell = $CELL
                                A_mChScale = CHARA_SCALE_BASE
                                _changeCharaState(ptrCharaA, ITEM_STATE_ENABLE)
                            }
                        }
                    }
                    @continue

                    //----------------------------
                    //弾
                    //威力、大きさ、角度、速度は発射する側で決める
                    //param1 : 角度  param2 : 速度
                    @label.set "updateAttack"
                    bl {
                        //----------------------------
                        //弾の共通処理
                        //角度
                        delta = A_mChParam_1
                        //速度
                        alpha = A_mChParam_2
                        //攻撃力
                        beta = A_mChPoint
                        //衝突(1:地形 2:キャラクタ)
                        hit = 0

                        //生成直後ではない
                        @if `!between(state, CHARA_STATE_NONE, CHARA_STATE_CREATE) bl {
                            //前進する
                            @if `alpha bl {
                                //三角関数
                                V2_getCosSin(rayCos, delta, UNIT_ANG, UNIT_TRI)
                                //地形との衝突判定
                                //少し進めた先で行う
                                V2_set(cx,
                                    (A_mChX + rayCos * 4 * UNIT_POS / UNIT_TRI) / UNIT_MAPPOS,
                                    (A_mChY + raySin * 4 * UNIT_POS / UNIT_TRI) / UNIT_MAPPOS
                                )
                                _checkCollFromMap(pix, cx, cy)
                                //衝突
                                @if `pix bl {
                                    hit = 1

                                //前進
                                } .else bl {
                                    V2_muldiv(vx, rayCos, alpha, UNIT_TRI)
                                    A_mChX += vx
                                    A_mChY += vy
                                }
                            }

                            //衝突判定
                            //攻撃力がある
                            @if `beta bl {
                                //敵との衝突判定
                                @if `between(A_mChType, CHARA_TYPE_PL_ATK_NORMAL, CHARA_TYPE_PL_ATK_TOBACCO) bl {
                                    @loop CHARA_NUM .dst(idxB) bl {
                                        //敵キャラクタのポインタ
                                        _getCharaPtr(ptrCharaB, idxB)
                                        //敵でないか、存在しないか、体力が無いか
                                        @if `!between(B_mChType, CHARA_TYPE_EN_ZOMBIE, CHARA_TYPE_EN_ZOMBIE + ENEMY_TYPE_NUM - 1) ||
                                            between(B_mChType, CHARA_TYPE_NONE, CHARA_STATE_CREATE) ||
                                            B_mChPoint <= 0 bl {
                                            @continue

                                        }
                                        //衝突判定
                                        V2_set(vx,
                                            A_mChX - B_mChX,
                                            A_mChY - B_mChY
                                        )

                                        //距離
                                        ex = sqrt(vx * vx + vy * vy, 1)
                                        //相手の半径は拡大率によって変わる
                                        ey = (A_mChScale + B_mChScale) * CHARA_HIT_RADIUS / CHARA_SCALE_BASE

                                        @if `abs(vx) < ey && abs(vy) < ey && ex <= ey bl {
                                            //衝突フラグ
                                            hit = 2
                                            //弾の体力が攻撃力となる
                                            B_mChPoint -= beta
                                            //撃破
                                            @if `B_mChPoint <= 0 bl {
                                                //撃破モーション
                                                _changeCharaState(ptrCharaB, ENEMY_STATE_DOWN)

                                                //敵が減り切るとマップが表示され、ゴールできるようになる
                                                bitOn(triggerFlg, TR_BIT_ENEMY_CNT)
                                                enemyCnt -= 1

                                                @if enemyCnt == 0 bl {
                                                    bitOn(triggerFlg, TR_BIT_MAP)
                                                    _screenColor(200, 200, 200, 50, 100, 4)
                                                    @se.play "Recovery8" .opt(100, 100, 50)
                                                }
                                            } .else bl {
                                                //待機状態のときは起動する
                                                @if `B_mChState == ENEMY_STATE_WAIT bl {
                                                    _changeCharaState(ptrCharaB, ENEMY_STATE_ENABLE)
                                                }
                                            }
                                        }
                                    }
                                //プレイヤーとの衝突判定
                                } .elif invincibleSwitch.isOff bl {
                                    //衝突判定
                                    V2_set(vx,
                                        A_mChX - camX,
                                        A_mChY - camY
                                    )
                                    ex = sqrt(vx * vx + vy * vy, 1)
                                    ey = (CHARA_SCALE_BASE * PLAYER_HIT_RADIUS + A_mChScale * CHARA_HIT_RADIUS) / CHARA_SCALE_BASE

                                    @if `abs(vx) < ey && abs(vy) < ey && ex <= ey bl {
                                        //衝突フラグ
                                        hit = 2
                                        //ダメージ蓄積
                                        plDamage -= beta
                                    }
                                }
                            }
                        }

                        //----------------------------
                        //プレイヤーの弱攻撃
                        @if type == CHARA_TYPE_PL_ATK_NORMAL bl {
                            $CELL = 1

                            //飛翔中
                            @if state == ATK_STATE_ENABLE bl {
                                //回転する
                                A_mChAngle = (A_mChAngle - 20 * UNIT_ANG + ROUND_ANGLE) % ROUND_ANGLE
                                //命中
                                @if `hit bl {
                                    A_mChPoint = 0
                                    _changeCharaState(ptrCharaA, ATK_STATE_HIT)
                                //寿命
                                } .elif timer > 120 bl {
                                    _changeCharaState(ptrCharaA, CHARA_STATE_DELETE)
                                }

                            //命中
                            } .elif state == ATK_STATE_HIT bl {
                                //少しずつ大きくなる
                                A_mChScale += 4
                                //最初のフレーム
                                //命中すると攻撃判定が消え、少し画面手前に移動する
                                @if timer == 0 bl {
                                    A_mChCell = $CELL + 2
                                    A_mChScale = CHARA_SCALE_BASE / 2
                                    A_mChParam_2 = 0
                                    A_mChX += muldiv(camCos, -4 * UNIT_POS, UNIT_TRI)
                                    A_mChY += muldiv(camSin, -4 * UNIT_POS, UNIT_TRI)
                                    @se.play "Fire3" .opt(70, 120, 50)
                                }

                                //消える
                                @if timer > 4 bl {
                                    _changeCharaState(ptrCharaA, CHARA_STATE_DELETE)
                                }

                            //初期化
                            } .elif state == CHARA_STATE_CREATE bl {
                                A_mChCell  = $CELL
                                _changeCharaState(ptrCharaA, ATK_STATE_ENABLE)
                            }

                        //----------------------------
                        //プレイヤーの強攻撃
                        } .elif type == CHARA_TYPE_PL_ATK_STRONG bl {
                            $CELL = 2
                            @if state == ATK_STATE_ENABLE bl {
                                //命中
                                @if `hit bl {
                                    _changeCharaState(ptrCharaA, ATK_STATE_HIT)
                                //寿命
                                } .elif timer > 120 bl {
                                    _changeCharaState(ptrCharaA, CHARA_STATE_DELETE)
                                }

                            //命中時の演出          
                            } .elif state == ATK_STATE_HIT bl {
                                //回転する
                                A_mChAngle = (A_mChAngle + 30 * UNIT_ANG + ROUND_ANGLE) % ROUND_ANGLE
                                //少しずつ縮小する
                                A_mChScale -= 1
                                //当たると爆発する
                                @if timer == 0 bl {
                                    A_mChScale = CHARA_SCALE_BASE * 3
                                    A_mChParam_2 = UNIT_POS / 2
                                    _screenColor(255, 64, 0, 50, 100, 4)
                                    @se.play "explo1" .opt(100, 80, 50)
                                }

                                //数フレーム攻撃判定が持続する
                                @if timer == 6 bl {
                                    A_mChPoint = 0
                                }

                                //消滅
                                @if timer > 30 bl {
                                    _changeCharaState(ptrCharaA, CHARA_STATE_DELETE)
                                }

                            //初期化
                            } .elif state == CHARA_STATE_CREATE bl {
                                A_mChCell = $CELL
                                _changeCharaState(ptrCharaA, ATK_STATE_ENABLE)
                            }

                        //----------------------------
                        //プレイヤーの煙草の煙
                        } .elif type == CHARA_TYPE_PL_ATK_SMOKE bl {
                            $CELL = 6

                            @if state == ATK_STATE_ENABLE bl {
                                //少しずつ大きくなる
                                A_mChScale += timer % 8 ? 0 : 1

                                @if timer > 32 bl {
                                    _changeCharaState(ptrCharaA, CHARA_STATE_DELETE)
                                }

                            //初期化
                            } .elif state == CHARA_STATE_CREATE bl {
                                A_mChCell = $CELL
                                _changeCharaState(ptrCharaA, ATK_STATE_ENABLE)
                            }

                        //----------------------------
                        //プレイヤーの煙草
                        } .elif type == CHARA_TYPE_PL_ATK_TOBACCO bl {
                            $CELL = 7

                            @if state == ATK_STATE_ENABLE bl {
                                //回転する
                                A_mChAngle = (A_mChAngle - 10 * UNIT_ANG + ROUND_ANGLE) % ROUND_ANGLE
                                //命中
                                @if `hit bl {
                                    _changeCharaState(ptrCharaA, CHARA_STATE_DELETE)
                                    @se.play "Fire3" .opt(60, 130, 50)
                                //寿命
                                } .elif timer > 60 bl {
                                    _changeCharaState(ptrCharaA, CHARA_STATE_DELETE)
                                }

                            //初期化
                            } .elif state == CHARA_STATE_CREATE bl {
                                A_mChCell = $CELL
                                _changeCharaState(ptrCharaA, ATK_STATE_ENABLE)
                            }

                        //----------------------------
                        //敵の弱攻撃弾
                        } .elif type == CHARA_TYPE_EN_ATK_NORMAL bl {
                            $CELL = 4

                            @if state == ATK_STATE_ENABLE bl {
                                //命中
                                @if `hit bl {
                                    _changeCharaState(ptrCharaA, CHARA_STATE_DELETE)
                                //寿命
                                } .elif timer > 60 bl {
                                    _changeCharaState(ptrCharaA, CHARA_STATE_DELETE)
                                }

                            //初期化
                            } .elif state == CHARA_STATE_CREATE bl {
                                A_mChCell  = $CELL
                                _changeCharaState(ptrCharaA, ATK_STATE_ENABLE)
                            }

                        //----------------------------
                        //敵のアイアンクロス手裏剣
                        } .elif type == CHARA_TYPE_EN_ATK_CROSS bl {
                            $CELL = 5

                            @if state == ATK_STATE_ENABLE bl {
                                //回転する
                                A_mChAngle = (A_mChAngle - 10 * UNIT_ANG + ROUND_ANGLE) % ROUND_ANGLE
                                //命中
                                @if `hit bl {
                                    _changeCharaState(ptrCharaA, CHARA_STATE_DELETE)
                                //寿命
                                } .elif timer > 60 bl {
                                    _changeCharaState(ptrCharaA, CHARA_STATE_DELETE)
                                }

                            //初期化
                            } .elif state == CHARA_STATE_CREATE bl {
                                A_mChCell = $CELL
                                _changeCharaState(ptrCharaA, ATK_STATE_ENABLE)
                            }
                        }
                    }
                    @continue

                    //----------------------------
                    //敵
                    //param1 : 角度  param2 : 速度
                    @label.set "updateEnemy"
                    bl {
                        //----------------------------
                        //メタ関数

                        //敵の初期パラメータを設定する
                        __fn _setEnemyParamater $ptr $point $scale $cell bl {
                            v[MC_POINT + $ptr] = $point
                            v[MC_SCALE + $ptr] = $scale
                            v[MC_CELL + $ptr]  = $cell
                        }

                        //敵を移動させる
                        __fn _moveEnemy $ptr $addAng $speed bl {
                            ftA = v[$ptr + MC_PARAM_1] + $addAng
                            v[__id(vx)..__id(vx) + 1] = [ cos(ftA, UNIT_ANG, $speed), sin(ftA, UNIT_ANG, $speed) ]
                        }

                        //射撃を予約する
                        __fn _setAttackParamater $type $point $scale $angle $speed bl {
                            v[__id(atkType)..__id(atkSpeed)] = [$type, $point, $scale, $angle, $speed]
                        }

                        //----------------------------
                        //視線フラグ(-1 : 判定なし 0:プレイヤー 1:壁 2:範囲外)
                        hit = VISION_NONE
                        //直前の座標
                        V2_set(sx, A_mChX, A_mChY)
                        //移動量
                        V2_set(vx, 0, 0)
                        //プレイヤーとの距離
                        V2_sub(ax, camX, sx)//axは後に使用しない
                        alpha = sqrt(ax * ax + ay * ay, 1)
                        //プレイヤーがいる方向
                        delta = alpha > 0 ? atan2(ay, ax, UNIT_ANG) : 0
                        //射撃予約
                        atkType = 0

                        //---------------------------
                        //共通処理1
                        //定期的に視線判定を行う
                        //壁に使うレイキャスティングよりも精度が荒い
                        //角で止まられると不都合なので、こっちの方がいい
                        @if `!(timer % ENEMY_VISION_INT) bl {
                            //描画の範囲外ならば判定はしない
                            @if alpha >= SCR_MAX_DEPTH bl {
                                hit = VISION_OUTRANGE

                            } .else bl {
                                hit = VISION_PLAYER
                                //8ドットずつ
                                ay = alpha / (8 * UNIT_POS)
                                @loop ay .dst(ax) bl {
                                    //自身からプレイヤーへ
                                    V2_lerp(cx, sx, camX, ax + 1, ay + 1)
                                    V2_asDivScalar(cx, UNIT_MAPPOS)
                                    _checkCollFromMap(pix, cx, cy)
                                    @if `pix bl {
                                        hit = VISION_WALL
                                        @break
                                    }
                                }
                            }
                        }

                        //待機
                        @if state == ENEMY_STATE_WAIT bl {
                            //プレイヤーと自身の合間に壁が無い時、起動する
                            @if `hit == VISION_PLAYER bl {
                                _changeCharaState(ptrCharaA, ENEMY_STATE_ENABLE)
                                @se.play "Shot2" .opt(50, 150, 50)
                            }

                        //活動中で、プレイヤーを見失った状態で一定時間経つと待機状態に移る
                         } .elif state == ENEMY_STATE_ENABLE bl {
                            @if `timer >= ENEMY_GIVEUP_INT && (hit == VISION_WALL || hit == VISION_OUTRANGE) bl {
                                _changeCharaState(ptrCharaA, ENEMY_STATE_WAIT)
                            }
                        }

                        //----------------------------
                        //悪魔兵
                        //距離を保つように動き、一発だけ速い弾を放つ。
                        //param1 : 移動方向
                        @if type == CHARA_TYPE_EN_ZOMBIE bl {
                            $CELL = 9
                            $HP = 3
                            $ATTACK = 8

                            //通常状態
                            @if state == ENEMY_STATE_ENABLE bl {
                                //歩行アニメーション
                                A_mChCell = (timer % 12 <= 6) ? ($CELL + 0) : ($CELL + 1)
                                //ランダムにずらす
                                @if timer == 0 bl {
                                    A_mChTimer = rnd(0, 4) * 20
                                }
                                //射撃
                                @if `timer > 150 && hit == VISION_PLAYER bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_ATTACK)
                                }
                                //角度を変える
                                @if `!(timer % 60) bl {
                                    //真っ直ぐ近づき、ある程度近いと横に動く
                                    $LENGTH = 30
                                    $ANGLE = 30
                                    @if `alpha < $LENGTH * UNIT_POS bl {
                                        theta = rnd(0, 1) * 2 - 1
                                        A_mChParam_1 = delta + 90 * theta * UNIT_ANG

                                    } .else bl {
                                        A_mChParam_1 = delta + rnd(-1, 1) * $ANGLE * UNIT_ANG
                                    }
                                }
                                _moveEnemy(ptrCharaA, 0, UNIT_POS / 6)

                            //攻撃
                            } .elif state == ENEMY_STATE_ATTACK bl {
                                //構える
                                A_mChCell = $CELL + 2

                                //射撃
                                @if timer == 20 bl {
                                    //少しブレる
                                    theta = delta + rnd(-5, 5) * UNIT_ANG
                                    _setAttackParamater(CHARA_TYPE_EN_ATK_NORMAL, $ATTACK, CHARA_SCALE_BASE / 3, theta, 4 * UNIT_POS )
                                    @se.play "Bow1" .opt(80, 80, 50)
                                }

                                @if timer >= 60 bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_ENABLE)
                                }

                            //待機
                            } .elif state == ENEMY_STATE_WAIT bl {
                                @if timer == 0 bl {
                                    A_mChCell = $CELL + 0
                                }

                            //死亡
                            } .elif state == ENEMY_STATE_DOWN bl {
                                //死亡アニメーション
                                A_mChCell = (timer < 12) ? ($CELL + 3) : ($CELL + 4)
                                //うめき声
                                @if timer == 0 bl {
                                    @se.play "voice_boy6" .opt(80, 50, 50)
                                }

                                @if timer >= 24 bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_DEAD)
                                }

                            //登場直後
                            } .elif state == CHARA_STATE_CREATE bl {
                                _setEnemyParamater(ptrCharaA, $HP, CHARA_SCALE_BASE, $CELL)
                                _changeCharaState(ptrCharaA, ENEMY_STATE_WAIT)
                            }

                        //----------------------------
                        //熊
                        //体力を多く持ち、ジグザクに動き、弾を二発放つ。
                        //param1 : 移動方向
                        } .elif type == CHARA_TYPE_EN_BEAR bl {
                            $CELL = 14
                            $HP = 9
                            $ATTACK = 10

                            //通常状態
                            @if state == ENEMY_STATE_ENABLE bl {
                                //歩行アニメーション
                                A_mChCell = (timer % 12 <= 6) ? ($CELL + 0) : ($CELL + 1)
                                //ランダムにずらす
                                @if timer == 0 bl {
                                    A_mChTimer = rnd(0, 2) * 20
                                }
                                //射撃
                                //近づきすぎても反応する
                                @if `(timer > 120 || (alpha <= 20 * UNIT_POS && timer > 30)) && hit == VISION_PLAYER bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_ATTACK)
                                }
                                @if `!(timer % 80) bl {
                                    $LENGTH = 25
                                    $ANGLE = 20
                                    @if `alpha < $LENGTH * UNIT_POS bl {
                                        theta = rnd(0, 1) * 2 - 1
                                        A_mChParam_1 = delta + 90 * theta * UNIT_ANG
                                    } .else bl {
                                        A_mChParam_1 = delta + rnd(-1, 1) * $ANGLE * UNIT_ANG
                                    }
                                }

                                _moveEnemy(ptrCharaA, 0, UNIT_POS / 3)

                            //攻撃
                            } .elif state == ENEMY_STATE_ATTACK bl {
                                A_mChCell = $CELL + 2

                                //二つに分かれる
                                @if timer == 30 bl {
                                    _setAttackParamater(CHARA_TYPE_EN_ATK_NORMAL, $ATTACK, CHARA_SCALE_BASE / 2, delta - 10 * UNIT_ANG, 2 * UNIT_POS )
                                    @se.play "Slash9" .opt(70, 120, 50)
                                }

                                @if timer == 32 bl {
                                    _setAttackParamater(CHARA_TYPE_EN_ATK_NORMAL, $ATTACK, CHARA_SCALE_BASE / 2, delta + 10 * UNIT_ANG, 2 * UNIT_POS )
                                }

                                @if timer >= 60 bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_ENABLE)
                                }

                            //待機
                            } .elif state == ENEMY_STATE_WAIT bl {
                                @if timer == 0 bl {
                                    A_mChCell = $CELL + 0
                                }

                            //死亡
                            } .elif state == ENEMY_STATE_DOWN bl {
                                A_mChCell = (timer < 12) ? ($CELL + 3) : ($CELL + 4)

                                @if timer == 0 bl {
                                    @se.play "voice_aa" .opt(80, 50, 50)
                                }

                                @if timer >= 24 bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_DEAD)
                                }

                            //登場直後
                            } .elif state == CHARA_STATE_CREATE bl {
                                _setEnemyParamater(ptrCharaA, $HP, CHARA_SCALE_BASE, $CELL)
                                _changeCharaState(ptrCharaA, ENEMY_STATE_WAIT)
                            }

                        //----------------------------
                        //植物
                        //その場から動かす、見つかると連射する
                        //param1 : 移動方向
                        } .elif type == CHARA_TYPE_EN_PLANT bl {
                            $CELL = 19
                            $HP = 6
                            $ATTACK = 6

                            //通常状態
                            @if state == ENEMY_STATE_ENABLE bl {
                                //起動アニメーション
                                A_mChCell = (timer < 16) ? ($CELL + 0) : ($CELL + 1)
                                //射撃
                                @if `timer > 30 && hit == VISION_PLAYER bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_ATTACK)
                                }

                            //攻撃
                            } .elif state == ENEMY_STATE_ATTACK bl {
                                A_mChCell = $CELL + 2

                                @if `timer >= 14 && !(timer % 14) bl {
                                    _setAttackParamater(CHARA_TYPE_EN_ATK_NORMAL, $ATTACK, CHARA_SCALE_BASE / 4, delta, 3 * UNIT_POS )
                                    @se.play "Bow1" .opt(80, 120, 50)
                                }

                                //見失うと待機状態に移る
                                @if `timer >= 32 && (hit == VISION_WALL || hit == VISION_OUTRANGE) bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_WAIT)
                                }

                            //死亡
                            } .elif state == ENEMY_STATE_DOWN bl {
                                A_mChCell = (timer < 12) ? ($CELL + 3) : ($CELL + 4)

                                @if timer == 0 bl {
                                    @se.play "voice_soiya" .opt(80, 60, 50)
                                }

                                @if timer >= 24 bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_DEAD)
                                }

                            //待機
                            } .elif state == ENEMY_STATE_WAIT bl {
                                @if timer == 0 bl {
                                    A_mChCell = $CELL + 0
                                }

                            //登場直後
                            } .elif state == CHARA_STATE_CREATE bl {
                                _setEnemyParamater(ptrCharaA, $HP, CHARA_SCALE_BASE, $CELL)
                                _changeCharaState(ptrCharaA, ENEMY_STATE_WAIT)
                            }

                        //----------------------------
                        //昆虫
                        //往復しながら近づき、一発撃ちながら下がる。攻撃力が高い。
                        //param1 : 移動方向
                        } .elif type == CHARA_TYPE_EN_BEETLE bl {
                            $CELL = 24
                            $HP = 4
                            $ATTACK = 15

                            //通常状態
                            @if state == ENEMY_STATE_ENABLE bl {
                                //歩行アニメーション
                                A_mChCell = (timer % 16 < 8) ? ($CELL + 0) : ($CELL + 1)

                                //蛇行しながら接近する
                                A_mChParam_1 = delta + sin( timer * 5, 1, 80 * UNIT_ANG )
                                _moveEnemy(ptrCharaA, 0, UNIT_POS / 2)

                                //タイマーをずらす
                                @if timer == 0 bl {
                                    A_mChTimer = rnd(0, 4) * 20
                                }

                                //射撃
                                @if `timer > 30 && alpha < 20 * UNIT_POS && hit == VISION_PLAYER bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_ATTACK)
                                }

                            //攻撃
                            } .elif state == ENEMY_STATE_ATTACK bl {
                                //方向を記録する
                                @if timer == 0 bl {
                                    A_mChParam_1 = delta + 180 * UNIT_ANG
                                    A_mChCell = $CELL + 2

                                    _setAttackParamater(CHARA_TYPE_EN_ATK_NORMAL, $ATTACK, CHARA_SCALE_BASE / 4, delta, 3 * UNIT_POS )
                                    @se.play "Slash9" .opt(60, 140, 50)
                                }

                                @if `timer >= 60 bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_WAIT)
                                }

                                //ゆっくりと下がる
                                _moveEnemy(ptrCharaA, 0, UNIT_POS / 5)

                            //待機
                            } .elif state == ENEMY_STATE_WAIT bl {
                                @if timer == 0 bl {
                                    A_mChCell = $CELL + 0
                                }

                            //死亡
                            } .elif state == ENEMY_STATE_DOWN bl {
                                A_mChCell = (timer < 12) ? ($CELL + 3) : ($CELL + 4)

                                @if timer == 0 bl {
                                    @se.play "voice_aa" .opt(80, 130, 50)
                                }

                                @if timer >= 24 bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_DEAD)
                                }

                            //登場直後
                            } .elif state == CHARA_STATE_CREATE bl {
                                _setEnemyParamater(ptrCharaA, $HP, CHARA_SCALE_BASE, $CELL)
                                _changeCharaState(ptrCharaA, ENEMY_STATE_WAIT)
                            }

                        //----------------------------
                        //怒り
                        //見つけると動きながら連射する。隠れてしばらくすると呪文を唱えて他の敵を蘇らせる
                        //param1 : 移動方向  param2 : 呪文カウンタ
                        } .elif type == CHARA_TYPE_EN_FURY bl {
                            $CELL = 29
                            $HP = 64
                            $ATTACK = 5

                            //通常状態
                            @if state == ENEMY_STATE_ENABLE bl {
                                //歩行アニメーション
                                A_mChCell = (timer % 12 <= 6) ? ($CELL + 0) : ($CELL + 1)
                                //呪文カウンタ
                                A_mChParam_2 += 1
                                //射撃
                                //近すぎても反応する
                                @if `(timer > 120 || (alpha <= 32 * UNIT_POS && timer > 30)) && hit == VISION_PLAYER bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_ATTACK)
                                }
                                //接近する
                                $ANGLE = 60
                                @if `!(timer % 60) bl {
                                    A_mChParam_1 = delta + rnd(-1, 1) * $ANGLE * UNIT_ANG
                                }

                                _moveEnemy(ptrCharaA, 0, UNIT_POS / 4)

                            //攻撃
                            } .elif state == ENEMY_STATE_ATTACK bl {
                                //歩行アニメーション
                                A_mChCell = (timer % 20 <= 10) ? ($CELL + 2) : ($CELL + 3)
                                //呪文カウンタ
                                A_mChParam_2 += 1
                                //接近する
                                $ANGLE = 40
                                @if `!(timer % 60) bl {
                                    A_mChParam_1 = delta + rnd(-1, 1) * $ANGLE * UNIT_ANG
                                }

                                //射撃
                                @if `!(timer % 10) bl {
                                    theta = delta + rnd(-12, 12) * UNIT_ANG
                                    _setAttackParamater(CHARA_TYPE_EN_ATK_CROSS, $ATTACK, CHARA_SCALE_BASE / 3, theta, 3 * UNIT_POS )
                                    @se.play "energy1" .opt(70, 100, 50)
                                }

                                //射線を切ると戻る
                                //範囲外になっても撃ち続けるが、仕様とする
                                @if `timer >= 60 && hit == VISION_WALL bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_ENABLE)
                                }

                                _moveEnemy(ptrCharaA, 0, UNIT_POS / 8)

                            //敵を蘇らせる
                            } .elif state == ENEMY_STATE_SPECIAL bl {
                                //詠唱アニメーション
                                A_mChCell = (timer % 12 <= 6) ? ($CELL + 4) : ($CELL + 5)

                                //効果音
                                @if timer == 0 bl {
                                    @se.play "Magic1" .opt(80, 80, 50)
                                }

                                //蘇らせる
                                @if timer == 60 bl {
                                    @loop CHARA_NUM .dst(idxB) bl {
                                        _getCharaPtr(ptrCharaB, idxB)
                                        @if `between(B_mChType, CHARA_TYPE_EN_ZOMBIE, CHARA_TYPE_EN_ZOMBIE + ENEMY_TYPE_NUM - 1) &&
                                            B_mChState == ENEMY_STATE_DEAD bl {

                                            _changeCharaState(ptrCharaB, CHARA_STATE_CREATE)
                                            enemyCnt += 1
                                        }
                                    }

                                    bitOn(triggerFlg, TR_BIT_ENEMY_CNT)
                                    _screenColor(0, 255, 255, 50, 100, 4)
                                    @se.play "Raise1" .opt(80, 80, 50)
                                }

                                //待機状態に移す
                                @if timer >= 90 bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_WAIT)
                                }

                            //待機
                            } .elif state == ENEMY_STATE_WAIT bl {
                                @if timer == 0 bl {
                                    A_mChCell = $CELL + 0

                                    //特殊動作
                                    //カウンタが溜まっており、敵が減っている時に発動する
                                    @if `A_mChParam_2 >= UNIT_FPS * 8 && enemyCnt < enemyNum bl {
                                        A_mChParam_2 = 0
                                        _changeCharaState(ptrCharaA, ENEMY_STATE_SPECIAL)
                                    }
                                }

                            //死亡
                            } .elif state == ENEMY_STATE_DOWN bl {
                                $TIME = 60
                                //効果音
                                @if timer == 0 bl {
                                    @se.play "Magic1" .opt(80, 100, 50)
                                } .elif timer == $TIME bl {
                                    @se.play "explo1" .opt(100, 80, 50)
                                }

                                //死亡アニメーション
                                @if timer <= $TIME bl {
                                    A_mChCell = (timer % 24 < 12) ? ($CELL + 4) : ($CELL + 5)
                                } .else bl {
                                    A_mChCell = (timer < $TIME + 12) ? ($CELL + 6) : ($CELL + 7)
                                }

                                @if timer >= $TIME + 60 bl {
                                    _changeCharaState(ptrCharaA, ENEMY_STATE_DEAD)
                                }

                            //登場直後
                            } .elif state == CHARA_STATE_CREATE bl {
                                _setEnemyParamater(ptrCharaA, $HP, CHARA_SCALE_BASE, $CELL)
                                _changeCharaState(ptrCharaA, ENEMY_STATE_WAIT)
                            }
                        }

                        //----------------------------
                        //共通処理2
                        //移動する
                        @if `vx || vy bl {
                            //移動後の座標
                            V2_add(ex, sx, vx)
                            //地形との衝突判定
                            //移動方向
                            V2_set(sigX,
                                vx > 0 ? 1 : -1,
                                vy > 0 ? 1 : -1
                            )
                            //4つの隅の内、2か所のピクセルを調べる
                            //X軸について調べた後、Y軸について調べる
                            @loop 4 .dst(idxA) bl {
                                //ループごとに判定座標が変わる
                                V2_set(cx,
                                    ((idxA <= 1 ? (sigX) : (idxA % 2 * 2 - 1)) * PLAYER_RADIUS + ex) / UNIT_MAPPOS,
                                    ((idxA >  1 ? (sigY) : (idxA % 2 * 2 - 1)) * PLAYER_RADIUS + (idxA <= 1 ? (sy) : (ey))) / UNIT_MAPPOS
                                )
                                //ピクセルを取得する
                                _checkCollFromMap(pix, cx, cy)
                                //壁と衝突している
                                @if `pix bl {
                                    //移動後の位置とマップタイルの中央を比較して、修正方向を決める
                                    @if `idxA <= 1  bl {
                                        ex = (ex - (cx * UNIT_MAPPOS + UNIT_MAPPOS / 2)) < 0 ? (cx * UNIT_MAPPOS - PLAYER_RADIUS - 1) : ((cx + 1) * UNIT_MAPPOS + PLAYER_RADIUS + 1)
                                    } .else bl {
                                        ey = (ey - (cy * UNIT_MAPPOS + UNIT_MAPPOS / 2)) < 0 ? (cy * UNIT_MAPPOS - PLAYER_RADIUS - 1) : ((cy + 1) * UNIT_MAPPOS + PLAYER_RADIUS + 1)
                                    }
                                }
                            }

                            //移動後の座標を拘束する
                            $A = UNIT_MAPPOS * MAP_SIZE 
                            V2_clampPointInsideRect2(ex, 0, 0, $A, $A )
                            //移動後の座標を適用する
                            A_mChX = ex
                            A_mChY = ey
                        }

                        //射撃
                        @if atkType > 0 bl {
                            //空きを探す
                            _getEmptyCharaPtr(ptrCharaB)
                            @if ptrCharaB > 0 bl {
                                //撃つ
                                _setCharaMembers(ptrCharaB, [CHARA_STATE_CREATE, -1, atkType, atkPoint, 0, atkScale, 0, atkAng, atkSpeed, A_mChX, A_mChY] )
                            }
                        }
                    }
                    @continue
                }

                //----------------------------
                //プレイヤーのダメージ処理
                @if plDamage != 0 bl {
                    //数値を更新する
                    bitOn(triggerFlg, TR_BIT_HEALTH_CNT | TR_BIT_FACE)
                    plHealth = clamp(plHealth + plDamage, 0, HEALTH_MAX)

                    //ダメージ演出
                    @if plDamage < 0 bl {
                        //死亡判定
                        @if plHealth > 0 bl {
                            _screenColor(200, 60, 0, 20, 100, 2)
                            _changeFaceState(FACE_STATE_DAMAGE, 60)
                            @se.play "voice_boy6" .opt(90, 100, 50)

                        } .else bl {
                            _changeFaceState(FACE_STATE_DEFEAT, 0)
                            _changeHandState(HAND_STATE_INIT)
                            @se.play "voice_boy13" .opt(90, 50, 50)

                        }

                    //回復処理
                    } .else bl {
                        //演出はアイテム側で行う
                    }

                    plDamage = 0
                }

                //----------------------------
                //手
                bl {
                    //カウンタ
                    handTimer += 1

                    $X = REF_X + HAND_X
                    $Y = REF_Y + HAND_Y

                    //下げる
                    @if handState == HAND_STATE_INIT bl {
                        @if handTimer == 0 bl {
                            @pic.move [PIC_HAND] .pos($X, $Y + 96) .time(4)
                        }

                    //両手で構え
                    } .elif handState == HAND_STATE_BOTH bl {
                        @if handTimer == 0 bl {
                            @pic.show [PIC_HAND] .pos($X, $Y + 96) .bottom .cell(2) handPicCmd
                            @pic.move [PIC_HAND] .pos($X, $Y + 16) .bottom .time(4)
                        }

                    //射撃
                    } .elif `handState == HAND_STATE_SHOOT bl {
                        @if handTimer == 0 bl {
                            @pic.show [PIC_HAND] .pos($X, $Y + 96) .bottom .cell(1) handPicCmd
                            @pic.move [PIC_HAND] .pos($X, $Y) .bottom .time(3)
                        }

                        $WAIT = 90
                        @if handTimer >= $WAIT bl {
                            _changeHandState(HAND_STATE_INIT)
                        }

                    //両手射撃後
                    } .elif handState == HAND_STATE_BOTH_SHOOT bl {
                        @if handTimer == 0 bl {
                            @pic.show [PIC_HAND] .pos($X, $Y) .bottom .cell(3) handPicCmd
                        }

                        $WAIT = 90
                        @if handTimer >= $WAIT bl {
                            _changeHandState(HAND_STATE_INIT)
                        }

                    //煙草
                    } .elif handState == HAND_STATE_SMOKE bl {
                        //弾のタイプ
                        alpha = 0

                        //吸う
                        @if handTimer == 0 bl {
                            @pic.show [PIC_HAND] .pos($X, $Y + 80) .bottom .cell(4) handPicCmd
                            @pic.move [PIC_HAND] .pos($X, $Y) .bottom .time(4)
                        }

                        //吐く
                        @if handTimer == 90 bl {
                            alpha = 1
                            @pic.move [PIC_HAND] .pos($X + 24, $Y + 24) .bottom .time(4)
                            @se.play "Breath" .opt(10, 120, 50)
                        }

                        //投げる
                        @if handTimer == 150 bl {
                            alpha = 2
                            @pic.show [PIC_HAND] .pos($X + 24, $Y + 8) .bottom .cell(1) handPicCmd
                            @pic.move [PIC_HAND] .pos($X + 32, $Y) .bottom .time(1)
                            @se.play "money2" .opt(100, 130, 50)
                        }

                        //戻る
                        @if handTimer == 180 bl {
                            @pic.move [PIC_HAND] .pos($X + 32, $Y + 96) .time(4)
                        }

                        //通常状態に戻る
                        @if handTimer >= 210 bl {
                            state = plPower > 0 ? HAND_STATE_BOTH : HAND_STATE_INIT
                            _changeHandState(state)
                        }

                        //弾を発射する
                        _getCharaPtr(ptrCharaA, 0)
                        @if `alpha > 0 && A_mChState == CHARA_STATE_NONE bl {
                            V2_set(ex,
                                camX + camCos * 4 * UNIT_POS / UNIT_TRI,
                                camY + camSin * 4 * UNIT_POS / UNIT_TRI
                            )

                            @if alpha == 1 bl {
                                //攻撃力0
                                _setCharaMembers(ptrCharaA, [CHARA_STATE_CREATE, -1, CHARA_TYPE_PL_ATK_SMOKE,   0, 0, CHARA_SCALE_BASE / 10, 0, camAng, UNIT_POS / 10, ex, ey] )
                            } .else bl {
                                //攻撃力6
                                //速度は通常の半分
                                _setCharaMembers(ptrCharaA, [CHARA_STATE_CREATE, -1, CHARA_TYPE_PL_ATK_TOBACCO, 6, 0, CHARA_SCALE_BASE / 3, 0, camAng, PLAYER_SHOOT_VEL / 2, ex, ey] )
                            }
                        }
                    }
                }

                //----------------------------
                //顔
                @if faceTimer > 0 bl {
                    faceTimer -= 1
                    //通常状態に戻る
                    @if faceTimer <= 0 bl {
                        $1 = FACE_STATE_NORMAL1
                        $2 = FACE_STATE_NORMAL2
                        $3 = FACE_STATE_NORMAL3
                        faceState = [$3, $2, $1, $1][clamp(plHealth / 25, 0, 3)]
                        bitOn(triggerFlg, TR_BIT_FACE)
                    }
                }

            }

            //----------------------------
            //ゲーム画面を更新する
            @if `CHK_UPDATE_SPRITE bl {
                //プレイヤーの位置をレーダーに表示する
                V2_set(sx,
                    REF_HUD_X + RADER_X - MAP_SIZE + 2 * camX / UNIT_MAPPOS,
                    REF_HUD_Y + RADER_Y - MAP_SIZE + 2 * camY / UNIT_MAPPOS
                )
                @pic.move[PIC_RADER] .pos(sx, sy) .angle(camAng, UNIT_ANG)
                
                //----------------------------
                //キャラクタの位置や奥行を更新する
                @loop CHARA_NUM .dst(idxA) bl {
                    //キャラクタポインタ
                    _getCharaPtr(ptrCharaA, idxA)
                    //キャラクタの状態
                    state = A_mChState
                    //処理を省略する
                    @if `between(state, CHARA_STATE_NONE, CHARA_STATE_CREATE) bl {
                        @continue
                    }
                    //スプライトポインタ
                    _getSprPtrFromChId(ptrSprA, idxA)
                    //ピクチャID
                    pid = A_mSprPId
                    //セル番号
                    cell = A_mChCell
                    //ローカル座標
                    //x: 奥+ y:右+ z:上+
                    V2_set(ax,
                        A_mChX - camX,
                        A_mChY - camY
                    )
                    V2_set(bx,
                        ( camCos * ax + camSin * ay) / UNIT_TRI,
                        (-camSin * ax + camCos * ay) / UNIT_TRI
                    )
                    //カメラとスプライトを結ぶ線の角度
                    delta = bx > 0 ? atan2(by, bx, UNIT_ANG) : 0
                    //深度を更新する
                    depth = bx
                    A_mSprDepth = depth
                    //角度は少しだけ余裕を持たせる
                    //深度は壁よりも手前で消える
                    $ANG = SCR_HALF_FOV + 10 * UNIT_ANG
                    @if `!between(depth, SCR_MIN_DEPTH, SCR_MAX_DEPTH - 1) || abs(delta) > $ANG bl {
                        //範囲外にある場合、ピクチャを隠す
                        @pic.show [pid] .pos(OUT_RANGE, OUT_RANGE) .center .cell(0) charaPicCmd
                    //ピクチャを更新する
                    } .else bl {
                        //拡大率
                        alpha = SCR_DIST * UNIT_POS * A_mChScale / depth
                        //スクリーン座標
                        V2_set(sx,
                            REF_X + SCR_CENTER_X + SCR_DIST * by / depth, 
                            REF_Y + SCR_CENTER_Y + SCR_DIST * (CHARA_OFFSET_Z + camZ) / depth
                        )
                        //ピクチャの回転角度
                        theta = A_mChAngle
                        @pic.show [pid] .pos(sx, sy) .center .scale(alpha) .cell(cell) .angle(theta, UNIT_ANG) charaPicCmd
                    }
                }

                //----------------------------
                //壁のピクチャを更新する
                //loopNum = 0
                //彩度は一定
                input = 100
                //start point
                V2_copy(sx, camX)
                @loop WALL_NUM .dst(idxA) bl {
                    //angle
                    delta = lerp(-SCR_HALF_FOV, SCR_HALF_FOV, idxA, WALL_NUM - 1)
                    //ray
                    alpha = camAng + delta
                    V2_getCosSin(rayCos, alpha, UNIT_ANG, UNIT_TRI)
                    //end point
                    V2_addMuldiv(ex, sx, rayCos, SCR_MAX_DEPTH, UNIT_TRI)
                    //vector
                    V2_sub(vx, ex, sx)
                    //side
                    V2_set(sigX,
                        vx > 0 ? 1 : -1,
                        vy > 0 ? 1 : -1
                    )
                    V2_set(adjX,
                        vx > 0 ? 1 : 0,
                        vy > 0 ? 1 : 0
                    )
                    //check point(mapX)
                    V2_divScalar(cx, sx, UNIT_MAPPOS)
                    //探索開始
                    gamma = -1
                    @loop bl {
                        //loopNum += 1
                        //各軸の境界への衝突時間
                        V2_set(ax,
                            (vx != 0) ? muldiv( (cx + adjX) * UNIT_MAPPOS - sx, SCR_MAX_DEPTH, vx ) : (SCR_MAX_DEPTH + 1),
                            (vy != 0) ? muldiv( (cy + adjY) * UNIT_MAPPOS - sy, SCR_MAX_DEPTH, vy ) : (SCR_MAX_DEPTH + 1)
                        )

                        //通り過ぎた
                        @if `ax > SCR_MAX_DEPTH && ay > SCR_MAX_DEPTH bl {
                            @break

                        //X軸の境界をまたいだ
                        } .elif `ax < ay bl {
                            //タイル座標
                            cx += sigX
                            //衝突軸(x or y)
                            beta = 0

                        //Y軸の境界をまたいだ
                        } .else bl {
                            cy += sigY
                            beta = 1
                        //角はY軸として扱う
                        }

                        //地形用のピクチャを探索する
                        _getPixelFromMap(pix, cx, cy)

                        //青色成分を含むピクセルを壁として認識する
                        pix &= 0xff
                        @if `between(pix, 1, WALL_TYPE_NUM) bl {
                            //成分量によって壁の種類が決まり、セル番号も変わる
                            cell = 1 + WALL_GRID_X * (pix - 1)
                            //東西の壁にぶつかった
                            @if beta == 0 bl {
                                //東/西
                                beta = sigX > 0 ? 0 : 2
                                //衝突座標
                                bx = (cx + (vx > 0 ? 0 : 1)) * UNIT_MAPPOS
                                by = sy + vy * (bx - sx) / vx
                                //深度(歪みあり)
                                gamma = (bx - sx) * UNIT_TRI / rayCos
                                //衝突座標に応じたセル番号
                                cell += (by % UNIT_MAPPOS) * WALL_GRID_X / UNIT_MAPPOS
                            //北南の壁にぶつかった
                            } .else bl {
                                beta = sigY > 0 ? 3 : 1
                                by = (cy + (vy > 0 ? 0 : 1)) * UNIT_MAPPOS
                                bx = sx + vx * (by - sy) / vy
                                gamma = (by - sy) * UNIT_TRI / raySin
                                cell += (bx % UNIT_MAPPOS) * WALL_GRID_X / UNIT_MAPPOS
                            }
                            @break
                        }
                    }

                    //描画範囲外でも最奥にピクチャを置く
                    @if gamma <= 0 bl {
                        beta = 0
                        gamma = SCR_MAX_DEPTH
                        cell = 1
                    }

                    //歪みを軽減する為、距離を補正する
                    gamma = cos(delta, UNIT_ANG, gamma)
                    //奥に行くほど暗くなる
                    //東か南の面は明るさが少し減る
                    pix = 100 - clamp(gamma * 100 / SCR_MAX_DEPTH + (beta <= 1 ? 20 : 0), 0, 100)
                    //位置
                    V2_set(ax,
                        REF_X + SCR_CENTER_X + lerp(-SCR_WIDTH / 2, SCR_WIDTH / 2, idxA, WALL_NUM - 1),
                        REF_Y + SCR_CENTER_Y + SCR_DIST * camZ / gamma
                    )
                    //拡大率
                    //余り引き延ばすと負荷が掛かりそうなので制限する
                    V2_set(bx,
                        WALL_SCALE_X,
                        min(SCR_DIST * WALL_SCALE_Y * UNIT_POS / gamma, WALL_MAX_SCALE)
                    )
                    //sprite id
                    _getSprPtr(ptrSprA, SPR_ID_WALL + idxA)
                    //深度を更新する
                    A_mSprDepth = gamma
                    //ピクチャを置き換える
                    pid = A_mSprPId
                    @pic.show [pid] .pos(ax, ay) .center .scale2(bx, by) .trans(0) .cell(cell) .rgbs(pix, pix, pix, input) wallPicCmd
                }

                //500回も判定してるようだ
                //db_log(__str(":\",loopNum))

                //----------------------------
                //スプライトのピクチャIDをソートする
                //Y座標とスプライトIDを列挙し、ピクチャIDをスプライトID順に並べる
                sortSprId.enum(0, SPRITE_NUM)
                @loop SPRITE_NUM .dst(idxA) bl {
                    _getSprPtr(ptrSprA, idxA)
                    v[__id(sortDepth) + idxA] = A_mSprDepth

                    //移動元ピクチャID
                    sx = A_mSprPId
                    //移動先ピクチャID
                    sy = idxA + PIC_SORTED
                    @pic[sx].setId .move(sy, 1)
                }

                //Y座標でスプライトIDを降順に並べ替える
                sortDepth.sortDescending(SPRITE_NUM) .sync(sortSprId)

                //並び替えた順にピクチャIDを移動させる
                @loop SPRITE_NUM .dst(idxB) bl {
                    //スプライトID
                    idxA = v[__id(sortSprId) + idxB]
                    //移動元ピクチャID
                    sx = idxA + PIC_SORTED
                    //移動先ピクチャID
                    sy = idxB + PIC_SPRITE
                    @pic[sx].setId .move(sy, 1)

                    //メンバー変数に代入
                    _getSprPtr(ptrSprA, idxA)
                    A_mSprPId = sy
                }
            }

            //----------------------------
            //トリガー
            @if `triggerFlg bl {
                //----------------------------
                //タイマーを表示する
                @if `triggerFlg & TR_BIT_TIMER_CNT bl {
                    bitOff(triggerFlg, TR_BIT_TIMER_CNT)

                    getTimerString(1, __id(strLine), gameTimer)
                    @pic.strpic [PIC_TIMER_CNT] strLine .pos(TIMER_CNT_X, TIMER_CNT_Y) .topRight .bold smallTextPicCmd
                }

                //----------------------------
                //マップを表示する
                @if `triggerFlg & TR_BIT_MAP bl {
                    bitOff(triggerFlg, TR_BIT_MAP)
                    input = (enemyCnt <= 0) ? 0 : 100
                    @pic.move [PIC_MAP] .pos(REF_HUD_X + RADER_X, REF_HUD_Y + RADER_Y) .center .scale(200) .trans(input)
                }

                //----------------------------
                //顔を表示する
                @if `triggerFlg & TR_BIT_FACE bl {
                    bitOff(triggerFlg, TR_BIT_FACE)
                    cell = faceState + 1
                    @pic.show [PIC_FACE] .pos(REF_HUD_X + FACE_X, $Y + FACE_Y) .topLeft .cell(cell) facePicCmd
                }
                
                //----------------------------
                //敵を表示する
                @if `triggerFlg & TR_BIT_ENEMY_CNT bl {
                    bitOff(triggerFlg, TR_BIT_ENEMY_CNT)
                    _showCounter(enemyCnt, PIC_ENEMY_CNT, COUNTER_DIGIT, REF_HUD_X + ENEMY_CNT_X, REF_HUD_Y + ENEMY_CNT_Y)
                }


                //----------------------------
                //階層を表示する
                @if `triggerFlg & TR_BIT_FLOOR_CNT bl {
                    bitOff(triggerFlg, TR_BIT_FLOOR_CNT)
                    _showCounter(floor, PIC_FLOOR_CNT, COUNTER_DIGIT, REF_HUD_X + FLOOR_CNT_X, REF_HUD_Y + FLOOR_CNT_Y)
                }

                //----------------------------
                //体力を表示する
                @if `triggerFlg & TR_BIT_HEALTH_CNT bl {
                    bitOff(triggerFlg, TR_BIT_HEALTH_CNT)
                    _showCounter(plHealth, PIC_HEALTH_CNT, COUNTER_DIGIT, REF_HUD_X + HEALTH_CNT_X, REF_HUD_Y + HEALTH_CNT_Y)
                }
            }
        }
    }

    //----------------------------
    //終了する
    @label.set "gameEnd"
    bl {
        initPicturesAndVariables(PIC_HEAD, NUM_OF_PIC, TV_MINIGAME, NUM_OF_VAR, TS_MINIGAME, NUM_OF_STR)
        restoreBGM()
        fastFadeInTintOnly(1)
    }
}