鼠标位置仅在第一帧上读取

时间:2015-04-27 04:28:19

标签: javascript html5 canvas

我在阅读画布上的鼠标位置时遇到了麻烦。代码正常工作(半),因为它在IE中单击画布时读取位置,但只在一帧上,在chrome中,它只是将值显示为0。

以下是完整代码:

    <script>
        var blip = new Audio("blip.mp3");
        blip.load();

        var levelUp = new Audio("levelUp.mp3");
        levelUp.load();

        var canvas = document.getElementById('game');
        var context = canvas.getContext('2d');
        context.font = '18pt Calibri';
        context.fillStyle = 'white';

        //load and draw background image
        var bgReady = false;
        var background = new Image();
        background.src = 'images/background.jpg';
        background.onload = function(){
            bgReady = true;
        }

        var startMessage = 'Click the canvas to start';

        //load plane image
        var planeReady = false;
        var planeImage = new Image();
        planeImage.src = 'images/plane.png';
        planeImage.onload = function() {
            planeReady = true;
        }

        //load missile image
        var missileReady = false;
        var missileImage = new Image();
        missileImage.src = 'images/missile-flipped.gif';
        missileImage.onload = function() {
            missileReady = true;
        }

        //initialise lives and score
        var score = 0;
        var lives = 3;
        var missilesLaunched = 0;
        var missileSpeed = 5;
        var level = 1;

        var missileX = 960;
        var missileY = Math.random() * 500;
        if (missileY > 480) {
            missileY = 480;
        }

        function getMousePos(canvas, event) {
            return {
                x: input.x - rect.left,
                y: input.y - rect.top
            };
        }

        function update_images(event) {
            var pos = getMousePos(canvas.getBoundingClientRect(), mouseInput);
            planeImage.y = pos.y;

            missileX = missileX - missileSpeed;

            if (missileX < - 70) {
                missilesLaunched++;
                missileX = 960;

                missileY = Math.random() * 500;
                if (missileY > 480) {
                    missileY = 480;
                }

                blip.play();
                score = missilesLaunched;

                if (score % 5 == 0) {
                    missileSpeed = missileSpeed + 2;
                    level++;
                    levelUp.play();
                }

            }
        }



        function reload_images() {

            if (bgReady = true) {
                context.drawImage(background, 0, 0);
            }

            if (planeReady = true) {
                context.drawImage(planeImage, 10, planeImage.y);
            }

            if (missileReady = true) {
                context.drawImage(missileImage, missileX, missileY);
            }



            context.fillText('Lives: ' + lives, 200, 30);
            context.fillText('Score: ' + score, 650, 30);
            context.fillText('Level: ' + missileSpeed, 420, 30);
            context.fillText('Position: ' + missileImage.y, 420, 70);
        }

        function main(event) {

            var mouseInput = { x: 0, y: 0 };

            document.addEventListener("mousemove", function (event) {
            mouseInput.x = event.clientX;
            mouseInput.y = event.clientY;
            });

            update_images(event);
            reload_images();

            if (lives > 0) {
                window.requestAnimationFrame(main);
            }
            else {

            }
        }

        function start() {

            context.drawImage(background, 0, 0);
            context.fillText('Click the canvas to start', 350, 250);

            function startMain(event) {
                game.removeEventListener("click", startMain);
                main(event);
            }

            canvas.addEventListener("mousedown", startMain);
        }

        start();

    </script>

1 个答案:

答案 0 :(得分:2)

乔,你每次点击时都应该抓住鼠标位置......

...但是,每次点击时,你实际上也开始了新游戏(不停止旧游戏)。

第一个问题:多次启动游戏引擎以在同一个画布上绘制

解决方案:

start功能中,您需要在触发后删除mousedown事件监听器。

function start () {
    // ... other setup
    function startMain (event) {
        canvas.removeEventListener("click", startMain);
        main(event);
    }
    canvas.addEventListener("click", startMain);
}

现在它只会在开始之前听取第一次点击,并且只会开始一次。

第二个问题:鼠标没有按预期更新

解决方案:这里有两个问题...... ...首先,您在第一次通话时将event传递给main ... ......之后,您将main传递给requestAnimationFrame

requestAnimationFrame不会使用某个事件调用它,它会在页面加载后以微秒数(或ms或其他单位为ms的小数精度)调用它。

所以你第一次得到main({ type: "mousedown", ... }); 下次您获得main(4378.002358007);

因此,让我们重构上面的startMain,以便main永远不会收集一个事件。

function startMain ( ) {
  canvas.removeEventListener("click", startMain);
  requestAnimationFrame(main);
}

接下来的问题是,即使你只获得了一些事件,你也只能捕获一个点击事件(正如我们之前提到的那样,它会触发一个新的游戏逻辑副本)。

您的解决方案是将捕获鼠标事件的代码与读取鼠标位置的代码分开。

var mouseInput = { x: 0, y: 0 };

document.addEventListener("mousemove", function (event) {
  mouseInput.x = event.clientX;
  mouseInput.y = event.clientY;
});


function getMousePos (rect, input) {
  return {
    x : input.x - rect.left,
    y : input.y - rect.top
  };
}


// currently in updateImages (should not be there, but... a different story)
var pos = getMousePos(canvas.getBoundingClientRect(), mouseInput);

你也遇到了其他问题...... 您现在正在呼叫getMousePos并传入game。我不知道你的JS中定义了game的位置,所以你要么在其他地方{乞讨错误} {strong> 或者它&#39}。 ; s game,您的应用就会在那里爆炸

你应该在你的控制台/开发工具打开时,以实际的方式构建它,并在每个部分清除错误。