sbiermanlytle / iioEngine

iio Engine: A JavaScript game engine for HTML5 Canvas
http://iioengine.com
455 stars 81 forks source link

Don't assign objects to a group, when using io.addObj #4

Closed tyilo closed 11 years ago

tyilo commented 11 years ago

When running the following app's code it will fail to run:

TestApp = function(io) {
    var obj1 = new iio.ioRect(10, 10, 20, 20)
        .setFillStyle('blue')
        .enableKinematics()
        .setVel(1, 0);
    io.addObj(obj1);
    io.addToGroup('obj1', obj1);

    var obj2 = new iio.ioRect(50, 10, 20, 20)
        .setFillStyle('red')
        .enableKinematics()
        .setVel(-1, 0);
    io.addObj(obj2);
    io.addToGroup('obj2', obj2);

    io.setCollisionCallback('obj1', 'obj2', function(obj1, obj2) {
        // Dummy
    });

    io.addObj(new iio.ioText('Test', io.canvas.width - 275, 30)
        .setFont('20px Consolas')
        .setFillStyle('blue'));

    io.setFramerate(60);
};

If you, however, moving the text creating code to the top of the function will work:

TestApp = function(io) {
    io.addObj(new iio.ioText('Test', io.canvas.width - 275, 30)
        .setFont('20px Consolas')
        .setFillStyle('blue'));

    var obj1 = new iio.ioRect(10, 10, 20, 20)
        .setFillStyle('blue')
        .enableKinematics()
        .setVel(1, 0);
    io.addObj(obj1);
    io.addToGroup('obj1', obj1);

    var obj2 = new iio.ioRect(50, 10, 20, 20)
        .setFillStyle('red')
        .enableKinematics()
        .setVel(-1, 0);
    io.addObj(obj2);
    io.addToGroup('obj2', obj2);

    io.setCollisionCallback('obj1', 'obj2', function(obj1, obj2) {
        // Dummy
    });

    io.setFramerate(60);
};

Also adding io.addGroup('text'); before the text creation will work.

It seems as if iio defaults the group of an object to the latest group defined. It should instead assign the text object to the undefined group, where it would be if the code was executed at the beginning of the function.

Bahlor commented 11 years ago

I believe it's correct as it is. It automatically creates a group based on z-index. In your case it would be enough to use io.addToGroup('obj1',obj1); instead of first using io.addObj(obj1); io.addToGroup('obj1',obj1);

iio seems to automatically use addObj when calling addToGroup();

ioAppManager.prototype.addToGroup = function(tag, obj, zIndex, c){
      c=c||0;
      var i = this.indexOfTag(tag, c);
      var a = iio.isNumber(i);
      if (typeof(this.cnvs[c].groups)=='undefined'||!a) 
         i = this.addGroup(tag, zIndex, c);
      this.cnvs[c].groups[i].addObj(obj, c);   // calls addObj by default
      return obj;
   }

ioAppManager.prototype.addObj = function(obj, zIndex, c){
      c=c||0;
      if (typeof(this.cnvs[c].groups)=='undefined') this.cnvs[c].groups = [];
      zIndex = zIndex || 0;
      for (var i=0; i<this.cnvs[c].groups.length; i++)
         if (this.cnvs[c].groups[i].zIndex == zIndex){
            this.cnvs[c].groups[i].addObj(obj);
            if (typeof this.fps == 'undefined' && typeof obj.pos!='undefined')
               obj.draw(this.ctxs[c]);
            return obj;
         }
      this.addGroup(zIndex, zIndex, c); 
      this.addToGroup(zIndex, obj, zIndex, c);
      if (typeof this.fps == 'undefined' && typeof obj.pos!='undefined')
         obj.draw(this.ctxs[c]);
      return obj;
   }
tyilo commented 11 years ago

My code works now, but shouldn't you be able to add an object without it having a group?

sbiermanlytle commented 11 years ago

Having a single management structure simplifies the architecture. The functions 'addObj' and 'rmvObj' are there to allow you to pretend the group structure doesn't exist. All the group does is add one more pointer between the array of objects and the functions that access it, so I don't think the phantom group should effect efficiency.

I may be wrong about that though - let me know if my reasoning is incorrect, it would be pretty easy to add this option, but the code would get a bit messier.

tyilo commented 11 years ago

I don't see why the code I posted in the first post shouldn't work. I now know why it doesn't, but I think it is wrong to just add an object to the first group with the required z-index if the group isn't specified.

At least if you want to keep it that way, could every ioAppEngine start out with an empty group called _default (or something else) with a z-index at 0?

That way every object created with just io.addObj would be added to the _default group, which shouldn't normally have any collision detection going on.

sbiermanlytle commented 11 years ago

Wait, I think there might be some confusion. This code

io.addObj(obj1);
io.addToGroup('obj1', obj1);

is redundant - 'addToGroup' calls 'addObj' for you, and if no group exists, 'addObj' will call 'addToGroup' for you.

If you don't want to deal with groups, just call this:

io.addObj(obj1);

and a default group at zIndex 0 with the tag 0 will be created automatically.

tyilo commented 11 years ago

The problem is that if I do this:

var cake = io.addToGroup('cakes', new iio.ioRect());

// Tons of unrelated code...

var notCake = io.addObj(new iio.ioText());

Now notCake will be in the group cakes, even though I didn't specify the group for notCake!

sbiermanlytle commented 11 years ago

That's true. I have altered 'addObj' to only add the given obj to an existing group if group's tag is 0 (Number 0). The update has been merged with the git distribution, your code should work with it.