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


cev[CEV_NAWABARIA] .name("mg_縄張りあ") {
    def {
        NUM_OF_VAR = 128
        NUM_OF_STR = 0
        NUM_OF_PIC = 20

        BASE_LAYER = 6

        PATH_BASE    = "nb\ba"
        PATH_CANVAS  = "nb\ca"
        PATH_CURSOR  = "nb\cu"
        PATH_TRACER  = "nb\tr"
        PATH_TOOL    = "nb\to"
        PATH_PALETTE = "nb\pa"

        PIC_HEAD    = 1
        PIC_BASE    = 2
        PIC_CANVAS  = 3
        PIC_TRACER  = 4//+0_+7
        PIC_TOOL    = 16
        PIC_PALETTE = 17
        PIC_TEXT    = 18
        PIC_CURSOR  = 19

        //実績
        ACHIEVE_LENGTH = 8000

        //操作方法
        CTRL_TYPE_KEY = 0
        CTRL_TYPE_MOUSE

        //トレーサー
        TR_NUM        = 8
        TR_UNIT_POS   = 10
        TR_CANVAS_Y   = -8
        TR_LEFT       = 40
        TR_WIDTH      = 24
        TR_HEIGHT     = 24
        TR_SPEED_LOW  = 3
        TR_SPEED_HIGH = 5
        TR_ROTATE     = 2
        TR_SENSOR_X   = 60
        TR_SENSOR_Y   = 40

        //トレーサーの状態
        TR_STATE_CATCH = 0
        TR_STATE_STOP
        TR_STATE_RUN

        //トレーサーの構造
        MT_STATE = 0
        MT_TIMER
        MT_ANG
        MT_X
        MT_Y
        SIZE_OF_TR

        //メンバー変数
        mTrStateA = v[ptr + MT_STATE]
        mTrTimerA = v[ptr + MT_TIMER]
        mTrAngA   = v[ptr + MT_ANG]
        mTrXA     = v[ptr + MT_X]
        mTrYA     = v[ptr + MT_Y]

        //定数
        TOOL_X = 0
        TOOL_Y = 0
        PALETTE_X = 0
        PALETTE_Y = 48
        PEN_WIDTH = 3
        OUT_RANGE = -320
        CURSOR_SPEED = 4
        CANVAS_X = 40
        CANVAS_Y = 24
        TEXT_X = 16
        TEXT_Y = (240 - 16)
        FILE_NAME = "nawabaria_screenshot"
    }

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

        baseStrPicCmd = bl {
            .topLeft
            .font("", 10)
            .spacing(0, 4)
            .skin ""
            .nobg .noframe .noPadding
            basePicCmd
        }

        tracerPicCmd = bl {
            PATH_TRACER
            .center
            .scale(100)
            .trans(0)
            .grid(12, 8)
            basePicCmd
        }

        palettePicCmd = bl {
            PATH_PALETTE
            .topLeft
            .scale(100)
            .trans(0)
            .grid(1, 9)
            basePicCmd
        }
    }

    defv {
        varHead = TV_MINIGAME

        ipt
        ptr
        pid
        cell
        idx
        err
        step
        steep
        loopNum
        color
        coll
        state
        ang
        ax
        ay
        bx
        by
        dx
        dy
        sx
        sy
        ex
        ey

        inputDec
        canvasX
        canvasY
        canvasWidth
        canvasHeight
        cursorX
        cursorY
        cursorCatch
        dragX
        dragY
        drawColor
        drawCount

        pixelHead
        tracerHead = (__id(pixelHead) + PEN_WIDTH * PEN_WIDTH)

        varFoot = (__id(tracerHead) + TR_NUM * SIZE_OF_TR)

    }

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

    //カラーパレット
    __fn _getColor $dvDst $idx bl {
        v[__id($dvDst)] = [0x00000000, 0xffff0000, 0xff0080FF, 0xffffff00, 0xff73E610, 0xffE66AE6, 0xffCD7339, 0xffA4D1FF, 0xff414141][$idx]
    }

    //描画用ピクセルを入力する
    __fn _setSourcePixels $col bl {
        v[__id(pixelHead)..__id(pixelHead) + PEN_WIDTH * PEN_WIDTH - 1] = $col
    }

    //トレーサーのポインタを取得する
    __fn _getTracerPtr $dvDst $idx bl {
        v[__id($dvDst)] = __id(tracerHead) + ($idx) * SIZE_OF_TR
    }

    //トレーサーのメンバー変数を一括代入する
    __fn _setTracerMembers $ptr $arr bl {
        v[$ptr..$ptr + SIZE_OF_TR - 1] = $arr
    }

    //トレーサーの状態を変える
    __fn _setTracerState $ptr $state bl {
        v[$ptr + MT_STATE] = $state
        v[$ptr + MT_TIMER] = -1
    }

    //------------------------------------------------------------------------------------
    //開始処理
    bl {
        initPicturesAndVariables(PIC_HEAD, NUM_OF_PIC, TV_MINIGAME, NUM_OF_VAR, 0, 0)
        msgBottom()
        
        @scr.tint .rgbs(50, 50, 50, 100) .time(1)
        //ピクチャ
        @pic.show [PIC_BASE] PATH_BASE .pos(CANVAS_X, CANVAS_Y) .topLeft basePicCmd
        @pic.show [PIC_TOOL] PATH_TOOL .pos(TOOL_X, TOOL_Y) .topLeft basePicCmd
        @pic.show [PIC_PALETTE] PATH_PALETTE .pos(PALETTE_X, PALETTE_Y) .cell(2) palettePicCmd
        @pic.show [PIC_CURSOR] PATH_CURSOR .pos(OUT_RANGE, OUT_RANGE) basePicCmd
        @pic.show [PIC_CANVAS] PATH_CANVAS .pos(CANVAS_X, CANVAS_Y) .topLeft basePicCmd
        @pic.strpic [PIC_TEXT] "" .pos(TEXT_X, TEXT_Y) baseStrPicCmd 
        //キャンバスの位置と幅を取得する
        @pic.getInfo [PIC_CANVAS] .currentRect(canvasX, canvasY, canvasWidth, canvasHeight) .xywh
        @label.jump "gameLoop"
    }

    //------------------------------------------------------------------------------------
    //ゲーム処理
    @label.set "gameLoop"
    bl {
        //入力を初期化する
        inputDec = 0
        //掴んでいるトレーサー
        cursorCatch = -1
        //カーソルを画面中央に置く
        V2_set(cursorX, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2)
        V2_set(dragX, -1, -1)
        //マウスカーソルも移動させる
        @if gameMode == CTRL_TYPE_MOUSE bl {
            @mouse.setPos(cursorX, cursorY)
        }
        //描画色
        _getColor(drawColor, 1)
        //トレーサーの初期化
        @loop TR_NUM .dst(idx) bl {
            _getTracerPtr(ptr, idx)
            //初期位置
            V2_set(ax,
                (88 + idx * 20) * TR_UNIT_POS,
                20 * TR_UNIT_POS
            )
            //メンバー変数
            _setTracerMembers(ptr, [ TR_STATE_STOP, -1, 90, ax, ay ] )
            //ピクチャ
            pid = PIC_TRACER + idx
            @pic.show [pid] .pos(OUT_RANGE, OUT_RANGE) .cell(0) tracerPicCmd
        }
        //少し待つ
        @wait(1)

        //----------------------------
        //ループ
        @loop bl {
            @wait(0)

            //----------------------------
            //ポーズ
            pauseProcces(TRUE, ipt, "gameEnd")

            //----------------------------
            //入力
            @if gameMode == CTRL_TYPE_KEY bl {
                //カーソル
                V2_getInput(ax)
                V2_asMulScalar(ax, CURSOR_SPEED)
                V2_asAdd(cursorX, ax)
                //決定
                @key.input .dst(ipt) bl {
                    .decision
                }
                inputDec = ipt ? inputDec + 1 : 0

            } .else bl {
                //マウスカーソルが画面外にあっても入力する
                @mouse.getPos(ax, ay)
                V2_copy(cursorX, ax)
                //決定
                @key.input .dst(ipt) bl {
                    .lclick
                }
                inputDec = ipt ? inputDec + 1 : 0
            }

            //カーソルの範囲を制限する
            V2_set(cursorX,
                clamp(cursorX, 0, WINDOW_WIDTH  - 4),
                clamp(cursorY, 0, WINDOW_HEIGHT - 4)
            )
            //ピクチャの位置
            @pic.move [PIC_CURSOR] .pos(cursorX, cursorY) .topLeft

            //----------------------------
            //ボタン
            @if `cursorCatch < 0 && inputDec == 1 bl {
                @if `cursorX - TOOL_X < 32 bl {
                    //カーソル位置でボタンを特定する
                    idx = (cursorY - TOOL_Y) / 16
                    //スクリーンショット
                    @if idx == 1 bl {
                        //背景を暗くし、ピクチャを非表示にする
                        @foreach [PIC_TOOL, PIC_PALETTE, PIC_CURSOR] .dst(pid) {
                            @pic.move [pid] .relative .pos(0, 0) .scale(0) .trans(100)
                        }
                        @scr.tint .rgbs(0, 0, 0, 100) .time(0)
                        //2f待たないと隠しきれない
                        @wait.frame(2)
                        //保存する
                        @img.save .screen .static .opaq .dst(FILE_NAME)
                        //彩度とピクチャを戻す
                        @foreach [PIC_TOOL, PIC_PALETTE, PIC_CURSOR] .dst(pid) {
                            @pic.move [pid] .relative .pos(0, 0) .scale(0) .trans(-100)

                        }
                        @scr.tint .rgbs(50, 50, 50, 100) .time(1)
                        //メッセージを表示する
                        @pic.strpic [PIC_TEXT] __str("スクリーンショットを保存しました。/ ", FILE_NAME) .pos(TEXT_X, TEXT_Y) baseStrPicCmd 
                        //シャッター演出
                        @scr.flash .once(4) .rgbv(31, 31, 31, 31)
                        @se.play "Open1" .opt(100, 150, 50)
                        @wait(2)
                        @se.play "robotarm1" .opt(80, 150, 50)
                        @wait(14)
                        //文章を下げる
                        @pic.move [PIC_TEXT] .relative .pos(0, 16) .scale(0) .trans(0) .time(2)
                    //破棄
                    } .elif idx == 2 bl {
                        drawCount = 0
                        @pic.show [PIC_CANVAS] PATH_CANVAS .pos(CANVAS_X, CANVAS_Y) .topLeft basePicCmd
                        @scr.flash .once(4) .rgbv(0, 0, 0, 15)
                        @se.play "Collapse1" .opt(100, 100, 50)
                        @wait(5)

                    //色
                    } .elif `between(idx, 4, 12) bl {
                        _getColor(drawColor, idx - 4)
                        cell = idx - 4 + 1
                        @pic.show [PIC_PALETTE] PATH_PALETTE .pos(PALETTE_X, PALETTE_Y) .topLeft .cell(cell) palettePicCmd
                        @se.play "Switch2" .opt(100, 120, 50)
                    }
                }
            }

            //掴み判定
            @if `cursorCatch < 0 && inputDec == 1 bl {
                @loop TR_NUM .dst(idx) bl {
                    _getTracerPtr(ptr, idx)

                    @if `abs(mTrXA / TR_UNIT_POS - cursorX) < TR_WIDTH / 2 && 
                         abs(mTrYA / TR_UNIT_POS + TR_CANVAS_Y - cursorY) < TR_HEIGHT / 2 bl {
                        _setTracerState(ptr, TR_STATE_CATCH)

                        cursorCatch = idx

                        @se.play "bubble1" .opt(80, 100, 50)
                        @break
                    }
                }
            }

            //トレーサーを移動させる
            @if `cursorCatch >= 0 bl {
                _getTracerPtr(ptr, cursorCatch)

                mTrAngA = 90
                mTrXA = clamp(cursorX, TR_LEFT, WINDOW_WIDTH - 8) * TR_UNIT_POS
                mTrYA = clamp(cursorY, 8, WINDOW_HEIGHT - 8) * TR_UNIT_POS

                //離す
                @if inputDec <= 0 bl {
                    //範囲外に置くと停止する
                    @if `between(cursorX, canvasX, canvasX + canvasWidth) &&
                         between(cursorY, canvasY, canvasY + canvasHeight) bl {
                        state = TR_STATE_RUN
                    } .else bl {
                        state = TR_STATE_STOP
                    }

                    _setTracerState(ptr, state)
                    cursorCatch = -1
                    @se.play "bubble1" .opt(80, 140, 50)
                }
            }

            //掴んでいる場合は描画しない
            @if `cursorCatch < 0 && inputDec > 0 bl {
                //描画ピクセル
                _setSourcePixels(drawColor)
                //開始位置
                @if dragX < 0 bl {
                    V2_copy(dragX, cursorX)
                }
                //線を描く
                //wikipediaからコピペ
                //copy
                V2_copy(sx, dragX)
                V2_copy(ex, cursorX)
                //steep
                steep = abs(cursorY - dragY) > abs(cursorX - dragX) ? TRUE : FALSE
                //swap
                @if `steep bl {
                    sx.swap(sy, 1)
                    ex.swap(ey, 1)
                }

                @if sx > ex bl {
                    sx.swap(ex, 1)
                    sy.swap(ey, 1)
                }

                //delta
                V2_set(dx,
                    ex - sx,
                    abs(ey - sy)
                )

                //start
                err = dx
                step = sy < ey ? 1 : -1
                by = sy
                loopNum = ex - sx + 1
                @loop loopNum .dst(bx) bl {
                    bx += sx
                    //draw pixel
                    @if `steep bl {
                        V2_set(ax, by, bx)
                    } .else bl {
                        V2_copy(ax, bx)
                    }

                    V2_set(ax,
                        ax - canvasX - 1,
                        ay - canvasY - 1
                    )

                    //check if in picture
                    @if `between(ax, 0, canvasWidth - 1) && between(ay, 0, canvasHeight - 1) bl {
                        @pic.setPixel [PIC_CANVAS] .xywh(ax, ay, PEN_WIDTH, PEN_WIDTH) .src(pixelHead)
                        drawCount += 1
                    }

                    //step
                    err -= dy * 2
                    @if err < 0 bl {
                        err += dx * 2
                        by += step
                    }
                }
                //カーソル位置を記録
                V2_copy(dragX, cursorX)
                //実績
                checkSetAchievement(achievedNawabaria, drawCount >= ACHIEVE_LENGTH)
            //記録したカーソル位置を初期化
            } .else bl {
                V2_set(dragX, -1, -1)
            }

            //----------------------------
            //トレーサー
            @loop TR_NUM .dst(idx) bl {
                _getTracerPtr(ptr, idx)
                //タイマー
                mTrTimerA += 1
                //メンバー変数
                state = mTrStateA
                ang   = mTrAngA
                //稼働中
                @if state == TR_STATE_RUN bl {
                    //sincos
                    V2_getCosSin(ax, ang, 1, TR_SENSOR_X)
                    V2_getCosSin(bx, ang + 90, 1, TR_SENSOR_Y)
                    //センサー
                    _getColor(color, idx + 1)
                    coll = 0x00
                    @loop 2 .dst(step) bl {
                        //判定位置
                        err = step == 0 ? -1 : 1
                        V2_set(sx,
                            (mTrXA + ax + bx * err) / TR_UNIT_POS - canvasX,
                            (mTrYA + ay + by * err) / TR_UNIT_POS - canvasY
                        )
                        //ピクセルの色を取得する
                        @if `between(sx, 0, canvasWidth) && between(sy, 0, canvasHeight) bl {
                            @pic.getInfo [PIC_CANVAS] .pixel(sx, sy, 1, 1) .dst(err)
 
                            @if err == color bl {
                                coll |= 1 << step
                            }
                        }
                    }

                    //反応なし、左のみ、右のみ、両方
                    //角度と移動量
                    ang  += [0, -TR_ROTATE, TR_ROTATE, 0][coll]
                    step = [TR_SPEED_HIGH, TR_SPEED_LOW, TR_SPEED_LOW, TR_SPEED_HIGH][coll]
                    //移動
                    V2_getCosSin(bx, ang, 1, step)
                    V2_set(ax,
                        mTrXA + bx,
                        mTrYA + by
                    )
                    //左端
                    $EDEG = TR_LEFT * TR_UNIT_POS
                    @if `ax < $EDEG bl {
                        ax = $EDEG + 1
                        ang = 0 + rnd(-30, 30)
                    }
                    //右端
                    $EDEG = (WINDOW_WIDTH  - 8) * TR_UNIT_POS
                    @if `ax > $EDEG bl {
                        ax = $EDEG - 1
                        ang = 180 + rnd(-30, 30)
                    }
                    //上端
                    $EDEG = 8 * TR_UNIT_POS
                    @if `ay < $EDEG bl {
                        ay = $EDEG + 1
                        ang = 90 + rnd(-30, 30)
                    }
                    //下端
                    $EDEG = (WINDOW_HEIGHT - 8) * TR_UNIT_POS
                    @if `ay > $EDEG bl {
                        ay = $EDEG
                        ang = 270 + rnd(-30, 30)
                    }
                    mTrAngA = (ang + 360) % 360
                    mTrXA = ax
                    mTrYA = ay
                }

                //ピクチャを更新する
                //スクリーン座標
                V2_set(ax,
                    mTrXA / TR_UNIT_POS,
                    mTrYA / TR_UNIT_POS + TR_CANVAS_Y
                )

                //セル番号
                //種類と向き
                err = ((ang + 45) / 90) % 4
                cell = 1 + idx * 12 + err * 3
                //色
                bx = [150, 100, 100][state]
                by = [100,  60, 100][state]
                //セル
                @if state == TR_STATE_RUN bl {
                    cell += [0, 1, 2, 1][ (mTrTimerA % 64) / 16 ]
                } .else bl {
                    cell += 1
                }

                //ピクチャID
                pid = PIC_TRACER + idx
                @pic.show [pid] .pos(ax, ay) .cell(cell) .rgbs(bx, bx, bx, by) tracerPicCmd
            }
        }
    }

    //------------------------------------------------------------------------------------
    //終了する
    @label.set "gameEnd"
    bl {
        initPicturesAndVariables(PIC_HEAD, NUM_OF_PIC, TV_MINIGAME, NUM_OF_VAR, 0, 0)
        @scr.tint .rgbs(100, 100, 100, 100) .time(1) .wait
    }
}