我是XNA和C#的新手(我在2天前开始,所以请原谅这些草率的编程),我遇到了一个我正在制作的简单游戏的问题。我似乎无法在任何在线教程中找到解决方案。我正在尝试使用矩形碰撞检测,但我无法让它正常工作。角色完全落在地板上,似乎在任何地方都没有碰撞。我在这里找不到我的逻辑错误。下面我发布了一些与碰撞检测有关的代码。如有必要我可以发布更多内容。感谢您的帮助!
Level.cs
//The method below is called in the initial LoadContent method in Game1.cs. 'LoadBlocks()' is supposed to read in a text file and setup the level's "blocks" (the floor or platforms in the game).
public void LoadBlocks(int level){
if (level == 0)
{
fileName = "filepath";
}
System.IO.StreamReader file = new System.IO.StreamReader(fileName);
while ((line = file.ReadLine()) != null)
{
for (int i = 0; i < 35; i++)
{
rectBlock = new Rectangle((int)positionBlock.X, (int)positionBlock.Y, width / 30, height / 30);
if (line.Substring(i, 1).Equals(","))
{
positionBlock.X += (width / 100) * 24;
}
if (line.Substring(i, 1).Equals("#"))
{ //block -> (bool isPassable, Texture2D texture, Rectangle rectangle, Vector2 position)
block = new Block(false, textureBlock, rectBlock, positionBlock);
blocks.Add(block);
positionBlock.X += (width / 100) * 24;
}
}
positionBlock.Y += (height / 100) * 8;
positionBlock.X = 0;
}
}
//This method below updates the character 'bob' position and velocity.
public void UpdatePlayer()
{
bob.position += bob.velocity;
bob.rectangle = new Rectangle((int)bob.position.X, (int)bob.position.Y, width / 30, height / 30);
float i = 1;
bob.velocity.Y += 0.15f * i;
foreach (Block block in blocks)
{
if (bob.isOnTopOf(bob.rectangle, block.rectangle))
{
bob.velocity.Y = 0f;
bob.hasJumped = false;
}
}
}
Character.cs
//Here is my whole Character class for 'bob'
public class Character
{
int height = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
int width = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
int health;
String name;
bool gender;
Texture2D texture;
public Vector2 position;
public Vector2 velocity;
public bool hasJumped;
public Rectangle rectangle;
public Character(int newHealth, String newName, bool newGender, Texture2D newTexture, Vector2 newPosition)
{
health = newHealth;
gender = newGender;
name = newName;
texture = newTexture;
position = newPosition;
hasJumped = true;
rectangle = new Rectangle(0,0, width/30,height/30);
velocity = Vector2.Zero;
}
public bool isOnTopOf(Rectangle r1, Rectangle r2)
{
const int penetrationMargin = 5;
return (r1.Bottom >= r2.Top - penetrationMargin &&
r1.Bottom <= r2.Top &&
r1.Right >= r2.Left + 5 &&
r1.Left <= r2.Right - 5);
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, rectangle,null, Color.White,0,position,SpriteEffects.None,0);
}
}
很抱歉,如果这是过多的代码或令人困惑,但任何帮助非常感谢!谢谢!
答案 0 :(得分:3)
交叉点的测试条件似乎不正确,至少。代码可能还有其他问题(有几个只是快速查看它),但让我们关注这个:
r1.Bottom >= r2.Top - penetrationMargin &&
r1.Bottom <= r2.Top &&
r1.Right >= r2.Left + 5 &&
r1.Left <= r2.Right - 5;
首先,不要为您编写库中存在的内容。 Xna矩形有一个Intersects方法,因此废弃该代码并改为使用它。
无论如何,我们会看看情况:
r1's Bottom is below r2's Top minus a margin AND
r1's Bottom is above r2's Top AND (...)
这已经不可能了。 r1.Bottom不能低于和高于 r2.Top。
此外,即使所有比较都是正确的,您也在使用AND(&amp;&amp;),这意味着只有当所有4个都为真时,条件才为真。基本上,你没有测试交集,你正在测试容器,即你正在测试r1完全在r2内。交叉点测试将使用OR(||)而不是AND(&amp;&amp;)来加入条件。
但是,尽管您可能希望自己编写代码以用于教育目的,但从工程角度来看,最佳解决方案是使用库提供的内容,此处为Rectangle.Intersects。
答案 1 :(得分:0)
我想出来了,但我不确定为什么这实际上有效。我的绘制方法出了点问题。我最初有:
spriteBatch.Draw(texture, rectangle, null, Color.White, 0, position, SpriteEffects.None, 0);
作为我的方法,但之后我将其更改为
spriteBatch.Draw(texture, rectangle, Color.White);
现在一切正常。