游戏编程入门之Bomb Catcher游戏
首先是代码:
MyDirectX.h:
1 #pragma once 2 //header file 3 #define WIN32_EXTRA_LEAN 4 #define DIRECTINPUT_VERSION 0x0800 5 #include<Windows.h> 6 #include<d3d9.h> 7 #include<d3dx9.h> 8 #include<dinput.h> 9 #include<xinput.h> 10 #include<time.h> 11 #include<iostream> 12 #include<iomanip> 13 #include<sstream> 14 using namespace std; 15 //libraries 16 #pragma comment(lib,"winmm.lib") 17 #pragma comment(lib,"user32.lib") 18 #pragma comment(lib,"gdi32.lib") 19 #pragma comment(lib,"dxguid.lib") 20 #pragma comment(lib,"d3d9.lib") 21 #pragma comment(lib,"d3dx9.lib") 22 #pragma comment(lib,"dinput8.lib") 23 #pragma comment(lib,"xinput.lib") 24 //program values 25 extern const string APPTITLE; 26 extern const int SCREENW; 27 extern const int SCREENH; 28 extern bool gameover; 29 //Direct3D objects 30 extern LPDIRECT3D9 d3d; 31 extern LPDIRECT3DDEVICE9 d3ddev; 32 extern LPDIRECT3DSURFACE9 backbuffer; 33 //Direct3D functions 34 bool Direct3D_Init(HWND hwnd, int width, int height, bool fullscreen); 35 void Direct3D_Shutdown(); 36 LPDIRECT3DSURFACE9 LoadSurface(string filename); 37 void DrawSurface(LPDIRECT3DSURFACE9 dest, float x, float y, LPDIRECT3DSURFACE9 source); 38 //DirectInput objects,devices,and states 39 extern LPDIRECTINPUT8 dinput; 40 extern LPDIRECTINPUTDEVICE8 dimouse; 41 extern LPDIRECTINPUTDEVICE8 dikeyboard; 42 extern DIMOUSESTATE mouse_state; 43 extern XINPUT_GAMEPAD controllers[4]; 44 //DirectInput functions 45 bool DirectInput_Init(HWND); 46 void DirectInput_Update(); 47 void DirectInput_Shutdown(); 48 int Key_Down(int); 49 int Mouse_Button(int); 50 int Mouse_X(); 51 int Mouse_Y(); 52 void XInput_Vibrate(int contNum = 0, int amount = 65535); 53 bool XInput_Controller_Found(); 54 //game functions 55 bool Game_Init(HWND window); 56 void Game_Run(HWND window); 57 void Game_End();
MyDirectX.cpp:
1 #include "MyDirectX.h" 2 #include<iostream> 3 using namespace std; 4 //Direct3D variables 5 LPDIRECT3D9 d3d = NULL; 6 LPDIRECT3DDEVICE9 d3ddev = NULL; 7 LPDIRECT3DSURFACE9 backbuffer = NULL; 8 //DirectInput variables 9 LPDIRECTINPUT8 dinput = NULL; 10 LPDIRECTINPUTDEVICE8 dimouse = NULL; 11 LPDIRECTINPUTDEVICE8 dikeyboard = NULL; 12 DIMOUSESTATE mouse_state; 13 char keys[256]; 14 XINPUT_GAMEPAD controllers[4]; 15 //Direct3D initiallization 16 bool Direct3D_Init(HWND window, int width, int height, bool fullscreen) 17 { 18 //initialize Direct3D 19 d3d = Direct3DCreate9(D3D_SDK_VERSION); 20 if (!d3d) return false; 21 //set Direct3D presentation parameters 22 D3DPRESENT_PARAMETERS d3dpp; 23 ZeroMemory(&d3dpp, sizeof(d3dpp)); 24 d3dpp.Windowed = (!fullscreen); 25 d3dpp.SwapEffect = D3DSWAPEFFECT_COPY; 26 d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; 27 d3dpp.BackBufferCount = 1; 28 d3dpp.BackBufferWidth = width; 29 d3dpp.BackBufferHeight = height; 30 d3dpp.hDeviceWindow = window; 31 //create Direct3D device 32 d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev); 33 if (!d3ddev) return false; 34 //get a pointer to the back buffer surface 35 d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); 36 return true; 37 } 38 //Direct3D shutdown 39 void Direct3D_Shutdown() 40 { 41 if (d3ddev) d3ddev->Release(); 42 if (d3d) d3d->Release(); 43 } 44 //Draw a surface to the screen using StretchRect 45 void DrawSurface(LPDIRECT3DSURFACE9 dest, float x, float y, LPDIRECT3DSURFACE9 source) 46 { 47 //get width/height from source surface 48 D3DSURFACE_DESC desc; 49 source->GetDesc(&desc); 50 //create rects for drawing 51 RECT source_rect = { 0,0,(long)desc.Width,(long)desc.Height }; 52 RECT dest_rect = { (long)x,(long)y,(long)x + desc.Width,(long)y + desc.Height }; 53 //draw the source surface onto the dest 54 d3ddev->StretchRect(source, &source_rect, dest, &dest_rect, D3DTEXF_NONE); 55 } 56 //Loads a bitmap file into a surface 57 LPDIRECT3DSURFACE9 LoadSurface(string filename) 58 { 59 LPDIRECT3DSURFACE9 image = NULL; 60 //get width and height from bitmap file 61 D3DXIMAGE_INFO info; 62 HRESULT result = D3DXGetImageInfoFromFile(filename.c_str(), &info); 63 if (result != D3D_OK) return NULL; 64 //create surface 65 result = d3ddev->CreateOffscreenPlainSurface( 66 info.Width, //width of the surface 67 info.Height, //height of the surface 68 D3DFMT_X8R8G8B8, //surface format 69 D3DPOOL_DEFAULT, //memorypool to use 70 & image, //pointer to the surface 71 NULL); //reserved(always NULL) 72 if (result != D3D_OK) return NULL; 73 //Load surface from file into newly created surface 74 result = D3DXLoadSurfaceFromFile( 75 image, //destination surface 76 NULL, //destination palette 77 NULL, //destination rectangle 78 filename.c_str(), //source filename 79 NULL, //source rectangle 80 D3DX_DEFAULT, //controls how image is filtered 81 D3DCOLOR_XRGB(0, 0, 0), //for transparency(0 for none) 82 NULL); //source image info(usually NULL) 83 //make sure file was loaded okay 84 if (result != D3D_OK) return NULL; 85 return image; 86 } 87 //DIrectInput initlization 88 bool DirectInput_Init(HWND hwnd) 89 { 90 //initialize DirectInput object 91 HRESULT result = DirectInput8Create( 92 GetModuleHandle(NULL), 93 DIRECTINPUT_VERSION, 94 IID_IDirectInput8, 95 (void**)&dinput, 96 NULL); 97 //initialize the keyboard 98 dinput->CreateDevice(GUID_SysKeyboard, &dikeyboard, NULL); 99 dikeyboard->SetDataFormat(&c_dfDIKeyboard); 100 dikeyboard->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); 101 dikeyboard->Acquire(); 102 //initialize the mouse 103 dinput->CreateDevice(GUID_SysMouse, &dimouse, NULL); 104 dimouse->SetDataFormat(&c_dfDIMouse); 105 dimouse->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); 106 dimouse->Acquire(); 107 d3ddev->ShowCursor(false); 108 return true; 109 } 110 //DirectInput update 111 void DirectInput_Update() 112 { 113 //update mouse 114 dimouse->GetDeviceState(sizeof(mouse_state), (LPVOID)&mouse_state); 115 //update keyboard 116 dikeyboard->GetDeviceState(sizeof(keys), (LPVOID)&keys); 117 //update controllers 118 for (int i = 0; i < 4; i++) 119 { 120 ZeroMemory(&controllers[i], sizeof(XINPUT_STATE)); 121 //get the state of the controller 122 XINPUT_STATE state; 123 DWORD result = XInputGetState(i, &state); 124 //store state in global controllers array 125 if (result == 0) controllers[i] = state.Gamepad; 126 } 127 } 128 //Return mouse x movement 129 int Mouse_X() 130 { 131 return mouse_state.lX; 132 } 133 //Return mouse y movement 134 int Mouse_Y() 135 { 136 return mouse_state.lY; 137 } 138 //Return mouse button state 139 int Mouse_Button(int button) 140 { 141 return mouse_state.rgbButtons[button] & 0x80; 142 } 143 //Return key press state 144 int Key_Down(int key) 145 { 146 return (keys[key] & 0x80); 147 } 148 //DirectInput shutdown 149 void DirectInput_Shutdown() 150 { 151 if (dikeyboard) 152 { 153 dikeyboard->Unacquire(); 154 dikeyboard->Release(); 155 dikeyboard = NULL; 156 } 157 if (dimouse) 158 { 159 dimouse->Unacquire(); 160 dimouse->Release(); 161 dimouse = NULL; 162 } 163 } 164 //Return true if controller is plugged in 165 bool XInput_Controller_Found() 166 { 167 XINPUT_CAPABILITIES caps; 168 ZeroMemory(&caps, sizeof(XINPUT_CAPABILITIES)); 169 XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps); 170 if (caps.Type != 0) return FALSE; 171 172 return TRUE; 173 } 174 //Vibrates the controller 175 void XInput_Vibrate(int contNum, int amount) 176 { 177 XINPUT_VIBRATION vibration; 178 ZeroMemory(&vibration, sizeof(XINPUT_VIBRATION)); 179 vibration.wLeftMotorSpeed = amount; 180 vibration.wRightMotorSpeed = amount; 181 XInputSetState(contNum, &vibration); 182 }
MyGame.cpp:
1 #include "MyDirectX.h" 2 const string APPTITLE = "Bomb Catcher Game"; 3 const int SCREENW = 1024; 4 const int SCREENH = 768; 5 LPDIRECT3DSURFACE9 bomb_surf = NULL; 6 LPDIRECT3DSURFACE9 bucket_surf = NULL; 7 struct BOMB 8 { 9 float x, y; 10 void reset() 11 { 12 x = (float)(rand() % (SCREENW - 128)); 13 y = 0; 14 } 15 }; 16 BOMB bomb; 17 18 struct BUCKET 19 { 20 float x, y; 21 }; 22 BUCKET bucket; 23 int score = 0; 24 int vibrating = 0; 25 bool Game_Init(HWND window) 26 { 27 Direct3D_Init(window, SCREENW, SCREENH, false); 28 DirectInput_Init(window); 29 bomb_surf = LoadSurface("images/bomb.bmp"); 30 if (!bomb_surf) { 31 MessageBox(window, "Error loadng bomb", "Error", 0); 32 return false; 33 } 34 bucket_surf = LoadSurface("images/bucket.bmp"); 35 if (!bucket_surf) { 36 MessageBox(window, "Error loadng bucket", "Error", 0); 37 return false; 38 } 39 //get the back buffer surface 40 d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); 41 //position the bomb 42 srand((unsigned int)time(NULL)); 43 bomb.reset(); 44 //psition the bucket 45 bucket.x = 500; 46 bucket.y = 630; 47 return true; 48 } 49 void Game_Run(HWND window) 50 { 51 //make sure the Direct3D device is valid 52 if (!d3ddev)return; 53 //update input device 54 DirectInput_Update(); 55 //move the bomb down the screen 56 bomb.y += 2.0f; 57 //see if bomb hit the floor 58 if (bomb.y > SCREENH) 59 { 60 MessageBox(0, "Oh,no, the bomb exploded!!", "YOU STINK", 0); 61 gameover = true; 62 } 63 //move the bucket with the mouse 64 int mx = Mouse_X(); 65 if (mx < 0) 66 bucket.x -= 6.0f; 67 else if (mx > 0) 68 bucket.x += 6.0f; 69 //move the bucket with the keyboard 70 if (Key_Down(DIK_LEFT)) bucket.x -= 6.0f; 71 else if (Key_Down(DIK_RIGHT)) bucket.x += 6.0f; 72 //move the bucket with the controller 73 if (XInput_Controller_Found()) 74 { 75 //left analog thumb stick 76 if (controllers[0].sThumbLX < -5000) 77 bucket.x -= 6.0f; 78 else if (controllers[0].sThumbLX > 5000) 79 bucket.x += 6.0f; 80 //left and right triggers 81 if (controllers[0].bLeftTrigger > 128) 82 bucket.x -= 6.0f; 83 else if (controllers[0].bRightTrigger > 128) 84 bucket.x += 6.0f; 85 //left and right D-PAD 86 if (controllers[0].wButtons&XINPUT_GAMEPAD_LEFT_SHOULDER) 87 bucket.x -= 6.0f; 88 else if (controllers[0].wButtons&XINPUT_GAMEPAD_RIGHT_SHOULDER) 89 bucket.x += 6.0f; 90 //left and right shoulders 91 if(controllers[0].wButtons&XINPUT_GAMEPAD_DPAD_LEFT) 92 bucket.x -= 6.0f; 93 if (controllers[0].wButtons&XINPUT_GAMEPAD_DPAD_RIGHT) 94 bucket.x += 6.0f; 95 } 96 //update vibration 97 if (vibrating > 0) 98 { 99 vibrating++; 100 if (vibrating > 20) 101 { 102 XInput_Vibrate(0, 0); 103 vibrating = 0; 104 } 105 } 106 //keep bucket inside the screen 107 if (bucket.x < 0) bucket.x = 0; 108 if (bucket.x > SCREENW - 128) bucket.x = SCREENW - 128; 109 //see if bucket caugth the bomb 110 int cx = bomb.x + 64; 111 int cy = bomb.y + 64; 112 if (cx > bucket.x&&cx<bucket.x + 128 && cy>bucket.y&&cy < bucket.y + 128) 113 { 114 //update and display score 115 score++; 116 std::ostringstream os; 117 os << APPTITLE << " [SCORE " << score << "]"; 118 string scoreStr = os.str(); 119 SetWindowText(window, scoreStr.c_str()); 120 //vibrate the controller 121 XInput_Vibrate(0, 65000); 122 vibrating = 1; 123 //restart bomb 124 bomb.reset(); 125 } 126 //clear the backbuffer 127 d3ddev->ColorFill(backbuffer, NULL, D3DCOLOR_XRGB(0, 0, 0)); 128 //start rendering 129 if (d3ddev->BeginScene()) 130 { 131 //draw the bomb 132 DrawSurface(backbuffer, bomb.x, bomb.y, bomb_surf); 133 //draw the bucket 134 DrawSurface(backbuffer, bucket.x, bucket.y, bucket_surf); 135 //stop rendering 136 d3ddev->EndScene(); 137 d3ddev->Present(NULL, NULL, NULL, NULL); 138 } 139 //escape key exits 140 if (Key_Down(DIK_SPACE) || Key_Down(DIK_ESCAPE)) 141 gameover = true; 142 //controller Back button also exits 143 if (controllers[0].wButtons&XINPUT_GAMEPAD_BACK) 144 gameover = true; 145 } 146 void Game_End() 147 { 148 if (bomb_surf) bomb_surf->Release(); 149 if (bucket_surf) bucket_surf->Release(); 150 DirectInput_Shutdown(); 151 Direct3D_Shutdown(); 152 }
MyWindows.cpp:
1 #include "MyDirectX.h" 2 using namespace std; 3 bool gameover = false; 4 //Windows event handler 5 LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 6 { 7 switch (msg) 8 { 9 case WM_DESTROY: 10 gameover = true; 11 break; 12 } 13 return DefWindowProc(hWnd, msg, wParam, lParam); 14 } 15 //Windows entry point 16 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 17 { 18 WNDCLASSEX wc; 19 MSG msg; 20 wc.cbSize = sizeof(WNDCLASSEX); 21 wc.lpfnWndProc = (WNDPROC)WinProc; 22 wc.style = 0; 23 wc.cbClsExtra = 0; 24 wc.cbWndExtra = 0; 25 wc.hIcon = NULL; 26 wc.hIconSm = NULL; 27 wc.hInstance = hInstance; 28 wc.lpszMenuName = NULL; 29 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 30 wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 31 wc.lpszClassName = "MainWindowClass"; 32 if (!RegisterClassEx(&wc)) 33 return FALSE; 34 HWND window = CreateWindow("MainWindowClass", APPTITLE.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, SCREENW, SCREENH, (HWND)NULL, (HMENU)NULL, 35 hInstance, (LPVOID)NULL); 36 if (window == 0) 37 return 0; 38 ShowWindow(window, nCmdShow); 39 UpdateWindow(window); 40 if (!Game_Init(window)) 41 return 0; 42 while (!gameover) 43 { 44 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 45 { 46 TranslateMessage(&msg); 47 DispatchMessage(&msg); 48 } 49 Game_Run(window); 50 } 51 Game_End(); 52 return msg.wParam; 53 }
结果: