Domanda

Qual è il modo migliore per creare un effetto di parallasse in un gioco XNA? Vorrei che la fotocamera per seguire il mio sprite come si muove in tutto il mondo, in questo modo posso costruire in effetti come lo zoom, panning, agitare, e altri effetti. Qualcuno ha un solido esempio di come questo viene fatto, preferibilmente in un GameComponent?

È stato utile?

Soluzione

così ho pensato che utilizzando una combinazione dei tutorial di cui sopra e hanno creato la classe inferiore. Questa si muove verso il vostro bersaglio e lo segue in giro. Provalo.

public interface IFocusable
{
    Vector2 Position { get; }
}

public interface ICamera2D
{
    /// <summary>
    /// Gets or sets the position of the camera
    /// </summary>
    /// <value>The position.</value>
    Vector2 Position { get; set; }

    /// <summary>
    /// Gets or sets the move speed of the camera.
    /// The camera will tween to its destination.
    /// </summary>
    /// <value>The move speed.</value>
    float MoveSpeed { get; set; }

    /// <summary>
    /// Gets or sets the rotation of the camera.
    /// </summary>
    /// <value>The rotation.</value>
    float Rotation { get; set; }

    /// <summary>
    /// Gets the origin of the viewport (accounts for Scale)
    /// </summary>        
    /// <value>The origin.</value>
    Vector2 Origin { get; }

    /// <summary>
    /// Gets or sets the scale of the Camera
    /// </summary>
    /// <value>The scale.</value>
    float Scale { get; set; }

    /// <summary>
    /// Gets the screen center (does not account for Scale)
    /// </summary>
    /// <value>The screen center.</value>
    Vector2 ScreenCenter { get; }

    /// <summary>
    /// Gets the transform that can be applied to 
    /// the SpriteBatch Class.
    /// </summary>
    /// <see cref="SpriteBatch"/>
    /// <value>The transform.</value>
    Matrix Transform { get; }

    /// <summary>
    /// Gets or sets the focus of the Camera.
    /// </summary>
    /// <seealso cref="IFocusable"/>
    /// <value>The focus.</value>
    IFocusable Focus { get; set; }

    /// <summary>
    /// Determines whether the target is in view given the specified position.
    /// This can be used to increase performance by not drawing objects
    /// directly in the viewport
    /// </summary>
    /// <param name="position">The position.</param>
    /// <param name="texture">The texture.</param>
    /// <returns>
    ///     <c>true</c> if the target is in view at the specified position; otherwise, <c>false</c>.
    /// </returns>
    bool IsInView(Vector2 position, Texture2D texture);
}

public class Camera2D : GameComponent, ICamera2D
{
    private Vector2 _position;
    protected float _viewportHeight;
    protected float _viewportWidth;

    public Camera2D(Game game)
        : base(game)
    {}

    #region Properties

    public Vector2 Position
    {
        get { return _position; }
        set { _position = value; }
    }
    public float Rotation { get; set; }
    public Vector2 Origin { get; set; }
    public float Scale { get; set; }
    public Vector2 ScreenCenter { get; protected set; }
    public Matrix Transform { get; set; }
    public IFocusable Focus { get; set; }
    public float MoveSpeed { get; set; }

    #endregion

    /// <summary>
    /// Called when the GameComponent needs to be initialized. 
    /// </summary>
    public override void Initialize()
    {
        _viewportWidth = Game.GraphicsDevice.Viewport.Width;
        _viewportHeight = Game.GraphicsDevice.Viewport.Height;

        ScreenCenter = new Vector2(_viewportWidth/2, _viewportHeight/2);
        Scale = 1;
        MoveSpeed = 1.25f;

        base.Initialize();
    }

    public override void Update(GameTime gameTime)
    {
        // Create the Transform used by any
        // spritebatch process
        Transform = Matrix.Identity*
                    Matrix.CreateTranslation(-Position.X, -Position.Y, 0)*
                    Matrix.CreateRotationZ(Rotation)*
                    Matrix.CreateTranslation(Origin.X, Origin.Y, 0)*
                    Matrix.CreateScale(new Vector3(Scale, Scale, Scale));

        Origin = ScreenCenter / Scale;

        // Move the Camera to the position that it needs to go
        var delta = (float) gameTime.ElapsedGameTime.TotalSeconds;

        _position.X += (Focus.Position.X - Position.X) * MoveSpeed * delta;
        _position.Y += (Focus.Position.Y - Position.Y) * MoveSpeed * delta;

        base.Update(gameTime);
    }

    /// <summary>
    /// Determines whether the target is in view given the specified position.
    /// This can be used to increase performance by not drawing objects
    /// directly in the viewport
    /// </summary>
    /// <param name="position">The position.</param>
    /// <param name="texture">The texture.</param>
    /// <returns>
    ///     <c>true</c> if [is in view] [the specified position]; otherwise, <c>false</c>.
    /// </returns>
    public bool IsInView(Vector2 position, Texture2D texture)
    {
        // If the object is not within the horizontal bounds of the screen

        if ( (position.X + texture.Width) < (Position.X - Origin.X) || (position.X) > (Position.X + Origin.X) )
            return false;

        // If the object is not within the vertical bounds of the screen
        if ((position.Y + texture.Height) < (Position.Y - Origin.Y) || (position.Y) > (Position.Y + Origin.Y))
            return false;

        // In View
        return true;
    }
}

E Ecco come si usa con SpriteBatch:

spriteBatch.Begin(SpriteBlendMode.AlphaBlend,
                  SpriteSortMode.FrontToBack,
                  SaveStateMode.SaveState,
                  Camera.Transform);
spriteBatch.Draw(_heliTexture,
                 _heliPosition,
                 heliSourceRectangle,
                 Color.White,
                 0.0f,
                 new Vector2(0,0),
                 0.5f,
                 SpriteEffects.FlipHorizontally,
                 0.0f);
spriteBatch.End();

farmi sapere se questo ti aiuta, e grazie alla StackOverflow e la comunità. W00t!

Altri suggerimenti

Lo so che è una vecchia questione, ma ho avuto lo stesso e ho trovato questa grande biblioteca fotocamera Monogame così ho pensato di condividere ...

https://github.com/aloisdeniel/Comora

E 'davvero facile da installare e da seguire sprite è sufficiente aggiungere

this.camera.Position = posizione del vostro sprite;

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top