碎砖机克隆、球砖碰撞和砖碰撞上的球行为

本文关键字:碰撞 砖机 | 更新日期: 2023-09-27 18:35:34

几周前我开始学习c#monogame,我想开始一个项目。我选择的项目是一个破砖机克隆,一切都很顺利。但我偶然发现了一些我花了几个小时在谷歌上寻找但没有答案的东西。我遇到的问题是球和砖块之间的碰撞检测。在桨和球工作之间,我有一个可行的解决方案。这是:

// Collision between the ball and player
    public void Collision(Player player, Ball ball)
    {
        MinX = (int)player.PlayerPosition.X - ball.Width;
        MaxX = (int)player.PlayerPosition.X + player.Width + ball.Width;
        MinY = 0;
        MaxY = (int)player.PlayerPosition.Y - ball.Height;
        Rectangle BallRectangle = new Rectangle((int)ball.BallPosition.X, (int)ball.BallPosition.Y, ball.Width, ball.Height);
        Rectangle PlayerRectangle = new Rectangle((int)player.PlayerPosition.X, (int)player.PlayerPosition.Y, player.Width, player.Height);
        if (BallRectangle.Intersects(PlayerRectangle))
        {
            ball.BallPosition.Y = MathHelper.Clamp(ball.BallPosition.Y, MinY, MaxY);
            ball.BallPosition.X = MathHelper.Clamp(ball.BallPosition.X, MinX, MaxX);
            ball.BallSpeed.Y *= -1;
            float BallMiddlePoint = ball.BallPosition.X + (ball.Width / 2);
            float PlayerMiddlePoint = player.PlayerPosition.X + (player.Width / 2);
            ball.BallSpeed.X = (BallMiddlePoint - PlayerMiddlePoint) / 10 + ball.ExtraSpeedOverTime;
        }
    }

现在回到我的问题,我使用Rectangle.Intersect(Rectangle)来检查冲突。主要问题是:如何让球在砖块上正确弹跳?

我希望我能提供足够的信息。

我的球类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace BrickBreakerV2
{
    class Ball
    {
        // The texture of the ball
        Texture2D BallTexture;
        // The position of the ball
        public Vector2 BallPosition;
        // The speed of the ball
        public Vector2 BallSpeed;
        // The speed that gets added over time
        public float ExtraSpeedOverTime;
        // Time values used in incrementing the speed over time
        TimeSpan IncreaseSpeed;
        TimeSpan PreviousSpeedIncrease;
        // The "active" state of the ball
        public bool Active;
        // The state of movement of the ball
        public bool Moveball;
        // The Width of the ball
        public int Width
        {
            get { return BallTexture.Width; }
        }
        // The Height of the ball
        public int Height
        {
            get { return BallTexture.Height; }
        }
        // Construct a class for Boundaries
        CollisionHandler Collision = new CollisionHandler();

        public void Initialize(ContentManager Content, GraphicsDevice graphicsDevice, Player player)
        {
            BallTexture = Content.Load<Texture2D>("Graphics''ball.png");
            BallPosition = new Vector2(player.PlayerPosition.X + (player.Width / 2) - (Width / 2), 
            player.PlayerPosition.Y - Height - 5);
            BallSpeed = new Vector2(5.0f, -5.0f);
            ExtraSpeedOverTime = 1.0f;
            IncreaseSpeed = TimeSpan.FromSeconds(12f);
            PreviousSpeedIncrease = TimeSpan.Zero;
            Active = true;
            Moveball = false;
        }
        public void Update(GraphicsDevice graphicsDevice, GameTime gameTime, Player player)
        {
            if (Moveball)
            {
                BallPosition += BallSpeed;
            }
            else
            {
                BallPosition = new Vector2(player.PlayerPosition.X + (player.Width / 2) - (Width / 2),
                player.PlayerPosition.Y - Height - 5);
            }
            if (gameTime.TotalGameTime - PreviousSpeedIncrease > IncreaseSpeed)
            {
                ExtraSpeedOverTime += 0.01f;
                BallSpeed.X *= ExtraSpeedOverTime;
                BallSpeed.Y *= ExtraSpeedOverTime;
                PreviousSpeedIncrease = gameTime.TotalGameTime;
            }
            // Makes sure that the ball doesn't go to fast
            if (BallSpeed.X > 10.50f)
                BallSpeed.X = 10.50f;
            if (BallSpeed.Y > 10.50f)
                BallSpeed.Y = 10.50f;
            if (BallSpeed.X < -10.50f)
                BallSpeed.X = -10.50f;
            if (BallSpeed.Y < -10.50f)
                BallSpeed.Y = -10.50f;
            // Keep the ball in the boundaries
            Collision.GetBoundaries(graphicsDevice, this);
            // Detect collision between ball and player
            Collision.Collision(player, this);
        }
        public void Update(Brick brick)
        {
            // Detect collision between ball and brick
            Collision.Collision(this, brick);
        }
        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(BallTexture, BallPosition, null, Color.White, 0f, Vector2.Zero, 1f, SpriteEffects.None, 1f);
        }
    }
}

我的砖块类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace BrickBreakerV2
{
    class Brick
    {
        // The texture of the brick
        public Texture2D BrickTexture;
        // The position of the bricks
        public Vector2 BrickPosition;
        // The color tint of the brick
        public Color ColorTint;
        // The "active" state of the brick
        public bool Active;
        // The width of the brick
        public int Width
        {
            get { return BrickTexture.Width; }
        }
        // The height of the brick
        public int Height
        {
            get { return BrickTexture.Height; }
        }
        // Construct a class for collisionhandler
        CollisionHandler Collision;
        public void Initialize(ContentManager Content)
        {
            BrickTexture = Content.Load<Texture2D>("Graphics''brick.png");
            BrickPosition = new Vector2(600, 500);
            Active = true;
            ColorTint = Color.White;
            Collision = new CollisionHandler();
        }

        public void Update(Ball ball)
        {
            Collision.Collision(ball, this);
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(BrickTexture, BrickPosition, null, ColorTint, 0f, Vector2.Zero, 1f, SpriteEffects.None, 1f);
        }
    }
}

还有我在 CollisionHandler 中处理球和砖块之间碰撞的代码块.cs:

    // Collision between ball and brick
    public void Collision(Ball ball, Brick brick)
    {
        Rectangle BallRectangle = new Rectangle((int)ball.BallPosition.X, (int)ball.BallPosition.Y, ball.Width, ball.Height);
        Rectangle BrickRectangle = new Rectangle((int)brick.BrickPosition.X, (int)brick.BrickPosition.Y, brick.Width, brick.Height);
        if (BallRectangle.Intersects(BrickRectangle))
        {
            int XOverlap;
            int YOverlap;
            if (BallRectangle.Center.X < BrickRectangle.Center.X)
            {
                XOverlap = (BallRectangle.X + ball.Width) - BrickRectangle.X;
            }
            else
            {
                XOverlap = (BrickRectangle.X + brick.Width) - BallRectangle.X;
            }
            if (BallRectangle.Center.Y < BrickRectangle.Center.Y)
            {
                YOverlap = (BallRectangle.Y + ball.Height) - BrickRectangle.Y;
            }
            else
            {
                YOverlap = (BrickRectangle.Y + brick.Height) - BallRectangle.Y;
            }

            if (XOverlap == YOverlap)
            {
                ball.BallSpeed.X *= -1;
                ball.BallSpeed.Y *= -1;
            }
            else if (XOverlap < YOverlap)
            {
                ball.BallSpeed.X *= -1;
            }
            else
            {
                ball.BallSpeed.Y *= -1;
            }
            brick.Active = false;
        }
    }

碎砖机克隆、球砖碰撞和砖碰撞上的球行为

我想帮助你,但我不会调试你的代码。幸运的是,基本的2D碰撞检测和砖块破碎机克隆之前已经做了很多次。

快速的谷歌搜索发现了以下教程。我自己没有做过,但如果我在哪里,我会从这里开始:

http://xnagpa.net/xna4beginner.php

祝你好运。