SCM player skins Line Up: [드래프트 강좌] 유닛의 체력바를 만들어보자

2/15/2015

[드래프트 강좌] 유닛의 체력바를 만들어보자


결과











원리









내용

GPTP 프로젝트는 https://code.google.com/p/gptp/에서 다운받고, IDE는 Visual C++ 2010 Express를 사용할 것입니다. Visual C++ 2010 Express를 설치하는 방법은 https://code.google.com/p/gptp/wiki/HowToInstallVisualCpp2010Express에 자세히 설명되있으니 참고바랍니다.





Visual C++ 2010 Express로 GPTP 프로젝트를 불러옵시다. 그러면 솔루션 탐색기에 다음과 같이 수많은 파일들이 나타날 것입니다.












그럼 여기서 'game_hooks.cpp'파일을 불러오도록 합시다. 그리고 다음 코드가 작성되 있는 부분을 찾도록 합니다.

bool nextFrame() {
  if (!scbw::isGamePaused()) { //If the game is not paused
    scbw::setInGameLoopState(true); //Needed for scbw::random() to work
    graphics::resetAllGraphics();
    hooks::updatePsiFieldProviders();
    
    //This block is executed once every game.
    if (*elapsedTimeFrames == 0) {
      //Write your code here
      scbw::printText(PLUGIN_NAME);
    }

    //Loop through all visible units in the game.
    for (CUnit *unit = *firstVisibleUnit; unit; unit = unit->link.next) {
      //Write your code here
    }

    scbw::setInGameLoopState(false);
  }
  return true;
}
여기서 nextFrame()안에 들어가는 코드들은 매 프레임마다 실행되는 코드들입니다. 우리가 만들 유닛의 체력바는 유닛의 체력이 변할때마다 표시해야하므로 이 부분에 코드를 작성해야합니다. 그 중에서도 for문을 살펴보면 맵 상에 놓여있는 모든 유닛들을 하나씩 순회합니다. 그러므로 이 for문 안에 유닛의 체력바를 표시하는 코드를 넣으면 됩니다.










일단 체력바의 총 길이를 구하도록 합시다. 사용할 것들은 다음과 같습니다.

unit->id : 유닛의 아이디를 가져온다. (0~227)
unit->getX(), unit->getY() : 유닛이 맵상에 위치한 좌표를 가져온다. (단위: 픽셀)
unit->hitPoints : 유닛의 현재 체력 (256 = 1hp)
units_dat::UnitBounds[유닛 아이디].left : 유닛크기(좌) (단위: 픽셀)
units_dat::UnitBounds[유닛 아이디].right : 유닛크기(우) (단위: 픽셀)
units_dat::UnitBounds[유닛 아이디].top : 유닛크기(상) (단위: 픽셀)
units_dat::UnitBounds[유닛 아이디].bottom : 유닛크기(하) (단위: 픽셀)
units_dat::MaxHitPoints[유닛 아이디] : 유닛의 데이터 상에 저장되어 있는 최대체력 (256 = 1hp)


자 그럼 다음과 같이 코드를 짜봅시다.
for (CUnit *unit = *firstVisibleUnit; unit; unit = unit->link.next) {
      int length = units_dat::UnitBounds[unit->id].left + units_dat::UnitBounds[unit->id].right;
      int c_length = length * ((float)unit->hitPoints / (float)units_dat::MaxHitPoints[unit->id]);
}
여기서 length는 체력바의 총 길이, c_length는 현재 체력바의 길이입니다. 길이가 length인 색상이 GREY인 네모상자를 그리고, 똑같은 위치에 길이가 c_length인 색상이 GREEN인 네모상자를 그리면 동영상에 보던 결과와 같은 효과를 낼 수 있을 것입니다.










그럼 이제 체력바를 위한 네모상자를 그려 볼건데 화면 상에 그림을 그리는 함수는 다음과 같습니다.
void drawFilledBox(int left, int top, int right, int bottom, ColorId color, CoordType ct = ON_SCREEN);
우린 unit->getX()와 unit->getY()를 통해 유닛이 맵상에 위치한 좌표를 알 수 있으니 이를 활용해 체력바를 나타낼 좌표값을 계산하여 코드를 작성해보면 다음과 같습니다. (저는 유닛의 머리위에 체력바가 나타나도록 유닛의 머리에서 16픽셀 위로 설정하였습니다.)
for (CUnit *unit = *firstVisibleUnit; unit; unit = unit->link.next) {
    int length = units_dat::UnitBounds[unit->id].left + units_dat::UnitBounds[unit->id].right;        
    int c_length = length * ((float)unit->hitPoints / (float)units_dat::MaxHitPoints[unit->id]);
    
    int left = unit->getX() - units_dat::UnitBounds[unit->id].left; 
    int top = unit->getY() - units_dat::UnitBounds[unit->id].top;        
    graphics::drawFilledBox(left, top - 18, left+length, top - 16, graphics::GREY, graphics::ON_MAP);
    graphics::drawFilledBox(left, top - 18, left + c_length, top - 16, graphics::GREEN, graphics::ON_MAP);
}









자, 이제 코드 작성을 완료하면 F7을 눌러 빌드를 합니다. (처음에는 정말 오래걸립니다...) 빌드를 성공하면 프로젝트 폴더\Debug 폴더 안에 'GPTP.qdp' 파일이 있을 것입니다. 이를 다음 그림과 같이 Firegraft에서 플러그인을 불러들어 옵니다. 그리고 저장하여 exe파일을 만들도록 합시다.










드래프트를 실행하고 확인을 해봅시다. 다음과 같이 정상적으로 작동함을 확인할 수 있습니다.


댓글 없음:

댓글 쓰기