/* Copyright 2016 Miguel Gonzalez Sanchez
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.bitbrain.braingdx.graphics;

import java.math.BigDecimal;

import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.math.Vector2;

import de.bitbrain.braingdx.GameObject;

/**
 * Using underlying vectors to calculate the camera tracking.
 *
 * @since 1.0.0
 * @version 1.0.0
 * @author Miguel Gonzalez Sanchez
 */
public class VectorCameraTracker implements CameraTracker {

    private final OrthographicCamera camera;
    private final Vector2 velocity;
    private GameObject target;
    private float speed = 5.2f;
    private float zoomScale = 0.0025f;
    private BigDecimal value;

    public VectorCameraTracker(OrthographicCamera camera) {
	this.camera = camera;
	velocity = new Vector2();
    }

    @Override
    public void setTarget(GameObject target) {
	this.target = target;
    }

    @Override
    public void update(float delta) {
	if (target == null)
	    return;
	velocity.x = (float) (target.getLeft() + Math.floor(target.getWidth() / 2.0f) - (camera.position.x));
	velocity.y = (float) (target.getTop() + Math.floor(target.getHeight() / 2.0f) - (camera.position.y + 100f));

	final float distance = velocity.len();
	velocity.nor();
	final double overAllSpeed = distance * speed;

	// Round it up to prevent camera shaking
	camera.position.x = (float) (camera.position.x + (velocity.x * overAllSpeed * delta));
	camera.position.y = (float) (camera.position.y + (velocity.y * overAllSpeed * delta));
	camera.zoom = 1.0f + zoomScale * distance;
    }

    @Override
    public void setSpeed(float speed) {
	this.speed = speed;
    }

    @Override
    public void setZoomScale(float zoomScale) {
	this.zoomScale = zoomScale;
    }

    @Override
    public void focus() {
	if (target == null)
	    return;
	camera.position.x = target.getLeft();
	camera.position.y = target.getTop();
	camera.zoom = 1;
    }
}

@@ -665,16 +665,46 @@
 Decimal;
+%0Aimport java.math.MathContext;
 %0A%0Aimport
@@ -1033,16 +1033,90 @@
 cker %7B%0A%0A
+    private static final MathContext PRECISION = MathContext.DECIMAL128;%0A%0A
     priv
@@ -1235,26 +1235,58 @@
 ate 
-float speed = 5.2f
+BigDecimal speed = new BigDecimal(5.2f, PRECISION)
 ;%0A  
@@ -1295,21 +1295,26 @@
 private 
-float
+BigDecimal
  zoomSca
@@ -1322,45 +1322,42 @@
 e = 
-0.0025f;%0A    private BigDecimal value
+new BigDecimal(0.0025f, PRECISION)
 ;%0A%0A 
@@ -1654,245 +1654,688 @@
 n;%0A%09
-velocity.x = (float) (target.getLeft() + Math.floor(target.getWidth() / 2.0f) - (camera.position.x));%0A%09velocity.y = (float) (target.getTop() + Math.floor(target.getHeight() / 2.0f) - (camera.position.y + 100f));%0A%0A%09final float distance = 
+BigDecimal preciseDelta = BigDecimal.valueOf(delta);%0A%09BigDecimal left = new BigDecimal(target.getLeft(), PRECISION);%0A%09BigDecimal width = new BigDecimal(target.getWidth(), PRECISION);%0A%09BigDecimal camLeft = new BigDecimal(camera.position.x, PRECISION);%0A%09BigDecimal top = new BigDecimal(target.getTop(), PRECISION);%0A%09BigDecimal height = new BigDecimal(target.getHeight(), PRECISION);%0A%09BigDecimal camTop = new BigDecimal(camera.position.y, PRECISION);%0A%09%0A%09velocity.x = left.add(width.divide(BigDecimal.valueOf(2.0))).subtract(camLeft).floatValue();%0A%09velocity.y = top.add(height.divide(BigDecimal.valueOf(2.0))).subtract(camTop).floatValue();%0A%0A%09BigDecimal distance = BigDecimal.valueOf(
 velo
@@ -2344,16 +2344,17 @@
 ty.len()
+)
 ;%0A%09veloc
@@ -2369,20 +2369,18 @@
 );%0A%09
-final double
+BigDecimal
  ove
@@ -2403,147 +2403,234 @@
 ance
- * 
+.multiply(
 speed
+)
 ;%0A%0A%09
-// Round it up to prevent camera shaking%0A%09camera.position.x = (float) (camera.position.x + (velocity.x * overAllSpeed * d
+BigDecimal deltaX = BigDecimal.valueOf(velocity.x).multiply(overAllSpeed).multiply(preciseDelta);%0A%09BigDecimal deltaY = BigDecimal.valueOf(velocity.y).multiply(overAllSpeed, PRECISION).multiply(preciseD
 elta)
-)
 ;%0A%09c
@@ -2648,76 +2648,97 @@
 ion.
-y = (float) (camera.position.y + (velocity.y * overAllSpeed * delta)
+x = camLeft.add(deltaX).floatValue();%0A%09camera.position.y = camTop.add(deltaY).floatValue(
 );%0A%09
@@ -2754,15 +2754,8 @@
 om =
- 1.0f +
  zoo
@@ -2764,19 +2764,60 @@
 cale
- * distance
+.multiply(distance).add(BigDecimal.ONE).floatValue()
 ;%0A  
@@ -2889,21 +2889,58 @@
 speed = 
-speed
+new BigDecimal(Math.abs(speed), PRECISION)
 ;%0A    %7D%0A
@@ -3020,25 +3020,52 @@
 Scale = 
-zoomScale
+new BigDecimal(zoomScale, PRECISION)
 ;%0A    %7D%0A

Make camera tracking much smoother due to BigDecimal