简体   繁体   中英

Creating Mouse Event Handlers For Canvas Shapes

I'm coding a tile based game in javascript using canvas and was wondering how I could create a simple event handler for when the mouse enters the dimensions of a tile.

I've used jquery's http://api.jquery.com/mousemove/ in the past but for a very simple application but can't seem to wrap my head around how I'll do it in this case (quickly).

Hmm..

I started writing this post without a clue of how to do it, but I just tried using the jquery mousemove like I started above. I have a working version, but it seems 'slow' and very clunky. It's doesn't seem smooth or accurate.

I put all mode code into a js fiddle to share easily: http://jsfiddle.net/Robodude/6bS6r/1/

so what's happening is:

1) jquery's mousemove event handler fires

2) Sends the mouse object info to the GameBoard

3) Sends the mouse object info to the Map

4) Loops through all the tiles and sends each one the mouse object

5) the individual tile then determines if the mouse coords are within its boundaries. (and does something - in this case, I just change the tiles properties to white)

but here are the sections I'm most concerned about.

        $("#canvas").mousemove(function (e) {
            mouse.X = e.pageX;
            mouse.Y = e.pageY;
            game.MouseMove(mouse);
            Draw();
        });



function GameBoard() {
    this.Map = new Map();
    this.Units = new Units();

    this.MouseMove = function (Mouse) {
        this.Map.MouseMove(Mouse);
    };
}


function Map() {
    this.LevelData = Level_1(); // array
    this.Level = [];
    this.BuildLevel = function () {
        var t = new Tile();
        for (var i = 0; i < this.LevelData.length; i++) {
            this.Level.push([]);
            for (var a = 0; a < this.LevelData[i].length; a++) {
                var terrain;
                if (this.LevelData[i][a] == "w") {
                    terrain = new Water({ X: a * t.Width, Y: i * t.Height });
                }
                else if (this.LevelData[i][a] == "g") {
                    terrain = new Grass({ X: a * t.Width, Y: i * t.Height });
                }
                this.Level[i].push(terrain);
            }
        }
    };
    this.Draw = function () {
        for (var i = 0; i < this.Level.length; i++) {
            for (var a = 0; a < this.Level[i].length; a++) {
                this.Level[i][a].Draw();
            }
        }
    };

    this.MouseMove = function (Mouse) {
        for (var i = 0; i < this.Level.length; i++) {
            for (var a = 0; a < this.Level[i].length; a++) {
                this.Level[i][a].MouseMove(Mouse);
            }
        }
    };

    this.BuildLevel();
}

    function Tile(obj) {
        //defaults
        var X = 0;
        var Y = 0;
        var Height = 40;
        var Width = 40;
        var Image = "Placeholder.png";
        var Red = 0;
        var Green = 0;
        var Blue = 0;
        var Opacity = 1;

// ...

        this.Draw = function () {
            ctx.fillStyle = "rgba(" + this.Red + "," + this.Green + "," + this.Blue + "," + this.Opacity + ")";
            ctx.fillRect(this.X, this.Y, this.Width, this.Height);
        };
        this.MouseMove = function (Mouse) {
            if ((Mouse.X >= this.X) && (Mouse.X <= this.Xmax) && (Mouse.Y >= this.Y) && (Mouse.Y <= this.Ymax)) {

                this.Red = 255;
                this.Green = 255;
                this.Blue = 255;
            }
        };
    }

If you have a grid of tiles, then given a mouse position, you can retrieve the X and Y index of the tile by dividing the X mouse position by the width of a tile and Y position with the height and flooring both.

That would make Map 's MouseMove :

this.MouseMove = function (Mouse) {
    var t = new Tile();
    var tileX = Math.floor(mouse.X / t.Width);
    var tileY = Math.floor(mouse.Y / t.Height);
    this.Level[tileY][tileX].MouseMove(Mouse);
};

Edit: You asked for some general suggestions. Here you go:

  • It's more common to use initial uppercase letters for only classes in JavaScript.
  • Mouse is a simple structure; I don't think it needs to have its own class. Perhaps use object literals. (like {x: 1, y: 2} )
  • You may want to use JavaScript's prototype objects, rather than using this.method = function() { ... } for every method. This may increase performance, since it only has to create the functions once, and not whenever a new object of that class is made.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM