Ok I've worked out what is going on here. Dynamic collisions (between entities) are detected during a game cycle. ImpactJS tries to determine upfront if there will be a collision (which is why sometimes small entities collide after they've overlapped or don't collide at all). Dynamic Collision detection uses the last.x and last.y positions + the size.x and size.y of an entity to determine when they overlap. You can see this in ig.Entity.js at the ig.Entity.solveCollision() function.
Under the scenes, Entity.init actually sets this.pos.x and this.pos.y to the x,y parameters of the function, but it doesn't set the last.x and last.y. These are 0. When you don't add a function to your NPC class, it still calls the parent() method, hence the x,y positions being set of your npc initially as it calls the parent.init(). Your empty update() method though never updates the last.x and last.y positions as it doesn't call the parent. As such the last.x and last.y positions never get updated from 0,0.
You mentioned this worked for you when you switched the extend to use ig.Entity directly. Did you change the same example, or did you knock up a new example where the npc happened to be at 0,0? If it was 0,0 then this would still work.
To get this working with your example, you would just need to add an init method to your npc class that looks like this.
init:function(x,y,settings){
this.last.x =x;
this.last.y = y;
this.parent(x,y,settings);
},
Then just provide your empty version of update();
Alternatively if you're feeling really adventurous, you could update ig.Entity.init to include
this.last.x =x;
this.last.y = y;
I'm going to post this suggestion for Entity regardless, as it might be worth including, or Dominic might have a good reason for doing this for other calculations