Gridlocked Player Tutorial - Accel/decel issues

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
Karai17
Party member
Posts: 930
Joined: Sun Sep 02, 2012 10:46 pm

Gridlocked Player Tutorial - Accel/decel issues

Post by Karai17 »

I went through the following tutorial to get my feet wet with love2d and I am noticing a bit of an issue but don't really know how to remedy it.

https://love2d.org/wiki/Tutorial:Gridlocked_Player

The problem I am having is that when I move the player, let's say left 5 times really fast, it is sending me to the 5th cell. So from where I currently am (0), to where I want to be, (5), it seems to be moving me there in the same speed it would move me to any other cell (say, 2). And to top it off, it also decelerates me on a wider margin if I move left 5 times, than if I move left twice.

Is there a better way to go about this so the speeds are more consistent, with no acceleration or deceleration of the player while maintaining a smooth animation? Below is a link to my current project. It has a little more to it than just the tutorial, as I am testing out (and enjoying!) love. :)

https://dl.dropbox.com/u/12958391/tutorial.zip.love

Thanks~
STI - An awesome Tiled library
LÖVE3D - A 3D library for LÖVE 0.10+

Dev Blog | GitHub | excessive ❤ moé
coffee
Party member
Posts: 1206
Joined: Wed Nov 02, 2011 9:07 pm

Re: Gridlocked Player Tutorial - Accel/decel issues

Post by coffee »

Karai17 wrote:I went through the following tutorial to get my feet wet with love2d and I am noticing a bit of an issue but don't really know how to remedy it.

https://love2d.org/wiki/Tutorial:Gridlocked_Player

The problem I am having is that when I move the player, let's say left 5 times really fast, it is sending me to the 5th cell. So from where I currently am (0), to where I want to be, (5), it seems to be moving me there in the same speed it would move me to any other cell (say, 2). And to top it off, it also decelerates me on a wider margin if I move left 5 times, than if I move left twice.

Is there a better way to go about this so the speeds are more consistent, with no acceleration or deceleration of the player while maintaining a smooth animation? Below is a link to my current project. It has a little more to it than just the tutorial, as I am testing out (and enjoying!) love. :)

https://dl.dropbox.com/u/12958391/tutorial.zip.love

Thanks~
Hello, welcome, not sure if there is a problem. I believe instead that you were expecting another type of movement that is was not intended to do with this tutorial. This guide was for simulate the grid movement where player moves from grid to grid coordinates and so move in a step of x/y pixels (the tile size). It was not intended to have "smooth" pixel to pixel movement or the player walk freely. It's for turn based games like roguelikes. If you want use a tiled map but the player walk as in action games you need to do a couple of alterations. One: change the type of key input (with the one used here https://love2d.org/wiki/Tutorial:Hamster_Ball). Two: Change the grid movement displacement to px to px movement (By changing your lines 65,66).

I hope I understood your problem.
Wojak
Party member
Posts: 134
Joined: Tue Jan 24, 2012 7:15 pm

Re: Gridlocked Player Tutorial - Accel/decel issues

Post by Wojak »

My main project “Tanks Reloaded” witch I consider to be an action game is based on the gridlocked player tutorial, however there was a ton of “wrong” things in it that I've fixed

first of all the movement formula makes the movement not constant...

tutorial:

Code: Select all

player.act_y = player.act_y - ((player.act_y - player.grid_y) * dt) 
my version:

Code: Select all

player.act_y = player.act_y – 32*player.speed*dt
also i've made it so the elements can only move to the next tile, when they stooped doing they previous task, and they can move only in one direction at once
User avatar
Karai17
Party member
Posts: 930
Joined: Sun Sep 02, 2012 10:46 pm

Re: Gridlocked Player Tutorial - Accel/decel issues

Post by Karai17 »

coffee wrote:Hello, welcome, not sure if there is a problem. I believe instead that you were expecting another type of movement that is was not intended to do with this tutorial. This guide was for simulate the grid movement where player moves from grid to grid coordinates and so move in a step of x/y pixels (the tile size). It was not intended to have "smooth" pixel to pixel movement or the player walk freely. It's for turn based games like roguelikes. If you want use a tiled map but the player walk as in action games you need to do a couple of alterations. One: change the type of key input (with the one used here https://love2d.org/wiki/Tutorial:Hamster_Ball). Two: Change the grid movement displacement to px to px movement (By changing your lines 65,66).

I hope I understood your problem.
I understand the intent of the tutorial, and I do want the gridlocked movement, not pixel-pixel movement. The problem I am having is that it is not moving at a constant speed. If I press "left" once, it accelerates a little, then decelerates near the tile. If I press left 5 times, it accelerates quickly, and decelerates a lot more (about 5x faster/slower). What I am looking for is a constant speed from grid to grid.

If I print out the values of act_x and grid_x, act_x is constantly changing but NEVER reaches the actual grid value (255.999999999999999999999999999 instead of 256).
Wojak wrote:My main project “Tanks Reloaded” witch I consider to be an action game is based on the gridlocked player tutorial, however there was a ton of “wrong” things in it that I've fixed

first of all the movement formula makes the movement not constant...

tutorial:

Code: Select all

player.act_y = player.act_y - ((player.act_y - player.grid_y) * dt) 
my version:

Code: Select all

player.act_y = player.act_y – 32*player.speed*dt
also i've made it so the elements can only move to the next tile, when they stooped doing they previous task, and they can move only in one direction at once
Your version seems to make my player fly off the top-left of my screen without any input. Shouldn't player.grid_y be a part of the formula so the player knows which direction it is moving in?
STI - An awesome Tiled library
LÖVE3D - A 3D library for LÖVE 0.10+

Dev Blog | GitHub | excessive ❤ moé
coffee
Party member
Posts: 1206
Joined: Wed Nov 02, 2011 9:07 pm

Re: Gridlocked Player Tutorial - Accel/decel issues

Post by coffee »

I will check later your code and your post then a most complete answer. But for now a quick answer to never reaching dt problem with grid tutorial. There should be better ways than mine for sure. I found two solutions in my code dealing grid-lock. Don't remember if are working well or which one was better.

Code: Select all

		player.y = player.y - ( (player.y - ((player.gy-1) * tile.height)) * tile_anim(_dt) )
		player.x = player.x - ( (player.x - ((player.gx-1) * tile.width )) * tile_anim(_dt) )

		if options.round then
			if math.abs((player.gx * tile.width - tile.width)  - player.x) < 1 then
				player.x = player.gx * tile.width - tile.width
			end
			if math.abs((player.gy * tile.height - tile.height) - player.y) < 1 then
				player.y = player.gy * tile.height - tile.height
			end
		end

Code: Select all

	player.smooth = 0.1
...
	player.y = player.y - ((player.y - player.grid_y) * player.speed * _dt) 
	player.x = player.x - ((player.x - player.grid_x) * player.speed * _dt)
	
	-- control roughness/smoothness of player displacement to grid
    if math.abs(player.x - player.grid_x)  < player.smooth then player.x = player.grid_x end
    if math.abs(player.y - player.grid_y)  < player.smooth then player.y = player.grid_y end
Wojak
Party member
Posts: 134
Joined: Tue Jan 24, 2012 7:15 pm

Re: Gridlocked Player Tutorial - Accel/decel issues

Post by Wojak »

Karai17 wrote:
Wojak wrote:My main project “Tanks Reloaded” witch I consider to be an action game is based on the gridlocked player tutorial, however there was a ton of “wrong” things in it that I've fixed

first of all the movement formula makes the movement not constant...

tutorial:

Code: Select all

player.act_y = player.act_y - ((player.act_y - player.grid_y) * dt) 
my version:

Code: Select all

player.act_y = player.act_y – 32*player.speed*dt
also i've made it so the elements can only move to the next tile, when they stooped doing they previous task, and they can move only in one direction at once
Your version seems to make my player fly off the top-left of my screen without any input. Shouldn't player.grid_y be a part of the formula so the player knows which direction it is moving in?
this is the full function responsible for moving everything in my game (as I said - there was many problems to be fixed...)

Code: Select all

function moveElement(elem,dt,dir) ----smooth moving, elem may be a player, dt is delta time, dir is x or y
   if not dir then -- I call the function without the specific dir, so it calls it self for x and y
	moveElement(elem,dt,"x")
	moveElement(elem,dt,"y")
   else
  	 if elem["act_"..dir] - elem["grid_"..dir] < 2*(32*elem.speed*dt) and elem["grid_"..dir] - elem["act_"..dir] < 2*(32*elem.speed*dt) then –- elem["act_"..dir] is player.act_y or player.act_x, the first condition checks if the player should not move
 	     elem["act_"..dir] = elem["grid_"..dir]
	     setisplayermowing(elem,false,dir) –- this function sum the x and y movement to get the overall movement witch is used do disable and enable the controls
 	  elseif not (elem["act_"..dir] - elem["grid_"..dir] < 2*(32*elem.speed*dt)) then –- this condition checks if the player should move right or down
 	     elem["act_"..dir] = elem["act_"..dir] - 32*elem.speed*dt
	     setisplayermowing(elem,true,dir)
 	  elseif not (elem["grid_"..dir] - elem["act_"..dir] < 2*(32*elem.speed*dt)) then –- this condition checks if the player should move left or up
 	     elem["act_"..dir] = elem["act_"..dir] + 32*elem.speed*dt
	     setisplayermowing(elem,true,dir)
 	  end
   end
end
edit: added the comments in the code to make it more clear
Last edited by Wojak on Tue Sep 04, 2012 5:26 am, edited 1 time in total.
coffee
Party member
Posts: 1206
Joined: Wed Nov 02, 2011 9:07 pm

Re: Gridlocked Player Tutorial - Accel/decel issues

Post by coffee »

Hello, I did a quick check on your code. I understood now what you wanted. Yes, since the turn movement isn't over but player already did another key movement then the dt based animation update tries to compensate accelerating the player movement to the now distant place.
So two ways to resolve this:
1 - End that endless non-lock of player with grid
2 - Disable command operation till the movement operation is done

Here is your code with dirty quick changes:

Code: Select all

-- teehee
require("lib/AnAL")

function love.load()
	-- Sprite map
	ayla_img = love.graphics.newImage("assets/ayla.png")
	
	-- Textures
	grass = love.graphics.newImage("assets/grass.png")
	stone = love.graphics.newImage("assets/stone.png")
	
	-- Animation
	local function newAnim(img, offset, frames)
		local anim = newAnimation(img, 32, 32, 0.125, 1)
		anim.frames = {}
		
		for i=0,frames-1 do
			anim:addFrame(i*32, offset*32, 32, 32, 0.125)
		end
		
		return anim
	end

	ayla = {
		down = newAnim(ayla_img, 0, 7),
		left = newAnim(ayla_img, 1, 7),
		right= newAnim(ayla_img, 1, 7),
		up   = newAnim(ayla_img, 2, 7),
	}
	current = "down"

	--anim:setMode("once")
	
	-- Player array
	player = {
		grid_x = 256,
		grid_y = 256,
		real_x = 256,
		real_y = 256,
		speed = 5,
		control = true
	}
	
	-- Map array
	map = {
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
		{ 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1 },
		{ 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1 },
		{ 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1 },
		{ 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	}
end

-- dt = delta time
function love.update(dt)
	anim = ayla[current]

	player.real_y = player.real_y - ((player.real_y - player.grid_y) * player.speed * dt)
	player.real_x = player.real_x - ((player.real_x - player.grid_x) * player.speed * dt)

    if math.abs(player.grid_x - player.real_x) < 1 then
       player.real_x = player.grid_x
    end
    if math.abs(player.grid_y - player.real_y) < 1 then
       player.real_y = player.grid_y
    end
    
    if player.real_x == player.grid_x and player.real_y == player.grid_y then player.control = true end
	
	anim:update(dt)
end

-- # = "number of things in this" aka count
function love.draw()
	for y = 1, #map do
		for x = 1, #map[y] do
			if map[y][x] == 1 then
				love.graphics.draw(stone, x * 32, y * 32, 0, 1, 1, 0, 0, 0, 0)
			else
				love.graphics.draw(grass, x * 32, y * 32, 0, 1, 1, 0, 0, 0, 0)
			end
		end
	end
	if current == "right" then
		anim:draw(player.real_x, player.real_y, 0, -1, 1, 32, 0)
	else
		anim:draw(player.real_x, player.real_y)
	end	
	
	love.graphics.print ("G_X:"..player.grid_x.." G_Y:"..player.grid_y.." X:"..player.real_x.." Y:"..player.real_y.." "..tostring(player.control),0,0)
	
end

function love.keypressed(key)
	if key == "escape" then
		love.event.push("quit")
	end
	
	if key == "up"  and player.control then
		current = key
		if testMap(0, -1) then
			player.grid_y = player.grid_y - 32
			player.control = false
		end
	end

	if key == "down" and player.control then
		current = key
		if testMap(0, 1) then
			player.grid_y = player.grid_y + 32
			player.control = false
		end
	end

	if key == "left" and player.control  then
		current = key
		if testMap(-1, 0) then
			player.grid_x = player.grid_x - 32
			player.control = false
		end
	end
 
	if key == "right" and player.control  then
		current = key
		if testMap(1, 0) then
			player.grid_x = player.grid_x + 32
			player.control = false
		end
	end
end

function testMap(x, y)
	if map[(player.grid_y / 32) + y][(player.grid_x / 32) + x] == 1 then
		return false
	end
	
	return true
end
If this still don't please you need then change instead dt formula.
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 151 guests