package org.andengine.engine.camera; /** * (c) 2010 Nicolas Gramlich * (c) 2011 Zynga Inc. * * @author Nicolas Gramlich * @since 22:11:17 - 25.03.2010 */ public class SmoothCamera extends ZoomCamera { // =========================================================== // Constants // =========================================================== // =========================================================== // Fields // =========================================================== protected float mMaxVelocityX; protected float mMaxVelocityY; protected float mMaxZoomFactorChange; protected float mTargetCenterX; protected float mTargetCenterY; protected float mTargetZoomFactor; // =========================================================== // Constructors // =========================================================== public SmoothCamera(final float pX, final float pY, final float pWidth, final float pHeight, final float pMaxVelocityX, final float pMaxVelocityY, final float pMaxZoomFactorChange) { super(pX, pY, pWidth, pHeight); this.mMaxVelocityX = pMaxVelocityX; this.mMaxVelocityY = pMaxVelocityY; this.mMaxZoomFactorChange = pMaxZoomFactorChange; this.mTargetCenterX = this.getCenterX(); this.mTargetCenterY = this.getCenterY(); this.mTargetZoomFactor = 1.0f; } // =========================================================== // Getter & Setter // =========================================================== public float getTargetCenterX() { return this.mTargetCenterX; } public float getTargetCenterY() { return this.mTargetCenterY; } public float getTargetZoomFactor() { return this.mTargetZoomFactor; } @Override public void setCenter(final float pCenterX, final float pCenterY) { this.mTargetCenterX = pCenterX; this.mTargetCenterY = pCenterY; } public void setCenterDirect(final float pCenterX, final float pCenterY) { super.setCenter(pCenterX, pCenterY); this.mTargetCenterX = pCenterX; this.mTargetCenterY = pCenterY; } @Override public void setZoomFactor(final float pZoomFactor) { if(this.mTargetZoomFactor != pZoomFactor) { if(this.mTargetZoomFactor == this.mZoomFactor) { this.mTargetZoomFactor = pZoomFactor; this.onSmoothZoomStarted(); } else { this.mTargetZoomFactor = pZoomFactor; } } } public void setZoomFactorDirect(final float pZoomFactor) { if(this.mTargetZoomFactor != this.mZoomFactor) { this.mTargetZoomFactor = pZoomFactor; super.setZoomFactor(pZoomFactor); this.onSmoothZoomFinished(); } else { this.mTargetZoomFactor = pZoomFactor; super.setZoomFactor(pZoomFactor); } } public float getMaxVelocityX() { return this.mMaxVelocityX; } public void setMaxVelocityX(final float pMaxVelocityX) { this.mMaxVelocityX = pMaxVelocityX; } public float getMaxVelocityY() { return this.mMaxVelocityY; } public void setMaxVelocityY(final float pMaxVelocityY) { this.mMaxVelocityY = pMaxVelocityY; } public void setMaxVelocity(final float pMaxVelocityX, final float pMaxVelocityY) { this.mMaxVelocityX = pMaxVelocityX; this.mMaxVelocityY = pMaxVelocityY; } public float getMaxZoomFactorChange() { return this.mMaxZoomFactorChange; } public void setMaxZoomFactorChange(final float pMaxZoomFactorChange) { this.mMaxZoomFactorChange = pMaxZoomFactorChange; } // =========================================================== // Methods for/from SuperClass/Interfaces // =========================================================== protected void onSmoothZoomStarted() { } protected void onSmoothZoomFinished() { } @Override public void onUpdate(final float pSecondsElapsed) { super.onUpdate(pSecondsElapsed); /* Update center. */ final float currentCenterX = this.getCenterX(); final float currentCenterY = this.getCenterY(); final float targetCenterX = this.mTargetCenterX; final float targetCenterY = this.mTargetCenterY; if(currentCenterX != targetCenterX || currentCenterY != targetCenterY) { final float diffX = targetCenterX - currentCenterX; final float dX = this.limitToMaxVelocityX(diffX, pSecondsElapsed); final float diffY = targetCenterY - currentCenterY; final float dY = this.limitToMaxVelocityY(diffY, pSecondsElapsed); super.setCenter(currentCenterX + dX, currentCenterY + dY); } /* Update zoom. */ final float currentZoom = this.getZoomFactor(); final float targetZoomFactor = this.mTargetZoomFactor; if(currentZoom != targetZoomFactor) { final float absoluteZoomDifference = targetZoomFactor - currentZoom; final float zoomChange = this.limitToMaxZoomFactorChange(absoluteZoomDifference, pSecondsElapsed); super.setZoomFactor(currentZoom + zoomChange); if(this.mZoomFactor == this.mTargetZoomFactor) { this.onSmoothZoomFinished(); } } } private float limitToMaxVelocityX(final float pValue, final float pSecondsElapsed) { if(pValue > 0) { return Math.min(pValue, this.mMaxVelocityX * pSecondsElapsed); } else { return Math.max(pValue, -this.mMaxVelocityX * pSecondsElapsed); } } private float limitToMaxVelocityY(final float pValue, final float pSecondsElapsed) { if(pValue > 0) { return Math.min(pValue, this.mMaxVelocityY * pSecondsElapsed); } else { return Math.max(pValue, -this.mMaxVelocityY * pSecondsElapsed); } } private float limitToMaxZoomFactorChange(final float pValue, final float pSecondsElapsed) { if(pValue > 0) { return Math.min(pValue, this.mMaxZoomFactorChange * pSecondsElapsed); } else { return Math.max(pValue, -this.mMaxZoomFactorChange * pSecondsElapsed); } } // =========================================================== // Methods // =========================================================== // =========================================================== // Inner and Anonymous Classes // =========================================================== }