abd
abd

Reputation: 3

Mouse position is only read on the first frame

i have been having trouble with reading a mouse position on a canvas. The code is working (semi) correctly as it reads the position when clicking he canvas in IE but only on one frame, in chrome it is just displaying the value as 0.

Here is the full code:

    <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>

Upvotes: 0

Views: 85

Answers (1)

LetterEh
LetterEh

Reputation: 26706

Joe, you should actually be capturing the mouse position every time you click...

...but you're actually also starting a new game (without stopping the old one), every time you click, too.

First problem: starting game engine several times to draw on the same instance of the canvas

Solution:

In your start function, you need to remove the mousedown event listener, after you've triggered it.

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

Now it will only listen for the first click, before starting, and will only start once.

Second Problem: mouse doesn't update as expected

Solution: two issues here... ...first, you are passing event into main on first call... ...after that, you're passing main into requestAnimationFrame.

requestAnimationFrame won't call it with an event, it will call it with the number of microseconds (or ms or some other unit as a fractional precision of ms) since the page was loaded.

So the first time you got main({ type: "mousedown", ... });.
The next time you get main(4378.002358007);

So lets refactor the startMain we had above, so that main never ever collects an event, just a time.

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

The next problem is that even if you were getting just events, you're only ever capturing a click event (which as we mentioned earlier, fires a new copy of the game logic).

Your solution is to separate the code which catches mouse events from the code which reads mouse position.

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);

You've got other problems, too...
You're calling getMousePos and passing in game at the moment. I don't see where game is defined in your JS, so either you're making game somewhere else (begging for bugs), or it's undefined, and your app blows up right there.

You should really be building this with your console / dev-tools open, in a hands-on fashion, and cleaning bugs in each section, as you go.

Upvotes: 2

Related Questions