1

所以我试图找出 XNA 中的边界框,但我遇到了一些麻烦。下面是我的代码。该程序仅由一个可以以 UDLR 方式移动的矩形对象(我只是使用了超级马里奥游戏中的 Thwomp 精灵)和一个随机生成的在屏幕上弹跳的框列表(我使用了问号框精灵,也来自马里奥)。我已经得到了盒子从 Thwomp 侧面反弹的代码,但不是顶部和底部(它只是穿过精灵)。所以边界框现在不再是一个盒子,而更像是一个左右墙。我可以对我的代码做些什么来使盒子也从 Thwomp 的顶部和底部反弹?

谢谢

游戏类:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace BoundingBoxCollision
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{


    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    Sprite playerOne;

    static public int height;
    static public int width;

    static Random rand = new Random();

    KeyboardState keyboardState;

    List<Sprite> ballList = new List<Sprite>();
    int ballCount = 10;

    private void CheckPaddleWallCollision()
    {

    }


    private void CheckBallCollision(Sprite ball)
    {

        int MaxX =
            graphics.GraphicsDevice.Viewport.Width - ball.BoundingBox.Width;
        int MinX = 0;
        int MaxY =
            graphics.GraphicsDevice.Viewport.Height - ball.BoundingBox.Height;
        int MinY = 0;



        if (ball.BoundingBox.Intersects(playerOne.BoundingBox))
        {
            ball.Velocity.X *= -1;
            ball.Position += ball.Velocity;
        }

        if (ball.BoundingBox.Y > MaxY)
        {
            ball.Velocity.Y *= -1;
            ball.Position += ball.Velocity;
        }

        if (ball.BoundingBox.Y < MinY)
        {
            ball.Velocity.Y *= -1;
            ball.Position += ball.Velocity;
        }

        if (ball.BoundingBox.X < MinX)
        {
            ball.Velocity.X *= -1;
            ball.Position += ball.Velocity;
        }

        if (ball.BoundingBox.X > MaxX)
        {
            ball.Velocity.X *= -1;
            ball.Position += ball.Velocity;
        }
        /*if ((ball.Position.X < -ball.BoundingBox.Width)
            || (ball.Position.X > Window.ClientBounds.Width))
            SetInStartPostion(); */
    }

    /*private void SetInStartPostion()
    {
        playerOne.Position.Y = (
            Window.ClientBounds.Height -
            playerOne.BoundingBox.Height) / 2;


        ball.Position.X = playerOne.BoundingBox.Right + 1;

        ball.Position.Y = (
            Window.ClientBounds.Height -
            ball.BoundingBox.Height) / 2;

        ball.Velocity = new Vector2(8f, -8f);
    } */

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    /// <summary>
    /// Allows the game to perform any initialization it needs to before starting to run.
    /// This is where it can query for any required services and load any non-graphic
    /// related content.  Calling base.Initialize will enumerate through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize()
    {
        // TODO: Add your initialization logic here

        base.Initialize();
    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to load
    /// all of your content.
    /// </summary>
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        height = GraphicsDevice.Viewport.Height;
        width = GraphicsDevice.Viewport.Width;

        Texture2D paddleTexture = Content.Load<Texture2D>("Thwomp");
        Vector2 position;

        position = new Vector2(
            100,
            (Window.ClientBounds.Height - paddleTexture.Height) / 2);
        playerOne = new Sprite(paddleTexture, position);

        position = new Vector2(
            (Window.ClientBounds.Width - paddleTexture.Width),
            (Window.ClientBounds.Height - paddleTexture.Height) / 2);

        Texture2D ballTexture = Content.Load<Texture2D>("QuestionMarkBlock");

        position = new Vector2(
                 playerOne.BoundingBox.Right + 1,
                 (Window.ClientBounds.Height - ballTexture.Height) / 2);

        for (int i = 0; i < ballCount; i++)
        {
            position = new Vector2(rand.Next(Game1.width), rand.Next(Game1.height));
            Sprite ball = new Sprite(
                     ballTexture,
                    position,
                     new Vector2(4f, -4f));
            ballList.Add(ball);
        }
    }


    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// all content.
    /// </summary>
    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();



        keyboardState = Keyboard.GetState();

        if (keyboardState.IsKeyDown(Keys.Up))
            playerOne.Position.Y -= 4f;

        if (keyboardState.IsKeyDown(Keys.Down))
            playerOne.Position.Y += 4f;

        if (keyboardState.IsKeyDown(Keys.Left))
            playerOne.Position.X -= 4f;

        if (keyboardState.IsKeyDown(Keys.Right))
            playerOne.Position.X += 4f;



        foreach (Sprite block in ballList)
        {
            block.Position += block.Velocity;
            CheckBallCollision(block);

        }

        CheckPaddleWallCollision();



        base.Update(gameTime);
    }


    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        spriteBatch.Begin();

        playerOne.Draw(spriteBatch);

        foreach (Sprite block in ballList)
        {
            block.Draw(spriteBatch);
        }

        spriteBatch.End();

        base.Draw(gameTime);
    }


    public static int vGameWidth { get; set; }
}
}

精灵类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace BoundingBoxCollision
{
public class Sprite
{



    Texture2D texture;
    public Vector2 Position;
    public Vector2 Velocity;


    public Rectangle BoundingBox
    {
        get
        {
            return new Rectangle(
                (int)Position.X,
                (int)Position.Y,
                texture.Width,
                texture.Height);
        }
    }

    public Sprite(Texture2D texture, Vector2 position)
    {
        this.texture = texture;
        this.Position = position;
    }

    public Sprite(Texture2D texture, Vector2 position, Vector2 velocity)
    {
        this.texture = texture;
        this.Position = position;
        this.Velocity = velocity;
    }



    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(texture, Position, Color.White);
    }

}
}
4

2 回答 2

1

最简单的方法是:

if (ball.BoundingBox.Intersects(playerOne.BoundingBox))
        {
            ball.Velocity.X *= -1;
            ball.Velocity.Y *= -1;
            ball.Position += ball.Velocity;
        }

这将是一个完整的反映。如果你想要一种更现实的方式,你想做这样的事情(伪代码):

  1. 检查球和球员是否碰撞
  2. 确定它是否在顶部/底部、左侧/右侧或精确角落发生碰撞
    1. 左右 :ball.Velocity.X*= -1;
    2. 顶部/底部:ball.Velocity.Y *= -1;
    3. 角落:ball.Velocity.X *= -1;&&ball.Velocity.Y *= -1;

我希望这能有所帮助!

问候

浮动

于 2012-09-28T08:36:25.000 回答
0

对于 2 号(顶部/底部),您可以使用

playerOne.BoundingBox.Top

playerOne.BoundingBox.Bottom?

.Top 和 .Bottom 应该返回矩形顶部或矩形底部的 Y 坐标。

于 2012-10-27T17:48:19.450 回答