我的球和我的矩形不会正确碰撞(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;
}
}
我目前正在为我的学校项目编写一个打砖块类型的游戏,并且刚开始开发 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;
}
}