Rectangle对象的声明失败,出现NullReferenceException,可能与for循环有关(yMax和xMax在tiles单元中) 谢谢你帮我理解为什么这给了我一个例外。
TileData[][] tile = GameMain.Level.getCollisionTiles();
int xMax = GameMain.Level.getMapHeight();
int yMax = GameMain.Level.getMapWidth();
for (int x = 0; x <= xMax; x++)
{
for (int y = 0; y <= yMax; y++)
{
Rectangle tileRectangle = tile[x][y].Target; //THIS LINE FAILS !!!!
if (tileRectangle.Contains(m_hitbox)) //Si il y a collision
{
if ((m_hitbox.X + m_hitbox.Width) > tileRectangle.X) //si le joueur percute par la gauche
{
m_hitbox.X--;
}
else if (m_hitbox.X < (tileRectangle.X + tileRectangle.Width)) //Droite
{
m_hitbox.X++;
}
if ((m_hitbox.Y + m_hitbox.Height) > tileRectangle.Y) //si le joueur percute par le haut
{
m_hitbox.Y--;
}
else if (m_hitbox.Y < (tileRectangle.Y + tileRectangle.Height)) //Bas
{
m_hitbox.Y++;
}
}
}
}
这是一些代码,
访问者(GameMain.Level。):
public TileData[][] getCollisionTiles()
{
return m_collisionTiles;
}
类“Level”属性和构造函数:
//Atributs
Map m_map;
List<TileLayer> m_layers;
TileLayer m_collisionLayer;
TileData[][] m_collisionTiles;
int m_mapWidth;
int m_mapHeight;
int m_tileWidth;
int m_tileHeight;
//Constructeur
public Level(ContentManager content, string levelName)
{
m_map = content.Load<Map>("Maps/"+levelName); //On charge la map
//params
m_mapWidth = m_map.Width;
m_mapHeight = m_map.Height;
m_tileWidth = m_map.TileWidth;
m_tileHeight = m_map.TileHeight;
//tiles / layers
m_layers = new List<TileLayer>(m_map.TileLayers); //On charge les calques / couches
m_collisionLayer = m_layers.Find( x => x.Name == "Collision"); //On charge le calque de collision
m_collisionTiles = m_collisionLayer.Tiles;
}
答案 0 :(得分:0)
如果此行抛出NullReferenceException
:
Rectangle tileRectangle = tile[x][y].Target
然后tile
,tile[x]
或tile[x][y]
为空。在调试器中运行它以找出哪一个。
答案 1 :(得分:0)
我的猜测是m_collisionLayer.Tiles
通过循环遍历碰撞切片列表并将它们添加到数组来构造二维数组。如果给定的x值不存在数组,它将创建它并将适当的tile粘贴到适当的y值。
这种方法的问题在于,如果给定的x值不存在碰撞图块,那么它永远不会为该x值创建数组(这将是空的),因此tile[x]
将保持为null tile[x][y]
将提供空引用异常。
解决方法是在第一次声明数组时完全初始化数组,或在循环y值之前检查tile[x]
是否为null,并在调用tile[x][y]
之前检查.Target
。
空检查可能是更好的方法,因为它意味着你绕过一个紧凑的数组(即间隙中没有对象而不是空对象)。既然你想在调用.Target
之前做一个空检查,那么你也可以添加以前的空检查。
此外,如果没有碰撞Tiles,那么tile可能为null,在这种情况下你也想要检查它。
for (int x = 0; x <= xMax; x++)
{
if (tile[x]==null)
continue;
for (int y = 0; y <= yMax; y++)
{
if (tile[x][y]==null)
continue;
Rectangle tileRectangle = tile[x][y].Target; //THIS LINE FAILS !!!!
//Snipped code here
}
}
初始化它将在TileLayer
对象中完成,基本上意味着你在创建数组的位置,你会做类似的事情:
int[][] arr = new int[10][];
for (int i= 0; i<arr.Length; i++)
{
arr[i] = new int[10];
}
最后一点需要注意的是[] []适用于锯齿状阵列。如果您的图块总是在矩形中,那么您可能实际上想要使用TileData[,]
。这是一个包含两个索引的单个数组,这可能是您想要的,而不是数组数组(这就是您现在拥有的数据)。
答案 2 :(得分:-1)
看起来你的循环中的边界范围不正确。
for (int x = 0; x < xMax; x++)
{
for (int y = 0; y < yMax; y++)
不是“更少或相等”,而只是“更少”比较。