collinhover / impactplusplus

Impact++ is a collection of additions to ImpactJS with full featured physics, dynamic lighting, UI, abilities, and more.
http://collinhover.github.com/impactplusplus
MIT License
276 stars 59 forks source link

Offset updating 1 frame too late #169

Closed itsOgden closed 10 years ago

itsOgden commented 10 years ago

I have an entity that requires 2 animations sheets. I'm using the methods used by vicman4 on the impactJS Forums to make the change. The issue I have is that the second animation is much taller than the original. To compensate, I change the offset.y of the entity. This particular entity doesn't have any collision, so I don't have to update the size.

In my update I change the animation and the offset at the exact same time. The issue is that when I do that, it takes the offset an extra tick to kick in so that the animation is in the wrong place for 1 frame every time I change the animation.

I am guessing it might be linked to https://github.com/collinhover/impactplusplus/issues/148, but I am not sure. Any ideas?

collinhover commented 10 years ago

@itsOgden just had time to look into this a bit. Are you updating your animation and offset during the entity's updateChanges method? That should take place before the recordChanges method, but keep in mind that offset changes are not recorded. Have you modified the entity's recordChanges and recordLast methods?

itsOgden commented 10 years ago

@collinhover I have modified recordChanges and recordLast, and I'm updating the offset and animation during the standard update. Updating it fixed an issue where during one animation switch it wouldn't change the offset at all, so that is gone, but the 1 frame delay still exists.

collinhover commented 10 years ago

Can you post the code for your update method where you do the animation and offset changes?

itsOgden commented 10 years ago

It's a little messy; not sure if you'll be able to tell what's going on, but here it is:

update: function(){
    this.parent();
    if(this.queue[0] && this.currentAnim != this.anims.exit){

        if(this.alpha == 0){
            this.enter();
        }
        else if((this.currentAnim == this.anims.enter && this.currentAnim.frame == this.currentAnim.sequence.length - 1) || this.currentAnim != this.anims.enter && this.currentAnim != this.anims['place' + this.queue[0].item]){
            this.moveMe();
        }
        else if (this.currentAnim == this.anims['place' + this.queue[0].item] && this.currentAnim.frame == this.currentAnim.sequence.length - 1) this.place();
    }
    else if(this.currentAnim == this.anims.exit && this.currentAnim.frame == this.currentAnim.sequence.length - 1){
        this.alpha = 0;
        this.currentAnim = this.anims.enter;
    }

},

exit: function(){
    this.offset.y = 896;
    this.type = ig.Entity.TYPE.NONE;
    this.currentAnim = this.anims.exit;
    this.currentAnim.playFromStart();
},

enter: function(){
    this.type = ig.Entity.TYPE.B;
    this.flip.x = false;
    this.pos = {x: 1024, y: 576 };
    this.currentAnim = this.anims.enter;
    this.currentAnim.playFromStart();
    this.alpha = 1;
},

idle: function(){
    this.offset.y = 128;
    this.currentAnim = this.anims.idle;
    this.currentAnim.playFromStart();
},

place: function(){ //place item
    var entity = this.queue[0].entity;

    if(this.queue[0].item == 'box'){
        entity.place();
    }
    this.posNeg = null; //allow move to be positive or negative for next item
    this.queue.splice(0,1); //remove item from queue
    if(!this.queue[0]){
        this.moving = false;
        this.exit();
    }
    else this.moveMe();
},

moveMe: function(){
    //determines if we should be moving left or right
    if(!this.posNeg){
        this.idle();
        if(this.queue[0].location.x > this.pos.x){
            this.flip.x = true;
            this.posNeg = -1;
        }
        else{
            if(this.queue[0].location.x < this.pos.x) this.flip.x = false;
            else this.flip.x = true;
            this.posNeg = 1;
        }
    }

    //determines position movement offsets
    var X = this.pos.x - this.queue[0].location.x,
        Y = this.pos.y - this.queue[0].location.y,
        S = this.speed,
        D = Math.sqrt((X*X) + (Y*Y)), //distance from player to endpoint
        a = Math.asin(Y / D), //angle from x axis
        b = S * Math.cos(a), //x offset per tick
        c = S * Math.sin(a); //y offset per tick

    //sets position each tick
    this.pos.x = this.pos.x - (b * this.posNeg);
    this.pos.y = this.pos.y - c;

    //checks to see if we have arrived at our destination
    if((this.queue[0].location.x >= this.pos.x && this.posNeg == 1) || (this.queue[0].location.x <= this.pos.x && this.posNeg == -1)){var entity = this.queue[0].entity;
        if(this.queue[0].entity.pos.x < this.pos.x){
            this.flip.x = false;
        }
        else {
            this.flip.x = true;
        }
        this.currentAnim = this.anims['place' + this.queue[0].item];
        this.currentAnim.playFromStart();
    }
},
collinhover commented 10 years ago

I'm pretty sure the issue is that you're calling this.parent() before updating your offset. The super class update will record all the changes made before you do your changes, hence the 1 frame delay. This is part of why I broke down the update method into several smaller parts, to avoid sequencing issues like this. Have you tried using the updateChanges method or just doing your changes before calling parent?

itsOgden commented 10 years ago

Didn't even think about that! Thank you very much, that seems to have solved the problem. I really appreciate the help again, @collinhover.