GameMaker Held item lags behind while moving

I made an off-hand item which I'm having move based on obj.player's x and y, + or - fixed distances based on obj.player's current animation frame to account for the position of the character's hand as the sprite cycles through its animation. It works perfectly if the player is against a wall (the animation playing while the player's x,y doesn't change), but when obj.player it actually moving, the off-hand item appears behind it, only catching up once obj.player hits a collision. Similarly, the off-hand item doesn't accurately follow obj.player while jumping, and I can't figure out why that is.

Here's the off-hand item's movement code:

Code:
var facingRight = global.facingRight;

if(facingRight = false){
    switch(global.player_xFrame){
        case 0:
            image_angle = 135;
            x = obj_player.x+6;
            y= obj_player.y-24;
        break;
        
        case 2:
            image_angle = 135;
            x = obj_player.x+6;
            y= obj_player.y-24;
        break;

        case 1:
            image_angle = 175;
            x = obj_player.x+16;
            y= obj_player.y-30;
        break;
        
        case 3:
            image_angle = 95;
            x = obj_player.x-6;
            y= obj_player.y-20;
        break;
    }
}

else{
    switch(global.player_xFrame){
        case 0:
            image_angle = 225;
            x = obj_player.x-6;
            y= obj_player.y-24;
        break;
        
        case 2:
            image_angle = 225;
            x = obj_player.x-6;
            y= obj_player.y-24;
        break;

        case 1:
            image_angle = 185;
            x = obj_player.x-16;
            y= obj_player.y-30;
        break;
        
        case 3:
            image_angle = 265;
            x = obj_player.x+6;
            y= obj_player.y-20;
        break;
    }
}
Thanks!
 

samspade

Member
Position is just a number (two numbers) so if something isn't where you want there's really only a few possibilities: (1) things are updated in the wrong order; or (2) there's a mistake in the math/code.

For update order, perhaps player's x for a frame is updated after player's x is used to update this x. It also looks like you are basing the x on a specific frame index. So you'd also need to account for that as well.

Otherwise double check all your math (and things the math is based off of). This could be off not only with the math you've used, but also with sprite origin positioning itself. This seems unlikely since you said it goes away, but given how you're doing it it seems like it would be easy to make a mistake. Remember that these could be affected by things like scale and rotation as well.
 

woods

Member
side note...probably unrelated but...

just curios why is case 0 and case 2 the exact same?

;o) could be a typo and causing issues?
 
side note...probably unrelated but...

just curios why is case 0 and case 2 the exact same?

;o) could be a typo and causing issues?
Because there are only 4 frames in this animation and frames 0 and 2 are identical, so this shouldn't affect anything.

I'm wondering if it has to do with the fact that frame_x is incremented in obj.player's draw event. If so, I guess I have to also have the item object draw itself for it to occur at the same time? I don't understand the timing of draw events yet.
 

samspade

Member
Because there are only 4 frames in this animation and frames 0 and 2 are identical, so this shouldn't affect anything.

I'm wondering if it has to do with the fact that frame_x is incremented in obj.player's draw event. If so, I guess I have to also have the item object draw itself for it to occur at the same time? I don't understand the timing of draw events yet.
You should not be incrementing the frame in the draw event. Not only would that cause this problem, for the reasons stated in my earlier post, if you ever have more than one view it will play at the wrong speed as the draw event fires once for each view. In short, remember (and follow) the manual's suggestion to only have draw code in the draw event.
 
Tried a few more thing and it still doesn't give the expected result...


Now only the actual draw functions are in obj.player's draw event. The following is in obj.player's step event

Code:
//speed up animation while running

if(run_pressed){
    var animationSpeed = 9;
}
else{
    animationSpeed = 6;
}

//select spritesheet row based on the direction the player is facing

if(moveX < 0) {
    y_frame = 0;
    global.facingRight = false;
    global.player_xFrame = x_frame;
    global.player_yFrame = y_frame;
}
else if(moveX > 0){
    y_frame = 1;
    global.facingRight = true;
    global.player_xFrame = x_frame;
    global.player_yFrame = y_frame;
}
else{
    x_frame = 0;  
    global.player_xFrame = x_frame;
    global.player_yFrame = y_frame;
}

//change animation while in mid-air
if(!place_meeting(x,y+1, obj_meta_colliderParent)){
    if(y < 0){
        if (global.facingRight = true) {
            x_frame = 0;
            y_frame = 2;
            global.player_xFrame = x_frame;
            global.player_yFrame = y_frame;
        }
        else{
            x_frame = 1;
            y_frame = 3;
            global.player_xFrame = x_frame;
            global.player_yFrame = y_frame;
        }
    }
    else if(global.facingRight = false){
        x_frame = 3;
        y_frame = 2;
        global.player_xFrame = x_frame;
        global.player_yFrame = y_frame;  
    }
    else{
        x_frame = 3;
        y_frame = 3;
        global.player_xFrame = x_frame;
        global.player_yFrame = y_frame;
    }

}

//increment frame for animation
if(x_frame + animationSpeed/60 < animationLength){
    x_frame += animationSpeed/60;
    }
else{
    x_frame = 0;
    }
and this is in the item object's end step event

Code:
//position held in off-hand
var facingRight = global.facingRight;

if(facingRight = false){
    switch(global.player_xFrame){
        case 0:
            image_angle = 135;
            x = obj_player.x+6;
            y= obj_player.y-24;
        break;
       
        case 2:
            image_angle = 135;
            x = obj_player.x+6;
            y= obj_player.y-24;
        break;

        case 1:
            image_angle = 175;
            x = obj_player.x+16;
            y= obj_player.y-30;
        break;
       
        case 3:
            image_angle = 95;
            x = obj_player.x-6;
            y= obj_player.y-20;
        break;
    }
}

else{
    switch(global.player_xFrame){
        case 0:
            image_angle = 225;
            x = obj_player.x-6;
            y= obj_player.y-24;
        break;
       
        case 2:
            image_angle = 225;
            x = obj_player.x-6;
            y= obj_player.y-24;
        break;

        case 1:
            image_angle = 185;
            x = obj_player.x-16;
            y= obj_player.y-30;
        break;
       
        case 3:
            image_angle = 265;
            x = obj_player.x+6;
            y= obj_player.y-20;
        break;
    }
}
 
Last edited:

samspade

Member
the end step code uses the global.player_xFrame which is still be updated before x_frame is incremented. Try moving this code to the beginning of the player step event:

Code:
//increment frame for animation
if(x_frame + animationSpeed/60 < animationLength){
   x_frame += animationSpeed/60;
   }
else{
   x_frame = 0;
   }
 
the end step code uses the global.player_xFrame which is still be updated before x_frame is incremented. Try moving this code to the beginning of the player step event:

Code:
//increment frame for animation
if(x_frame + animationSpeed/60 < animationLength){
   x_frame += animationSpeed/60;
   }
else{
   x_frame = 0;
   }
I tried it, but it didn't fix the issue. Any other thoughts?
 

TsukaYuriko

☄️
Forum Staff
Moderator
Instead of letting things follow the player, consider making the player drag things along. That is, move the thing in the player's code, not in the thing's code. That way, you can ensure this happens after all movement has been applied to the player.

That aside, check your Draw code and make sure they match. Ensure that both the player and the thing are using the same rounding, no mix-and-matching between round/floor/ceil or absence of either.
 
Instead of letting things follow the player, consider making the player drag things along. That is, move the thing in the player's code, not in the thing's code. That way, you can ensure this happens after all movement has been applied to the player.

That aside, check your Draw code and make sure they match. Ensure that both the player and the thing are using the same rounding, no mix-and-matching between round/floor/ceil or absence of either.
I would love to be able to avoid the positioning issue like that, but then I'd still have collision issues so I can't take a shortcut this time.

Edit: When I first read your post I thought of it in terms of drawing the object, but then I realized that you were talking of actually moving it so I tried to add the modified code to the player's step and it still didn't work.
 
Last edited:
Top