Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I need to draw some 2D objects on a canvas. And I need to map the 2D coordinates of clicks to objects.

What is the usual way to maintain a 2D object's size and position (which data structures, etc.)? What's the effective way to say: this object is at coordinates (x, y)?

share|improve this question

2 Answers 2

up vote 1 down vote accepted

Iterating through an array of objects checking for their intersection with a given point would be an effective method. But a more efficient method would be using a spatial subdivision data structure like a Quadtree.

share|improve this answer
    
Thnx, Quadtree is, what i was looking for! –  Skip Nov 28 '12 at 8:37
    
It's true. Still, it depends on the item count. There is quite a cost for a QuadTree, so maybe if there are less than 20 items an array is better, and if you have more than 50 items you can be sure a Quadtree will be way better. –  GameAlchemist Nov 28 '12 at 10:30

I don't know if you are using a Game Framework, so i will give you here a few hints using 'standard' javascript. You might have to adapt them to your Framework.

So let us say we have a 'namespace' gg:

 var gg={};

We create an array containing all our graphic objects :

 var gg.GraphicObjects = [];

We add a method to add a graphic object :

 var gg.addGraphicObject = function (x, y, width, height, parameters)
  {
     var newGraphicObject = { x:x, y:y, width: width, height : height, 
              id : parameters.id, clickCallback : parameters.clickCallback , 
              hoveringCallback : parameters.hoveringCallback };
     gg.GraphicObjects.push( newGraphicObject );
     return newGraphicObject;
  }

parameters containing : id : string identifying the object, hoveringCallback : ..., clickCallback : ... , and you might think of other properties.

Rq that you must bind the callbacks if you reference to 'this' in the callbacks :

 var myObjectHandle = gg.addGraphicObject(100,100,60,60, { id : 'start',
                                    clickCallBack: this.start.bind(this) });

then you must handle click, which is done like this in a standard way (again, your framework might handle it allready) :

// myCanvas is the main page canvas ( = document.getElementById('myCanvasName'); )
myCanvas.addEventListener('click', on_click, false);
var  on_click = function(ev) {
    var mx = ev.clientX ;  //- CanvasLeftOffset ; if you use offsets (offsetLeft)
    var my = ev.clientY ; // - CanvasTopOffset ;  if you use offsets  (offsetTop)
    for (var i=0; i <gg.GraphicObjects.lenght ; i++) {
       var gObj=gg.GraphicObjects[i];
       if (gg._inRect(mx, my, gObj) ) 
          {
            if (gObj.clickCallBack) { gObj.clickCallBack(); }
          }
     }
 } 

 gg._inRect : function(x, y, gObj ) {
         return   x >= gObj.x               &&
                  x <  gObj.x + gObj.width   &&
                  y >= gObj.y               &&
                  y <  gObj.y + gObj.height;
    }

if you want to handle mouseOver, it's a little bit trickyer (?), since the mousemove event is just triggering too often and is annoying... but you can cool it down using a setTimeout in this way :

gg.mouseMoveRefresh = 30; // number of mouse move refresh per second

gg._onmousemove =   function() {
   for (var i=0; i <gg.GraphicObjects.lenght ; i++) {
       var gObj=gg.GraphicObjects[i];
       if (gg._inRect(mx, my, gObj) ) 
          {  
            gObj.isMouseOver = true;
            if (gObj.hoveringCallback ) { gObj.hoveringCallback (); }
          }
        else gObj.isMouseOver = false; 
     }
    myCanvas.onmousemove= null;
    setTimeout( gg.onMouseMoveSet, 1000 / gg.mouseMoveRefresh);
     }

gg.onMouseMoveSet =  function() {
    myCanvas.onmousemove = gg._onmousemove; 
  }

gg.onMouseMoveSet();

Notice that if you resize your canvas you might have to set again event listeners (i couldn't get a clear opinion about this behaviour cross-browsers/OS/versions/etc...).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.