Hi,
I was trying to implement a camera follow class that can consider viewport size and screen scaling, but I’m having quite the problems.
It kind of works if I just jump to where the camera is supposed to be (although I’m not pleased by the effect of it). But if I go from scale 1x to 2.5x the player slowly crawls into view and often flickers like crazy.
What I’d wish to achieve is to be able to define how fast the camera will move to the target object/point, and to make sure that the target is put into view quickly (and in a pleasing-to-see way). All while having a smooooth camera movement. (don’t know if my troubles come from rounding issues - doubt it - , but I’ve tried to cast to int and nothing good came back).
Relevant code called from World.update()
- obj
is the camera-tracked entity:
public function cameraFollow(obj:*, scale:Number):void
{
// desired position of camera on target
// ([.5, .5] means centered in the viewport - drawn in punk pink)
viewportPoint = new Point(.5, .5);
// set viewport size and top-left offset (based on scale)
if (scale < 1) {
viewportSize = new Point(FP.width * scale, FP.height * scale);
screenTopLeft = new Point(FP.halfWidth * (1 - scale), FP.halfHeight * (1 - scale));
} else {
viewportSize = new Point(FP.width, FP.height);
screenTopLeft = new Point(0, 0);
}
// center viewport in window
FP.screen.x = screenTopLeft.x;
FP.screen.y = screenTopLeft.y;
// final camera position
targetPoint = new Point( -viewportPoint.x * viewportSize.x / scale + obj.x,
-viewportPoint.y * viewportSize.y / scale + obj.y);
// if I use this then all is fine - kind of - ... but I also want
// friction AND the target to stay in view!!
/*
FP.camera.x = targetPoint.x;
FP.camera.y = targetPoint.y;
*/
// difference vector (from FP.camera to targetPoint)
diffVector = targetPoint.clone().subtract(new Point(FP.camera.x, FP.camera.y));
var friction:Number = .9; // friction, so that camera doesn't jump to target, but approaches it slowly
var speed:Number = 350; // camera speed
// move camera (jump to targetPoint if distance is minimal - not working as expected!!)
if (diffVector.length > 1 * scale) {
diffVector.normalize(1);
FP.camera.x += diffVector.x * speed * friction * FP.elapsed * scale;
FP.camera.y += diffVector.y * speed * friction * FP.elapsed * scale;
} else {
FP.camera.x = targetPoint.x;
FP.camera.y = targetPoint.y;
}
// adjust camera x for world boundaries
FP.camera.x = FP.clamp(FP.camera.x, 0, WIDTH - viewportSize.x / scale);
}
SWF to see what it looks like (press SPACE to change the scaling (pink rect represents the viewport)): CameraScaleTest
I’m totally sure I’ve done something really stupid along the way, but holy crop I can’t figure it out. Hints anyone?
PS: I’ve just noticed that there are some problems with the right world boundary when played in the browser (but weirdly works well when run through the Flash Player) o.O.