0

我可以轻松地旋转我的精灵,但是如何旋转我的矩形以进行碰撞(考虑使用分离轴定理,但我不知道如何应用它)帮助或示例将不胜感激:)

游戏1类:

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 CombatTank
{

public class Game1 : Microsoft.Xna.Framework.Game
{
    //Declare Graphic Manager & Spritebatch
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    //Declare Player 1
    theBody player1TankBody;

    //Declare Player 2
    theBody player2TankBody;

    //Save Player 1 Position
    Vector2 savedPlayer1TankBodyPosition;

    //Save Player 2 Position
    Vector2 savedPlayer2TankBodyPosition;

    //Declare Keyboard States
    KeyboardState currentkeyboardState;
    KeyboardState previousKeyboardState;


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

    protected override void Initialize()
    {
        //TankBody Position Player 1
        Vector2 player1TankBodyPosition = new Vector2(200, 200);
        Vector2 player2TankBodyPosition = new Vector2(400, 200);

        //TankBody Scale 
        float player1TankBodyScale = 1.0F;
        float player2TankBodyScale = 1.0F;

        //TankBody Rotation
        float player1TankBodyRotation = 0.0F;
        float player2TankBodyRotation = 0.0F;

        //TankBody Color
        Color player1TankBodyColor = Color.Red;
        Color player2TankBodyColor = Color.Blue;

        //Create Tank
        player1TankBody = new theBody(player1TankBodyPosition,player1TankBodyScale, player1TankBodyRotation, player1TankBodyColor);
        player2TankBody = new theBody(player2TankBodyPosition, player2TankBodyScale, player2TankBodyRotation, player2TankBodyColor);

        base.Initialize();
    }

    protected override void LoadContent()
    {
        //Create New SpriteBatch
        spriteBatch = new SpriteBatch(GraphicsDevice);

        //Load The Player 1 TankBody Texture
        Texture2D player1SpriteTankBody = Content.Load<Texture2D>("TankBody");
        player1TankBody.LoadContent(Content,"TankBody");

        //Extract Collision Data For Player 1
        player1TankBody.TankBodyTextureData = new Color[player1TankBody.Texture.Width * player1TankBody.Texture.Height];
        player1TankBody.Texture.GetData(player1TankBody.TankBodyTextureData);

        //Load The Player 2 TankBody Texture
        Texture2D player2SpriteTankBody = Content.Load<Texture2D>("TankBody");
        player2TankBody.LoadContent(Content, "TankBody");

        //Extract Collision Data For Player 2
        player2TankBody.TankBodyTextureData = new Color[player2TankBody.Texture.Width * player2TankBody.Texture.Height];
        player2TankBody.Texture.GetData(player2TankBody.TankBodyTextureData);

    }

    protected override void UnloadContent()
    {

    }


    protected override void Update(GameTime gameTime)
    {
        //Save Player 1 Postion
        savedPlayer1TankBodyPosition.X = player1TankBody.Position.X;
        savedPlayer1TankBodyPosition.Y = player1TankBody.Position.Y;

        //Save Player 2 Position
        savedPlayer2TankBodyPosition.X = player2TankBody.Position.X;
        savedPlayer2TankBodyPosition.Y = player2TankBody.Position.Y;

        //Updates Player 1
        UpdatePlayer1(gameTime);

        //Update Player 2
        UpdatePlayer2(gameTime);

        //Collision Player 1
        CollisionPlayer1(gameTime);

        //Collision Player 2
        CollisionPlayer2(gameTime);

        base.Update(gameTime);
    }

    private void UpdatePlayer1(GameTime gameTime)
    {
        //Save the previous state of the keyboard
        previousKeyboardState = currentkeyboardState;

        //Read the current state of the keyboard
        currentkeyboardState = Keyboard.GetState();

        //TankBody Movement
        if (currentkeyboardState.IsKeyDown(Keys.W))
        {
            //Move Tank Forward
            player1TankBody.Position.X -= 5 * (float)Math.Cos(player1TankBody.Rotation);
            player1TankBody.Position.Y -= 5 * (float)Math.Sin(player1TankBody.Rotation);
        }
        if (currentkeyboardState.IsKeyDown(Keys.S))
        {
            //Move Tank Backwards
            player1TankBody.Position.X += 5 * (float)Math.Cos(player1TankBody.Rotation);
            player1TankBody.Position.Y += 5 * (float)Math.Sin(player1TankBody.Rotation);

        }
        if (currentkeyboardState.IsKeyDown(Keys.A))
        {
            player1TankBody.Rotation -= 0.03f;
        }
        if (currentkeyboardState.IsKeyDown(Keys.D))
        {
            player1TankBody.Rotation += 0.03f;
        }

    }

    private void UpdatePlayer2(GameTime gameTime)
    {
        //Save the previous state of the keyboard
        previousKeyboardState = currentkeyboardState;

        //Read the current state of the keyboard
        currentkeyboardState = Keyboard.GetState();

        //TankBody Movement
        if (currentkeyboardState.IsKeyDown(Keys.Up))
        {
            //Move Tank Forward
            player2TankBody.Position.X -= 5 * (float)Math.Cos(player2TankBody.Rotation);
            player2TankBody.Position.Y -= 5 * (float)Math.Sin(player2TankBody.Rotation);
        }
        if (currentkeyboardState.IsKeyDown(Keys.Down))
        {
            //Move Tank Backward
            player2TankBody.Position.X += 5 * (float)Math.Cos(player2TankBody.Rotation);
            player2TankBody.Position.Y += 5 * (float)Math.Sin(player2TankBody.Rotation);
        }
        if (currentkeyboardState.IsKeyDown(Keys.Left))
        {
            player2TankBody.Rotation -= 0.03f;
        }
        if (currentkeyboardState.IsKeyDown(Keys.Right))
        {
            player2TankBody.Rotation += 0.03f;
        }

    }

    private void CollisionPlayer1(GameTime gameTime)
    {


        if (IntersectPixels(player1TankBody.BoundingBox, player1TankBody.TankBodyTextureData, player2TankBody.BoundingBox, player2TankBody.TankBodyTextureData))
        {
            player1TankBody.Position.X = savedPlayer1TankBodyPosition.X;
            player1TankBody.Position.Y = savedPlayer1TankBodyPosition.Y;

        }



    }

    private void CollisionPlayer2(GameTime gameTime)
    {
        if (IntersectPixels(player2TankBody.BoundingBox, player2TankBody.TankBodyTextureData, player1TankBody.BoundingBox, player1TankBody.TankBodyTextureData))
        {
            player2TankBody.Position.X = savedPlayer2TankBodyPosition.X;
            player2TankBody.Position.Y = savedPlayer2TankBodyPosition.Y;

        }
    }


    static bool IntersectPixels(Rectangle rectangleA, Color[] dataA, Rectangle rectangleB, Color[] dataB)
    {
        //Find top Bound of the Rectangle
        int top = Math.Max(rectangleA.Top, rectangleB.Top);
        int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);
        int left = Math.Max(rectangleA.Left, rectangleB.Left);
        int right = Math.Min(rectangleA.Right, rectangleB.Right);

        for (int y = top; y < bottom; y++)
        {
            for (int x = left; x < right; x++)
            {
                //Get Color of both Pixels
                Color colorA = dataA[(x - rectangleA.Left) + (y - rectangleA.Top) * rectangleA.Width];
                Color colorB = dataB[(x - rectangleB.Left) + (y - rectangleB.Top) * rectangleB.Width];

                //Both pixel are not completely Transparent
                if (colorA.A != 0 && colorB.B != 0)
                {
                    //Then an intersection is found 
                    return true;
                }

            }

        }


        //No Intersection
        return false;
    }





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

        spriteBatch.Begin();

        player1TankBody.Draw(spriteBatch);
        player2TankBody.Draw(spriteBatch);

        spriteBatch.End();

        base.Draw(gameTime);
    }
}
}

身体类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;

namespace CombatTank
{
class theBody
{
    //TankBody Texture
    private Texture2D texture;
    public Texture2D Texture
    {
        get
        { 
            return texture; 
        }
    }

    //TankBody Height
    private float height;
    public float Height
    {
        get
        {
            return height;
        }
    }

    //TankBody Width
    private float width;
    private float Width
    {
        get
        {
            return width;
        }

    }

    //TankBody Position
    public Vector2 Position;

    //TankBody Origin
    public Vector2 Origin;

    //TankBody Rotation
    public float Rotation = 0.0F;

    //TankBody Color
    public Color Color = Color.White;

    //TankBody Scale
    public float Scale = 1F;

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

    //TankBody color Data(Used For Pixel Collision)
    public Color[] TankBodyTextureData;

    //TankBody Constructor
    public theBody(Vector2 position,float scale,float rotation, Color color)
    {
        Position = position;
        Scale = scale;
        Rotation = rotation;
        Color = color;
    }

    //LoadContent
    public void LoadContent(ContentManager contentManager, string assetname)
    {
        texture = contentManager.Load<Texture2D>(assetname);
        Origin = new Vector2(Texture.Width / 2, Texture.Height / 2);
    }

    //Draw
    public virtual void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(texture, Position, null, Color, Rotation, Origin, Scale, SpriteEffects.None, 0);
    }

    //Update
    public void Update(GameTime gameTime)
    {

    }
}
}
4

3 回答 3

1

除非这是学习如何编写物理引擎的实践,否则我建议使用免费的 2D 碰撞/物理库而不是重新发明轮子;我想到了Box2D 。

刚刚注意到您正在尝试根据透明度在它们的纹理之间进行逐像素碰撞。现代游戏(即使是非常小的游戏)基于凸面进行碰撞和物理处理,这使您可以获得更复杂的影响结果(如果两个像素命中,那么正常情况是什么?)。

于 2013-02-03T07:42:21.083 回答
0

I understand in your question that you are using AABBs, and now you are trying to rotate the sprites, so now you need to rotate the AABB (That is, a OBB).

If Im not wrong and that is your case, one approach is what you suggested: SAT. But another approach is to use AABBs:

Note that an OBB its only an AABB defined in its own coordinate system (The optimal coordinate system that fits the AABB better to the object). You have two OOBBs (A and B), so you have two AABBs in two coordinate systems.

Get the AABB of B, and compute its AABB in the coordinate system of A (We can call this new AABB "C"). Check C and the AABB of A collision. Now do the same in reverse order (A's AABB in coordinate system of B (We call this new AABB "D"), and check collision with B's AABB).

If the two checks gets collision, the OBBs are in collision. See the picture:

enter image description here

于 2013-07-14T22:04:54.153 回答
0

我还没有看过你的代码,但是这里有一个很好的教程,它用示例代码解释了 SAT。它不是 C#,但很容易转换;)

于 2013-07-14T23:49:58.773 回答