0
\$\begingroup\$

I'm trying to implement a pinch zoom on a sprite. I would like to get an effect like the SmoothCamera, but on a single sprite. I've managed to pinch zoom on the sprite by changing its scale, but the zoom is really fast and not smooth... it doesn't feel right.

This code is on my sprite :

public class BoardSprite extends Sprite implements IPinchZoomDetectorListener {
...
private float scale = 1;
    @Override
    public void onPinchZoom(PinchZoomDetector pPinchZoomDetector,
            TouchEvent pTouchEvent, float pZoomFactor) {
        float newScale = scale * pZoomFactor;
        if (newScale > 3) {
            newScale = 3;
        } else if ( newScale < 1) {
            newScale = 1;
        } 

        scale = newScale;
        this.setScale(newScale);        
    }

I'm looking for a way to improve this solution or for a better approach.

\$\endgroup\$
2
  • \$\begingroup\$ Just curious: what if you tried float newScale = pZoomFactor; -- what effect would that produce? \$\endgroup\$
    – Thomas
    Commented Jan 20, 2014 at 13:54
  • \$\begingroup\$ That's actually pretty good, the only problem is that it seems to start back to 1 each time I start a new pinch. I'll have a look at it later today. \$\endgroup\$
    – Phil-R
    Commented Jan 21, 2014 at 14:14

2 Answers 2

2
\$\begingroup\$

I have no experience with AndEngine, but from your code I suspect that since you update the scale variable with the result of scale * pZoomFactor every time onPinchZoom is called, you're basically turning this multiplication into an exponentiation.

To avoid this, simply delete the scale = newScale; assignment. But now, since you want to compute the scale relative to the scale at the beginning of the pinch zoom, you have to add a method that initializes scale to that value. The following might work:

private float scale = 1;

@Override
public void onPinchZoomStarted(PinchZoomDetector pPinchZoomDetector, 
                               TouchEvent pSceneTouchEvent) {
    this.scale = Math.min(getScaleX(), getScaleY());
}

@Override
public void onPinchZoom(PinchZoomDetector pPinchZoomDetector,
                        TouchEvent pTouchEvent, float pZoomFactor) {
    float newScale = scale * pZoomFactor;
    if (newScale > 3) {
        newScale = 3;
    } else if (newScale < 1) {
        newScale = 1;
    } 

    // scale = newScale;
    this.setScale(newScale);        
}
\$\endgroup\$
1
\$\begingroup\$

Try setting a target scale, then ease towards that value, rather than setting the value directly. This is how the pinch zoom works in Angry Birds. It eases in over time.

The basic method is to increase the scale of your sprite by a fraction of the difference between the target scale and the current scale each update.

so in your onManagedUpdate(pUpdateSeconds) you'll add soemthing like this (writing from memory, code not tested)

float easeRate = 0.01; // Higher for faster easing;

float newscale = this.getScale() + (targetScale - this.getScale()) * easeRate * pUpdateSeconds/1000;

this.setScale(newscale);
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .