
here's the source (heavily commented, but taken from shreds I could find)
If anybody knows of some good DirectX 9 2D tutorials, I would really appreciate it if they posted the links

Main.cpp
/* PacChief, a game that attempts to show some of Halo 3's AI Tree * @author *** * Last modified: 05 February 2012 * * Notes for getting this running: * built using Feb 2011 build of DX9.0c, need to include lib(x86) & include directories */ #define DIRECTINPUT_VERSION 0x0800 //includes / namespaces #include <Windows.h> #include <WindowsX.h> #include <MMSystem.h> #include <d3d9.h> #include <d3dx9.h> #include <dinput.h> #include <list> #include "resource.h" #include "sprite.h" using namespace std; //Prototypes LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); HRESULT WinInit(HINSTANCE hInst, int nCmdShow, HWND* phWnd, HACCEL* phAccel); LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); HRESULT GameStart(HWND hWnd); HRESULT GameMain(HWND hWnd); HRESULT InitDirect3D(HWND hWnd, BOOL bWindowed); void GameOver(void); void FreeDirect3D(void); HRESULT InitDirectInput(HWND hWnd); void FreeDirectInput(void); void InitializeSprites(void); HRESULT DisplayFrame(); //Macros #define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } #define KEYDOWN(name,key) (name[key] & 0x80) //Global vars HWND g_hWnd = NULL; LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; LPDIRECTINPUT8 g_lpdi = NULL; LPDIRECTINPUTDEVICE8 g_pKeyboard = NULL; RECT g_rcWindow; BOOL g_bWindowed = true; BOOL g_bActive = false; DWORD g_dwLastFireTick = 0; double g_dElapsedTime; double g_dCurTime; double g_dLastTime; double g_dAnimationTimer = 0.0; //sprite linked list typedef list<CSprite> SPRITELIST; SPRITELIST g_SpriteList; SPRITELIST::iterator g_sprite_i; SPRITELIST::iterator g_sprite_j; SPRITELIST::iterator g_sprite_k; /* * WinMain(): entry point of game, inits / calls everything hInst: "handle to an instance", 32bit int that IDs a prgm, hPrevInst: handle to a previous instance; if there's multiplce copes of the same app open, this contains a handle to the last instance created lpCmdLine: long pntr to a string containing cmd used to run prgm, can check for special params nCmdShow: indicates how window should appear when created (minimized, max, normal, background, etc.) View possible values: Table 2.1: http://www.directxtutorial.com/Tutorial9/A-Win32/dx9A2.aspx#still */ int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow){ //this struct holds Windows even messages MSG msg; //the handle for the window, filled by a function HWND hWnd; //Hardware acceleration; ? HACCEL hAccel; //??? memset(&msg, 0, sizeof(msg)); //int window WinInit(hInstance, nCmdShow, &hWnd, &hAccel); //start window GameStart(hWnd); /* //wait for the next message in teh queue, store the result in msg //can't use this because no time to wait for a new message; should just check and continue while(GetMessage(&msg, NULL, 0, 0)){ //while their are messages to process (always, unless end of prgm) -> translate and dispatch them -> //to my WindowProc, because wc.lpfnWndProc = WindowProc //WindowProc listens for some messages, handles them, passes rest to defaultWindowProc() */ //enter main loop while(true){ //check to see if any messages are witing in the queue //PeekMessage(LPMSG, HWND, UINT msgFilterMin, UINT msgFilterMax, UINT removeMsg [remove it?] ) if( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) ){ if( 0 == GetMessage(&msg, NULL, 0, 0 ) ){ // WM_QUIT was posted, so exit return (int)msg.wParam; } // Translate and dispatch the message if( 0 == TranslateAccelerator(hWnd, hAccel, &msg) ){ TranslateMessage(&msg); DispatchMessage(&msg); } }else{ if(g_bActive){ //move the sprites, by blting them to the back buffer, then flip|blt to back buff to primary buff g_dCurTime = timeGetTime(); g_dElapsedTime = ((g_dCurTime - g_dLastTime) * 0.001); g_dLastTime = g_dCurTime; if(FAILED(GameMain(hWnd))){ MessageBox(hWnd, TEXT("GAMEMAIN() FAILED.") TEXT("The game will now exit."), TEXT("PrototypeX"), MB_IConerror | MB_OK); return FALSE; } }else{ //go to sleep if we have nothing to do WaitMessage(); } } } /* OLD, KEEP FOR OWN NOTES //create a "hello world" message box, has a return int stating what value was pressed //see Table 2.4 for a full listing: http://www.directxtutorial.com/Tutorial9/A-Win32/dx9A2.aspx#still MessageBox(NULL, //HWND: "handle to a window", no window to launch from, so use the desktop via NULL L"Hello World", //long pointer to a string: the content of the message L"Just another Hello World program!", //long pointer to a string: the title of the message box MB_ICONEXCLAMATION | MB_OK); //UINT: unisigned int, use with a logical or to display icons and buttons // see table 2.2 and 2.3 for a full listing http://www.directxtutorial.com/Tutorial9/A-Win32/dx9A2.aspx#still //return 0 to Windows return 0; */ } /* * Init the game's window */ HRESULT WinInit( HINSTANCE hInst, int nCmdShow, HWND *phWnd, HACCEL *phAccel ){ //this struct holds info for the window class WNDCLASSEX wc; HWND hWnd; HACCEL hAccel; //clear out the window class for use ZeroMemory(&wc, sizeof(WNDCLASSEX)); //fill in the struct with the needed info wc.cbSize = sizeof(WNDCLASSEX); wc.lpszClassName = TEXT("SNAKE_GAME_CLASS"); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = MainWndProc; wc.hInstance = hInst; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.cbClsExtra = 0; wc.cbWndExtra = 0; //register the window class if(RegisterClassEx(&wc) == 0) return E_FAIL; //load keyboard accelerators hAccel = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_MAIN_ACCEL)); //IDR found in resource.h //calc proper size for window given client ox 640x480 (given in resource.h) DWORD dwFrameWidth = GetSystemMetrics(SM_CXSIZEFRAME); DWORD dwFrameHeight = GetSystemMetrics(SM_CYSIZEFRAME); DWORD dwMenuHeight = GetSystemMetrics(SM_CYMENU); DWORD dwCaptionHeight = GetSystemMetrics(SM_CYCAPTION); DWORD dwWindowWidth = SCREEN_WIDTH + dwFrameWidth * 2; DWORD dwWindowHeight = SCREEN_HEIGHT + dwFrameHeight * 2 + dwMenuHeight + dwCaptionHeight; //create the window and use the result as the handle DWORD dwStyle = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX; //??? hWnd = CreateWindowEx(0, L"SNAKE_GAME_CLASS", //name of the window class L"Snake Game v1.0", //title of the window dwStyle, //window style, can take out min/max buttons, etc. CW_USEDEFAULT, //x-position of the window CW_USEDEFAULT, //y-position of the window dwWindowWidth, //width of the window dwWindowHeight, //height of the window NULL, //we have no parent window, so NULL NULL, //we aren't using menus, so NULL hInst, //application handle NULL); //used with multi windows, NULL //if window failed to init, say so if(hWnd == NULL) return E_FAIL; //display the window on the screen ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); //save window size&pos for switching modes GetWindowRect(hWnd, &g_rcWindow); *phWnd = hWnd; *phAccel = hAccel; return S_OK; } //this is the main message handler for the program LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ //sort through and find what code to run for the message given switch(message){ case WM_COMMAND: switch(LOWORD(wParam)){ case IDM_TOGGLEFULLSCREEN: //TODO return 0L; case IDM_EXIT: //received key/menu cmd to exit app PostMessage(hWnd, WM_CLOSE, 0, 0); return 0L; } break; case WM_GETMINMAXINFO: { //don't allow window resizing (fix size of window to 800x600 MINMAXINFO* pMinMax = (MINMAXINFO*) lParam; DWORD dwFrameWidth = GetSystemMetrics(SM_CXSIZEFRAME); DWORD dwFrameHeight = GetSystemMetrics(SM_CYSIZEFRAME); DWORD dwMenuHeight = GetSystemMetrics(SM_CYMENU); DWORD dwCaptionHeight = GetSystemMetrics(SM_CYCAPTION); pMinMax->ptMinTrackSize.x = SCREEN_WIDTH + dwFrameWidth * 2; pMinMax->ptMinTrackSize.y = SCREEN_HEIGHT + dwFrameHeight *2 + dwMenuHeight + dwCaptionHeight; pMinMax->ptMaxTrackSize.x = pMinMax->ptMinTrackSize.x; pMinMax->ptMaxTrackSize.y = pMinMax->ptMinTrackSize.y; } return 0L; case WM_SIZE: // Check to see if we are losing our window... if( SIZE_MAXHIDE == wParam || SIZE_MINIMIZED == wParam ) g_bActive = FALSE; else g_bActive = TRUE; break; case WM_SETCURSOR: //hide the cursor if in full screen if(!g_bWindowed){ SetCursor(NULL); return true; } break; case WM_EXITMENULOOP: //do nothing for now break; case WM_EXITSIZEMOVE: //do nothing for now break; case WM_SYSCOMMAND: //prevent moving/sizign and power loss in full screen mode switch(wParam){ case SC_MOVE: case SC_SIZE: case SC_MAXIMIZE: case SC_MONITORPOWER: if(!g_bWindowed) return true; } break; case WM_ACTIVATE: if(WA_INACTIVE != wParam && g_pKeyboard){ //make sure device is acquired if gaining focus g_pKeyboard->Acquire(); } break; //this message is read when the window is closed case WM_DESTROY:{ //close the application entierely GameOver(); PostQuitMessage(0); return 0L; } break; } //Handle any messages the switch didn't return DefWindowProc(hWnd, message, wParam, lParam); } /* * Init all direct 3D */ HRESULT InitDirect3D(HWND hWnd, BOOL bWindowed){ g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); D3DCAPS9 d3dCaps; g_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps); D3DDISPLAYMODE d3ddm; g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm); D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); if(bWindowed == true){ d3dpp.Windowed = true; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = d3ddm.Format; }else{ d3dpp.Windowed = false; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferWidth = SCREEN_WIDTH; d3dpp.BackBufferHeight = SCREEN_HEIGHT; d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; } d3dpp.EnableAutoDepthStencil = true; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //don't sync to vert retrace d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice); D3DXMATRIX matProj; D3DXMatrixPerspectiveFovLH(&matProj, D3DXToRadian(45.0f), SCREEN_WIDTH / SCREEN_HEIGHT, 0.1f, 100.0f); g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj); g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); return S_OK; } /* * init the DirX input vars */ void FreeDirectInput(void){ //unacquire device, incase app exited while device still acquired if(g_pKeyboard) g_pKeyboard->Unacquire(); //release any DirIn objs SAFE_RELEASE(g_pKeyboard); SAFE_RELEASE(g_lpdi); } /* * Init directX's input */ HRESULT InitDirectInput(HWND hWnd){ HRESULT hr; FreeDirectInput(); //create DirIn obj if(FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&g_lpdi, NULL))) return hr; //grab interface to sys keyboard device if(FAILED(hr = g_lpdi->CreateDevice(GUID_SysKeyboard, &g_pKeyboard, NULL))) return hr; //set data format to a predefined "keyboard" format //a format specifies what to do with the controls specified //this tells DirIn that a 256 byte array will be passed to IDirectInputDevice::GetDeviceState if(FAILED(hr = g_pKeyboard->SetDataFormat(&c_dfDIKeyboard))) return hr; //set cooperative level hr = g_pKeyboard->SetCooperativeLevel(hWnd, DISCL_NOWINKEY | DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); if(hr == DIERR_UNSUPPORTED){ FreeDirectInput(); MessageBox(hWnd, TEXT("SetCooperativeLevel() returned DIERR_UNSUPPORTED.\n") TEXT("FOR security reasons, background exclusive keyboard\n") TEXT("access is not allowed."), TEXT("PrototypeX"), MB_OK); return S_OK; } if(FAILED(hr)) return hr; //acquire the new device g_pKeyboard->Acquire(); return S_OK; } /* * create each sprite, set their properties & loads them into the linked list */ void InitializeSprites(void){ CSprite sprite; int i = 0; sprite.zeroSpriteValues(); sprite.m_nID = 555; strcpy( sprite.m_chType, "player"); strcpy( sprite.m_chSpriteTextureName, "player.bmp"); sprite.m_nWidth = 32; sprite.m_nHeight = 32; sprite.m_fPosition_x = 0; sprite.m_fPosition_y = 256; sprite.m_bActive = true; sprite.m_bSingleFrame = true; sprite.m_nFrameWidth = 32; sprite.m_nFrameHeight = 32; g_SpriteList.push_back(sprite); } /* * GameStart(), oversees init of DX3D functions */ HRESULT GameStart(HWND hWnd){ HRESULT hr; //init all surfaces needed if(FAILED(hr = InitDirect3D(hWnd, g_bWindowed))) return hr; if(FAILED(hr = InitDirectInput(hWnd))) return hr; InitializeSprites(); g_dwLastFireTick = timeGetTime(); return S_OK; } VOID GameOver(){ //FreeDirect3D(); //DO LATER ??? //FreeDirectInput(); for( g_sprite_i = g_SpriteList.begin(); g_sprite_i != g_SpriteList.end(); ++g_sprite_i ) g_sprite_i->releaseMemory(); // Cleanup the STL generated linked list g_SpriteList.erase( g_SpriteList.begin(), g_SpriteList.end() ); } /* * Call each function for input/collisions/score/display for the game */ HRESULT GameMain(HWND hWnd){ g_dAnimationTimer += g_dElapsedTime; if(g_dAnimationTimer >= 0.016) g_dAnimationTimer = 0.0; //target of 60FPS (1/60th of a second) reached, render new frame else return S_OK; //it's too early to change, return now and render nothing //collect user input and move the player //MovePlayer(); //move the game sprites //MoveSprites(); //check for collision //CheckCollisions(); //assign the score //ComputeScore(); //display the sprites DisplayFrame(); return S_OK; } /* * Display a single frame (the sprites) */ HRESULT DisplayFrame(){ HRESULT hr; //clear the primary buffer g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_COLORVALUE(0.0f, 0.0f, 0.0f, 1.0f), 1.0f, 0); g_pd3dDevice->BeginScene(); g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); for(g_sprite_i = g_SpriteList.begin(); g_sprite_i != g_SpriteList.end(); ++g_sprite_i) g_sprite_i->drawSprite(g_pd3dDevice); g_pd3dDevice->EndScene(); if(FAILED(hr = g_pd3dDevice->Present(NULL, NULL, NULL, NULL))) return hr; return S_OK; }
Sprite.cpp
/* * function definitions for CSprite class * */ #include "sprite.h" /* * CSprite Constructor */ CSprite::CSprite(): m_pSpriteTexture( NULL ), m_pD3DXSprite( NULL ), m_nWidth( 0 ), m_nHeight( 0 ), m_nID( 0 ), m_nState( 0 ), m_fPosition_x( 0.0f ), m_fPosition_y( 0.0f ), m_fVelocity_x( 0.0f ), m_fVelocity_y( 0.0f ), m_bVisible( true ), m_bCollide( true ), m_bAutoAnimate( true ), m_bActive( true ), m_bScripting( false ), m_bModifyCollision( false ), m_bSingleFrame( false ), m_bDestroy( false ), m_nFrameRateModifier( 0 ), m_nFrameSkipCount( 0 ), m_nFrameWidth( 0 ), m_nFrameHeight( 0 ), m_nFramesAcross( 1 ), m_nFrameOffset_x( 0 ), m_nFrameOffset_y( 0 ), m_nWidthScaling( 0 ), m_nHeightScaling( 0 ), m_nCurrentAnimation( 0 ), m_nCurrentFrame( 0 ), m_nCurrentScript( 0 ), m_nCollisionTop( 0 ), m_nCollisionBottom( 0 ), m_nCollisionLeft( 0 ), m_nCollisionRight( 0 ) { for(int i = 0; i < MAX_ANIM_PER; i++){ m_nAnimations[i] = NULL; } for(int i = 0; i < MAX_SIZE; i++){ m_chType[i] = NULL; m_chName[i] = NULL; m_chSpriteTextureName[i] = NULL; } } /* * Destructor */ CSprite::~CSprite(){ if(m_pSpriteTexture != NULL) m_pSpriteTexture->Release(); if(m_pD3DXSprite != NULL) m_pD3DXSprite->Release(); } /* * resets all member vars to ther defaults */ void CSprite::zeroSpriteValues(){ m_nWidth = 0; m_nHeight = 0; m_nID = 0; m_nState = 0; m_fPosition_x = 0; m_fPosition_y = 0; m_fVelocity_x = 0; m_fVelocity_y = 0; m_bVisible = true; m_bCollide = true; m_bAutoAnimate = true; m_bActive = true; m_bScripting = false; m_bModifyCollision = false; m_bSingleFrame = false; m_bDestroy = false; m_nFrameRateModifier = 0; m_nFrameSkipCount = 0; m_nFrameWidth = 0; m_nFrameHeight = 0; m_nFramesAcross = 1; m_nFrameOffset_x = 0; m_nFrameOffset_y = 0; m_nWidthScaling = 0; m_nHeightScaling = 0; m_nCurrentAnimation = 0; m_nCurrentFrame = 0; m_nCurrentScript = 0; m_nCollisionTop = 0; m_nCollisionBottom = 0; m_nCollisionLeft = 0; m_nCollisionRight = 0; for( int i = 0; i < MAX_ANIM_PER; i++ ) m_nAnimations[i] = NULL; for(int i = 0; i < MAX_SIZE; i++ ) { m_chType[i] = NULL; m_chName[i] = NULL; m_chSpriteTextureName[i] = NULL; } } /* * releases all memory allocated for the sprite's anim arrays */ void CSprite::releaseMemory(){ for(int i = 0; i < MAX_ANIM_PER; i++){ //dealloc mem for each anim sequence if(m_nAnimations[i] != NULL){ delete [] m_nAnimations[i]; m_nAnimations[i] = NULL; } } } /* * creates an array of frame numbers for creation of animation effects */ void CSprite::loadAnimation(int nAnimNumber, int nStartFrame, int nEndFrame, AnimEndOption nOption, int nNextAnimation){ // This function loads the frame numbers that make up an animation // sequence into an array by calculating the frame number values // that exist between the nStartFrame and nEndFrame values passed in. // After it determines how big the array will need to be, it then // creates the array dynamically on the heap. The pointer to the new // array is then stored in the Animations[] array where it can be // accessed later by specifying the proper index value. The frame // numbers are then pulled from the number range between nStartFrame // and nEndFrame and loaded into the new array. bool bOverFlow = false; int nFrameNumber = 0; int nTotalFrames = 0; int i = 0; if(nAnimNumber >=0 && nAnimNumber < MAX_ANIM_PER && m_nAnimations[nAnimNumber] == NULL){ if(nStartFrame < nEndFrame) nTotalFrames = (nEndFrame - nStartFrame); if(nStartFrame > nEndFrame) nTotalFrames = (nStartFrame - nEndFrame); //make room for the ctrl codes to be added later nTotalFrames += 3; m_nAnimations[nAnimNumber] = new int[nTotalFrames]; m_nFrameCount[nAnimNumber] = nTotalFrames; nFrameNumber = nStartFrame; if(nAnimNumber >= 0 && nAnimNumber < MAX_ANIM_PER){ while(nFrameNumber != (nEndFrame +1)){ if(i <= (nTotalFrames - 1)) m_nAnimations[nAnimNumber][i] = nFrameNumber; else bOverFlow = true; if(nStartFrame < nEndFrame) ++nFrameNumber; else if(nStartFrame > nEndFrame) --nFrameNumber; ++i; } //add control code stored in nOptions //this is so the sprite object will now how to reaches //the last frame in the animation sequence if(nOption == LOOP_ANIMATION) m_nAnimations[nAnimNumber][i] = LOOP_ANIMATION; if(nOption == MAINTAIN_LAST_FRAME) m_nAnimations[nAnimNumber][i] = MAINTAIN_LAST_FRAME; if(nOption == GOTO_NEXT_ANIMATION){ m_nAnimations[nAnimNumber][i] = GOTO_NEXT_ANIMATION; m_nAnimations[nAnimNumber][i+1] = nNextAnimation; } if(nOption == GO_INACTIVE) m_nAnimations[nAnimNumber][i] = GO_INACTIVE; } } } /* * increments the cur anim to the next frame (allows for manual animation) */ void CSprite::incFrame(bool bUseModifier){ DWORD dwNextNumber; int nTempHolder = 0; if(bUseModifier == false){ nTempHolder = m_nFrameRateModifier; m_nFrameRateModifier = 0; } if(m_nFrameRateModifier > 0){ //frame rate has been speed up->skip ahead # of frames given by nFrameRateModifier for(int i = 0; i < m_nFrameRateModifier; ++i){ //check if cur frame # is ctrl code dwNextNumber = m_nAnimations[m_nCurrentAnimation][m_nCurrentFrame + 1]; if(dwNextNumber == LOOP_ANIMATION) m_nCurrentFrame = -1; if(dwNextNumber == GOTO_NEXT_ANIMATION) return; if(dwNextNumber == MAINTAIN_LAST_FRAME) return; if(dwNextNumber == GO_INACTIVE) return; ++m_nCurrentFrame; } }else if(m_nFrameRateModifier < 0){ //frame rate has been slowed->keep skipping until move to next frame --m_nFrameSkipCount; if(m_nFrameRateModifier == m_nFrameSkipCount){ //check if cur frame # is ctrl code dwNextNumber = m_nAnimations[m_nCurrentAnimation][m_nCurrentFrame + 1]; if(dwNextNumber == LOOP_ANIMATION) m_nCurrentFrame = -1; if(dwNextNumber == GOTO_NEXT_ANIMATION) return; if(dwNextNumber == MAINTAIN_LAST_FRAME) return; if(dwNextNumber == GO_INACTIVE) return; ++m_nCurrentFrame; m_nFrameSkipCount = 0; } }else if(m_nFrameRateModifier == 0){ //check if cur frame # is ctrl code dwNextNumber = m_nAnimations[m_nCurrentAnimation][m_nCurrentFrame + 1]; if(dwNextNumber == LOOP_ANIMATION) m_nCurrentFrame = -1; if(dwNextNumber == GOTO_NEXT_ANIMATION) return; if(dwNextNumber == MAINTAIN_LAST_FRAME) return; if(dwNextNumber == GO_INACTIVE) return; ++m_nCurrentFrame; } if(bUseModifier == false) m_nFrameRateModifier = nTempHolder; } /* * decrements cur animation to frame before current frame num */ void CSprite::decFrame(bool bUseModifier){ DWORD dwNextNumber; int nTempHolder = 0; if(bUseModifier == false){ nTempHolder = m_nFrameRateModifier; m_nFrameRateModifier = 0; } if(m_nFrameRateModifier > 0){ //frame rate increases->skip ahead num frames given for( int i = 0; i < m_nFrameRateModifier; ++i ){ if( m_nCurrentFrame <= 0 ){ for( int i = 0; i < m_nFrameCount[m_nCurrentAnimation]; i++ ){ dwNextNumber = m_nAnimations[m_nCurrentAnimation][i]; if( dwNextNumber == LOOP_ANIMATION ) m_nCurrentFrame = i - 1; if( dwNextNumber == GOTO_NEXT_ANIMATION ) return; if( dwNextNumber == MAINTAIN_LAST_FRAME ) return; if( dwNextNumber == GO_INACTIVE ) return; } }else{ --m_nCurrentFrame; } } }else if( m_nFrameRateModifier < 0 ){ // The frame rate for animations has been slowed! // Keep skipping cycles until we can move on to // the next frame --m_nFrameSkipCount; if( m_nFrameRateModifier == m_nFrameSkipCount ){ if( m_nCurrentFrame <= 0 ){ for( int i = 0; i < m_nFrameCount[m_nCurrentAnimation]; i++ ){ dwNextNumber = m_nAnimations[m_nCurrentAnimation][i]; if( dwNextNumber == LOOP_ANIMATION ) m_nCurrentFrame = i - 1; if( dwNextNumber == GOTO_NEXT_ANIMATION ) return; if( dwNextNumber == MAINTAIN_LAST_FRAME ) return; if( dwNextNumber == GO_INACTIVE ) return; } }else{ --m_nCurrentFrame; } m_nFrameSkipCount = 0; } }else if( m_nFrameRateModifier == 0 ){ if( m_nCurrentFrame <= 0 ){ for( int i = 0; i < m_nFrameCount[m_nCurrentAnimation]; i++ ){ dwNextNumber = m_nAnimations[m_nCurrentAnimation][i]; if( dwNextNumber == LOOP_ANIMATION ) m_nCurrentFrame = i - 1; if( dwNextNumber == GOTO_NEXT_ANIMATION ) return; if( dwNextNumber == MAINTAIN_LAST_FRAME ) return; if( dwNextNumber == GO_INACTIVE ) return; } }else{ --m_nCurrentFrame; } } if( bUseModifier == false ) m_nFrameRateModifier = nTempHolder; } /* * Use sprite's properties to select bitmap, then copies onto give display */ HRESULT CSprite::drawSprite(LPDIRECT3DDEVICE9 pDevice){ if(m_pD3DXSprite == NULL){ D3DXIMAGE_INFO d3dxImageInfo; D3DXCreateTextureFromFileEx(pDevice, (LPCWSTR)m_chSpriteTextureName, m_nWidth, m_nHeight, 1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_COLORVALUE(0.0f, 0.0f, 0.0f, 1.0f), &d3dxImageInfo, NULL, &m_pSpriteTexture); D3DXCreateSprite( pDevice, &m_pD3DXSprite); } HRESULT hr = 0; if(m_bActive == true){ RECT rcSource; DWORD dwFrameNumber; DWORD dwNextNumber; if(m_bSingleFrame == false){ dwFrameNumber = m_nAnimations[m_nCurrentAnimation][m_nCurrentFrame]; }else{ dwFrameNumber = 0; m_nFramesAcross = 1; } //create RECT that represents section of bitmap where the next frame of animation will be copied from during call to Draw() rcSource.top = ((dwFrameNumber / m_nFramesAcross) * m_nFrameHeight); rcSource.left = ((dwFrameNumber % m_nFramesAcross) * m_nFrameWidth); rcSource.bottom = rcSource.top + m_nFrameHeight; rcSource.right = rcSource.left + m_nFrameWidth; //apply offset, if there is one if(m_nFrameOffset_x != 0 || m_nFrameOffset_y != 0){ rcSource.top += m_nFrameOffset_y; rcSource.left += m_nFrameOffset_x; rcSource.bottom += m_nFrameOffset_y; rcSource.right += m_nFrameOffset_x; } D3DXVECTOR3 vCenter(0.0f, 0.0f, 0.0f); D3DXVECTOR3 vPosition(m_fPosition_x, m_fPosition_y, 0.0f); m_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND); { m_pD3DXSprite->Draw(m_pSpriteTexture, &rcSource, &vCenter, &vPosition, D3DCOLOR_COLORVALUE(1.0f, 1.0f, 1.0f, 1.0f)); } m_pD3DXSprite->End(); if(m_bAutoAnimate == true && m_bSingleFrame == false){ //check if next frame # is ctrl code dwNextNumber = m_nAnimations[m_nCurrentAnimation][m_nCurrentFrame+1]; if(dwNextNumber == LOOP_ANIMATION) m_nCurrentFrame = -1; if(dwNextNumber == GOTO_NEXT_ANIMATION){ m_nCurrentAnimation = m_nAnimations[m_nCurrentAnimation][m_nCurrentFrame+2]; m_nCurrentFrame = -1; } if(dwNextNumber == GO_INACTIVE){ m_bActive = false; m_nCurrentFrame = -1; } if(dwNextNumber == MAINTAIN_LAST_FRAME) return hr; if(m_nFrameRateModifier == 0){ ++m_nCurrentFrame; }else{ if( m_nFrameRateModifier < 0 ) { // The frame rate for animations has been slowed! // Keep skipping cycles until we can move on to // the next frame --m_nFrameSkipCount; if( m_nFrameRateModifier == m_nFrameSkipCount ) { ++m_nCurrentFrame; m_nFrameSkipCount = 0; } } else { // The frame rate for animations has been speeded up! // Skip ahead the number of frames given // by nFrameRateModifier for( int i = 0; i < m_nFrameRateModifier; ++i ) { incFrame(false); } } } } } return hr; }
Sprite.h
/*** * Sprite class declaration for gathering * */ #include <d3d9.h> #include <d3dx9.h> #ifndef CSPRITE_H_INCLUDED const int MAX_ANIM_PER = 5; //max number of animation states per sprite const int MAX_SIZE = 25; //declare the class class CSprite{ public: enum AnimEndOption{ LOOP_ANIMATION = 200, GOTO_NEXT_ANIMATION, MAINTAIN_LAST_FRAME, GO_INACTIVE, DESTROY_SPRITE }; //func defitions CSprite(); ~CSprite(); void zeroSpriteValues(); void releaseMemory(); void incFrame(bool bUseModifier = true); void decFrame(bool bUseModifier = true); void loadAnimation(int nAnimNumber, int nStartFrame, int nEndFrame, AnimEndOption nOption, int nNextAnimation = NULL); void loadAnimationString(int nAnimNumber, char* chString, AnimEndOption nOption, int nNextAnimation = NULL); HRESULT drawSprite(LPDIRECT3DDEVICE9 pDevice); //global vars LPDIRECT3DTEXTURE9 m_pSpriteTexture; LPD3DXSPRITE m_pD3DXSprite; int m_nWidth; int m_nHeight; int m_nID; int m_nState; char m_chType[MAX_SIZE]; char m_chName[MAX_SIZE]; char m_chSpriteTextureName[MAX_SIZE]; float m_fPosition_x; float m_fPosition_y; float m_fVelocity_x; float m_fVelocity_y; bool m_bVisible; bool m_bCollide; bool m_bAutoAnimate; bool m_bActive; bool m_bScripting; bool m_bModifyCollision; bool m_bSingleFrame; bool m_bDestroy; int m_nFrameRateModifier; int m_nFrameWidth; int m_nFrameHeight; int m_nFramesAcross; int m_nFrameOffset_x; int m_nFrameOffset_y; int m_nWidthScaling; int m_nHeightScaling; int m_nCurrentAnimation; int m_nCurrentFrame; int m_nCurrentScript; int m_nCollisionTop; int m_nCollisionBottom; int m_nCollisionLeft; int m_nCollisionRight; private: int *m_nAnimations[MAX_ANIM_PER]; int m_nFrameCount[MAX_ANIM_PER]; int m_nFrameSkipCount; }; #define CSPRITE_H_INCLUDED #endif /* CSPRITE_H_INCLUDED */
resource.h
//#define statements, used throughout Main.cpp #define IDI_MAIN_ICON 101 #define IDI_MAIN 101 #define IDR_MENU 102 #define IDR_MAIN_ACCEL 103 #define IDB_DIRECTX 107 #define IDM_ABOUT 1000 #define IDM_EXIT 1001 #define IDM_TOGGLEFULLSCREEN 1002 //constants const int SCREEN_WIDTH = 800; const int SCREEN_HEIGHT = 600; const int SCREEN_BPP = 16; const int TOTAL_STARS = 100; const int TOTAL_PARTICLES = 250; const int SHIP_SPEED = 5;
Thanks in advance
