Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I want to zoom about an arbitrary zoom point. For example, if the player tabs on a place on his windows phone display, this place(position) should get the new center of his viewport. In addition, the camera zooms so that the place looks bigger. If the player tabs again in zoom mode, the camera just needs to zoom out and the center of the viewport rests the same like in zoom mode.

I'm doing a 2D point and click adventure, so it is very important to examine the environment.

If I tab on a place, it's not getting the center of the viewport. The center of the viewport always is somewhere else. What is wrong with my code?

I found the camera class in this tutorial: http://www.david-amador.com/2009/10/xna-camera-2d-with-zoom-and-rotation/

How can I do the zoom? I found a similar question on stackoverflow but I don't understand how they solved the problem: http://stackoverflow.com/questions/9348866/xna-2d-camera-with-arbitrary-zoom-center

Camera class:

public class Camera2d 
{ 
    protected float _zoom; // Camera Zoom 
    public Matrix _transform; // Matrix Transform 
    public Vector2 _pos; // Camera Position 
    protected float _rotation; // Camera Rotation 

    public Camera2d() 
    { 
        _zoom = 1.0f; 
        _rotation = 0.0f; 
        _pos = Vector2.Zero; 
    } 

    // Sets and gets zoom 
    public float Zoom 
    { 
        get { return _zoom; } 
        set { _zoom = value; if (_zoom < 0.1f) _zoom = 0.1f; } // Negative zoom will flip image 
    } 

    public float Rotation 
    { 
        get { return _rotation; } 
        set { _rotation = value; } 
    } 

    // Auxiliary function to move the camera 
    public void Move(Vector2 amount) 
    { 
        _pos += amount; 
    } 
    // Get set position 
    public Vector2 Pos 
    { 
        get { return _pos; } 
        set { _pos = value; } 
    } 

    public Matrix get_transformation(GraphicsDevice graphicsDevice) 
    { 
        Viewport viewPort = graphicsDevice.Viewport; 
        _transform =        
          Matrix.CreateTranslation(new Vector3(-_pos.X, -_pos.Y, 0)) * 
                                     Matrix.CreateRotationZ(Rotation) * 
                                     Matrix.CreateScale(new Vector3(Zoom, Zoom, 1)) * 
                                     Matrix.CreateTranslation(new Vector3(viewPort.Width * 0.5f, viewPort.Height * 0.5f, 0)); 
        return _transform; 
    } 
}

How I use the camera:

GestureSample gs;
cam.Pos = new Vector2(graphics.PreferredBackBufferWidth / 2, graphics.PreferredBackBufferHeight / 2); 
TouchPanel.EnabledGestures = GestureType.Tap; 

 void UpdateZoom(float newZoom)
     {
       Vector2 currentMouseTarget = new Vector2(cam.Zoom * gs.Position.X, cam.Zoom * gs.Position.Y);
       Vector2 nextMouseTarget = new Vector2(newZoom * gs.Position.X, newZoom * gs.Position.Y);
       cam.Pos += (nextMouseTarget - currentMouseTarget) * newZoom;
       cam.Zoom = newZoom;          
     }

    protected override void Update(GameTime gameTime)
    {
        while (TouchPanel.IsGestureAvailable)
        {
           gs = TouchPanel.ReadGesture();
           switch (gs.GestureType)
            {
                case GestureType.Tap:
                    UpdateZoom(2.0f);
                    break;
            }
        }

        base.Update(gameTime);
    }



 protected override void Draw(GameTime gameTime) 
    { 
        GraphicsDevice.Clear(Color.CornflowerBlue); 

        spriteBatch.Begin(SpriteSortMode.BackToFront, 
                    BlendState.AlphaBlend, 
                    null, 
                    null, 
                    null, 
                    null, 
                    cam.get_transformation(graphics.GraphicsDevice)); 

        spriteBatch.Draw(TestSprite, new Rectangle(200, 200, TestSprite.Width,TestSprite.Height), null,Color.White,0,new Vector2(TestSprite.Width/2,TestSprite.Height/2), SpriteEffects.None,1); 

        spriteBatch.End(); 

        base.Draw(gameTime); 
    } 
share|improve this question
    
Typically "What is wrong with my code" questions are frowned upon. They're usually only beneficial to the one individual asking the question, since they're likely the only ones using that exact code. You may want to rephrase the question to ask about strategies for doing this, or explain where you think the problem is, what you've tried and how it hasn't worked. –  Byte56 Aug 6 '13 at 23:34
add comment

1 Answer

up vote 0 down vote accepted

You should calculate the target position with the previous zoom, and calculate it again with the new zoom, and then add the difference to the camera position.

Should be something similar to this (not tested):

 void UpdateZoom(float newZoom) {
      currentMouseTarget = Zoom * MousePos;
      nextMouseTarget = newZoom *  MousePos;

      CameraPos += (nextMouseTarget - currentMouseTarget) (/ or *) newZoom;

      Zoom = newZoom;          
 }

EDIT:

If you want to zoom about a certain point (target) and translate camera to the meet center of viewport... your code should similar to this:

  Camera.Position += ( Target.Position * Camera.Zoom - Camera.Position ) * 0.1f;

This way it will interpolate with easing to move the camera to the target.Position

share|improve this answer
    
Why are you writing (/ or *)? –  Bryan Aug 7 '13 at 5:43
    
Because I was not sure ... have you tested it? –  Blau Aug 7 '13 at 6:43
    
I tried it with / and *, but it's not working. If I tab on a place, the place isn't getting the center of the viewport. I updated my question with the new code. In addition, I found a similar question on stackoverflow but I don't understand how they solved the problem. –  Bryan Aug 7 '13 at 15:33
    
I understood that you want to zoom about a point... not translate that point to the center –  Blau Aug 7 '13 at 16:25
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.