2012-06-10 2 views
0

저는 C++에서 간단한 2D 하향식 젤다 스타일 게임을 진행하고 있지만 적군 클래스의 여러 인스턴스를 생성하는 데 문제가 있습니다. 적 중 하나, 첫 번째 센서 만 충돌 감지를 등록합니다. 다른 모든 적들은 단순히 화면에 표시되는 시각적 인 "유령"인 것처럼 보입니다. 첫 번째 적이 죽을 때, 오직 유일한 것, 그리고 다른 모든 "유령"도 함께 사라집니다.적 귀신 인스턴스/고유하지 않은 개체

저는 적군 매니저 클래스를 만들었습니다. 적군 매니저 클래스는 활성 적을 잡고, 전달 된 상자와의 충돌을 확인하고, 적을 업데이트/렌더링합니다.

class cEnemyMgr { 
public: 
std::vector<cEnemy*> mobList; 

cEnemyMgr(){} 
~cEnemyMgr(){ 
    for (int i=0; i < mobList.size(); i++) { 
     mobList[i]->texture.Close(); 
      //delete mobList[i]; 
    } 
} 

    void render() { 
     for (int i=0; i < mobList.size(); i++) { 
      mobList[i]->render(); 
     } 
    } 

    void update(float dt){ 
     for (int i=0; i < mobList.size(); i++) { 
      if (mobList[i]->hp <= 0){ 
       mobList[i]->die(); 
       mobList.pop_back(); 
      } else { 
       mobList[i]->update(dt); 
      } 
     } 
    } 

    void spawnMob(int x, int y){ 
     cEnemy* pEnemy = new cMeleeEnemy(); 
     pEnemy->init(x, y); 
     mobList.push_back(pEnemy); 
    } 

    cEnemy* checkCollisions(int x, int y, int wd, int ht){ 
     for (int i=0; i < mobList.size(); i++) { 
      int left1, left2; 
      int right1, right2; 
      int top1, top2; 
      int bottom1, bottom2; 

      left1 = x; 
      right1 = x + wd; 
      top1 = y; 
      bottom1 = y + ht; 

      left2 = mobList[i]->pos.x; 
      right2 = mobList[i]->pos.x + 64; 
      top2 = mobList[i]->pos.y;  
      bottom2 = mobList[i]->pos.y + 64; 

      if (bottom1 < top2) { return NULL; } 
      if (top1 > bottom2) { return NULL; } 
      if (left1 > right2) { return NULL; } 
      if (right1 < left2) { return NULL; } 

      return mobList[i]; 
     } 
    } 
}; 

적 등급 자체는 매우 기본입니다. cEnemy는 cMeleeEnemy가 파생 된 기본 클래스입니다. 표준 hp, dmg 및 이동 변수가있어 화면에서 크롤링하여 플레이어의 아바타와 충돌하거나 플레이어의 공격에 대응할 수 있습니다. 이 모든 작업은 정상적으로 작동합니다. 여러 개의 적을 만들려고 할 때 처음 생성 된 것만 제대로 작동하고 나머지는 빈 껍질이며 화면의 텍스처가됩니다. 동일한 블록에서 spawnMob을 명시 적으로 호출하거나 타이머를 사용하여 동적으로 공간을 할당하는 것은 중요하지 않습니다. 결과는 같습니다. 누구든지 올바른 방향으로 나를 가리킬 수 있습니까? 아직 경험이 당신이 말할 수

#include "enemy.h" 

void cPlayer::update(float dt){ 
// Player Controls 
if (KEY_DOWN('W')) { 
    pos.y -= speed * dt; 
    facing = 0; 
} else if(KEY_DOWN('S')) { 
    pos.y += speed * dt; 
    facing = 2; 
} 

if (KEY_DOWN('A')) { 
    pos.x -= speed * dt; 
    facing = 3; 
} else if(KEY_DOWN('D')) { 
    pos.x += speed * dt; 
    facing = 1; 
} 

// Hit Recovery 
if (hitStun == true) {  
    hitStunned(1.0); 
} 
} 

void cMeleeEnemy::update(float dt){ 
extern cPlayer player1; 
extern int ScreenWd; 
extern int ScreenHt; 

D3DXVECTOR2 dir; 
dir = player1.pos - pos; 
D3DXVec2Normalize(&dir, &dir); 
//fwd = (fwd * 0.2) + (dir * 0.8); 
fwd = dir; 
vel = vel + fwd * speed * dt; 

pos = pos + vel * dt; 

//keep em on screen 
if (pos.x < 0) { pos.x = 0; } 
if (pos.x > ScreenWd - 64) { pos.x = ScreenWd - 64; } 
if (pos.y < 0) { pos.y = 0; } 
if (pos.y > ScreenHt - 64) { pos.y = ScreenHt - 64; } 

// Hit Recovery 
if (hitStun == true) {  
    hitStunned(0.5); 
} 

} 

void cMeleeEnemy::die(){ 
extern int score; 
extern int numMobs; 
score += 1; 
numMobs -= 1; 
//texture.Close(); 
} 

void cPlayer::die(){ 
extern char gameState[256]; 
sprintf(gameState, "GAMEOVER"); 
} 

void cMeleeEnemy::init(int x, int y){ 
hp = 6; 
dmg = 1; 
speed = 25; 
fwd.x = 1; 
fwd.y = 1; 
vel.x = 0; 
vel.y = 0; 
pos.x = x; 
pos.y = y; 
rotate = 0.0; 
color = 0xFFFFFFFF; 
hitStun = false; 
texture.Init("media/vader.bmp"); 
} 

void cPlayer::init(int x, int y){ 
facing = 0; 
hp = 10; 
dmg = 2; 
color = 0xFFFFFFFF; 
speed = 100; 
fwd.x = 1; 
fwd.y = 1; 
vel.x = 0; 
vel.y = 0; 
pos.x = x; 
pos.y = y; 
rotate = 0.0; 
hitStun = false; 
texture.Init("media/ben.bmp"); 
} 

, 아니에요 :

#ifndef ENEMY_H 
#define ENEMY_H 

#include "texture.h" 
#include "timer.h" 

#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) 

class cEnemy { 
public: 
int hp; 
int dmg; 
D3DXVECTOR2 pos; 
D3DXVECTOR2 fwd; 
D3DXVECTOR2 vel; 
D3DCOLOR color; 
int speed; 
float rotate; 
bool hitStun; 
float hitTime; 
CTexture texture; 

virtual void init(int x, int y) = 0; 
virtual void update(float dt) = 0; 
virtual void die() = 0; 

void render(){ 
    texture.Blit(pos.x, pos.y, color, rotate); 
} 

void takeDamage(int dmg) { 
    if (hitStun == false){ 
     extern CTimer Timer;   
     hitTime = Timer.GetElapsedTime(); 
     hp -= dmg; 
     color = 0xFFFF0000; 
     hitStun = true; 
    } 
} 

void hitStunned(float duration) { 
    extern CTimer Timer; 
    float elapsedTime = Timer.GetElapsedTime(); 
    if (elapsedTime - hitTime > duration){ 
     color = 0xFFFFFFFF; 
     hitStun = false; 
    } 
} 

}; 

class cPlayer : public cEnemy { 
public: 
int facing; 

void init(int x, int y); 
void update(float dt); 
void die(); 

}; 

class cMeleeEnemy : public cEnemy { 
public: 
cMeleeEnemy(){} 
~cMeleeEnemy(){ 
    texture.Close(); 
} 

void init(int x, int y); 
void update(float dt); 
void die(); 

}; 
#endif 

을 그리고 enemy.cpp :

--EDIT-- 다음은이 enemy.h의 코드입니다 . 이것은 학교에서 처음으로 나만의 프로젝트입니다. 나는 텍스쳐를 닫고 객체를 삭제해야하는 곳에서 약간 혼란스러워한다고 말해야합니다. 시간 내 주셔서 감사합니다.

+0

적 개체에 대한 코드를 확인해야합니다. 또한,'die'가 객체가 스스로를 파괴하지 않는 한, 당신은 메모리를 새고있는 것처럼 보입니다. – tmpearce

+0

해당 클래스에 checkCollisions() 코드를 게시하십시오 –

+0

맞습니다. 각 인스턴스가 만들어진 후이를 파손하지는 않습니다. Die()는 현재 관련 점수 점과 몹 임계 값 변수를 변경합니다. hp가 <= 0 인 if 문에서 delete mobList [i]와 같은 것을 사용하여이 작업을 수행합니까? – DanTheMan

답변

2

checkCollisions 함수에서 모든 루프 이후에 NULL 또는 적군 벡터의 첫 번째 인덱스 위치에있는 객체를 반환합니다.

따라서 첫 번째 고스트가 히트되지 않으면 checkCollisions 함수는 벡터의 후속 고스트를 반복하는 대신 NULL을 반환합니다.

는 다음에 checkCollisions 기능을 변경,이 문제를 해결하려면 다음

cEnemy* checkCollisions(int x, int y, int wd, int ht){ 
    for (int i=0; i < mobList.size(); i++) { 
     int left1, left2; 
     int right1, right2; 
     int top1, top2; 
     int bottom1, bottom2; 

     left1 = x; 
     right1 = x + wd; 
     top1 = y; 
     bottom1 = y + ht; 

     left2 = mobList[i]->pos.x; 
     right2 = mobList[i]->pos.x + 64; 
     top2 = mobList[i]->pos.y;  
     bottom2 = mobList[i]->pos.y + 64; 

     if (bottom1 < top2) { continue; } 
     if (top1 > bottom2) { continue; } 
     if (left1 > right2) { continue; } 
     if (right1 < left2) { continue; } 

     return mobList[i]; 
    } 

    return NULL; 
} 

희망이 도움이!

편집 : 그것은 HP, 당신은, mobList.pop_back()를 사용하고 0 이하의 경우 목록에서 적을 제거하지만,이 벡터의 마지막 요소를 제거 할 때, 당신은 같은 것을 사용한다고

주 목록에서 원하는 적을 제거하려면 다음을 실행하십시오.

std::remove_if(mobList.begin(), mobList.end() [](cEnemy* pEnemy)->bool 
{ 
    if(pEnemy->hp <= 0) 
    { 
     pEnemy->die(); 
     return true; 
    } 
    else 
    { 
     pEnemy->update(); 
     return false; 
    } 
}); 
+0

그는 CheckCollisions를 호출하여 관련 고스트를 삭제 한 다음 다시 호출 할 수 있습니다. 이것은 부분적으로 만 문제를 해결할 수 있습니다. 그러나 좋은 캐치. –

+0

이것은 부분적으로 문제를 해결했습니다! 나는 타격을 가할 수 있고 모든 경우에 부딪 힐 수 있지만, 적을 파괴 한 적이있는 것처럼 보이면 그 후에 만들어지는 모든 것을 가져 간다. – DanTheMan

+0

@DanTheMan 더 나아가 도움을 받으려면 전화 코드를 확인해야합니다. –

0

문제가 해결되었습니다! 나는 pop_back()mobList.erase() 방법으로 대체했습니다.

void update(float dt){ 
     for (int i=0; i < mobList.size(); i++) { 
      if (mobList[i]->hp <= 0){ 
       mobList[i]->die(); 
       mobList.erase(mobList.begin() + i); 
      } else { 
       mobList[i]->update(dt); 
      } 
     } 
    } 

여러분의 도움에 감사드립니다.