Techniques for "Smooth" camera scroll with mouse

Started by
8 comments, last by CelticSir 8 years, 6 months ago

I have made a scrolling function on my canvas that lets the user click and drag their view point.

Currently it moves with raw mouse movement. But I wanted to know what are common techniques people use to apply a smoother feel to it.

My current function looks like this:

Javascript:


function drag(evt,el){
if(evt.button == 2){
    mousePos = {};
    mousePos.x = evt.offsetX / scale;
    mousePos.y = evt.offsetY / scale;

    function update(e){
    var difx = mousePos.x - (e.offsetX/scale),
        dify = mousePos.y - (e.offsetY/scale);


        camera.x += difx;
        camera.y += dify;
        mousePos.x = e.offsetX / scale;
        mousePos.y = e.offsetY / scale;
} 
  function clear(){
     el.removeEventListener('mousemove', update, false);
     this.removeEventListener('mouseup', clear, false);
  }
    el.addEventListener('mousemove',update,false);
    document.body.addEventListener('mouseup',clear,false); 
   }
}
element.addEventListener('mousedown', function(e) { drag(e,this);}, false);

I have added a jsFiddle of this function working too http://jsfiddle.net/jmnte8cL/

So, what are common simple ways to smooth out the scrolling so it feels a bit less dry that are commonly used in games?

Advertisement

I don't know about the implementation in Javascript, but you could do something like have the mouse directly drive a target point and have the current point interpolate towards that target point over time. The rate at which you interpolate towards the target will govern the responsiveness, so a long delay (slow interpolation) will feel smooth but a bit laggy, while a short delay will be twitchier but more direct.

Visit http://www.mugsgames.com

Stroids, a retro style mini-game for Windows PC. http://barryskellern.itch.io/stroids

Mugs Games on Twitter: [twitter]MugsGames[/twitter] and Facebook: www.facebook.com/mugsgames

Me on Twitter [twitter]BarrySkellern[/twitter]

Are you able to explain with pseudo logic code so i understand what you mean then i can try implement the similar idea in Javascript ?

Inertia can also help make the movement feel smoother:

When releasing the mouse button don't immediately stop moving. Keep moving the canvas with the velocity of the last mouse movement and slowly move the velocity towards zero.

You can simply change the move by a velocity vector and add a friction which each update reduce the velocity vector :


float friction = 1.0f - m_friction * elapsed;
m_velocity *= friction;
vector3 velocity = m_velocity * elapsed;
AddTranslation( velocity.x, velocity.y, velocity.z );

I'm not fully understanding it. Say i click and move the mouse, currently i measure the "difference" from last movement when the function was called.

This difference is there for basically 1px at a time so i simply add that difference to the camera.

If i add a loop which increments ve, would it not cause me to have multiple loops running as each time i move the mouse it is starting a new loop to increase the velocity again, causing an exponential increase ?

I don't know about the implementation in Javascript, but you could do something like have the mouse directly drive a target point and have the current point interpolate towards that target point over time. The rate at which you interpolate towards the target will govern the responsiveness, so a long delay (slow interpolation) will feel smooth but a bit laggy, while a short delay will be twitchier but more direct.



L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

The method said by L. Spiro and Barry is the friction alike way but it's a timer param and not friction, you go from start to end using a timer.

Using a timer as param you always have the same time to go from start to end.

I have a kinda working version here: http://jsfiddle.net/bbb9q2c3/

But i can't get it to accurately hit the target x,y position so currrently I can't exit out of the animation loop.

This is what i did :


var	difx 	        = mousePos.x - (e.offsetX/scale),
        dify 	        = mousePos.y - (e.offsetY/scale);
       	mousePos.x 	= e.offsetX / scale;
        mousePos.y	= e.offsetY / scale; 
var     targetX         = camera.x + difx;
var     targetY         = camera.y + dify;
    
        
        function smooth(){
            if(camera.x != targetX){
                camera.x  += (difx * lerp);
            }
            if(camera.y != targetY){
                camera.y  += (dify * lerp);
            }
        }
        
	timer = setInterval(smooth,16);

Is there a way I can guarentee it will hit the target co ordinates that i set?

Problem solved: http://jsfiddle.net/gswcnb/

Thought i'd post the link just encase it helps others smile.png

This topic is closed to new replies.

Advertisement