我的球和我的矩形不会正确碰撞(Monogame)

My ball and my rectangle wont collide properly (Monogame)

我目前正在为我的学校项目编写一个打砖块类型的游戏,并且刚开始开发 monogame。我在大红色矩形和球上遇到了碰撞问题。我只是无法弄清楚我的代码有什么问题。感谢您提前提供的所有帮助。

碰撞视频:https://youtu.be/HOuUS8bUKn4

Game1.cs

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;

namespace TSA3
{
    public class Game1 : Game
    {
        private GraphicsDeviceManager graphics;
        private SpriteBatch spriteBatch;

        // Platform
        Platform platform;
        Texture2D platformTexture;
        Rectangle platformRectangle;
        Color platformColor;

        // Ball
        Ball ball;
        Texture2D ballTexture;
        Rectangle ballRectangle;
        Color ballColor;
        bool ballDirectionX = true, ballDirectionY = true;

        // Enemy
        Enemy enemy;
        Texture2D enemyTexture;
        Rectangle enemyRectangle;
        Color enemyColor;

        Random random = new Random();

        public const int ScreenW = 1200, ScreenH = 720;

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

        }

        protected override void Initialize()
        {
            graphics.PreferredBackBufferWidth = ScreenW;
            graphics.PreferredBackBufferHeight = ScreenH;
            graphics.ApplyChanges();

            Window.AllowUserResizing = false;
            Window.AllowAltF4 = true;
            Window.Title = "Arkanoid";

            // Platform
            platformTexture = Content.Load<Texture2D>("platform");
            platformRectangle = new Rectangle(0, Window.ClientBounds.Height - 50, 100, 30);
            platformColor = Color.White;

            // Ball
            ballTexture = Content.Load<Texture2D>("ball");
            ballRectangle = new Rectangle(0, 0, 20, 20);
            ballColor = Color.DarkBlue;

            // Enemy
            enemyTexture = Content.Load<Texture2D>("enemyPiece");
            enemyRectangle = new Rectangle(Window.ClientBounds.Width / 2, Window.ClientBounds.Height / 2, 200, 200);
            enemyColor = Color.White;

            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Player
            platform = new Platform(platformTexture, platformRectangle, platformColor, Window.ClientBounds.Width - 100);

            // Ball
            ball = new Ball(ballTexture, ballRectangle, ballColor, Window.ClientBounds.Width - 20, Window.ClientBounds.Height - 20, ballDirectionX, ballDirectionY);

            // Enemy
            enemy = new Enemy(enemyTexture, enemyRectangle, enemyColor);

            spriteBatch = new SpriteBatch(GraphicsDevice);

        }

        float spawn = 0;

        protected override void Update(GameTime gameTime)
        {
            spawn += (float)gameTime.ElapsedGameTime.TotalSeconds;

            ball.ballBounce(platform.PlatformRectangle);

            Keys[] k = Keyboard.GetState().GetPressedKeys();
            foreach (Keys key in k)
            {
                platform.platformMovement(key);
                break;
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Space) && !ball.StartGame)
                ball.StartGame = true;

            ball.ballCollision(platform.PlatformRectangle);
            ball.enemyCollision(enemy.enemyRectangle);

            base.Update(gameTime);
        }


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

            spriteBatch.Begin();
            spriteBatch.Draw(ball.BallTexture, ball.BallRectangle, ball.BallColor);
            spriteBatch.Draw(platform.PlatformTexture, platform.PlatformRectangle, platform.PlatformColor);
            spriteBatch.Draw(enemy.enemyTexture, enemy.enemyRectangle, enemy.enemyColor);
            spriteBatch.End();


            base.Draw(gameTime);
        }
    }
}

Ball.cs

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Text;

namespace TSA3
{
    public class Ball
    {
        Texture2D ballTexture;
        Rectangle ballRectangle;
        Color ballColor;

        int boundaryX, boundaryY;
        bool ballDirectionX, ballDirectionY;
        bool startGame;

        public const int BALL_SPEED = 7;

        public Ball(Texture2D ballTexture, Rectangle ballRectangle, Color ballColor, int boundaryX, int boundaryY, bool ballDirectionX, bool ballDirectionY)
        {
            this.ballTexture = ballTexture;
            this.ballRectangle = ballRectangle;
            this.ballColor = ballColor;
            this.boundaryX = boundaryX;
            this.boundaryY = boundaryY;
            this.ballDirectionX = ballDirectionX;
            this.ballDirectionY = ballDirectionY;

            startGame = false;
        }

        public Texture2D BallTexture { get => ballTexture; }
        public Rectangle BallRectangle { get => ballRectangle; }
        public Color BallColor { get => ballColor; }
        public bool StartGame { get => startGame; set => startGame = value; }

        public void ballBounce(Rectangle platformRectangle)
        {
            if (startGame)
            {
                if (ballRectangle.X <= 0)
                    ballDirectionX = true;
                else if (ballRectangle.X >= boundaryX)
                    ballDirectionX = false;

                if (ballRectangle.Y <= 0)
                {
                    ballDirectionY = true;
                }
                else if (ballRectangle.Y >= boundaryY)
                {
                    startGame = false;
                }

                if (ballDirectionX)
                    ballRectangle.X += BALL_SPEED;
                else
                    ballRectangle.X -= BALL_SPEED;

                if (ballDirectionY)
                    ballRectangle.Y += BALL_SPEED;
                else
                    ballRectangle.Y -= BALL_SPEED;
            }
            else
            {
                ballRectangle.Location = new Point(platformRectangle.X + (platformRectangle.Width / 2) - 10, platformRectangle.Y - (ballRectangle.Height - 5));
            }
        }

        public void ballCollision(Rectangle platform)
        {
            if (ballRectangle.Intersects(platform))
                ballDirectionY = false;    
        }

        public void enemyCollision(Rectangle enemyRectangle)
        {
            if (ballRectangle.Intersects(enemyRectangle))
                ballDirectionY = false;
        }


    }
}

Enemy.cs

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Text;

namespace TSA3
{
    public class Enemy
    {
        public Texture2D enemyTexture;
        public Rectangle enemyRectangle;
        public Color enemyColor;

        public bool isVisible = true;

        Random random = new Random();

        public Enemy(Texture2D enemyTexture, Rectangle enemyRectangle, Color enemyColor)
        {
            this.enemyTexture = enemyTexture;
            this.enemyRectangle = enemyRectangle;
            this.enemyColor = enemyColor;
        }

        public Texture2D EnemyTexture { get => enemyTexture; }
        public Rectangle EnemyRectangle { get => enemyRectangle; }
        public Color EnemyColor { get => enemyColor; }
    }
}

Platform.cs

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

namespace TSA3
{
    public class Platform
    {
        Texture2D platformTexture;
        Rectangle platformRectangle;
        Color platformColor;

        int boundaryX;

        public const int PLATFORM_SPEED = 10;

        public Platform(Texture2D platformTexture, Rectangle platformRectangle, Color platformColor, int boundaryX)
        {
            this.platformTexture = platformTexture;
            this.platformRectangle = platformRectangle;
            this.platformColor = platformColor;
            this.boundaryX = boundaryX;
        }

        public Texture2D PlatformTexture { get => platformTexture; }
        public Rectangle PlatformRectangle { get => platformRectangle; }
        public Color PlatformColor { get => platformColor; }

        public void platformMovement(Keys controls)
        {
            if (controls == Keys.A && platformRectangle.X > 0)
                platformRectangle.X -= PLATFORM_SPEED;

            if (controls == Keys.D && platformRectangle.X < boundaryX)
                platformRectangle.X += PLATFORM_SPEED;
        }

    }
}

提前感谢任何愿意提供帮助的人!

此方法缺少必要的代码,无法正常运行以从任何一侧接近该块:

public void enemyCollision(Rectangle enemyRectangle)
{
    if (ballRectangle.Intersects(enemyRectangle))
        ballDirectionY = false;
}

目前它的工作原理与您的平台相同:在碰撞时将 Y 方向设置为向上。
这对于平台来说效果很好,因为它很薄而且靠近屏幕边缘,因此不需要其他碰撞检查。

尝试改进此方法,类似于您对屏幕边缘的球碰撞所做的操作。

这里重要的是知道红色矩形角的位置,这样您就可以计算出球击中矩形的位置。

据我所知,你不可能有精确的边界,但你可以通过计算角的位置来测量相同的边界。例如,您可以采用 EnemyRectangle 并获得它们的 x/y 位置,即它在左上角,然后您可以添加矩形的宽度,并且您将拥有右上角(同样有效底角的高度)。如果您计算球的位置以及矩形角,您就会知道球在哪一侧与屏幕发生碰撞。

顶部碰撞示例:

public void enemyCollision(Rectangle enemyRectangle)
{
    if (ballRectangle.Intersects(enemyRectangle))
    {
        if (ballRectangle.x > enemyRectangle.x && 
            ballRectangle.x < enemyRectangle.x + enemyRectangle.Width && 
            ballRectangle.y > enemyRectangle.y)
             ballDirectionY = false;
    }
}