2013-11-18 4 views
0

Объявление объекта Rectangle завершается с ошибкой NullReferenceException, возможно, оно связано с циклами for (yMax и xMax находятся в блоке фрагментов) Спасибо, что помогли мне поймать, почему это дает я исключение.NullReferenceException при чтении массива [] []

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

класс "Уровень" атрибуты и конструктор:

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

Покажите нам свой код GameMain.Level.getCollisionTiles(); Кажется, что вы делаете что-то неправильно при инициализации массива. – user1567896

+0

Ну, что у вас есть в 'tile [x] [y]', когда он терпит неудачу? Я знаю. Это null! Вы должны заполнить каждый элемент массива 'tile' допустимым объектом' TileData'. Основной сбой в вашем методе GameMain.Level.getCollisionTiles(). –

+2

[Что такое исключение NullReferenceException] (http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it/4660186#4660186) –

ответ

0

Я предполагаю, что m_collisionLayer.Tiles строит два массива измерений, перейдя по списку столкновений и добавив их в массив. Если массив не существует для заданного значения x, он создаст его и привяжет соответствующий элемент для соответствующего значения y.

Проблема с этим подходом состояла бы в том, что если для заданного значения x не существует столкновений, то он никогда не создаст массив для этого значения x (который будет пустым), и поэтому tile[x] останется нулевым, и поэтому tile[x][y] даст исключение нулевой ссылки.

Решение этой проблемы является либо полностью инициализировать ваш массив, когда вы сначала объявить его или проверить, если tile[x] является нулем перед циклом над у значений и проверить tile[x][y] перед вызовом .Target.

Нулевые проверки, вероятно, являются лучшим подходом, поскольку это будет означать, что вы проходите вокруг компактного массива (т.е. нет объектов в пробелах, а не пустых объектах). И так как вы захотите сделать нулевую проверку, вероятно, перед вызовом .Target, то вы также можете добавить и предыдущую нулевую проверку.

Также, если нет столкновений, это может быть то, что плитка может быть нулевой, и в этом случае вы тоже захотите ее проверить.

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[,]. Это единый массив с двумя индексами, который скорее всего вам нужен, а не массив массивов (вот что у вас есть сейчас).

+0

Спасибо за ответ! Я не думал об этом ... Кажется, это решение, но как его инициализировать в конструкторе? – stalker2106

+0

Ну, я нашел обходное решение, я тестирую, если плитка [x] [y]! = Null перед созданием прямоугольника, теперь она дает мне IndexOutOfRangeException на тестовой строке «if» – stalker2106

+0

Я обновил свой ответ. Индекс вне диапазона звучит так, как будто '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' – Chris

-1

Похоже у вас есть неправильный диапазон границ в ваших циклах.

for (int x = 0; x < xMax; x++) 
{ 
    for (int y = 0; y < yMax; y++) 

Не «меньше или равно», а просто «меньше».

+0

Да, это прекрасно, я изменил его для тестирования, но спасибо, что напомнил мне об этом! – stalker2106

+1

Зачем это нужно исключать NullReferenceException? –

+0

@SriramSakthivel, ты прав, моя ошибка. –

0

Если эта линия бросает NullReferenceException:

Rectangle tileRectangle = tile[x][y].Target 

затем либо tile, tile[x] или tile[x][y] равна нулю. Запустите его в отладчике, чтобы узнать, какой из них.

+0

@ Крис получил это, спасибо. –

Смежные вопросы