Kinetic scrolling

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.
adge
Citizen
Posts: 54
Joined: Mon Dec 14, 2015 8:50 pm

Kinetic scrolling

Post by adge »

Imagine a list on your smartphone. If you scroll down and you stop scrolling the list will continue scrolling until the momentum is gone.
How would you implement something like that in love2d using the mouse. I have an object and I can grab the object and rotate it around its x,y and z axis. Depending on how fast I dragged it I want it to keep rotating until the momentum is gone when I release the mouse.
Last edited by adge on Tue May 03, 2016 11:15 am, edited 1 time in total.
User avatar
Beelz
Party member
Posts: 234
Joined: Thu Sep 24, 2015 1:05 pm
Location: New York, USA
Contact:

Re: Move after mousereleased

Post by Beelz »

I would think to use a rotational velocity... I see 2 ways to go about this:

Either drag the mouse to adjust the velocity...
Or keep a table of mouse update positions, then when you release the mouse figure the average velocity over the last few frames.

Then after the fact, reduce the velocity incrementally per frame.

Code: Select all

if self:hasBeer() then self:drink()
else self:getBeer() end
GitHub -- Website
adge
Citizen
Posts: 54
Joined: Mon Dec 14, 2015 8:50 pm

Re: Move after mousereleased

Post by adge »

How would you do that in code. I really don't know how I would add data to a table every frame.

This obviously wouldn't work.
for i = 0, 100, 1 do
table = velocity
end
User avatar
Tjakka5
Party member
Posts: 243
Joined: Thu Dec 26, 2013 12:17 pm

Re: Move after mousereleased

Post by Tjakka5 »

Maybe something like this could help.
Attachments
Scroll test.love
(10.7 KiB) Downloaded 141 times
User avatar
Beelz
Party member
Posts: 234
Joined: Thu Sep 24, 2015 1:05 pm
Location: New York, USA
Contact:

Re: Move after mousereleased

Post by Beelz »

adge wrote:How would you do that in code. I really don't know how I would add data to a table every frame.

This obviously wouldn't work.
for i = 0, 100, 1 do
table = velocity
end


Code: Select all

-- First, declare the table:
_mousePos = {}

-- Then every update:
function love.update(dt)
	local mx, my = love.mouse.getPosition()

	-- Regulate size of table to say 10 frames:
	if #_mousePos == 10 then table.remove(_mousePos, 1) end
	_mousePos[#_mousePos+1] = {mx, my, dt}
end
*Note: Not tested, written on phone.

Then when you release the mouse, check the average distance between all the table entries.

Code: Select all

if self:hasBeer() then self:drink()
else self:getBeer() end
GitHub -- Website
adge
Citizen
Posts: 54
Joined: Mon Dec 14, 2015 8:50 pm

Re: Move after mousereleased

Post by adge »

Ok but now the problem is that I don't know how to decrease the momentum over a couple frames.
I have this function:

Code: Select all

function love.mousemoved(x, y, dx, dy)
	if mouseIsDown == true then
		moveY3D = (x + dx - x) * 0.01
		moveX3D = (y + dy - y) * 0.01
		rotateY3D((x+dx-x) * 0.01)--* math.pi/36)
		rotateX3D((y+dy-y) * 0.01)--* math.pi/36)
	end
end 

function love.mousereleased(x, y)
	moveY3D = moveY3D - 0.00000001
	moveX3D = moveX3D - 0.00000001
	rotateY3D(moveY3D)
	rotateX3D(moveX3D)
end
Mousereleased is only called when the mouse is actually released so this code is only executed in one frame. How do I write this so that it keeps on for 1-2 seconds? I can't put mousereleased into love.update(). I thought about a timer but I think there is a much easier and better way.
In general I don't know how you would move an object without input from one point to another without just teleporting it to the end. A while or a for loop? But what if you wanted the object to move slower? You can't just do a for loop from 1 to 1000000000. That would be very power hungry.
User avatar
pgimeno
Party member
Posts: 3656
Joined: Sun Oct 18, 2015 2:58 pm

Re: Move after mousereleased

Post by pgimeno »

I think you need to learn about tweening. These are basically timers that make a variable go from a given value A to another given value B in a set time, with a certain progression curve. Look for example http://hump.readthedocs.org/en/latest/timer.html or viewtopic.php?f=5&t=77904
adge
Citizen
Posts: 54
Joined: Mon Dec 14, 2015 8:50 pm

Re: Move after mousereleased

Post by adge »

Yeah I will look into that. However I got it to work.

I just did this:

Code: Select all

function love.update()
	if mousereleased == true then
		moveY3D = moveY3D / 1.05
		moveX3D = moveX3D / 1.05
		rotateY3D(moveY3D)
		rotateX3D(moveX3D)
	end
end


function love.mousemoved(x, y, dx, dy)
	if mouseIsDown == true then
		moveY3D = (x + dx - x)
		moveX3D = (y + dy - y)
		rotateY3D(moveY3D)--* math.pi/36)
		rotateX3D(moveX3D)--* math.pi/36)
	end
end 

function love.mousereleased(x, y)
	mousereleased = true
end
I thought it just had to work that way since it makes sense. If the mouse is released it stores the last direction vector of the mouses movement. Then in the update function it decrements these two values till they are 0.
Kinda strange is that if do:

Code: Select all

moveY3D = moveY3D / 0.5
	 moveX3D = moveX3D / 0.5
It speeds up the whole thing and keeps spinning till it vanishes. Probably has to do something with the calculation because the values become 10^24 after some time if I use the wrong dampening factor.
There has to be some kind of end value implemented because moveY3D always gets divided and goes to 0 but never really reaches it. So this is a endless calculation.
For sure there is an more elegant way to solve this problem but I'm not smart enough :D

Feel free to play around. It's actually a bit funny.
Like always I have to zip up the .love to be able to post it.
Attachments
kinetic rotation.love.zip
(4.17 KiB) Downloaded 103 times
User avatar
pgimeno
Party member
Posts: 3656
Joined: Sun Oct 18, 2015 2:58 pm

Re: Kinetic scrolling

Post by pgimeno »

Doesn't work for me:

Code: Select all

Error: main.lua:4: module 'object' not found
Anyway, yes, what you've implemented is an iterative exponential function. An exponential decay never reaches zero in theory (in practice it may, due to reaching the limit of the precision of floating-point numbers). See https://en.wikipedia.org/wiki/File:Plot ... -decay.svg - that's the shape of the function you've implemented.

Imagine you divide by 10 every iteration, and the starting speed is 1. In the next frame, it will be 1 / 10 = 0.1; in the next, 0.1 / 10 = 0.01, then 0.001, then 0.0001, then 0.00001 and so on. It's easy to see that it will never reach zero (in theory).

Note that dividing by 0.5 is the same as multiplying by two. If you double the number every iteration, it will grow and grow exponentially, and it's quite likely to cause overflows pretty soon. For the value to be reduced every frame, you have to multiply by some number less than 1 (or equivalently, divide by some number greater than 1). For the value to grow every frame, you have to multiply by some number greater than 1 (or equivalently, divide by some number less than 1). If you multiply or divide by 1, the value obviously won't change.

The iterative approach has the problem that it's frame-rate-dependent, unlike the tweening approach that I suggested. The speed will be different depending on the frame rate, e.g. my video card supports 60 and 75 Hz modes, so it will run at a different speed in each, and in some old buggy cards that don't support vsync (or if you disable vsync), it will run uncontrolled. I haven't done the math to adjust it so it adapts to a given dt.
adge
Citizen
Posts: 54
Joined: Mon Dec 14, 2015 8:50 pm

Re: Kinetic scrolling

Post by adge »

God I'm an idiot! Of course dividing by below 1 increases! Jesus!!!!

This one should work. *zipping the zip*

1,2,3 loads different models.
Attachments
kinetic scrolling.love.zip
(15.83 KiB) Downloaded 133 times
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 4 guests