Reputation: 3540
I'm writing a 2D side scrolling game for Android, and am trying to implement a kind of rubber banding/elastic camera movement that follows the player's character up and down.
For example, say the normal state of the screen is such that the character is always centered vertically. If the character jumps, the 'camera' follows the character, first upward as he rises, then downward as he falls.
I've accomplished this using canvas.translate(x,y)
with code like this:
drawBackground();
canvas.save();
canvas.translate(0, canvasHeight/2 - player.y);
drawPlayer();
canvas.restore();
However this looks unnatural because it doesn't account for speed, so no matter how fast the character is rising or falling, the screen is always centered on him. I've tried to use some sort of canvas speed variables but I can't seem to get it right. What I want to have is the camera stay centered on the player if he is still, but when he jumps, the camera should 'lag' a little behind him and try to catch up.
Can anyone give me some suggestions on how I should do this? Please be as specific as possible!
Thanks
Upvotes: 1
Views: 858
Reputation: 97555
Just write a low pass filter for the camera position:
var player = {x: 0, y: 0};
var camera = {x: 0, y: 0};
var t = 0.1;
while(true) {
camera.x = camera.x*(1 - t) + player.x*t
camera.y = camera.y*(1 - t) + player.y*t
drawStuff(camera, player)
}
The larger the value of t
, the faster the reaction of the camera. drawStuff
is a function I can't write without knowing how your game works. Hopefully, you do!
var playerPosition = {x: 0, y: 0};
var playerVelocity = {x: 0, y: 0};
var camera = {x: 0, y: 0};
var t = 0.1;
while(true) {
var targetPosition = f(playerPosition, playerVelocity);
camera.x = camera.x*(1 - t) + targetPosition.x*t
camera.y = camera.y*(1 - t) + targetPosition.y*t
drawStuff(camera, player)
}
Where f is some function that describes where the camera should point for a given velocity and position. Something like this might be sufficient:
function f(pos, vel) {
var k = 0.5;
return {x: pos.x + vel.x * k, y: pos.x + vel.y*k}
}
Obviously, that will place the player offscreen if the camera moves too fast!
Upvotes: 5