破砖者克隆,球砖碰撞和砖碰撞的球行为

时间:2013-10-16 16:13:09

标签: c# collision-detection monogame bounce pong

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

// 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;
        }
    }

1 个答案:

答案 0 :(得分:1)

我想帮助你,但我不打算调试你的代码。幸运的是,基本的二维碰撞检测和破碎机克隆已经做过很多次了。

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

http://xnagpa.net/xna4beginner.php

祝你好运。