4

Say you've got a tile image that you use to build an isometric map. Each tile is selectable. The problem is that the transparent corners around the tile image are overlapping the tiles behind them. I want the transparent area of the image to be ignored so that the other tiles can be more accurately selected.

Here is an example of such a tile. The outline has been made red so its easy to see the transparent area.

enter image description here

We're using a browser that supports pointer-event. I was wondering if there was a way to incorporate that into the corner areas, or if I need to find a way to have the program recognize the transparent pixels on their own.

These tile images are not built using canvas. The CSS is simply this:

div.content 
{
   position: absolute;
   top: 105px;
   width: 10px;
   height: 50%;
}

div.content div.tile 
{
   width:96px;
   position: absolute;
   height:102px;
   line-height:96px;
   background-image:url('images/tiles.png');
}

div.content div.tile:hover 
{ 
   opacity:0.8; 
}
Briz
  • 175
  • 1
  • 2
  • 12

4 Answers4

2

As far as I know, pointer-event applies only to SVG elements.

What I would do

  1. create a canvas element for each tile, having the size of the tile
  2. draw the tiles into each canvas
  3. get the imageData from each canvas context and store it somewhere
  4. mousedown events provide coordinates, get the pixel color from that tiles imageData and check it's alpha value.

edit:

Rethinking it, there could be complications with events, since the tiles in the foreground will probably cover the tiles behind them.
You'll probably have to let the mousedown events bubble to the container element and manually select the tiles which are "hit" by the click and perform the "per pixel check" on all those.

Roman
  • 5,888
  • 26
  • 47
  • You have to note however that drawing to the the HTML5canvas is (still) extremely slow, so using multiple canvases and rendering extensive content like an isometric RPG game in them is likely to cost tons of calculation time. – Qqwy Nov 30 '11 at 16:39
  • @Qqwy, He draws the tiles only once, while loading the game or whatever. It's just to access the imageData. If the tiles all have the same size, he could also use only 1 canvas element, clearing it for each tile. And... canvas isn't that slow, I get decent fps (60+) drawing fullHD canvases with thousands of pixel manipulations (particle system) each frame on my mediocre notebook. – Roman Nov 30 '11 at 16:46
  • Upvoted for providing links to various steps. I'll have to wait for tomorrow to select a final answer as I'll have more time to think about each answer then. – Briz Nov 30 '11 at 16:49
0

I would try and do something like what is outlined in this question in order to get the color of the pixel that is under your mouse. once you have that, you can say that when there is a click, for it not to select the tile if the color of that pixel is equal to the color of your background (white looks like).

Community
  • 1
  • 1
Evan
  • 5,975
  • 8
  • 34
  • 63
0

You could:

  1. use HTML Image Maps:HTML Image Maps. This is a simple option. The con is however that you need to create a map of all tiles yourself.

  2. I know that some people created an Isometric game engine used a Canvas object not to draw things, but just to calculate if the mouse clicked on a transparent tile to delegate the onclick event to the next tile. Explanation of the project including their mouse event delegation can be found here.

Qqwy
  • 5,214
  • 5
  • 42
  • 83
0

i would suggest:

  1. create a canvas of the size of a tile

  2. on a mouse event (hover, click, whatever) you draw the tile that caused the event to that canvas

  3. get the alpha value and bind the counter-event to reset canvas

3.1. if alpha is zero delegate the event to the geometric next tile (right-top, left-top, right-bottom or left-bottom) and execute actions there

3.2. if alpha is greater zero execute actions on tile that caused event

this will only draw to canvas if neccessary and thereby saves some calculation time

zuloo
  • 1,310
  • 1
  • 8
  • 12