Blog (98)
게임개발 (32)
디버깅전쟁 (2)
여행/그림 (11)
3DMAX (1)
매일매일 영어훈련 (7)
(27)
스타2 자유의날개 캠페인(테란) (1)
티스토어  안드로이드 어플 추천  위자드캐슬  무료게임  무료어플  추천게임  두더지  위자드 캐슬 
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
+ Total :
+ Today :
+ Yesterday :
  

 

 

 

게임개발 _해당되는 글 32건
2009.03.22   공의 위치 예측에 따른 NPC의 AI처리 2
2009.03.18   슈퍼마리오 쿠퍼 발리볼 
2009.03.15   공튀기기 및 충돌처리 데모 프로그램 영상 
2009.03.06   점프 구현 코드 및 결과물 5
2008.12.26   자작 오우거 메시 뷰어 0.1 
2008.12.06   유니코드 <-> 안시 문자열 변환 
2008.11.30   MFC+Ogre3D 
2008.02.06   CEGUI LayoutEditor 빌드 성공 
2008.01.06   사원수(쿼터니온)를 이용하여 캐릭터 제어하기 
2007.12.15   가상함수가 있는 클래스 초기화할때 주의점. 

 

공의 위치 예측에 따른 NPC의 AI처리
+   [게임개발]   |  2009. 3. 22. 00:21  

                              [화면에서 왼쪽 캐릭터가 NPC이다.]


초간단 NPC AI처리 루틴을 구현했다.

첫번째로 공이 벽이나 플레이어에게 닿아 반사되거나 튕겨져나가는 순간,
1초뒤의 도착위치를 예상한 후(체공시간을 최소 1초로 해두었기 때문에),
현재 NPC의 좌표보다 크다면 오른쪽으로, 작다면 왼쪽으로 속도를 주어 이동하게끔 한다.

두번째로 위에서 계산한 좌표가 NPC의 충돌영역을 벗어난다면
시간을 좀 더 길게 혹은 작게 잡은 뒤 다시한번 예측을 해준다.
이것을 판단하는 기준은 예측된 Y좌표로 이루어진다.

수평(X좌표)이동은 등속운동이라 직관적으로도 예측할 수 있는데,
수직(Y좌표)은 가속도가 들어간 포물선 운동이라 좀 많이 삽질을 했다.;;
막연히 이렇게 하면 되겠지 라고 생각했었는데,
직접 손으로 계산하고 결과를 확인하는게 제일 확실한것 같다.
해보고나니 별로 차이도 없었는데 수학에 기초가 없어서 그런지 한참 어리버리했다.ㅋ

이 과정에서 점프공식을 약간 바꿔서 적용시켰다.
원래는 이렇게 했었는데,

y = y - (v * dt)
v = v - (a * dt)


아래처럼 바꿨다.
v = v - (a * dt)
y = y - (v * dt) + (0.5 * a * (dt*dt))

v를 먼저 계산해주고,
그다음에 y를 계산해줘야 정확한값이 나온다.;;

처음 적용한 공식은 시간값을 넣고 계산해보면 조금씩 오차가 발생하는 것이었다.
물론 게임을 플레이 하는데는 문제가 없지만,
예측한 좌표값과 실제 진행된 시간상의 값을 보면 시간이 클수록 몇십픽셀 이상씩 차이가 났다.
그래서 두번째 공식으로 계산했더니 오차가 사라졌다.

등가속도운동을 하는 운동의방정식인데 학창시절 수학과 물리를 좀 게을리 해서 그런지
기억이 가물가물하다.ㅋ;
xevious7님의 블로그에도 비슷한 내용이 나오는것 같아서 적용시켜보려 했지만
이해를 잘 못해서 계속 허공에 맴돌기만 했다.

근데 한가지 좀 찝찝한게 남아있는데 부동소수점 오차인듯한것이 좀 보인다.
정수로 계산했을땐 몇십만단위가 넘어가도 정확히 맞아떨어지는데,
실수로 계산을 하니 약 2~4픽셀정도 차이가 났다.
어차피 예측이니 이정도 티나는거야 상관없긴 하다.^^;


AI관련해서 이제 아주 기본적인 처리만 했지만 처음해보는거라 이정도를 하는데도 좀 막막했었다.
일단 gpgstudy, 다른개발자분들의 블로그, 구글등을 뒤져보았는데,
gamedev에 나랑 똑같은 고민을 한 사람이 있었던 것이다.
너무 반가운 마음에 게시물을 긁어왔다.ㅋ
일단 이런방향으로 풀어나가 볼 생각이다.

http://www.gamedev.net/community/forums/topic.asp?topic_id=131330&whichpage=1??

For sure that you have to develop the maths part of it, but if I had to do such an AI I will do it in the following way:

- First of all, you need a function to predict the arc of the ball (as InnocuousFox said).

- Then, at each moment, you have to make the following tests:
a) Do the player will be able to shot the ball if he jumps right now?
b) Do the player will be able to shot the ball if he desn't jump?

If the answers are both "no", there is no need to move, since you have no chance of hitting the ball.
If the answers are one "yes" and one "no", then the decision is easy.
The single problem is when both answers are "yes". In such a case, you have to find which is the best shot that the player will achieve if jumping (you need a heuristic function to assess which shot is the best), let's call it BESTJUMPSHOT. Then you have to compute which is the best shot that the player can achieve without jumping: BESTSTANDSHOT. Then, if BESTJUMPSHOT better than BESTSTANDSHOT, the player has to jump.

To compute the best shots, you have to do some math, but I guess that they shouldn't be too complex.

I hope this helps!

 

 
 
        

 

슈퍼마리오 쿠퍼 발리볼
+   [게임개발]   |  2009. 3. 18. 23:43  
사용자 삽입 이미지


사용자 삽입 이미지



슈퍼마리오 게임의 이미지를 올려봤다.
(인터넷 검색해서 얻은 이미지인데 나중에 제대로 만들면 디자이너에게 부탁할 생각이다.ㅋ)
쿠퍼의 머리부분을 몇단계로 나누어 공(버섯)이 팅겨져 나가는 것 까진 구현이 됐다.
이제 CPU 인공지능을 어떻게 할 것인지를 생각해야 한다.

언뜻 생각나는 방법은
좌우로 왔다갔다 하다가 공이 머리 앞쪽에 위치하는 순간에 점프를 하여 넘기는 방식인데,
이것 하나만 쓰면 너무 단순해질것 같고 공을 놓치는 일이 자주 일어날 것 같다.

사람이 직접 플레이하는 패턴을 저장시켜서 따라하게 하는 방법은 없을까?ㅡㅠ
도무지 떠오르지가 않는다.@_@

 
 
        

 

공튀기기 및 충돌처리 데모 프로그램 영상
+   [게임개발]   |  2009. 3. 15. 16:23  

지난번에 작성했던 기초 점프 코드에 충돌체크를 넣어
화면을 이리저리 튕기며 돌아다니는 데모를 작성했다.

점프구현 코드와 사각형 충돌박스 방식을 사용했는데,
나중에 다른 2D게임을 만들때도 사용할 수 있도록
충돌감지시 콜백함수를 호출하는 형태로 작성을 해놨다.

캐릭터와 바닥은 슈퍼마리오에서 따왔는데,
역시 이미지가 이쁘게 나와야 뭔가 있어보인다.ㅋ;;
아무래도 디자이너를 한명 섭외해야 할 것 같다.ㅡㅠ











 
 
        

 

점프 구현 코드 및 결과물
+   [게임개발]   |  2009. 3. 6. 23:26  



점프의 구현방법은 gpg에서 검색한 http://www.xevious7.com/102 게시물을 참고하여 작성했다.
좋은 내용을 공개해주신 xevious님께 감사드립니다.^^)
직접 해보니 2D, 3D구분없이 똑같은 로직으로 적용이 가능하다.

동영상은 프레임이 좀 떨어져서 약간 거칠어 보이지만
"피카추배구"라는 게임에 나오는 점프와 최대한 비슷하게 맞춰보았다.
실제 코드를 돌려보면 너무나 부드럽고 자연스럽게 돌아간다.^^

먼저 초기화를 해준다. 아래 상수 값들은 만들고 있는 게임에 맞도록 적절히 수정해주면 된다.
날림으로 코딩한거라 변수명의 의미가 잘 안맞을 수 있다.ㅡㅡ^

      const float ACCEL_VALUE = 38.0f;   // 점프력으로 생각하면 됨.
      const float MOVING_VALUE = 0.08f;   // 시간값.
      const float OFFSET_VALUE = 5.0f;    // 이동할 거리(?) 그냥 오프셋값.

      m_fAccValue = ACCEL_VALUE;
      m_fTimeMoveValue= MOVING_VALUE;
      m_fOffsetValue = OFFSET_VALUE;
      m_bJump = false;


점프상태가 시작되면 매 프레임마다 아래 루틴을 호출해준다.
fDeltaTime은 프레임 시간값인데 이전 프레임에서 현재 프레임까지 얼마만큼의 시간이 흘렀는지를 갖고 있는 변수이다.
Ogre엔진을 사용한다면 frameStarted의 evt.timeSinceLastFrame 값을 사용하면 된다.

if(m_bJump)
{
   g_vDummy.y -= ((m_fAccValue * fDeltaTime) / m_fTimeMoveValue);
   m_fAccValue -= ((m_fOffsetValue * fDeltaTime) / m_fTimeMoveValue);
   if(g_vDummy.y >= 500)
   {
      // 땅에 착지했으므로 점프를 끝내고 관련된 값들을 초기화시킨다.
      // 다른 건물 위로 떨어지는등의 액션이 가능하다면
      // 따로 충돌체크를 해준 뒤 아래 값들을 초기화시켜주면 된다.
      m_fAccValue = ACCEL_VALUE;
      m_fTimeMoveValue= MOVING_VALUE;
      m_fOffsetValue = OFFSET_VALUE;
      m_bJump = false;
   }
}


만약 앞으로 나아가면서 점프를 해야 한다면(대부분이 이런 상황일 것이다)
전진, 후진은 원래 하던대로 현재 방향으로 속도를 주고(X좌표, 3D라면 X,Z)
점프는 점프대로 위 로직을 돌려주면 된다.

 
 
        

 

자작 오우거 메시 뷰어 0.1
+   [게임개발]   |  2008. 12. 26. 23:25  
사용자 삽입 이미지


최초 버전을 릴리즈 했습니다.(Ogre3D 1.6.0버전)
첨부파일을 받으시면 바로실행해 볼 수 있는 "소스+exe+dll+media파일"들이 들어있습니다.
간단하게 메시 로드/스켈레톤 에니메이션 로드가 가능합니다.

kldp에서 svn저장소를 제공해주길래 프로젝트를 등록하고 앞으로 계속 만들어나갈 생각입니다.
http://kldp.net/projects/ogremesh/

svn익명 체크아웃이 되니 소스를 받으실 분들은 위 주소로 가시면 됩니다.^^
같이 개발해 나가요~
 

 
 
        

 

유니코드 <-> 안시 문자열 변환
+   [게임개발]   |  2008. 12. 6. 17:25  
오우거엔진이 MultiByte로 설정되어있길래, Unicode로 바꿨더니 컴파일 에러를 내뿜었다.
꼭 Unicode로 안해도 되지만 파일명을 넣어줄때 일일히 변환해줘야했기 때문에
엔진자체를 Unicode로 빌드해놓으려고 했었다.
 매번 문자열 할당하고 WideCharToMultiByte등으로 바꿔주려니 너무 귀찮았기 때문에....ㅡㅡ;;

한참 방법을 찾던중 예전에 어디서 본 ATL관련 함수들을 다시 찾아냈다.
이걸왜 이제 알았을까.ㅡㅠ
매크로를 따라가보니 내부에선 똑같은 함수를 쓰고 있었다.
하지만 타이핑이 줄었다는게 너무 좋은것 같다.ㅋ



헤더를 먼저 넣어주고...

#include <atlcore.h>

// 이걸 꼭 써줘야 한다.
USES_CONVERSION;

std::wstring strWide;
strWide = A2W(animation->GetName().c_str());




std::string strChar;
strChar = W2A(strWide.c_str());




 
 
        

 

MFC+Ogre3D
+   [게임개발]   |  2008. 11. 30. 23:42  
사용자 삽입 이미지


간단히 올려본 Ninja 캐릭터.
3DMAX와 동일한 카메라 컨트롤을 적용하였는데
이렇게 하려면 카메라 하나만가지고는 힘들고 노드를 두개 추가해야 한다.

먼제 중앙에 루트노드를 만들고,
자식으로 노드 하나를 더 만든다.
그리고 카메라는 자식노드에 붙인다.(attach)

이동시에는 자식노드를 전진,후진,좌,우로 이동 시켜주고,
회전시에는 루트노드를 x, y 축 기준으로 회전시켜준다.

이동및 회전하는 값은 이전 마우스 포지션과 현재 마우스 포지션의 차를 구해
사용하면 되는데 이 때 offset값을 곱해줘서 사용하면 움직임 범위를 쉽게 조절할 수 있다.

이동은 단순히 x,y,z축으로 좌표를 더해주기면 하면 되었는데
회전은 x축과 y축을 구분하여 작성해줘야 했다.

x축의 경우 쿼터니온을 하나 만들어서 루트노드의 현재 쿼터니온과 곱해준것을 사용하면 된다.
Ogre::Quaternion quatNode = m_pCameraRootNode->getOrientation();
Ogre::Quaternion quatRotate(Ogre::Radian(Ogre::Degree(-fRotationDelta)),Ogre::Vector3(1,0,0));
quatNode = quatNode * quatRotate;
m_pCameraRootNode->setOrientation(quatNode);

y축의 경우 쿼터니온을 사용하지 않고 노드의 rotate라는 함수를 사용하였다.
m_pCameraRootNode->rotate(Ogre::Vector3(0,1,0),
Ogre::Radian(Ogre::Degree(-fRotationDelta)),
Ogre::Node::TS_WORLD);

마지막 인자를 TS_WORLD로 줘야 3DMAX에서처럼 원하는 회전모양이 나온다.


알쏭달쏭... 알듯모를듯한 3D 프로그래밍.;;

 
 
        

 

CEGUI LayoutEditor 빌드 성공
+   [게임개발]   |  2008. 2. 6. 18:41  

cegui사이트에 가보니 0.6버전이 올라와 있더군요.
근데 테스트버전인듯...
포럼을 찾아봤는데 빌드하는 법까지 나와있네요.
한글로 따로 정리를 할지는 모르겠지만 만약 하게되면 올려놓겠습니다.^^

포럼URL :
http://www.cegui.org.uk/phpBB2/viewtopic.php?t=2760&highlight=editor+source


 
 
        

 

사원수(쿼터니온)를 이용하여 캐릭터 제어하기
+   [게임개발]   |  2008. 1. 6. 20:14  


사원수(쿼터니온)를 이용하여 캐릭터 제어하기


3D게임에서는 자신이 원하는 위치와 방향에 캐릭터를 배치시킬 수 있어야 합니다.
사원수에 관한 복잡한 공식들은 저도 잘 모르고,
단지 일리힛에서 어떤방법으로 쓸 수 있는지에 대해 알아보겠습니다.

먼저 적절한 모델 하나를 불러온 뒤, y축을 기준으로 45도 각도로 회전시켜보죠.
일리힛 엔진에서는 다음과 같이 작성할 수 있습니다.
[예1.]
node->setRotation(vector3df(0,45,0));


하지만 다음과 같이 표현할 수도 있습니다.
[예2.]

// 도를 라디안값으로 변환해서 사용해야 합니다.

// PI / 180.0f     대신 일리힛에 정의되어 있는    core::DEGTORAD      을 사용해도 됩니다.
float rad = 45.0f * PI / 180.0f;
quaternion quat;
quat.fromAngleAxis(rad, vector3df(0,1,0));        // 회전할 축을 정해줍니다. 여기서는 y축이며 이것은 단위벡터여야 합니다.
vector3df rot;
quat.toEuler(rot);
rot = rot * 180 / PI;           // 이것도      180 / PI    대신에      core::RADTODEG      를 사용해도 됩니다.
node->setRotation(rot);


예2가 좀 복잡하지만 결과는 둘 다 똑같습니다.
바로 사원수를 이용하여 회전을 표현한 것인데 이 방법을 사용하면 여러가지 응용이 가능합니다.

캐릭터가 0,0,0에 위치해 있고 어떤 한 방향을 보고 있다고 가정합시다.
이 캐릭터의 앞쪽에 몬스터를 갖다 놓으려 한다면 간단하게 다음과 같이 하면 됩니다.


vector3df position = quat * vector3df(0,0,50);


여기서 quat는 캐릭터의 쿼터니온값이고 뒤에 (0,0,50)은 캐릭터로부터 어느 방향으로 얼마만큼 떨어져
있는지를 나타내는 벡터입니다.
즉, 캐릭터의 z축 방향으로 50만큼 떨어진 위치라고 보시면 됩니다.
이제 몬스터의 위치를 설정해 보죠.


moster_node->SetPosition( position );


이렇게 해주면 캐릭터가 바라보고 있는 방향에서 50만큼 떨어진 위치에 몬스터가 놓일것입니다.
여기서 한가지 주의해야 할 점이 있는데 위 예제는 캐릭터가 원점(0,0,0)에 있다고 가정한 것입니다.
당연한 얘기지만 만약 원점이 아닌 임의의 위치에 있다면 position에 캐릭터의 위치를 더해줘야 합니다.


이런 방법을 적용하면 공격을 받았을때 어느 방향으로 튕겨져 나가야 하는지에 대한 고민이 해결됩니다.


오우거엔진에서는 사원수값이 노드에 같이 들어 있어 node->getOrientation()하면 사원수값을 뽑아낼 수가 있습니다.
하지만 일리힛에서는 사원수값을 따로 저장하지 않는듯 하더군요.
그래서 위 방법대로 쓰려면 노드를 처음 생성할때부터 사원수값도 같이 생성하여 갖고 있어야 하며,
회전을 줄 때도 [예제2]의 방법대로 회전하게끔 처리해줘야 할 것 같습니다.
좀 애매한것 같은데 혹시 다른 방법이 있는지 모르겠네요.


 
 
        

 

가상함수가 있는 클래스 초기화할때 주의점.
+   [게임개발]   |  2007. 12. 15. 18:10  

다음과 같은 구조의 클래스가 있다.
class Base
{
  virtual void Login() {}
};


class Main : public Base
{
  void Login();
};

그런데 Login을 호출하려는 순간 엑세스위반 에러가 뜨면서 프로그램이 죽는것이었다.
자세히 살펴보니 가상함수 테이블을 가지고 있는 포인터의 값이 모두 0으로 초기화가 된것이 아닌가.

문제는 클래스의 생성자 안에서 해주는

ZeroMemory(this, sizeof(*this));

초기화 코드 한줄이었다.

이런식으로 초기화를 할때,
만약 이 클래스가 가상함수를 포함하고 있다면 절대로 이렇게 해서는 안된다.
가상함수테이블 까지도 모두 초기화가 되어버리기 때문이다.

검색을 해보니 이에 대한 해결책이 몇몇 존재하였지만 웬만하면 이렇게 쓰지 않고,
그냥 하나하나 초기화해주는게 나을듯 싶다.




관련 글 링크
http://D00D00.egloos.com/93008
http://www.gpgstudy.com/gpgiki/Programming%20%ED%8C%81%20%EB%AA%A8%EC%9D%8C
http://www.gpgstudy.com/forum/viewtopic.php?t=11156&highlight=%B0%A1%BB%F3+%C7%D4%BC%F6+%C5%D7%C0%CC%BA%ED

 
 
        
<<이전 | 1 | 2 | 3 | 4 | 다음>>

이석현's Blog is powered by Daum