如何在c#中检测两个不同形状的碰撞
how to detect collisions of two different shapes in c#
我有两种不同的形状。使用上下左右键移动的矩形和在固定位置移动的圆(Y 轴上下)。我正在尝试检测碰撞,如果我将矩形移动到圆中,就会检测到碰撞并停止游戏。我试过这段代码,但它不起作用:
public bool collision()
{
if (PlayerPositionX == EnemyPosX & PlayerPositionY == EnemyPosY )
{
_movementTimer.Stop();
}
if (collision()==true)
{
_movementTimer.Stop();
}
return collision();
}
这是完整代码。有人知道怎么做吗?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Timers;
using System.Drawing.Imaging;
using Timer = System.Windows.Forms.Timer;
namespace prot_4
{
public partial class Form1 : Form
{
int PlayerPositionX = 40, PlayerPositionY = 200, width = 40, height = 40; // player
int EnemyWidth = 40, EnemyHeight = 40, EnemyPosX = 100, EnemyPosY = 0, EnemySpeedX = 0, EnemySpeedY = 20; // enemy
int EnemyWidth2 = 40, EnemyHeight2 = 40, EnemyPosX2 = 200, EnemyPosY2 = 400, EnemySpeedX2 = 0, EnemySpeedY2 = 20; // enemy2
int EnemyWidth3 = 40, EnemyHeight3 = 40, EnemyPosX3 = 300, EnemyPosY3 = 0, EnemySpeedX3 = 0, EnemySpeedY3 = 20; // enemy3
int EnemyWidth4 = 40, EnemyHeight4 = 40, EnemyPosX4 = 400, EnemyPosY4 = 400, EnemySpeedX4 = 0, EnemySpeedY4 = 20; // enemy4
int EnemyWidth5 = 40, EnemyHeight5 = 40, EnemyPosX5 = 500, EnemyPosY5 = 0, EnemySpeedX5 = 0, EnemySpeedY5 = 20; // enemy5
int EnemyWidth6 = 40, EnemyHeight6 = 40, EnemyPosX6 = 600, EnemyPosY6 = 400, EnemySpeedX6 = 0, EnemySpeedY6 = 20; // enemy6
private bool moveUp, moveDown, moveLeft, moveRight;
private System.Windows.Forms.Timer _movementTimer = new Timer { Interval = 100 };
public bool collision()
{
if (PlayerPositionX == EnemyPosX & PlayerPositionY == EnemyPosY )
{
_movementTimer.Stop();
}
if (collision()==true)
{
_movementTimer.Stop();
}
return collision();
}
public Form1()
{
InitializeComponent();
_movementTimer.Tick += movementTimer_Tick;
}
private void movementTimer_Tick(object sender , EventArgs e)
{
playerControls();
}
//Form1_KeyDown
private void playerControls() // Player controls
{
if (moveRight)
{
PlayerPositionX += 5;
if (PlayerPositionX >= 800 - width)
{
PlayerPositionX = 800 - width;
}
}
if (moveLeft)
{
PlayerPositionX -= 5;
if (PlayerPositionX <= -43 + width)
{
PlayerPositionX = -43 + width;
}
}
if (moveUp)
{
PlayerPositionY -= 5;
if (PlayerPositionY <= 0)
{
PlayerPositionY = 0;
}
}
if (moveDown)
{
PlayerPositionY += 5;
if (PlayerPositionY >= 410)
{
PlayerPositionY = 410;
}
}
}
public void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up:
moveUp = true;
break;
case Keys.Down:
moveDown = true;
break;
case Keys.Left:
moveLeft = true;
break;
case Keys.Right:
moveRight = true;
break;
}
playerControls();
_movementTimer.Start();
}
public void Form1_KeyUp(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up:
moveUp = false;
break;
case Keys.Down:
moveDown = false;
break;
case Keys.Left:
moveLeft = false;
break;
case Keys.Right:
moveRight = false;
break;
}
if (!(moveUp || moveDown || moveLeft || moveRight ))
{
_movementTimer.Stop();
}
}
public void player(object sender, PaintEventArgs e) // drawing the player
{
e.Graphics.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.Clear(this.BackColor);
e.Graphics.FillRectangle((Brushes.Blue), PlayerPositionX, PlayerPositionY, width, height);
e.Graphics.DrawRectangle(Pens.Black,
PlayerPositionX, PlayerPositionY,
width, height);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX, EnemyPosY,
EnemyWidth, EnemyHeight);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX, EnemyPosY,
EnemyWidth, EnemyHeight);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX2, EnemyPosY2,
EnemyWidth2, EnemyHeight2);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX2, EnemyPosY2,
EnemyWidth2, EnemyHeight2);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX3, EnemyPosY3,
EnemyWidth3, EnemyHeight3);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX3, EnemyPosY3,
EnemyWidth3, EnemyHeight3);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX4, EnemyPosY4,
EnemyWidth, EnemyHeight);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX4, EnemyPosY4,
EnemyWidth4, EnemyHeight4);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX5, EnemyPosY5,
EnemyWidth5, EnemyHeight5);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX5, EnemyPosY5,
EnemyWidth5, EnemyHeight5);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX6, EnemyPosY6,
EnemyWidth6, EnemyHeight6);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX6, EnemyPosY6,
EnemyWidth6, EnemyHeight6);
}
private void PlayerMoveTimer(object sender, EventArgs e ) // timer 2
{
Invalidate();
}
private void moveTimer(object sender, EventArgs e) // timer
{
//update coorndinates
EnemyPosX += EnemySpeedX; // how the enemy moves //timer 1
if (EnemyPosX < 0 ||
EnemyPosX + EnemyWidth > this.ClientSize.Width
)
{
EnemySpeedX = -EnemySpeedX;
}
EnemyPosY -= EnemySpeedY;
if (EnemyPosY < 0 ||
EnemyPosY + EnemyHeight > this.ClientSize.Height
)
{
EnemySpeedY = -EnemySpeedY;
}
EnemyPosX2 += EnemySpeedX2; // how the enemy moves //timer 1
if (EnemyPosX2 < 0 ||
EnemyPosX2 + EnemyWidth2 > this.ClientSize.Width
)
{
EnemySpeedX2 = -EnemySpeedX2;
}
EnemyPosY2 += EnemySpeedY2;
if (EnemyPosY2 < 0 ||
EnemyPosY2 + EnemyHeight2 > this.ClientSize.Height
)
{
EnemySpeedY2 = -EnemySpeedY2;
}
EnemyPosX3 += EnemySpeedX3; // how the enemy moves //timer 1
if (EnemyPosX3 < 0 ||
EnemyPosX3 + EnemyWidth3 > this.ClientSize.Width
)
{
EnemySpeedX3 = -EnemySpeedX3;
}
EnemyPosY3 -= EnemySpeedY3;
if (EnemyPosY3 < 0 ||
EnemyPosY3 + EnemyHeight3 > this.ClientSize.Height
)
{
EnemySpeedY3 = -EnemySpeedY3;
}
EnemyPosX4 += EnemySpeedX4; // how the enemy moves //timer 1
if (EnemyPosX4 < 0 ||
EnemyPosX4 + EnemyWidth4 > this.ClientSize.Width
)
{
EnemySpeedX4 = -EnemySpeedX4;
}
EnemyPosY4 += EnemySpeedY4;
if (EnemyPosY4 < 0 ||
EnemyPosY4 + EnemyHeight4 > this.ClientSize.Height
)
{
EnemySpeedY4 = -EnemySpeedY4;
}
EnemyPosX5 += EnemySpeedX5; // how the enemy moves //timer 1
if (EnemyPosX5 < 0 ||
EnemyPosX5 + EnemyWidth5 > this.ClientSize.Width
)
{
EnemySpeedX = -EnemySpeedX;
}
EnemyPosY5 -= EnemySpeedY5;
if (EnemyPosY5 < 0 ||
EnemyPosY5 + EnemyHeight5 > this.ClientSize.Height
)
{
EnemySpeedY5 = -EnemySpeedY5;
}
EnemyPosX6 += EnemySpeedX6; // how the enemy moves //timer 1
if (EnemyPosX6 < 0 ||
EnemyPosX6 + EnemyWidth6 > this.ClientSize.Width
)
{
EnemySpeedX6 = -EnemySpeedX6;
}
EnemyPosY6 += EnemySpeedY6;
if (EnemyPosY6 < 0 ||
EnemyPosY6 + EnemyHeight6 > this.ClientSize.Height
)
{
EnemySpeedY6 = -EnemySpeedY6;
}
//refresh windows
Invalidate();
}
}
}
抱歉,但通过简要查看您的代码,我觉得它没有多大意义。递归碰撞函数,从不 returns 一个实际值。这背后的想法是什么?它甚至可以编译吗?
话虽如此,您所追求的具体碰撞检测并没有那么复杂。这是执行此操作的一般方法。
如果知道矩形四个角的坐标,圆知道圆心的坐标和半径的长度。您所要做的就是计算从每个矩形角到圆心的距离(使用毕达哥拉斯公式)。如果这些距离中的一个或多个小于圆的半径,则发生碰撞。
更新
在对这个问题进行了更多思考之后,我现在看到了一些矩形和圆形发生碰撞的情况,而我的方法没有涵盖这些情况。但是我仍然认为我的方法是一个很好的开始。
我有两种不同的形状。使用上下左右键移动的矩形和在固定位置移动的圆(Y 轴上下)。我正在尝试检测碰撞,如果我将矩形移动到圆中,就会检测到碰撞并停止游戏。我试过这段代码,但它不起作用:
public bool collision()
{
if (PlayerPositionX == EnemyPosX & PlayerPositionY == EnemyPosY )
{
_movementTimer.Stop();
}
if (collision()==true)
{
_movementTimer.Stop();
}
return collision();
}
这是完整代码。有人知道怎么做吗?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Timers;
using System.Drawing.Imaging;
using Timer = System.Windows.Forms.Timer;
namespace prot_4
{
public partial class Form1 : Form
{
int PlayerPositionX = 40, PlayerPositionY = 200, width = 40, height = 40; // player
int EnemyWidth = 40, EnemyHeight = 40, EnemyPosX = 100, EnemyPosY = 0, EnemySpeedX = 0, EnemySpeedY = 20; // enemy
int EnemyWidth2 = 40, EnemyHeight2 = 40, EnemyPosX2 = 200, EnemyPosY2 = 400, EnemySpeedX2 = 0, EnemySpeedY2 = 20; // enemy2
int EnemyWidth3 = 40, EnemyHeight3 = 40, EnemyPosX3 = 300, EnemyPosY3 = 0, EnemySpeedX3 = 0, EnemySpeedY3 = 20; // enemy3
int EnemyWidth4 = 40, EnemyHeight4 = 40, EnemyPosX4 = 400, EnemyPosY4 = 400, EnemySpeedX4 = 0, EnemySpeedY4 = 20; // enemy4
int EnemyWidth5 = 40, EnemyHeight5 = 40, EnemyPosX5 = 500, EnemyPosY5 = 0, EnemySpeedX5 = 0, EnemySpeedY5 = 20; // enemy5
int EnemyWidth6 = 40, EnemyHeight6 = 40, EnemyPosX6 = 600, EnemyPosY6 = 400, EnemySpeedX6 = 0, EnemySpeedY6 = 20; // enemy6
private bool moveUp, moveDown, moveLeft, moveRight;
private System.Windows.Forms.Timer _movementTimer = new Timer { Interval = 100 };
public bool collision()
{
if (PlayerPositionX == EnemyPosX & PlayerPositionY == EnemyPosY )
{
_movementTimer.Stop();
}
if (collision()==true)
{
_movementTimer.Stop();
}
return collision();
}
public Form1()
{
InitializeComponent();
_movementTimer.Tick += movementTimer_Tick;
}
private void movementTimer_Tick(object sender , EventArgs e)
{
playerControls();
}
//Form1_KeyDown
private void playerControls() // Player controls
{
if (moveRight)
{
PlayerPositionX += 5;
if (PlayerPositionX >= 800 - width)
{
PlayerPositionX = 800 - width;
}
}
if (moveLeft)
{
PlayerPositionX -= 5;
if (PlayerPositionX <= -43 + width)
{
PlayerPositionX = -43 + width;
}
}
if (moveUp)
{
PlayerPositionY -= 5;
if (PlayerPositionY <= 0)
{
PlayerPositionY = 0;
}
}
if (moveDown)
{
PlayerPositionY += 5;
if (PlayerPositionY >= 410)
{
PlayerPositionY = 410;
}
}
}
public void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up:
moveUp = true;
break;
case Keys.Down:
moveDown = true;
break;
case Keys.Left:
moveLeft = true;
break;
case Keys.Right:
moveRight = true;
break;
}
playerControls();
_movementTimer.Start();
}
public void Form1_KeyUp(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up:
moveUp = false;
break;
case Keys.Down:
moveDown = false;
break;
case Keys.Left:
moveLeft = false;
break;
case Keys.Right:
moveRight = false;
break;
}
if (!(moveUp || moveDown || moveLeft || moveRight ))
{
_movementTimer.Stop();
}
}
public void player(object sender, PaintEventArgs e) // drawing the player
{
e.Graphics.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.Clear(this.BackColor);
e.Graphics.FillRectangle((Brushes.Blue), PlayerPositionX, PlayerPositionY, width, height);
e.Graphics.DrawRectangle(Pens.Black,
PlayerPositionX, PlayerPositionY,
width, height);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX, EnemyPosY,
EnemyWidth, EnemyHeight);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX, EnemyPosY,
EnemyWidth, EnemyHeight);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX2, EnemyPosY2,
EnemyWidth2, EnemyHeight2);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX2, EnemyPosY2,
EnemyWidth2, EnemyHeight2);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX3, EnemyPosY3,
EnemyWidth3, EnemyHeight3);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX3, EnemyPosY3,
EnemyWidth3, EnemyHeight3);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX4, EnemyPosY4,
EnemyWidth, EnemyHeight);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX4, EnemyPosY4,
EnemyWidth4, EnemyHeight4);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX5, EnemyPosY5,
EnemyWidth5, EnemyHeight5);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX5, EnemyPosY5,
EnemyWidth5, EnemyHeight5);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX6, EnemyPosY6,
EnemyWidth6, EnemyHeight6);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX6, EnemyPosY6,
EnemyWidth6, EnemyHeight6);
}
private void PlayerMoveTimer(object sender, EventArgs e ) // timer 2
{
Invalidate();
}
private void moveTimer(object sender, EventArgs e) // timer
{
//update coorndinates
EnemyPosX += EnemySpeedX; // how the enemy moves //timer 1
if (EnemyPosX < 0 ||
EnemyPosX + EnemyWidth > this.ClientSize.Width
)
{
EnemySpeedX = -EnemySpeedX;
}
EnemyPosY -= EnemySpeedY;
if (EnemyPosY < 0 ||
EnemyPosY + EnemyHeight > this.ClientSize.Height
)
{
EnemySpeedY = -EnemySpeedY;
}
EnemyPosX2 += EnemySpeedX2; // how the enemy moves //timer 1
if (EnemyPosX2 < 0 ||
EnemyPosX2 + EnemyWidth2 > this.ClientSize.Width
)
{
EnemySpeedX2 = -EnemySpeedX2;
}
EnemyPosY2 += EnemySpeedY2;
if (EnemyPosY2 < 0 ||
EnemyPosY2 + EnemyHeight2 > this.ClientSize.Height
)
{
EnemySpeedY2 = -EnemySpeedY2;
}
EnemyPosX3 += EnemySpeedX3; // how the enemy moves //timer 1
if (EnemyPosX3 < 0 ||
EnemyPosX3 + EnemyWidth3 > this.ClientSize.Width
)
{
EnemySpeedX3 = -EnemySpeedX3;
}
EnemyPosY3 -= EnemySpeedY3;
if (EnemyPosY3 < 0 ||
EnemyPosY3 + EnemyHeight3 > this.ClientSize.Height
)
{
EnemySpeedY3 = -EnemySpeedY3;
}
EnemyPosX4 += EnemySpeedX4; // how the enemy moves //timer 1
if (EnemyPosX4 < 0 ||
EnemyPosX4 + EnemyWidth4 > this.ClientSize.Width
)
{
EnemySpeedX4 = -EnemySpeedX4;
}
EnemyPosY4 += EnemySpeedY4;
if (EnemyPosY4 < 0 ||
EnemyPosY4 + EnemyHeight4 > this.ClientSize.Height
)
{
EnemySpeedY4 = -EnemySpeedY4;
}
EnemyPosX5 += EnemySpeedX5; // how the enemy moves //timer 1
if (EnemyPosX5 < 0 ||
EnemyPosX5 + EnemyWidth5 > this.ClientSize.Width
)
{
EnemySpeedX = -EnemySpeedX;
}
EnemyPosY5 -= EnemySpeedY5;
if (EnemyPosY5 < 0 ||
EnemyPosY5 + EnemyHeight5 > this.ClientSize.Height
)
{
EnemySpeedY5 = -EnemySpeedY5;
}
EnemyPosX6 += EnemySpeedX6; // how the enemy moves //timer 1
if (EnemyPosX6 < 0 ||
EnemyPosX6 + EnemyWidth6 > this.ClientSize.Width
)
{
EnemySpeedX6 = -EnemySpeedX6;
}
EnemyPosY6 += EnemySpeedY6;
if (EnemyPosY6 < 0 ||
EnemyPosY6 + EnemyHeight6 > this.ClientSize.Height
)
{
EnemySpeedY6 = -EnemySpeedY6;
}
//refresh windows
Invalidate();
}
}
}
抱歉,但通过简要查看您的代码,我觉得它没有多大意义。递归碰撞函数,从不 returns 一个实际值。这背后的想法是什么?它甚至可以编译吗?
话虽如此,您所追求的具体碰撞检测并没有那么复杂。这是执行此操作的一般方法。
如果知道矩形四个角的坐标,圆知道圆心的坐标和半径的长度。您所要做的就是计算从每个矩形角到圆心的距离(使用毕达哥拉斯公式)。如果这些距离中的一个或多个小于圆的半径,则发生碰撞。
更新
在对这个问题进行了更多思考之后,我现在看到了一些矩形和圆形发生碰撞的情况,而我的方法没有涵盖这些情况。但是我仍然认为我的方法是一个很好的开始。