watamochi517221
@watamochi517221

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

javascript判定タイミングの表示がうまく行きません。

jvascriptで音ゲーを作っています。
4×4のマスをタイミングよくタッチするというゲームです。
そのタッチするタイミングをわかるようにするためにnotesの配列からどこのマスにどの時間(time)で表示するかを読ませてそのマスの中心から小さい四角を表示し徐々に大きくしてマスの大きさまで行ったら辞めるというコードを作成しました。

問題はここからで四角を大きくするためにcountという変数を作ったのですが、1回140に到達すると140のまま止まってしまいます。
NotesDraw関数内に入れると毎回初期化されてしまい四角が小さいままです。
コード内にカウント140になったら0にするというコードも書いてみましたが、
やはり他のタイミングと被って初期化されてしまいます。誰かいい方法ないですか。
コードが雑だしうまく説明できなくてすいません。

<script>
    let can = document.getElementById("can");
    let ctx = can.getContext("2d");

    // マスのサイズと枠の幅の定義
    const size = 140;
    const rows = 4;
    const cols = 4;
    const border = 5;

    let offsetX;
    let offsetY;

    function SquareDraw(x, y, fillColor, borderColor,size) {
        // マスを描画
        ctx.fillStyle = fillColor;
        ctx.fillRect(x, y, size, size);

        // 枠を描画
        ctx.strokeStyle = borderColor;
        ctx.lineWidth = border;

        // 上
        ctx.beginPath();
        ctx.moveTo(x, y);
        ctx.lineTo(x + size, y);
        ctx.stroke();

        // 右
        ctx.beginPath();
        ctx.moveTo(x + size, y);
        ctx.lineTo(x + size, y + size);
        ctx.stroke();

        // 下
        ctx.beginPath();
        ctx.moveTo(x, y + size);
        ctx.lineTo(x + size, y + size);
        ctx.stroke();

        // 左
        ctx.beginPath();
        ctx.moveTo(x, y);
        ctx.lineTo(x, y + size);
        ctx.stroke();
    }

    function SquareOrder() {
        // すべての四角を表示
        for (let row = 0; row < rows; row++) {
            for (let col = 0; col < cols; col++) {
                const x = offsetX + col * (size + border);
                const y = offsetY + row * (size + border);
                SquareDraw(x, y, "rgba(170,170,170,0.1)", "#000",size);
            }
        }

        // タッチした四角を色付ける
        for (let i = 0; i < touchPoints.length; i++) {
            const touchPoint = touchPoints[i];
            SquareDraw(
                offsetX + (touchPoint.x - 1) * (size + border),
                offsetY + (touchPoint.y - 1) * (size + border),
                "red", "#000",size
            );
        }
    }

    let touchPoints = []; // 各タッチポイントの情報を保持するための配列

    let touchX;
    let touchY;

    document.addEventListener('touchstart', function (event) {
        touchPoints = []; // タッチ開始時に配列をクリア
        for (let i = 0; i < event.touches.length; i++) {
            const touch = event.touches[i];
            const touchX = Math.floor((touch.clientX - offsetX) / (size + border * 3)) + 1;
            const touchY = Math.floor((touch.clientY - offsetY) / (size + border * 3)) + 1;

            if (touchX >= 1 && touchY >= 1 && touchX <= cols && touchY <= rows) {
                touchPoints.push({ x: touchX, y: touchY });
                PlayerAction(touchX, touchY);

            
    }
        }
    });

    let lastTouchX = null;
    let lastTouchY = null;

    document.addEventListener('touchmove', function (event) {
        // タッチ移動時の処理
        touchPoints = [];
        for (let i = 0; i < event.touches.length; i++) {
            const touch = event.touches[i];
            const touchX = Math.floor((touch.clientX - offsetX) / (size + border * 3)) + 1;
            const touchY = Math.floor((touch.clientY - offsetY) / (size + border * 3)) + 1;

            if (touchX >= 1 && touchY >= 1 && touchX <= cols && touchY <= rows) {
                touchPoints.push({ x: touchX, y: touchY });
                if (touchX !== lastTouchX || touchY !== lastTouchY) {
                PlayerAction(touchX, touchY);
                lastTouchX = touchX;
                lastTouchY = touchY;
    
            }
            }
        }
    });

    document.addEventListener('touchend', function (event) {
        touchPoints = []; // タッチ終了時に配列をクリア
    });

    let time = 0;

    const notes = [
        [2, 2,30],
        [1, 3,30],
        [2, 4,40],
        [1, 2,90],
        [4, 2,100]
    ];

   
    let count = 0; 

    function NotesDraw() {
for (let i = 0; i < notes.length; i++) {
    if (time > notes[i][2] && time < notes[i][2] + 40) {

        if(count < 140){
        count += 2;
        console.log(count);
        SquareDraw(
            (offsetX + size * (notes[i][0] - 1) + border) + size / 2 - count / 2,
            (offsetY + size * (notes[i][1] - 1) + border) + size / 2 - count / 2,
            "blue",
            "#000",
            count
        );
        }


    }
}

}

    function PlayerAction(x,y){
        if( x == notes[0][0] && y == notes[0][1] && time > notes[0][2] && time < notes[0][2] + 70){
        console.log("f")
    }
    }

    function KeyDown(event) {
        if (event.keyCode === 32) {
            setInterval(function(){time++;},100)
        }
    }

    document.addEventListener("keydown", KeyDown);

    function gameLoop() {
        can.width = window.innerWidth;
        can.height = window.innerHeight;

        offsetX = (can.width - (size * cols + border * (cols - 1))) / 2;
        offsetY = (can.height - (size * rows + border * (rows - 1))) / 2;

        document.addEventListener('contextmenu', function (e) {
            // 長押し時のデフォルトのコンテキストメニューを無効化
            e.preventDefault();
        });

        SquareOrder();
        NotesDraw();
        requestAnimationFrame(gameLoop);
    }

    // 最初の呼び出し
    requestAnimationFrame(gameLoop);

</script>
0

1Answer

ソースコードはそのままベタ張りせずCode blocksを使用して貼り付けてください.
プレビューで正しく表示されていることを確認してください.

https://qiita.com/Qiita/items/c686397e4a0f4f11683d#code-blocks---%E3%82%B3%E3%83%BC%E3%83%89%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF

方法論としては単純な話で,countにあたる数値をノーツごとに管理するだけです.
notesで一緒に管理するとかでもいいでしょう.

結構処理落ちを起こしやすい環境ですので,一定時間ごとにタイマーを加算して判定しているとどんどん判定がズレていったり,setIntervalしたオブジェクトを消す手段がない等については何かしら対策すべきと思います.

0Like

Comments

  1. 回答ありがとうございます。とても参考になりました。タイマーの加算で判定がずれるのとオブジェクトを消す手段がないというのは、変数とsetIntervalではなく、performance.now();を使えば解決しますか?解決しない場合どんな方法があるか教えてくれませんか?何度も質問申し訳ありません。

Your answer might help someone💌