(SOLVED) Newbie problem with dt

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
User avatar
molul
Party member
Posts: 264
Joined: Sun Feb 05, 2012 6:51 pm
Location: Valencia, Spain
Contact:

(SOLVED) Newbie problem with dt

Post by molul »

I'm trying to code a basic tiledbased platformer following this guide and Sonic's Physics Guide (http://info.sonicretro.org/SPG:Running).

My current problem is that I don't seem to be able to handle "dt" properly. If I set or unset vsync in this simple test, the player moves really differently and I don't get why. I use dt in "CHero:updateSpeedX" when adding acceleration or deceleration constant to speed. I thought I should use it in "CHero:updatePosition" too (changing it to self.x = self.x + (self.spX * dt)) but the result is still very different with vsync on and off.

Would someone please tell me what I'm doing wrong? I'd love finally understanding one of my common mistakes. I bet it must be a very basic thing.

Code: Select all

CHero = class:new()

function CHero:init (x, y)
	self.x 				= x or 300
	self.y 				= y or 210
	self.width 			= gTileSize
	self.height 		= (2 * gTileSize)
	self.edgeX 			= x
	self.edgeY 			= y
	
	self.spX 			= 0
	self.maxSpX 		= 1000
	self.acc 			= 5
	self.dec 			= 10
	self.friction 		= 5
end

function CHero:update(dt)
	self:updateSpeedX(dt)
	self:updatePosition(dt)
end

function CHero:updateSpeedX(dt)
	if (gKeyPressed.left) then 
		if (self.spX > 0) then 
			self.spX = self.spX - (self.dec * dt)
		elseif (self.spX > -self.maxSpX) then 
			self.spX = self.spX - (self.acc * dt)
		end
	elseif (gKeyPressed.right) then 
		if (self.spX < 0) then 
			self.spX = self.spX + (self.dec * dt )
		elseif (self.spX < self.maxSpX) then 
			self.spX = self.spX + (self.acc * dt)
		end
	else 
		self.spX = self.spX - math.min(math.abs(self.spX), (self.friction * dt)) * math.sign (self.spX)
	end
end

-- UPDATE POSITION
function CHero:updatePosition(dt)
	self.x = self.x + self.spX
end


--DRAW
function CHero:draw()
	love.graphics.setColor(self.color)
	love.graphics.rectangle('fill', self.x, self.y, self.width, -self.height)
	love.graphics.setColor(255,255,255)
end
Thanks a lot in advance.
Last edited by molul on Wed Feb 17, 2016 7:15 pm, edited 1 time in total.
bobbyjones
Party member
Posts: 730
Joined: Sat Apr 26, 2014 7:46 pm

Re: Newbie problem with dt

Post by bobbyjones »

What is the fps with vsync off? If it's 1000 then I would assume that dt wouldn't do much. Dt still affects things. It just makes it less different. I bet if you removed dt completely you would see it move extremely fast at both 1000 and 60 fps. (Also it could be something obvious that I don't see)

Edit 1: when adding your speed to your position you need to use dt. It's in the linear kinetics equation.

Code: Select all

 d = di + vi*t + 1/2a*t^2 
 --or 
 d = di + V*t -- this is what you are doing. t is dt. Or should be doing anyways.
User avatar
molul
Party member
Posts: 264
Joined: Sun Feb 05, 2012 6:51 pm
Location: Valencia, Spain
Contact:

Re: Newbie problem with dt

Post by molul »

Thanks bobbyjones. Fps are more or less 660 with vsync off. Does it make sense that the code is behaving really different from 60 to 660 fps then?
bobbyjones wrote: Edit 1: when adding your speed to your position you need to use dt. It's in the linear kinetics equation.

Code: Select all

 d = di + vi*t + 1/2a*t^2 
 --or 
 d = di + V*t -- this is what you are doing. t is dt. Or should be doing anyways.
I'll give it a try again. The problem is, when updating position, the collision detection makes something like

hero.speed = min(hero.speed, closerTileDistance)

as seen in the first link in the OP. I'll try to fix that.


EDIT: adding "dt" to the line where "x" is updated with "speedX" does nothing. With Vsync On it accelerates instantly, while with Vsync Off it slowly builds speed.

I hate it when I can't get to work such a basic thing XD
User avatar
Tesselode
Party member
Posts: 555
Joined: Fri Jul 23, 2010 7:55 pm

Re: Newbie problem with dt

Post by Tesselode »

Post all your current code so far. It mostly seems right, although...should math.abs(self.spX) (under the else line) be math.abs(self.spX * dt)?
User avatar
zorg
Party member
Posts: 3441
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Newbie problem with dt

Post by zorg »

To my eyes, the following stood out where dt could have been missing:

Code: Select all

-- UPDATE POSITION
function CHero:updatePosition(dt)
   self.x = self.x + self.spX -- from here
end
Edit: nevermind, just saw that you tried this already, and it didn't work; yes, please post your code then instead :3
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
molul
Party member
Posts: 264
Joined: Sun Feb 05, 2012 6:51 pm
Location: Valencia, Spain
Contact:

Re: Newbie problem with dt

Post by molul »

Checking all my current code might be a bit tedious. This evening I'll reduce it as much as I can and I'll post it. Thanks for the help so far! :)
User avatar
molul
Party member
Posts: 264
Joined: Sun Feb 05, 2012 6:51 pm
Location: Valencia, Spain
Contact:

Re: Newbie problem with dt

Post by molul »

Here's a a simplified version of this test. The problem is the same and there's not as much code to read :)

EDIT: keys are left and right arrows, and esc to close.
Attachments
platformerTest.zip
(4.44 KiB) Downloaded 98 times
User avatar
Kingdaro
Party member
Posts: 395
Joined: Sun Jul 18, 2010 3:08 am

Re: Newbie problem with dt

Post by Kingdaro »

Try this for your update method instead. I notice it could be simplified a bit, and doing that might be a good path towards a solution.

Code: Select all

function CHero:updateSpeedX(dt)
   local targetSpeed =
      gKeyPressed.left and -self.maxSpX or
      gKeyPressed.right and self.maxSpX or
      0

   self.spX = self.spX + (targetSpeed - self.spX) * math.max(dt * self.acc, 1)
end
It uses a linear interpolation formula to interpolate the player's speed to its max speed, in the direction depending on which key is down. math.max() is used so the speed is guaranteed not to exceed the maximum or minimum speed. In other words, the line says "slowly change this value towards this other value over time".

It doesn't factor in deceleration or friction, but you could probably figure that yourself.
User avatar
molul
Party member
Posts: 264
Joined: Sun Feb 05, 2012 6:51 pm
Location: Valencia, Spain
Contact:

Re: Newbie problem with dt

Post by molul »

Thanks Kingdaro. This works the same with vsync on or off if I set "self.x = self.x + (self.spX * dt)" in CHero:updatePosition(dt).

However, if possible, I'd like to know what was wrong in my updateSpeed function. I mean, some theory like "you shouldn't use dt here if you already used it there" or "you can't use dt twice in the same function", or something like that. I'm sure I'll find myself in similar situations in the future and I'd like to be able to figure out myself what's wrong :)


EDIT: ok, I think I figured it out :D My main problem was that I wasn't using "self.x = self.x + (self.spX * dt)" in CHero:updatePosition(dt). I removed the " * dt" in my full code because, after updating speed and before updating position, I was also checking the closest tile distance, with the final line "hero.speed = min (hero.speed, closestTileDistance)". I have to rework that part.

I tried fixing that problem by adding the line "hero.speed = hero.speed * dt" at the end of the updateSpeed function. That's very wrong, as speed will always be really slow.

Finally, another problem is that I was using very low values for the hero's top speed, acceleration, deceleration and friction.

Thanks for the quick replies everyone. I think I can manage to fix this now ^_^
Post Reply

Who is online

Users browsing this forum: No registered users and 22 guests