SalTheThief
Member
Hey all,
I've been having this weird but subtle stutter with my grid based movement. I used a tutorial from @GMWolf (found here:
). I don't believe it to be animation based, but I could be wrong on that count. I've slowed my animation speed down a lot because it's harder to see when things are moving at full speed.
It seems as if the character is ever-so-slightly being warped back a bit. I believe this is caused by the walk_anim_length variable because if I change it back to 0.5 or even 0.4 I don't notice the stutter. However, when I change walk_anim_length to 0.1, the stutter becomes more apparent:
That's as far as I've been able to figure it out. Here is my relevant code:
I've been having this weird but subtle stutter with my grid based movement. I used a tutorial from @GMWolf (found here:
It seems as if the character is ever-so-slightly being warped back a bit. I believe this is caused by the walk_anim_length variable because if I change it back to 0.5 or even 0.4 I don't notice the stutter. However, when I change walk_anim_length to 0.1, the stutter becomes more apparent:
That's as far as I've been able to figure it out. Here is my relevant code:
GML:
//States for state machine
enum states {
idle,
walking,
locked,
running
}
state = states.idle;
//Movement based variables
x_pos = x div tile_width;
y_pos = y div tile_height;
x_from = x_pos;
y_from = y_pos;
x_to = x_pos;
y_to = y_pos;
walk_anim_length = 0.1;
walk_anim_time = 0;
inputMagnitude = 0;
timeWalk = 0;
moveFinished = true;
timeToMove = 0.6;
moveBuffer = 0;
facing = -1;
//Animation
image_speed = 0;
anim_speed = 0;
x_frame = 1;
y_frame = 0;
//Collision
var tile_layer = layer_get_id("Walls");
tile_map = layer_tilemap_get_id(tile_layer);
//Dialogue
portrait_index = 3;
voice = sndVoice1;
_name = "Player";
radius = 16;
active_textbox = noone;
can_move = true;
spotted = noone;
sprinting = false;
GML:
//Controls
input_interact = keyboard_check_pressed(ord("E"));
moveLeft = keyboard_check(vk_left)
moveRight = keyboard_check(vk_right)
moveUp = keyboard_check(vk_up)
moveDown = keyboard_check(vk_down)
//Check for player direction
inputDirection = point_direction(0,0,moveRight-moveLeft,moveDown-moveUp);
//Check for player input
inputMagnitude = (moveRight - moveLeft != 0) || (moveDown - moveUp != 0);
if(inputMagnitude != 0)
{
//moveBuffer exists so that a player can change direction without moving
moveBuffer += 0.1;
}
//Check for dialogue. If in a conversation, do not allow movement.
if (!instance_exists(objTextBox) && can_move == true)
{
//Do not allow player to change directions if they are currently moving
if(inputMagnitude != 0 && moveFinished == true)
{
switch(inputDirection)
{
case 0:
facing = directions.right;
if(moveBuffer > timeToMove) move(directions.right);
break;
case 90:
facing = directions.up;
if(moveBuffer > timeToMove) move(directions.up);
break;
case 180:
facing = directions.left;
if(moveBuffer > timeToMove) move(directions.left);
break;
case 270:
facing = directions.down;
if(moveBuffer > timeToMove) move(directions.down);
break;
}
}
}
//Code to apply movement to next tile
if (state == states.walking) {
moveFinished = false;
walk_anim_time += delta_time / 1000000;
timeWalk = walk_anim_time / walk_anim_length;
//Reset variables so the code can be re-used to move to next tile
if (timeWalk >= 1)
{
walk_anim_time = 0;
timeWalk = 1;
state = states.idle;
moveFinished = true;
}
//Move from old tile to new tile
var _x = lerp(x_from, x_to, timeWalk);
var _y = lerp(y_from, y_to, timeWalk);
//Only move in increments of 32.
x = _x * tile_width;
y = _y * tile_height;
}
//Set facing to -1 if player has finished moving and there is no input
if (state == states.idle && inputMagnitude == 0)
{
facing = -1;
//Reset moveBuffer so that a player can again change directions without moving
moveBuffer = 0;
}
//Code used for room transitions to make sure that the player is facing the correct way when entering a new room
var transInst = instance_place(x, y, objTransition);
if(transInst != noone && facing == transInst.playerFacingBefore){
with(objGame){
if(!doTransition) {
spawnRoom = transInst.targetRoom;
spawnX = transInst.targetX;
spawnY = transInst.targetY;
spawnPlayerFacing = transInst.playerFacingAfter;
doTransition = true;
}
}
}
//Textbox code. Used to interact with NPCs and world objects.
if(input_interact){
if(active_textbox == noone){
var inst = collision_rectangle(x-radius, y-radius, x+radius, y+radius, parNPC, false, false);
if(inst != noone){
with(inst){
var tbox = CreateTextbox(text, speakers, next_line, scripts);
can_move = false;
}
active_textbox = tbox;
}
}
}
GML:
/// @desc
var anim_length = 4;
var frame_size = 64;
var offset = 6;
switch(facing){
case directions.right: if(sprinting == false) y_frame = 7;
if (x_from < x_to && state == states.walking && sprinting == false) anim_speed = 8;
else if (x_from < x_to && state == states.walking && sprinting == true) y_frame = 11;
break;
case directions.left: if(sprinting == false) y_frame = 6;
if (x_from > x_to && state == states.walking && sprinting == false) anim_speed = 8;
else if (x_from > x_to && state == states.walking && sprinting == true) y_frame = 10;
break;
case directions.up: if(sprinting == false) y_frame = 5;
if (y_from > y_to && state == states.walking && sprinting == false) anim_speed = 8;
else if (y_from > y_to && state == states.walking && sprinting == true) y_frame = 9;
break;
case directions.down: if(sprinting == false) y_frame = 4;
if (y_from < y_to && state == states.walking && sprinting == false) anim_speed = 8;
else if (y_from < y_to && state == states.walking && sprinting == true) y_frame = 8;
break;
case -1: x_frame = 0;
}
x_frame += anim_speed/60;
if(x_frame >= anim_length) x_frame = 1;
//if(x_frame + (anim_speed/60) < anim_length) { x_frame += anim_speed/60;}
//else { x_frame = 1;}
//Draw shadow
draw_sprite(sprShadow, 0, x+8, y+16)
//Draw base
draw_sprite_part(global.sprBase, 0, floor(x_frame)*frame_size, (floor(y_frame)*frame_size) + (y_frame * offset), frame_size, frame_size, x-16, y-16);
//Draw pants
draw_sprite_part(global.sprBot, 0, floor(x_frame)*frame_size, (floor(y_frame)*frame_size) + (y_frame * offset), frame_size, frame_size, x-16, y-16);
//Draw top
draw_sprite_part(global.sprTop, 0, floor(x_frame)*frame_size, (floor(y_frame)*frame_size) + (y_frame * offset), frame_size, frame_size, x-16, y-16);
//Draw accessory
draw_sprite_part(global.sprAcc, 0, floor(x_frame)*frame_size, (floor(y_frame)*frame_size) + (y_frame * offset), frame_size, frame_size, x-16, y-16)
//Draw hat/hair
draw_sprite_part(global.sprHat, 0, floor(x_frame)*frame_size, (floor(y_frame)*frame_size) + (y_frame * offset), frame_size, frame_size, x-16, y-16);
GML:
function move(inputDir)
{
var dir = inputDir;
var components = global.components[dir]
var dx = components[0];
var dy = components[1];
if (state == states.idle) {
if !(tilemap_get(tile_map, x_pos + dx, y_pos + dy)){
x_from = x_pos;
y_from = y_pos;
x_to = x_pos + dx;
y_to = y_pos + dy;
x_pos = x_to;
y_pos = y_to;
state = states.walking;
}
}
}
Last edited: