달력

09

« 2018/09 »

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



흔히 쓰는, ++, -- 연산자에 대해서 설명하고 있는 항목이다.

i++이나, ++i냐,
i--이냐, --i냐...
이것의 원리를 좀 알아 보고자 하는거 같다.

역시나 가장 기본은,
사용 후 더하느냐,
더한 후 사용 하느냐.

라고 보면 되겠지만
조금 자세히 파보자.

먼저 i++, ++i의 차이인데,
증가, 감소 연산자는 전위형태이든, 후위형태이든, 인자를 받지 않는(사용하지 않는) 구조이다.

그렇기 때문에 오버로딩을 하기 위해서 걸리는 매개변수의 타입이나, 갯수등으로 구별 하기가 까다로워 진 것이다.

이를 위해 약속한 것이,
전위는 그냥두고, 후위 형태는 int 타입의 인자를 받는 것으로 하자.
라고 약속하였다고 한다.

다음과 같이 말이다.

다음은, 전위, 후위 형태의 내부 구조이다.

쉽게 말해서 전위, 후위를 나누기 위해 후위의 경우 인자 int를 받고 있지만,
전혀 의미가 없다는 것을 알 수 있다.

이제 내부 구조를 조금 살펴 보면,
후위 구조의 경우 return 값이 const를 가지고 있다.
쉽게 말해서 i++++; 을 방지 하기 위해서 이다.
저 i++++을 사용한 의도가 뭘까?
i+=1 이후 계산 한 다음..? ++?
아니면 i +=2 이후 계산?
어떻게 생각해도 애매한 코드이다. 그런 부분을 일절 용납 하지 않겠다는 것이다.

마지막으로, ++i, i++ 뭐가더 빠를까?
물어볼 것도 없다. 당연히 ++i 가 더 빠른 것이다.
이리저리 뺑 돌아가긴 했지만, 결국 여기서 의도한 것은
가능하면 i++ 을 쓰지 말고 ++i을 써라,
어차피 후위 연산자를 사용하면, 전위 연산자를 지나칠 수 밖에 없기 때문이다.

Posted by 안식의후크




이번 항목은 타입변환에 대한 내용.

코드를 통해 문제점 부터 파악해 보자.




사실 코드만 보면 << 에 대한 연산자 오버로딩이 없기 때문에 안될거 같은데? 라고 생각하겠지만,
실제론 형변환이 이루어 지면서 출력이 된다.
이런 상황을 제거하기 위해, operator double가 아닌, 함수로써 변경을 하는 방법이 존재한다.


다음 예제를 보자.

다음과 같이, 암시적 변환을 사용하게 되었을 때는 원하지 않는 결과에 도출하게 된다.
물론 a == b[i]가 의도한 코딩이라면 상관없을지도 모르겠지만,
현재 상황에서 저 코드에 문제가 있다는 것을 시력이 좋거나,
런타임 후에 확인하거나,,
둘중 하나일 것이다.
코드를 하나하나 따라가 보면,
a 의 생성자에 10번,
operator==에 10번 들른다.
그 부분에 대해서는 항목 19에서 다시 설명한다고 한다.
자 문제는 파악 했고, 이제 저런 상황에서 우리가 원하지 않는 암시적 변환을 막고 싶다고 하였을 때,
어떻게 해야 할까? 답은 생각보다 쉬웠다.

explicit

이로써 이전에 if( a == b[i] ) 부분에서 컴파일 오류가 날것이다.
하지만 모든 문제가 해결된 것은 아니다.
비록 암시적 변환은 해결 됐지만,
명시적 타입 변환은 여전히 허용되는 것이다.
현재로썬 저런 어색한 부분에 대한 해결책은 언급하고 있지 않지만,
명시적 타입 변환이라고 해도, 이전에 이야기 했듯이 지나친 형변환은 지양하자는 말이 떠오르는 코드다.
이번 타입 변환과는 별개로, 2번째 if문에 존재하는 > > 사이의 공백에 대해 언급을 하고 있는데,
저곳에 공백을 넣지 않으면 operator >> 를 호출 한다고 하니, 주의하도록 하자.
(필자는 그냥 무조건 공백을 주는 습관을 가지고 있으니 괜찮다!)
이 후에는 explicit 를 지원하지 않는 컴파일러에서의 해결 방법을 이야기 하고 있는데,
안봐도 되지만, 내용이 프록시 클래스 라는 것에 대해 미리 이야기 하고 싶었던것 같다.
한번 그냥 훑어 보는 정도로 넘어가면 될듯.

Posted by 안식의후크




차암.. 이 부분은 읽으면 읽을 수록,
"아. 어쩌라고 ㅋㅋ"
라는 말이 절로 나온다.

쉽게 풀어 설명하면,


다음과 같은 클래스가 있다고 치자.
사용자는 무언가 생성할때 ID를 같이 초기화 하고 싶은것이다.
각 id는 중복 되서는 안되고, 고유의 id를 가지고 있다고 치자.
그렇기 때문에 생성할 때 id를 넣어 주는 식의 방법을 채택 하였는데,
문제는 이거다.

책에서는 여러 가지 방법들이 보여지는데,
이래저래 쭉 읽다 보면 결론은,
그냥 내비 둬라(?) ... 라는 결론이 나오게 되는데,
해결책의 첫번째에는, 생성을 객체의 배열을 포인터로써 생성한다는 방법인데,
사실 이 부분도, 결과적으론 최종 생성할때 생성자에 인자를 넣어 주는 방식이고,
(어찌 보면 괜히 메모리만 더 먹는거 같기도 하다.)
다음 부분은 기본 생성자를 생성하여 문제를 직접 해결하고,
추후에 값이 올바른지 그렇지 않은지 예외 조건을 넣으라는 것이다.
하지만 그 부분은 포퍼먼스가 많이 떨어지고, 다른 작업자가, 그런 예외 처리를 해주지 않을 수도 있다는 것이 단점,
근데 솔직히 내가 생각 했을 때 가장 편한건,
기본생성자를 하나 넣어주고, static이나, 전역 변수를 하나 잡아주어,
중복을 피하는 식으로 무작정 데이터를 삽입하는게 어떤가 싶은데,
내 예상 해결책은 다음과 같다.

하지만 이 부분에 문제점은 여전히 존재한다.
사실상, 어떤 값이 어떻게 들어 가게 될지 예측을 못한다는 것이다.
순차적으로 들어갈 수도 있고, 중간에 뛰엄뛰엄 들어갈 수도 있고..
의도한다면 중복된 값또한 넣을 수 있다는 것이다.

이 부분에 대해선 사실 정해진 답이 존재 한다기 보단,
생성자에 대해서 정확히 파악하고,
생길 수 있는 문제에 대해서 미리 한번 생각해 보라...
라는것을 말하고 있다고 생각한다.
Posted by 안식의후크





이번 새로 이력서를 넣기 위해 게임 동영상을 찍다 보니, 여기에 올리는것도 좋을것 같아서 올리게 되네 ㅎ
Posted by 안식의후크
2011.01.24 11:34

MapTool - Ver 1.0 게임이야기/제작2011.01.24 11:34






이번 졸작때 완성된 맵툴의 스크린샷.

'게임이야기 > 제작' 카테고리의 다른 글

맵툴 시연용 영상  (0) 2011.02.01
KGCA 19기 졸업 프로젝트 -팀 : Pathfinder, 터치다운(함정을 달리다)-  (0) 2011.02.01
MapTool - Ver 1.0  (0) 2011.01.24
WrapUp!  (0) 2010.12.08
MapTool - 완성본  (0) 2010.12.06
API-Catch Me If You Can  (0) 2010.06.10
Posted by 안식의후크
2010.12.06 15:44

MapTool - 완성본 게임이야기/제작2010.12.06 15:44






이래저래 한바탕 폭풍이 지나가고,

이제는 다시 블로그질을 시작합니다.

아이콘 작업은 권수영(Nick_수바리)님께서 해주셨습니다.

ps : 초심으로 대동단결.

'게임이야기 > 제작' 카테고리의 다른 글

MapTool - Ver 1.0  (0) 2011.01.24
WrapUp!  (0) 2010.12.08
MapTool - 완성본  (0) 2010.12.06
API-Catch Me If You Can  (0) 2010.06.10
Chtch Me If You Can Ver 2.1  (0) 2010.05.08
Chtch Me If You Can Ver 1.0  (0) 2010.05.05
Posted by 안식의후크




DX에서 키보드 입력을 받게 될때,

API함수를 사용해 보았는데,

자꾸 까먹게 되어 따로 포스팅을 한다.

키보드 입력을 처리 하는 함수로는
GetAsyncKeyState 함수와 GetKeyState가 존재 하는데

GetAsyncKeyState에 대해서 간단하게 필요한 부분만

빠르게 포스팅하도록 하자.

주로 GetAsyncKeyState를 사용할 때 함수만 딸랑 쓰는게 아니라

추가적인 연산을 해주게 되는데,

GetAsyncKeyState는 키가 눌렸을 때 GetAsyncKeyState의 0x8000 bit가 1이된다.
그리고,
GetAsyncKeyState가 호출되었을 때부터 다음 GetAsyncKeyState가 호출될 때까지
키가 계속 눌려 있는 상태라면 0x0001 bit는 0, 그렇지 않은 경우는 1이 된다.

즉, 키를 한번만 눌리게 하고 싶다면, &연산을 사용 0x0001에 대해 검사하면 될것이고,
한번 눌릴키가 쭉 눌렸을때 무언가 반응하고 싶다면
0x8000 을 사용하면 될것이다.

상황에 따라 적절하게 사용하도록 하자.

'프로그래밍 > API' 카테고리의 다른 글

API-GetAsyncKeyState( 키보드 입력함수 )  (1) 2010.06.28
API-ini파일  (1) 2010.05.10
API-알파값(비트맵 이미지 투명화)  (0) 2010.05.10
API-애니메이션  (0) 2010.05.10
API-PlaySound  (0) 2010.05.10
API-더블 버퍼링  (0) 2010.05.10
Posted by 안식의후크
2010.06.14 11:38

DirectX - 행렬(Matrices) 프로그래밍/DirectX2010.06.14 11:38





Dx에서 3차원의 정점(Vertex)를 화면상의 모니터로 출력해 주기 위해서는

3가지의 행렬 변환이 필요 하다.

1. 월드 행렬
2. 뷰 행렬
3. 투영 행렬

월드 행렬의 경우에는 3D오브젝트의 로컬좌표를 3차원의 필드에 특정 위치에 뿌려 주기 위해서,
( 좀더 간단하게 말하면, 로컬 좌표를 월드 좌표로 변환 하는 작업 )

뷰 행렬은 카메라를 셋팅한다고 생각하면 되는데,
뷰 행렬을 만들기 위해서는 추가적인 3개의 백터가 필요 하다.
카메라의 위치, 카메라가 바라보는 방향, 카메라의 Up벡터가 필요 하다.

마지막으로 투영 행렬은,
각각의 3D좌표들을 우리의 눈으로 보게 되는 2D로 변경하는 작업을 한다.

이런 작업을 렌더링 파이프라인이라고 하는데,

3D의 좌표를 모니터 화면에 뿌려주기 위한 작업이라고 보면 된다.


이제 이 작업을 Render할때 마다 해주어야 한다.
D3DInit나 InitVB와는 다르게,

행렬에 관한 연산은 매번 처리를 해 주어야 한다.

전체 소스는 생략,

Posted by 안식의후크
2010.06.10 11:15

API-Catch Me If You Can 게임이야기/제작2010.06.10 11:15





최종 버전

아직 좌표 수정이나 그런거 좀 있긴 하지만

완성본도 진작 떳지만 걍 지금 올림 ㅋㅋ





'게임이야기 > 제작' 카테고리의 다른 글

WrapUp!  (0) 2010.12.08
MapTool - 완성본  (0) 2010.12.06
API-Catch Me If You Can  (0) 2010.06.10
Chtch Me If You Can Ver 2.1  (0) 2010.05.08
Chtch Me If You Can Ver 1.0  (0) 2010.05.05
나의 정신적 지주 ㅋ  (1) 2010.05.02
Posted by 안식의후크





먼저 정점을 띄우기 위해서는 정점을 보관할 정점 버퍼가 필요 합니다.

정점 버퍼에 FVF(사용자 정의 정점 형식)를 사용하여 생성할 수 있습니다.

최초 생성한 정점 버퍼는 쓰레기 값이 들어가 있기 때문에,

Lock함수를 사용하여 값을 넣을 수 있는 포인터를 가져 옵니다.

그 후 미리 지정해 놓은 정점 정보를 정점 버퍼에 저장합니다.


바로 그 일을 하는 함수가 InitVB입니다.

이제 정점 버퍼를 생성하고 값을 대입하였으니,

화면에 띄워 주는 일만 남았습니다.

화면에 띄워 주기 위해선 정점 버퍼를 출력 스트림에 할당하고,
셰이더 정보를 삽입한 후에,
화면에 출력시켜 주면됩니다.

이게 전반적인 흐름이고,
조금 자세히 한번 살펴 보도록 합시다.

CreateVertexBuffer 함수는 정점 버퍼를 생성하는 함수인데,
UINT Length,( 생성할 정점 버퍼의 바이트 단위 크기 )
DWORD Usage,( 정점 버퍼의 종류 혹은 처리 방식(SW, HW) 지정 )
DWORD FVF, ( 정점 정보 구조체에 따라 선언된 FVF 플래그 값 )
D3DPOOL Pool, ( 정점 버퍼가 저장될 메모리의 위치( 비디오카드, 시스템 메로리) 와 관련 방식 지정 )
IDirect3DVertexBuffer9** ppVertexBuffer, ( 반환될 정점 버퍼의 인터페이스 )
HANDLE* pSharedHandle
로 이루어져 있는데 HANDLE의 경우는 NULL을 넣어 주는것 같습니다.

다음으로 Lock 함수 같은 경우에는,
UINT OffsetToLock, ( Lock을 할 버퍼의 시작점, SizeToLock과 함께 양쪽 모두 0이면 버퍼 전체 )
UINT SizeToLock, ( Lock을 할 버퍼의 크기, OffsetToLock과 함께 양쪽 모두 0이면 버퍼 전체 )
void** ppbData, ( 읽고 쓸 수 있게 된 메모리 영역의 포인터 )
DWORD Flags ( Lock을 수행할 때 함께 사용하는 플래그 )
예제의 사용을 보면 버퍼의 시작점은 0으로 두고
사이즈는 sizeof를 사용해 할당 받고,
VOID* pVertices 라는 변수에 메모리 영역의 포인터를 삽입,
플래그는 주지 않은 상태인것을 확인 할 수 있습니다.

Lock함수의 주의점은 꼭 마지막에 UnLock를 해주어야 한다는 것을 잊지 맙시다.

다음으로 Render를 해줄때 사용하는
SetStreamSource, SetFVF, DrawPrimitive 함수를 살펴 봅시다.

책에선 SDK도움말을 확인 하라길래 그냥 인터넷에서 뒤져서 대충 정리해 보았습니다.

SetStreamSource 함수,
UINT StreamNumber, ( 스트림의 최대숫자까지 설정 할 수 있다는데, 보통 0으로 한다고 함 )
IDirect3DVertexBuffer9* pStreamData, ( 정점 버퍼가 저장된 데이타 )
UINT OffsetInBytes, (정점 버퍼에 시작될 스트림 오프셋 값, 보통 0을 지정한다.)
UINT Stride ( 한 정점의 크기로 앞서 설정된 구조체 크기를 넣어 준다.)

SetFVF 함수,
DWORD FVF ( 유연 정점 포맷, FVF의 설정 )

DrawPrimitive 함수,
D3DPRIMITIVETYPE PrimitiveType, ( 어떤 방식으로 그려줄 것인가에 대한 속성 값 )
UINT StartVertex, ( 로드하는 최초 정점 인덱스 )
UINT PrimitiveCount ( 랜더링 하는 도형의 갯수 )

대충 이정도 개념을 잡고 있으면 정점에 대해선 어느정도 이해한거라고 생각합니다.

// 전체 소스


// 실행 화면
Posted by 안식의후크