Как добавить прослушиватель событий (щелчок) к объекту Canvas? - PullRequest
0 голосов
/ 03 мая 2020

Я создаю новую Javascript игру с холстом, и я хотел бы добавить прослушиватель событий для каждого объекта. Хочу нарисовать полезный джойстик (стрелки) при открытии игры со смартфона / планшета. Таким образом, игрок сможет перемещать персонажа, нажимая каждую стрелку.

Вот что у меня есть:

Игра. js:

class Game {
    constructor() {
        this.touchDevice = false;
        this.joystickDown = new Down();
        this.joystickLeft = new Left();
        this.joystickRight = new Right();
        this.joystickUp = new Up();
        this.imgDownArrow = new Image();
        this.imgLeftArrow = new Image();
        this.imgRightArrow = new Image();
        this.imgUpArrow = new Image();
        this.gameStruct = new Object();
        this.gameLoaded = true;
        this.gameOver = false;
    }
}

    initialize(width = 640, height = 480) {
        console.log("Game initialized");
        this.canvas = document.getElementById("canvas");
        this.canvas.width = width;
        this.canvas.height= height;

        if(this.canvas && this.canvas.getContext) {
            this.ctx = this.canvas.getContext("2d");
            if(this.ctx) {
                this.ctx.strokeStyle="#000";

                this.gameStruct.ctx = this.ctx;
                this.gameStruct.canvas = this.canvas;

                function is_touch_device() {  
                    try {  
                      document.createEvent("TouchEvent");
                      return true;  
                    } catch (e) {  
                      return false;  
                    }  
                  }

                this.touchDevice = is_touch_device();

                if(this.touchDevice) {                  
                    this.imgDownArrow.src = "img/joystick/arrow_down.png";
                    this.imgLeftArrow.src = "img/joystick/arrow_left.png";
                    this.imgRightArrow.src = "img/joystick/arrow_right.png";
                    this.imgUpArrow.src = "img/joystick/arrow_up.png";

                    this.gameStruct.imgDownArrow = this.imgDownArrow;
                    this.gameStruct.imgLeftArrow = this.imgLeftArrow;
                    this.gameStruct.imgRightArrow = this.imgRightArrow;
                    this.gameStruct.imgUpArrow = this.imgUpArrow;

                    this.joystickDown.initialize(this.gameStruct);
                    this.joystickLeft.initialize(this.gameStruct);
                    this.joystickRight.initialize(this.gameStruct);
                    this.joystickUp.initialize(this.gameStruct);                    
                }

            } else 
                alert("error_context");
            }
    }

    animate() {
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);

        if(!this.gameOver) {
            this.player.draw();
            if(this.touchDevice) {
                this.joystickDown.draw();
                this.joystickLeft.draw();
                this.joystickRight.draw();
                this.joystickUp.draw();
            }
        }
        window.requestAnimationFrame(this.animate.bind(this));
    }

Вниз. js:

class Down {
    constructor() {
    }

    initialize(gameStruct) {

        this.gameStruct = gameStruct;
        this.ctx = gameStruct.ctx;
        this.width = gameStruct.canvas.width / 15;
        this.height = gameStruct.canvas.width / 15;
        this.x = (gameStruct.canvas.width) - (this.width*2);
        this.y = gameStruct.canvas.height-this.height;
        this.limitTop = 0;
        this.limitBottom = gameStruct.canvas.height;
        this.limitLeft = 0;
        this.limitRight = gameStruct.canvas.width;
        this.shiftX = this.width / 8;
        this.shiftY = this.height / 8;
        console.log("Joystick initialized");
        return this;
    }

    draw() {
        this.ctx.drawImage(this.gameStruct.imgDownArrow, this.x, this.y, this.width, this.height);
        addEventListener("click", function() {
            console.log("clicked");
        });
        return this.gameStruct;
    }
}

(Код одинаков для классов Left, Right и Up. Единственное отличие состоит в их положении (X и Y) и их изображение в drawImage).

Как вы можете видеть в моем коде, я пытался добавить addEventListener ("click"), но когда я тестирую его в веб-браузере, он работает, когда я нажимаю в любом месте экрана. Однако я хочу, чтобы он работал только при нажатии каждого объекта (Вниз, Влево, Вправо и Вверх).

Я также пытался использовать this.addEventListener, но теперь он тоже работал.

Вот что происходит, когда я нажимаю Вниз:

enter image description here

Кроме того, я не понимаю, почему он печатает "щелчок" так много раз. Я нажал стрелку вниз только один раз! Таких как 600 отпечатков! Это должен быть только один из Down.js.

Кто-нибудь может помочь?

1 Ответ

1 голос
/ 03 мая 2020

Причина, по которой этот щелчок запускается так много раз, заключается в том, что вы добавляете прослушиватель событий в функцию рисования, которая вызывается каждый кадр и по одному разу для каждой кнопки. Если игра работает на скорости 60 кадров в секунду и работает всего одну секунду, это 240 слушателей событий, которые делают одно и то же!

Слушатели событий не go уходят, поэтому вам нужно добавить только один , Также, просто наличие addEventListener() добавляет прослушиватель событий к объекту документа. Это не проблема, так как ваш холст занимает весь экран, но вы можете прикрепить слушатель событий к холсту специально с помощью this.canvas.addEventListener() (внутри класса игры). Я думаю, что это будет лучше всего работать в функции инициализации.

Теперь о регистрации в кнопках только нажатия: К сожалению, вы не можете добавлять прослушиватели событий к объектам, которые не являются HTML узлами. Единственный способ обойти это - добавить прослушиватель событий, который запускается каждый раз, когда вы нажимаете на холст, а затем l oop через все кнопки, проверяя, был ли щелчок в пределах кнопок. .

Функция в прослушивателе событий может иметь параметр

class Game {
    //...
    initialize() {
        //...

        // I put the buttons in an array so that you can loop through them.
        let buttons = [this.joystickDown, this.joystickUp, this.joystickLeft, this.joystickRight];
        this.canvas.addEventListener('mousedown', function(evt) {
            // The X and Y coordinates of the mouse, relative to the top left corner
            let x = evt.clientX;
            let y = evt.clientY;

            for (let button of buttons) {
                // checkClick is a method you'll have to add to the joystick classes. It'll
                // take in X and Y coordinates and tell if they are within the button.
                if (button.checkClick(x, y)) {
                    // This is a method you'll have on the joystick classes to handle the click.
                    button.handleClick();
                }
            }
        });
        //...
    }
    //...
}

Надеюсь, я не допустил ошибок в этом ... Вы заметите, что я заменил событие "click" с «mousedown», потому что событие щелчка не срабатывает, пока вы не отпустите кнопку go, но mousedown срабатывает, когда вы нажимаете кнопку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...