// wasd 로 구체 이동 , 방향키로 평면기울기 변경
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <time.h>
#include <math.h>
#include <d3dx9.h>
//#define _FULLMODE
#ifdef _FULLMODE
BOOL gFullScreen =TRUE;
#else
BOOL gFullScreen =FALSE;
#endif
#define WIDTH_RES 1024
#define HEIGHT_RES 768
#define Random(num) (int)(((long)rand() * (num) )/ (RAND_MAX+1) )
#define Randomize() srand( (unsigned) time(NULL) )
#define RandomA( s, e ) ( (s) + (Random( (e) - (s) + 1 )) )
// FVF 선언
#define D3DFVF_CUSTOMFVF1 (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
#define D3DFVF_CUSTOMFVF2 (D3DFVF_XYZ | D3DFVF_DIFFUSE)
// 구조체
struct CUSTOMVERTEX1
{
FLOAT x, y, z, rhw;
DWORD color;
};
struct CUSTOMVERTEX2
{
FLOAT x, y, z;
DWORD color;
};
//전역변수
LPDIRECT3D9 g_pD3D =NULL;
LPDIRECT3DDEVICE9 g_pd3dDevice =NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVB =NULL;
LPDIRECT3DVERTEXBUFFER9 g_p2VB =NULL;
LPD3DXMESH g_Mesh = NULL;
BOOL g_bGameOver =FALSE;
TCHAR *g_pProjectName =_T("3DSample");
BYTE g_bKey[256] = {0,};
WORD g_MouseX, g_MouseY;
BOOL g_bClick[2] = { FALSE, };
BOOL IntersectTriangle( const D3DXVECTOR3& orig,
const D3DXVECTOR3& dir, D3DXVECTOR3& v0,
D3DXVECTOR3& v1, D3DXVECTOR3& v2,
FLOAT* t, FLOAT* u, FLOAT* v )
{
// Find vectors for two edges sharing vert0
D3DXVECTOR3 edge1 = v1 - v0;
D3DXVECTOR3 edge2 = v2 - v0;
// Begin calculating determinant - also used to calculate U parameter
D3DXVECTOR3 pvec;
D3DXVec3Cross( &pvec, &dir, &edge2 );
// If determinant is near zero, ray lies in plane of triangle
FLOAT det = D3DXVec3Dot( &edge1, &pvec );
D3DXVECTOR3 tvec;
if( det > 0 )
{
tvec = orig - v0;
}
else
{
tvec = v0 - orig;
det = -det;
}
if( det < 0.0001f )
return FALSE;
// Calculate U parameter and test bounds
*u = D3DXVec3Dot( &tvec, &pvec );
if( *u < 0.0f || *u > det )
return FALSE;
// Prepare to test V parameter
D3DXVECTOR3 qvec;
D3DXVec3Cross( &qvec, &tvec, &edge1 );
// Calculate V parameter and test bounds
*v = D3DXVec3Dot( &dir, &qvec );
if( *v < 0.0f || *u + *v > det )
return FALSE;
// Calculate t, scale parameters, ray intersects triangle
*t = D3DXVec3Dot( &edge2, &qvec );
FLOAT fInvDet = 1.0f / det;
*t *= fInvDet;
*u *= fInvDet;
*v *= fInvDet;
return TRUE;
}
HRESULT InitD3D( HWND hWnd )
{
D3DDISPLAYMODE d3ddm;
if( !(g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
{ return E_FAIL; }
if( FAILED( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm) ) )
{ return E_FAIL; }
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof( d3dpp ) );
#ifdef _FULLMODE
//풀모드 세팅
d3dpp.BackBufferWidth = WIDTH_RES;
d3dpp.BackBufferHeight = HEIGHT_RES;
d3dpp.BackBufferFormat = D3DFMT_R5G6B5;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.Windowed = !gFullScreen;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
#else
//윈도우 모드
d3dpp.BackBufferWidth = WIDTH_RES;
d3dpp.BackBufferHeight = HEIGHT_RES;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.Windowed = !gFullScreen;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
#endif
if( FAILED ( g_pD3D->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&g_pd3dDevice )
)
)
{
return E_FAIL;
}
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
//g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_NONE );
return S_OK;
}
D3DXVECTOR3 g_Plane[4];
HRESULT InitData( void )
{
//==========================================================
//초기화와 관련된 모든 코드
//==========================================================
//구체 생성
if(FAILED(D3DXCreateSphere( g_pd3dDevice, 2.0f, 16, 8, &g_Mesh, NULL)) )
{
return E_FAIL;
}
//바닥생성
g_Plane[0] = D3DXVECTOR3( -20.0f, 0.0f, 20.0f );
g_Plane[1] = D3DXVECTOR3( 20.0f, 0.0f, 20.0f );
g_Plane[2] = D3DXVECTOR3( -20.0f, 0.0f, -20.0f );
g_Plane[3] = D3DXVECTOR3( 20.0f, 0.0f, -20.0f );
CUSTOMVERTEX2 cv[] =
{
{ g_Plane[0].x , g_Plane[0].y , g_Plane[0].z , 0xffffffff }, { g_Plane[1].x , g_Plane[1].y , g_Plane[1].z , 0xffffffff }, { g_Plane[3].x , g_Plane[3].y , g_Plane[3].z , 0xffffffff },
{ g_Plane[0].x , g_Plane[0].y , g_Plane[0].z , 0xffffffff }, { g_Plane[3].x , g_Plane[3].y , g_Plane[3].z , 0xffffffff }, { g_Plane[2].x , g_Plane[2].y , g_Plane[2].z , 0xffffffff },
};
if(FAILED(g_pd3dDevice->CreateVertexBuffer( sizeof(CUSTOMVERTEX2)*6, 0, D3DFVF_CUSTOMFVF2, D3DPOOL_DEFAULT, &g_pVB, NULL )) )
{
return E_FAIL;
}
VOID* pV;
g_pVB->Lock( 0, sizeof(cv), (VOID**)&pV, 0);
memcpy( pV, cv, sizeof(cv) );
g_pVB->Unlock();
return S_OK;
}
void Cleanup(void)
{
if( g_Mesh != NULL )
{ g_Mesh->Release(); }
if( g_pVB != NULL )
{ g_pVB->Release(); }
if( g_pd3dDevice != NULL )
{ g_pd3dDevice->Release(); }
if( g_pD3D != NULL )
{ g_pD3D->Release(); }
}
D3DXVECTOR3 g_Vector(0.0f,0.0f,0.0f); //출력 위치
FLOAT g_fRotY = D3DX_PI*2.0f*0.5f; //이동각도
void FrameMove( UINT interval )
{
//==========================================================
//변수 갱신과 관련된 모든 코드
//==========================================================
//키 처리
short rotSpeed = 1000; //한바퀴도는대 걸리는 시간
FLOAT SPEED = 1.0f; //초당 이동속도
FLOAT intervalRot = (FLOAT)interval / (FLOAT)rotSpeed; //현재 프래임 이동 각도
FLOAT intervalSpeed = SPEED / interval; //현재 프래임 이동 거리
D3DXVECTOR3 vDir(0.0f, 0.0f, 0.0f); //이동백터
//키처리
//구 움직임 처리
BOOL isDown = false;
if( g_bKey['A'] )
{
g_fRotY -= D3DX_PI*2.0f*intervalRot;
}
if( g_bKey['D'] )
{
g_fRotY += D3DX_PI*2.0f*intervalRot;
}
if( g_bKey['W'] )
{
vDir.z = 1.0f;
vDir *= intervalSpeed;
isDown = TRUE;
}
if( g_bKey['S'] )
{
vDir.z = 1.0f;
vDir *= -intervalSpeed;
isDown = TRUE;
}
//지면 움직임 처리
BOOL isPlaneDown = false;
if( g_bKey[37] )
{
g_Plane[0].y += intervalSpeed;
g_Plane[2].y += intervalSpeed;
g_Plane[1].y -= intervalSpeed;
g_Plane[3].y -= intervalSpeed;
isPlaneDown = TRUE;
}
if( g_bKey[39] )
{
g_Plane[0].y -= intervalSpeed;
g_Plane[2].y -= intervalSpeed;
g_Plane[1].y += intervalSpeed;
g_Plane[3].y += intervalSpeed;
isPlaneDown = TRUE;
}
if( g_bKey[38] )
{
g_Plane[0].y -= intervalSpeed;
g_Plane[1].y -= intervalSpeed;
g_Plane[2].y += intervalSpeed;
g_Plane[3].y += intervalSpeed;
isPlaneDown = TRUE;
}
if( g_bKey[40] )
{
g_Plane[0].y += intervalSpeed;
g_Plane[1].y += intervalSpeed;
g_Plane[2].y -= intervalSpeed;
g_Plane[3].y -= intervalSpeed;
isPlaneDown = TRUE;
}
//지면 갱신
if( isPlaneDown )
{
CUSTOMVERTEX2 cv[] = {
{ g_Plane[0].x , g_Plane[0].y , g_Plane[0].z , 0xffffffff }, { g_Plane[1].x , g_Plane[1].y , g_Plane[1].z , 0xffffffff }, { g_Plane[3].x , g_Plane[3].y , g_Plane[3].z , 0xffffffff },
{ g_Plane[0].x , g_Plane[0].y , g_Plane[0].z , 0xffffffff }, { g_Plane[3].x , g_Plane[3].y , g_Plane[3].z , 0xffffffff }, { g_Plane[2].x , g_Plane[2].y , g_Plane[2].z , 0xffffffff },
};
VOID* pV;
g_pVB->Lock(0, sizeof(cv), (void**)&pV, 0);
memcpy( pV, cv, sizeof(cv) );
g_pVB->Unlock();
}
//이동
D3DXMATRIXA16 matRot;
D3DXMatrixRotationY(&matRot, g_fRotY );
D3DXVec3TransformCoord( &vDir, &vDir, &matRot );
//출력위치 갱신
D3DXVECTOR3 vTemp = g_Vector;
vTemp += vDir;
//픽
vTemp.y = 1000.0f;
FLOAT t,u,v;
BOOL isPick = false; //픽 유무
isPick = ::IntersectTriangle( vTemp, D3DXVECTOR3( 0.0f, -1.0f, 0.0f), g_Plane[0], g_Plane[1], g_Plane[3] , &t, &u, &v );
if( !isPick )
isPick = ::IntersectTriangle( vTemp, D3DXVECTOR3( 0.0f, -1.0f, 0.0f), g_Plane[0], g_Plane[3], g_Plane[2] , &t, &u, &v );
if( isPick )
{
//면의 법선을 구하기
D3DXVECTOR3 v1,v2,vNormal;
v1 = g_Plane[1] - g_Plane[0] ;
v2 = g_Plane[3] - g_Plane[0] ;
D3DXVec3Cross(&vNormal, &v1 , &v2 );
D3DXVec3Normalize(&vNormal, &vNormal);
//미끄러짐 백터 구하기
D3DXVECTOR3 v( 0.0f, -1.0f , 0.0f );
D3DXVECTOR3 b = -vNormal;
D3DXVECTOR3 a = v - D3DXVec3Dot(&b,&v)*b;
//픽위치 구하기
vTemp = vTemp + (v*t);
//결과 갱신
vTemp += a;
g_Vector = vTemp;
}
else
{
FLOAT G=9.81f;
g_Vector += D3DXVECTOR3(0.0f, -1.0f, 0.0f)*G*(interval/1000.0f);
}
//떨어질때 처음 위치로
if( g_Vector.y < -30.0f )
{
g_Vector = D3DXVECTOR3(0.0f, 20.0f, 0.0f);
}
}
void SetupMatrices( void )
{
//==========================================================
// World, View, Project Setting
//==========================================================
D3DXMATRIXA16 matView;
D3DXVECTOR3 eye(0.0f, 5.0f , -40.0f);
D3DXVECTOR3 lookat(0.0f, 0.0f , 0.0f);
D3DXVECTOR3 up(0.0f, 1.0f , 0.0f);
D3DXMatrixLookAtLH(&matView, &eye, &lookat, &up);
g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveLH( &matProj, D3DX_PI/2.0f , (float)WIDTH_RES/(float)HEIGHT_RES, 1.0f, 5000.0f );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}
HRESULT Render( UINT interval )
{
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(0x80,0x80,0x80), 1.0f, 0 );
g_pd3dDevice->BeginScene();
SetupMatrices();
//==========================================================
// 그려주세요~
//==========================================================
//월드 설정
UINT iTime = timeGetTime() % 1000;
FLOAT fAngle = iTime / 1000.0f * 2.0f* D3DX_PI;
D3DXMATRIXA16 matWorld, matTrans, matRot;
D3DXMatrixTranslation(&matTrans, g_Vector.x, g_Vector.y+2.0f, g_Vector.z);
D3DXMatrixRotationY( &matRot, g_fRotY );
D3DXMatrixIdentity(&matWorld);
//지면 출력
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX2) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMFVF2 );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
//구출력
matWorld = matRot * matTrans;
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
g_Mesh->DrawSubset(0);
g_pd3dDevice->EndScene();
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
return true;
}
// 윈도우 프로시져
LRESULT WINAPI WindowProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch (msg)
{
//마우스입력
case WM_MOUSEMOVE:
{
g_MouseX = LOWORD(lParam);
g_MouseY = HIWORD(lParam);
}
break;
case WM_LBUTTONDOWN:
{
g_MouseX = LOWORD(lParam);
g_MouseY = HIWORD(lParam);
g_bClick[0] = 1;
}
break;
case WM_LBUTTONUP:
{
g_bClick[0] = 0;
}
break;
case WM_RBUTTONDOWN:
{
g_MouseX = LOWORD(lParam);
g_MouseY = HIWORD(lParam);
g_bClick[1] = 1;
}
break;
case WM_RBUTTONUP:
{
g_bClick[1] = 0;
}
break;
//키보드 처리
case WM_KEYDOWN:
switch( wParam )
{
case VK_ESCAPE :
g_bGameOver = TRUE;
break;
}
g_bKey[wParam] = 1;
break;
case WM_KEYUP:
g_bKey[wParam] = 0;
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
HWND g_hWnd;
WNDCLASS wc;
MSG msg;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = g_pProjectName;
RegisterClass( &wc );
if( !gFullScreen )
{
//윈도우 모드
g_hWnd = CreateWindowEx( 0, g_pProjectName, g_pProjectName, WS_POPUP | WS_SYSMENU,
( GetSystemMetrics(SM_CXSCREEN) / 2) - (WIDTH_RES /2 ),
( GetSystemMetrics(SM_CYSCREEN) / 2) - (HEIGHT_RES /2 ),
WIDTH_RES, HEIGHT_RES, NULL, NULL, hInst, NULL );
}
else
{
//전체 모드
g_hWnd = CreateWindowEx( 0, g_pProjectName, g_pProjectName, WS_POPUP | WS_SYSMENU,
0, 0, WIDTH_RES, HEIGHT_RES, NULL, NULL, hInst, NULL );
}
if( g_hWnd == NULL ) {return FALSE;}
if( FAILED( InitD3D( g_hWnd ) ) ) {return FALSE;}
if( FAILED( InitData() ) ) {return FALSE;}
ShowWindow(g_hWnd, nCmdShow);
UpdateWindow(g_hWnd);
SetFocus(g_hWnd);
ShowCursor( TRUE );
static UINT preTime = timeGetTime();
while( !g_bGameOver )
{
if( PeekMessage( &msg, NULL ,0, 0, PM_NOREMOVE ) )
{
if( !GetMessage( &msg, NULL, 0, 0) )
{ return msg.wParam; }
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
Sleep(1);
UINT iTime = timeGetTime();
FrameMove(iTime - preTime );
Render(iTime - preTime);
preTime = iTime;
}
}
Cleanup();
UnregisterClass( g_pProjectName, wc.hInstance );
return TRUE;
}
'게임프로그래밍 공부' 카테고리의 다른 글
4주간 만들다가...... (0) | 2013.07.08 |
---|---|
코딩안되서하는 물리공부1 (0) | 2013.06.28 |
지형에디터 및 MD2로더 재수정 (0) | 2013.05.19 |
MD2뷰어, 지형에디터 수정 (0) | 2013.05.13 |
안되는거..... (0) | 2013.05.08 |