I'm making a side scrolling game and I want the player to be able to flick the screen to scroll the view. Much like most modern smartphones. I have it working now like this:
Store AbsoluteX into global variable TouchStartX
Is in touch:
set scrollx = scrollx - (Touch.AbsoluteX - TouchStartX)
Store AbsoluteX into global variable TouchStartX again
This allows me to scroll but it doesn't take the velocity of the flick into account to keep the screen scrolling. Has anyone implemented this?
You have to give it a velocity. For example, the change in X over the last 30 ticks. On release use some kind of linear or exponential scale to slow it down.
The one I used had a lot of events and variables to get it feel silky smooth and to make it stick to certain points when it stopped. Somebody probably has a more efficient way than me.
Perhaps you must consider storing the X range between actual "Touch.X" and the previous one when "in touch" ... and so, when not "in touch" continue to activate the scroll using this value as reference and decreasing it in time.
The smoothing of the scrolling algorithm is very simple as far as I can tell. Let's say you have two positions A (X = 0) and B (X = 360). To smoothly move from position A to position B, start at position A and then add a fraction of the difference between A and B. The number you divide by determines the speed of the scroll. It provides a nice smooth scrolling effect without the need for any fancy calculations. Something like:
Scroll.X = A.X + (B.X - A.X)/30 (experiment with that number 30, the higher it is, the slower the scroll). In this example, on the first frame, Scroll.X will be 0. On the last frame of this algorithm, it will be 360. The only thing that changes based on the '30' is the speed at which the scroll takes place. The starting and ending points will remain the same (which is one of the things Mulkaccino was talking about when he mentioned stick-to points). So this (the 30) is the number that should be tweaked based on the flick velocity. We can call this number the 'smoothing ratio'.
To determine the smoothing ratio (which is what I'm calling the number to divide by i.e 30 in the example), take the flick velocity into account. Whenever they let go, get the difference between the initial touch point X and the release point X and divide by the time it took for them to perform this action (which will get you the velocity = distance/time). So you'll need to record the time the initial touch occurs, and then find the difference when they release, and then calculate your speed. The greater the speed, the lower your smoothing ratio should be, creating a faster scroll.
A simple way to determine the smoothing ratio might be something like 30/speed. So now when you have really high speeds, you'll get a really low smoothing ratio. Experiment with numbers until you get something that looks natural based on the velocity of the flick. I chose 30 randomly. The best part about this technique is that no matter the speed of the flick, it will always scroll to the same position, and smoothly too. All the flick will determine is how fast this scroll will take place.
Alternatively, you could do what Mulkaccino was talking about, which is a great way to do it that offers the user control over HOW much they scroll based on velocity. Calculate the velocity using what I said above and then apply that velocity to the scroll as follows:
Scroll.X = Scroll.X + Velocity * dt.
Every frame, keep decreasing the Velocity (by a multiple of dt I guess) until it equals zero.
The only problem with my version of this approach is that you won't have a defined end point for the scroll. They could potentially flick too fast, causing the scroll to go on for way longer than expected. You could limit the speed of the scroll, but then it may feel unnatural because the speed did not initially correspond to the flick. Mulkaccino may be able to offer more insight in this area.
I'm really interested in that system too.
Would it be possible to post a .capx ?
Thanks to the great replies everyone!!
I can't upload my capx due to it containing original art for a commercial project. But, I can take a screen cap of my event page as its pretty short and the algorithm isn't too complex.
Sorry for the quality, but it was the only way I could get it all onto one page without editing anything :)
EDIT: The 'ScrollHistory' and 'TimeHistory' are two arrays added to the layout. 'ScrollHistory.HistoryLength' is the max amount of history snap shots that you want to store. I keep this around 5 and I recommend you don't go any higher as it will consume unnecessary resources. Other than that everything should be self-explanatory. If you have any questions don't hesitate to ask!
thank you for your answer.
Image is great, and I tried to insert the code in construct 2 but I'm afraid I'm missing some point and couldn't get it working.
I you got any time, I'd appreciate very much a .capx. I understand your issue with copyright art. Maybe you can replace it by generic graphics ?
I forgot to mention that 'VelocityX' is an instance variable of 'ScrollHistory'. Does that help? What problems are you having specifically?
It might be an issue of project settings. I have my window size set to 800x480 and the layout size set to 2800x1024. Unbound scrolling is set to No. Make sure the layout is much wider than the window.
Also make sure that in your 'Touch' instance you have 'Use mouse input' set to Yes. This will let you test it in the browser.
Thanks for the precision, but I'm afraid I'm not good enough with construct to be able to correctly insert the code...
I am not able to get it working with your code, could you please help ?
or anyone can suggest ideas on how to implement smooth scrolling controller similar to in iPad/iPhone or any touch devices, basically having flick to scroll ( various scrolling speed based on how fast u flick) & drag to scroll.
Here is the capx , basically trying to smooth scroll the set of images at the bottom,
<img src="smileys/smiley19.gif" border="0" align="middle" /> Also i have searched the forum to get this behavior , seems this the closest i have got to but unfortunately it doesn't work.
Is it possible to scroll a portion of the layer instead to the entire height or width of the layer. Is it only possible by masking the layer with another layer and show only that portion that needs scrolling ?
Develop games in your browser. Powerful, performant & highly capable.
I have written a tutorial on getting the touch based scroll with inertia (gradual slow down). It might help this thread. I have been seeing a lot of people asking for this.
It doesn't have the bounce effect when it reaches the edge, but that can be easily coded as the entire effect is achieved with just 1 sprite and 14 lines of code.
Check it out here: https://www.scirra.com/tutorials/560/swipe-based-smooth-scrolling-with-inertia