2015-01-17 11 views
0

내 문제는 다음과 같습니다.
작은 게임을 디자인하고 있습니다. 그러나, 나는 아주 큰 문제에 봉착했다. 나는 지금 당분간 고쳐 내려고 노력했다. 본질적으로, 사용에 충분한 점수가 있지만 Building 개체의 데이터가 손상되면 건물을 업그레이드하고 싶습니다. '있는 것으로 가정 된'유일한 개체는 buildingsvector의 첫 번째 할당 된 개체입니다.

건물 클래스 : 나는 검은 화면에 직면하고있는 프로그램을 실행하면
'For 루프'초기화에서 손상된 개체, 벡터

(그 의미가 제대로 시작) 디버깅 할 때 다음과 같은 오류가 발생합니다 : Access violation reading location 0x00000008. 의미는 NULL 값이 사용되었습니다.

void Level::addBuilding(Building building, int x, int y) { 
     buildings.push_back(building); 
     tiles.at(x + (y*this->width)) = buildID(building.buildingID[building.buildingLevel-1], &buildings.at(buildings.size()-1)); 
    } 

그리고 타일/건물립니다 마지막으로 기능 :

를 건물을 추가

void Level::generateTerrain() { 
     for (int i = 0; i < width; i++) 
      for (int j = 0; j < height; j++) { 
       int tile = rand()%100; 
       if (tile >= 25 && tile <= 28) this->tiles.at(i + (j*this->width)) = 2; 
       else if (tile < 24) this->tiles.at(i + (j*this->width)) = 1; 
       else if (tile == 29) { 
        this->addBuilding(Building(vector<int>{4, 3, 2, 1}, i * 75, j * 75, vector<int>{1, 1, 1, 1}), i, j); 
       } 
       else this->tiles.at(i + (j*this->width)) = 0; 
      } 
    } 

기능 : 건물을 생성

class Building { 
    public: 
     int x = 0, y = 0; 
     vector<int> buildingID; 
     vector<int> upgradeCost; 

     int size = 4; 

     Building(vector<int> buildingID, int x, int y, vector<int> upgradeCost) 
     : buildingID(buildingID), x(x), y(y), upgradeCost(upgradeCost) { } 

     virtual void upgrade(); 
     void drawTile(SDL_Rect, SDL_Surface*); 

     int buildingLevel = 1; 

    protected: 
    }; 

    void Building::upgrade() { 
     if((buildingLevel+1) <= size)buildingLevel += 1; 
    } 

    void Building::drawTile(SDL_Rect drawRect, SDL_Surface* drawnTo) { 
     Tile::Tiles.at(buildingID[buildingLevel - 1]).drawTile(drawRect, drawnTo); 
    } 

기능

void Level::drawLevel(int x, int y, int width, int height, SDL_Surface* drawnTo, int beginningX, int beginningY) { 
     SDL_Rect tempRect; 
     tempRect.w = 75; 
     tempRect.h = 75; 

     for (int i = x; i <= (x + width); i++) 
      for (int j = y; j <= (y + height); j++) { 
      if (tiles.at(i + (j*this->width)).id == 999999) continue; 

      tempRect.x = (i*Tile::Tiles.at(tiles.at(i + (j*this->width)).id).tileSurface->w) + beginningX; 
      tempRect.y = (j*Tile::Tiles.at(tiles.at(i + (j*this->width)).id).tileSurface->h) + beginningY; 

      Tile::Tiles.at(tiles.at(i + (j*this->width)).id).drawTile(tempRect, drawnTo); 
      } 
    } 

코드가 더 필요한 경우 그냥 물어보십시오. 도움을 주셔서 감사합니다.

+0

다음과 같이 생성자를 축소 할 수 있습니다 :'Building (vector buildingID, int x, int y, vector upgradeCost) : buildingID (buildingID), x (x), y (y), upgradeCost (upgradeCost) {}' . 또한 일정한 크기가 필요한 경우 ['std :: array '] (http://en.cppreference.com/w/cpp/container/array) – Borgleader

+0

사용하는 것이 좋습니다. 도움이됩니다. 감사합니다. 문제를 해결하기 위해 모든 것을 하드 코딩 방식으로 해결했습니다. – Cartier

+0

아직 알지 못하는 또 다른 버그가 있습니다. 표준 컨테이너에'Building' 유형의 객체를 저장하는 것 같습니다. 이것들은 저장된 요소를 복사하지만,'Building'에서 파생 된 객체를 전달하면, 이것으로'Building' 유형의 객체를 생성하고 초기화합니다. 즉, 객체의 유형이 잘립니다. 또한 유형에 가상 함수가있는 경우에는 가상 소멸자가 필요하며 복사 생성 및 할당을 방지해야합니다. –

답변

1

나를 의심하는 코드 부분은 addBuilding()에서 vector의 요소 주소를 buildID()에 대한 두 번째 매개 변수로 사용하는 방법입니다. Vector 클래스는 용량 증가가 필요할 때 사용하는 메모리를 다시 할당하므로 기존 요소는 포인터가 가리키는 동일한 주소에 더 이상 있지 않게됩니다.

+0

답변 해 주셔서 감사합니다. 나는 이것이 이것이 문제라고 믿는다. 이걸 취해야 할 길에 대한 제안이 있습니까? – Cartier

+0

포인터를 사용하여 건물 벡터 밖으로 건물을 가져 오는 코드를 다시 작성하거나 건물 벡터의 용량을 최대 한도로 설정하고 addBuilding()을 사용하지 않도록 두 가지 옵션을 선택할 수 있습니다. 그 값을 초과하면 (vector :: reserve() 함수 사용), 벡터로부터 요소를 제거하지 않는 한 포인터는 안전하게 사용되어야합니다. –

+0

네, 감사합니다. 요소 자체 대신 요소 번호를 참조하도록 코드를 변경했습니다. – Cartier