C# 将对象钳制到 window?

C# Clamp object to window?

在 Monogame (c#) 中,我无法弄清楚如何让一个对象(在本例中是一个汉堡)留在游戏 window 的边界内,这样它就不会离开game window 当光标出现时。或者换句话说,"clamp" 游戏对象 window.

    public class Burger
{
    #region Fields

    // graphic and drawing info
    Texture2D sprite;
    Rectangle drawRectangle;

    // burger stats
    int health = 100;

    // shooting support
    bool canShoot = true;
    int elapsedCooldownMilliseconds = 0;

    // sound effect
    SoundEffect shootSound;

    #endregion

    #region Constructors

    /// <summary>
    ///  Constructs a burger
    /// </summary>
    /// <param name="contentManager">the content manager for loading content</param>
    /// <param name="spriteName">the sprite name</param>
    /// <param name="x">the x location of the center of the burger</param>
    /// <param name="y">the y location of the center of the burger</param>
    /// <param name="shootSound">the sound the burger plays when shooting</param>
    public Burger(ContentManager contentManager, string spriteName, int x, int y,
        SoundEffect shootSound)
    {
        LoadContent(contentManager, spriteName, x, y);
        this.shootSound = shootSound;
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets the collision rectangle for the burger
    /// </summary>
    public Rectangle CollisionRectangle
    {
        get { return drawRectangle; }
    }

    #endregion

    #region Public methods

    /// <summary>
    /// Updates the burger's location based on mouse. Also fires 
    /// french fries as appropriate
    /// </summary>
    /// <param name="gameTime">game time</param>
    /// <param name="mouse">the current state of the mouse</param>
    public void Update(GameTime gameTime, MouseState mouse)
    {
        // burger should only respond to input if it still has health

        // move burger using mouse
        if (health > 0)
        {
            drawRectangle.X = mouse.X;
            drawRectangle.Y = mouse.Y;

        }

        // clamp burger in window

        [THIS IS WHERE THE CODE SHOULD GO]

        // update shooting allowed
        // timer concept (for animations) introduced in Chapter 7

        // shoot if appropriate

    }

    /// <summary>
    /// Draws the burger
    /// </summary>
    /// <param name="spriteBatch">the sprite batch to use</param>
    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(sprite, drawRectangle, Color.CornflowerBlue);
    }

    #endregion

    #region Private methods

    /// <summary>
    /// Loads the content for the burger
    /// </summary>
    /// <param name="contentManager">the content manager to use</param>
    /// <param name="spriteName">the name of the sprite for the burger</param>
    /// <param name="x">the x location of the center of the burger</param>
    /// <param name="y">the y location of the center of the burger</param>
    private void LoadContent(ContentManager contentManager, string spriteName,
        int x, int y)
    {
        // load content and set remainder of draw rectangle
        sprite = contentManager.Load<Texture2D>(spriteName);
        drawRectangle = new Rectangle(x - sprite.Width / 2,
            y - sprite.Height / 2, sprite.Width,
            sprite.Height);
    }

    #endregion
}

有什么想法可以解决这个问题吗?我试过使用 mouse.Getstate 并尝试将鼠标光标锁定到 window 但这似乎不起作用。

问题似乎是您从汉堡 class 内部控制坐标(有点问题)并且您似乎没有任何对 window 边界的引用.

我的看法是您有 2 个选择:

选项 1。这还不错,但在较大的项目中,它可能会适得其反地推进项目的后续阶段:

public void Update(GameTime gameTime, MouseState mouse)
{
    if (health > 0)
    {
        //Simple version
        //if mouse is within borders, continue with position update.
        if(mouse.X > 0 && mouse.X < windowWidth && mouse.Y > 0 && mouse.Y < windowHeight){
           drawRectangle.X = mouse.X;
           drawRectangle.Y = mouse.Y;
        }else{
           //stuff to do if it it's not updating   
        }

        //a little different (better) version that should trace walls
        if(mouse.X < 0){
           drawRectangle.X = 0;
        }else if(mouse.X + drawRectangle.width > windowWidth){ //if I made no mistakes it should subtract the size of the picture and trace the inside border if mouse is outside
           drawRectangle.X = windowWidth - drawRectangle.width;
        }else{
           drawRectangle.X = mouse.X
        }
        if(mouse.Y < 0){
           drawRectangle.Y = 0;
        }else if(mouse.Y + drawRectangle.height > windowHeight ){
           drawRectangle.Y = windowHeight - drawRectangle.height;
        }else{
           drawRectangle.Y = mouse.Y
        }
    }

}

选项 2 限制在 main 更新函数中当鼠标在边界外时调用更新:

class YourApp{
   ....
   public void Update(GameTime gameTime, MouseState mouse)
    {
         if([mouse is within the window]){
            burger.Update(...);
            //+most of your updates here
         }else{
            //pause game or just display a warning that mouse is outside of the window
         }
    }
    ...
}

当您为 drawRectangle 的 X 和 Y 属性赋值时,您应该执行 Min 和 Max 函数以确保其位置在 window.

drawRectangle.X = Math.Min(Math.Max(mouse.X, 0), GraphicsDevice.Viewport.Width);
drawRectangle.Y = Math.Min(Math.Max(mouse.Y, 0), GraphicsDevice.Viewport.Height);

如果你想让精灵完全有界,你将不得不考虑 sprite/rectangle 自己的高度和宽度(假设 X 和 Y 位置是矩形的左上角,我不记得 XNA 的矩形是否与 System.Drawing) 中的不同。

drawRectangle.X = Math.Min(Math.Max(mouse.X, 0), (GraphicsDevice.Viewport.Width - drawRectangle.Width));
drawRectangle.Y = Math.Min(Math.Max(mouse.Y, 0), (GraphicsDevice.Viewport.Height - drawRectangle.Height));

您可以使用 MathHelper.Clamp() 进行限制,GraphicsDevice.Viewport 进行屏幕尺寸:

public void Update(GameTime gameTime, MouseState mouse)
{
    if (health > 0)
    {
        drawRectangle.X = (int) MathHelper.Clamp(mouse.X, 0, 
                  GraphicsDevice.Viewport.Width - drawRectangle.Width);
        drawRectangle.Y = (int) MathHelper.Clamp(mouse.Y, 0,
                  GraphicsDevice.Viewport.Height - drawRectangle.Height);
    }
    // ...
}