Direct3D学习笔记(一)——精灵(Bomo_catcher游戏)

一、Visual Studio 2015设置

1、Bomo_Catcher属性-常规-字符集-使用多字节字符集

2、Bomo_Catcher属性- VC++目录-包含目录 C:\Program Files (x86)\Microsoft DirectX SDK (February 2010)\Include

3、Bomo_Catcher属性- VC++目录-库目录     C:\Program Files (x86)\Microsoft DirectX SDK (February 2010)\Lib\x86


二、MydirectX.h

#pragma once  

//header files  
#define WIN32_EXTRA_LEAN  
#define DIRECTINPUT_VERSION 0x0800  
#include <windows.h>  
#include <d3d9.h>  
#include <d3dx9.h>  
#include <dinput.h>  
#include <xinput.h>  
#include <ctime>  
#include <iostream>  
#include <iomanip>  
#include <sstream>
using namespace std;

//libraries  
#pragma comment(lib,"winmm.lib")  
#pragma comment(lib,"user32.lib")  
#pragma comment(lib,"gdi32.lib")  
#pragma comment(lib,"dxguid.lib")  
#pragma comment(lib,"d3d9.lib")  
#pragma comment(lib,"d3dx9.lib")  
#pragma comment(lib,"dinput8.lib")  
#pragma comment(lib,"xinput.lib")  

//program values  
extern const string APPTITLE;
extern const int SCREENW;
extern const int SCREENH;
extern bool gameover;

//Direct3D objects  
extern LPDIRECT3D9 d3d;
extern LPDIRECT3DDEVICE9 d3ddev;
extern LPDIRECT3DSURFACE9 backbuffer;
extern LPD3DXSPRITE spriteobj; //纹理
extern LPD3DXFONT font; //文字
extern LPDIRECTINPUT8 dinput;
extern LPDIRECTINPUTDEVICE8 dimouse;
extern LPDIRECTINPUTDEVICE8 dikeyboard;
//extern ID3DXFont* g_pFont = NULL;
extern DIMOUSESTATE mouse_state;
extern XINPUT_GAMEPAD controllers[4];





//Direct3D functions  
bool Direct3D_Init(HWND hwnd, int width, int height, bool fullscreen);
void Direct3D_Shutdown();
LPDIRECT3DSURFACE9 LoadSurface(string filename);
LPD3DXFONT MakeFont(string name, int size); //设置字体
void DrawSurface(LPDIRECT3DSURFACE9 dest, float x, float y, LPDIRECT3DSURFACE9 source);


//DirectInput objects, devices, and states  

//DirectInput functions  
bool DirectInput_Init(HWND);
void DirectInput_Update();
void DirectInput_Shutdown();
int Key_Down(int);
int Mouse_Button(int);
int Mouse_X();
int Mouse_Y();
void XInput_Vibrate(int contNum = 0, int amount = 65535);
bool XInput_Controller_Found();

//game functions  
bool Game_Init(HWND window);
void Game_Run(HWND window);

void MouseUpdate();
void KeyBoardUpdate();
void XInputUpdate();
void Game_End();


D3DXVECTOR2  GetBitmapSize(string filename);
LPDIRECT3DTEXTURE9 LoadTexture(string filename, D3DCOLOR transcolor = D3DCOLOR_XRGB(0, 0, 0));
void FontPrint(LPD3DXFONT font, int x, int y, string text, D3DCOLOR color = D3DCOLOR_XRGB(255, 255, 255));


三、MyDirectX.cpp

#include "MyDirectX.h"  
#include <iostream>  
using namespace std;

//Direct3D variables  
LPDIRECT3D9 d3d = NULL;
LPDIRECT3DDEVICE9 d3ddev = NULL;
LPDIRECT3DSURFACE9 backbuffer = NULL;

//DirectInput variables  
LPDIRECTINPUT8 dinput = NULL;
LPDIRECTINPUTDEVICE8 dimouse = NULL;
LPDIRECTINPUTDEVICE8 dikeyboard = NULL;
DIMOUSESTATE mouse_state;
char keys[256];
XINPUT_GAMEPAD controllers[4];

/**
** Direct3D initialization
**/
bool Direct3D_Init(HWND window, int width, int height, bool fullscreen)
{
	//initialize Direct3D  
	d3d = Direct3DCreate9(D3D_SDK_VERSION);
	if (!d3d) return false;

	//set Direct3D presentation parameters  
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp, sizeof(d3dpp));
	d3dpp.Windowed = (!fullscreen);
	d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
	d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
	d3dpp.BackBufferCount = 1;
	d3dpp.BackBufferWidth = width;
	d3dpp.BackBufferHeight = height;
	d3dpp.hDeviceWindow = window;

	//create Direct3D device  
	d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);

	if (!d3ddev) return false;

	//get a pointer to the back buffer surface  
	d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
	D3DXCreateSprite(d3ddev, &spriteobj);  //纹理
	return true;
}

/**
** Direct3D shutdown
**/
void Direct3D_Shutdown()
{	
	if (spriteobj)spriteobj->Release(); 
	if (d3ddev) d3ddev->Release();
	if (d3d) d3d->Release();
}

/**
** Draws a surface to the screen using StretchRect
**/
void DrawSurface(LPDIRECT3DSURFACE9 dest, float x, float y, LPDIRECT3DSURFACE9 source)
{
	//get width/height from source surface  
	D3DSURFACE_DESC desc;
	source->GetDesc(&desc);

	//create rects for drawing  
	RECT source_rect = { 0, 0, (long)desc.Width, (long)desc.Height };
	RECT dest_rect = { (long)x, (long)y, (long)x + desc.Width, (long)y + desc.Height };

	//draw the source surface onto the dest  
	d3ddev->StretchRect(source, &source_rect, dest, &dest_rect, D3DTEXF_NONE);

}

/**
** Loads a bitmap file into a surface
**/
LPDIRECT3DSURFACE9 LoadSurface(string filename)
{
	LPDIRECT3DSURFACE9 image = NULL;

	//get width and height from bitmap file  
	D3DXIMAGE_INFO info;
	HRESULT result = D3DXGetImageInfoFromFile(filename.c_str(), &info);
	if (result != D3D_OK)
		return NULL;

	//create surface  
	result = d3ddev->CreateOffscreenPlainSurface(
		info.Width,         //width of the surface  
		info.Height,        //height of the surface  
		D3DFMT_X8R8G8B8,    //surface format  
		D3DPOOL_DEFAULT,    //memory pool to use  
		&image,             //pointer to the surface  
		NULL);              //reserved (always NULL)  

	if (result != D3D_OK) return NULL;

	//load surface from file into newly created surface  
	result = D3DXLoadSurfaceFromFile(
		image,                  //destination surface  
		NULL,                   //destination palette  
		NULL,                   //destination rectangle  
		filename.c_str(),       //source filename  
		NULL,                   //source rectangle  
		D3DX_DEFAULT,           //controls how image is filtered  
		D3DCOLOR_XRGB(0, 0, 0),   //for transparency (0 for none)  
		NULL);                  //source image info (usually NULL)  

								//make sure file was loaded okay  

	
	if (result != D3D_OK) return NULL;

	return image;

}


LPDIRECT3DTEXTURE9 LoadTexture(string filename, D3DCOLOR transcolor) {
	LPDIRECT3DTEXTURE9 texture = NULL;
	D3DXIMAGE_INFO info;
	HRESULT result = D3DXGetImageInfoFromFile(filename.c_str(), &info);
	if (result != D3D_OK) return NULL;
	result = D3DXCreateTextureFromFileEx(d3ddev, filename.c_str(), info.Width, info.Height, 1, D3DPOOL_DEFAULT, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, transcolor, &info, NULL, &texture);

	if (result != D3D_OK) return NULL;
	return texture;
}
D3DXVECTOR2 GetBitmapSize(string filename) {
	D3DXIMAGE_INFO info;
	D3DXVECTOR2 size = D3DXVECTOR2(0.0f, 0.0f);
	HRESULT result = D3DXGetImageInfoFromFile(filename.c_str(), &info);
	if (result == D3D_OK) {
		size = D3DXVECTOR2((float)info.Width, (float)info.Height);
	}
	else {
		size = D3DXVECTOR2((float)info.Width, (float)info.Height);
	}
	return size;
}



/**
** DirectInput initialization
**/
bool DirectInput_Init(HWND hwnd){
	//initialize DirectInput object  
	HRESULT result = DirectInput8Create(
		GetModuleHandle(NULL),
		DIRECTINPUT_VERSION,
		IID_IDirectInput8,
		(void**)&dinput,
		NULL);

	//initialize the keyboard  
	dinput->CreateDevice(GUID_SysKeyboard, &dikeyboard, NULL);                     //创建设备
	dikeyboard->SetDataFormat(&c_dfDIKeyboard);                                    //格式
	dikeyboard->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);  //协作级别
	dikeyboard->Acquire();

	//initialize the mouse  
	dinput->CreateDevice(GUID_SysMouse, &dimouse, NULL);
	dimouse->SetDataFormat(&c_dfDIMouse);
	dimouse->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
	dimouse->Acquire();
	d3ddev->ShowCursor(false);

	return true;
}

/**
** DirectInput update
**/
void DirectInput_Update()
{
	//update mouse  
	dimouse->GetDeviceState(sizeof(mouse_state), (LPVOID)&mouse_state);

	//update keyboard  
	dikeyboard->GetDeviceState(sizeof(keys), (LPVOID)&keys);

	//update controllers  
	for (int i = 0; i< 4; i++)
	{
		ZeroMemory(&controllers[i], sizeof(XINPUT_GAMEPAD));

		//get the state of the controller  
		XINPUT_STATE state;
		DWORD result = XInputGetState(i, &state);

		//store state in global controllers array  
		if (result == 0) controllers[i] = state.Gamepad;
	}

}

/**
** Return mouse x movement
**/
int Mouse_X()
{
	return mouse_state.lX;
}

/**
** Return mouse y movement
**/
int Mouse_Y()
{
	return mouse_state.lY;
}

/**
** Return mouse button state
**/
int Mouse_Button(int button)
{
	return mouse_state.rgbButtons[button] & 0x80;
}

/**
** Return key press state
**/
int Key_Down(int key)
{
	return (keys[key] & 0x80);
}

/**
** DirectInput shutdown
**/
void DirectInput_Shutdown()
{
	if (dikeyboard)
	{
		dikeyboard->Unacquire();
		dikeyboard->Release();
		dikeyboard = NULL;
	}
	if (dimouse)
	{
		dimouse->Unacquire();
		dimouse->Release();
		dimouse = NULL;
	}
}

/**
** Returns true if controller is plugged in
**/
bool XInput_Controller_Found()
{
	XINPUT_CAPABILITIES caps;
	ZeroMemory(&caps, sizeof(XINPUT_CAPABILITIES));
	XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps);
	if (caps.Type != 0) return false;

	return true;
}

/**
** Vibrates the controller
**/
void XInput_Vibrate(int contNum, int amount)
{
	XINPUT_VIBRATION vibration;
	ZeroMemory(&vibration, sizeof(XINPUT_VIBRATION));
	vibration.wLeftMotorSpeed = amount;
	vibration.wRightMotorSpeed = amount;
	XInputSetState(contNum, &vibration);
}

void FontPrint(LPD3DXFONT font, int x, int y, string text, D3DCOLOR color)
{
    //figure out the text boundary
    RECT rect = { x, y, 0, 0 };
    font->DrawText(NULL, text.c_str(), text.length(), &rect, DT_CALCRECT, color);
}

LPD3DXFONT MakeFont(string name, int size)
 {
	D3DXFONT_DESC desc;
	ZeroMemory(&desc, sizeof(desc));
	desc.Height = size;
	desc.Width = 0;
	desc.Weight = 0;
	desc.MipLevels = 0;
	desc.Italic = FALSE;
	desc.CharSet = DEFAULT_CHARSET;
	desc.OutputPrecision = OUT_TT_PRECIS;
	desc.Quality = CLIP_DEFAULT_PRECIS;
	desc.PitchAndFamily = DEFAULT_PITCH;
    strcpy_s(desc.FaceName, name.c_str());
    D3DXCreateFontIndirect(d3ddev, &desc, &font);
    return font;
 }


四、MyGame.cpp

#include "MyDirectX.h"  
using namespace std;

const string APPTITLE = "Bomb Catcher Game";
const int SCREENW = 1024;
const int SCREENH = 768;

LPDIRECT3DTEXTURE9 bomb_surf = NULL;
LPDIRECT3DTEXTURE9 bucket_surf = NULL;
LPD3DXFONT font = NULL;
//在MyDirectX.h 文件中定义为extren 在使用的文件当中重新声明  否则会出现发现多个定义的错误
LPD3DXSPRITE spriteobj = NULL; //定义为null 
struct BOMB
{
	
	float x, y;

	void reset()
	{	
		x = (float)(rand() % (SCREENW - 128));
		y = 0;
	}

};

BOMB bomb;


struct BUCKET
{
	float x, y;
};

BUCKET bucket;

int score = 0;
float speek = 1.0f;
int vibrating = 0;

/**
** Game initialization
**/
bool Game_Init(HWND window)
{
	Direct3D_Init(window, SCREENW, SCREENH, false);

	DirectInput_Init(window);  //初始化输入设备

	bomb_surf = LoadTexture("F:/image/bomb.png");

	if (!bomb_surf) {
		MessageBox(window, "Error loading bomb", "Error", 0);
		return false;
	}

	bucket_surf = LoadTexture("F:/image/bucket.png");
	if (!bucket_surf) {
		MessageBox(window, "Error loading bucket", "Error", 0);
		return false;
	}

	font = MakeFont("Arial", 24);
	if (!font) {
		MessageBox(window, "Error Init Font", "Error", 0);
		return false;
	}
	srand((unsigned int)time(NULL));
	bomb.reset();

	bucket.x = 500;
	bucket.y = 630;

	/*
	if (FAILED(D3DXCreateFont(d3ddev, 36, 0, 0, 1, false, DEFAULT_CHARSET,
		OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, 0, "score "+ score, &g_pFont))){
		return E_FAIL;
	}
	*/

	return true;
}

void Game_Run(HWND window)
{
	if (!d3ddev) return;

	//update input devices  
	DirectInput_Update();

	//bomb.y += 1.0f;   由于direct是左手坐标系  x,y,z(0,0,0) 的坐标为左上角
	bomb.y += speek;
	if (bomb.y > SCREENH)
	{
		MessageBox(0, "Oh no, the bomb exploded!!", "YOU STINK", 0);
		gameover = true;
	}
	if (bomb.y == 0) {
		bomb.reset();
	}

	MouseUpdate();      //更新鼠标操作
	KeyBoardUpdate();   //更新键盘操作
	XInputUpdate();     //更新手柄操作
	


	if (bucket.x < 0) bucket.x = 0;
	if (bucket.x > SCREENW - 128) bucket.x = SCREENW - 128;

	int cx = bomb.x + 64;
	int cy = bomb.y + 64;

	//检测碰撞
	if (cx > bucket.x && cx < bucket.x + 128 && cy > bucket.y && cy < bucket.y + 128)
	{
		
		if (score % 5 == 0) {
			speek+=1.0f;
		}

		score++;
		//char s[255];
		//sprintf_s(s, "%s [SCORE %d]", APPTITLE.c_str(), score);
		//SetWindowText(window, s);
		
		XInput_Vibrate(0, 65000);
		vibrating = 1;

		bomb.reset();
	}

	d3ddev->ColorFill(backbuffer, NULL, D3DCOLOR_XRGB(0, 0, 0));

	if (d3ddev->BeginScene())
	{

		ostringstream oss;   //需要在头文件中 #include <sstream>
		oss << "Score = " << score;

		char s[255];
		FontPrint(font, 100, 100, oss.str());
		

		//DrawSurface(backbuffer, bomb.x, bomb.y, bomb_surf);
		
		//DrawSurface(backbuffer, bucket.x, bucket.y, bucket_surf);

		//D3DXSPRITE_ALPHABLEND 支持透明精灵
		spriteobj->Begin(D3DXSPRITE_ALPHABLEND);
		//D3DXVECTOR3 pos1(10, 10, 0);
		D3DXVECTOR3 bombxy((float)bomb.x, (float)bomb.y, 0);  //x  y  z
		
		//(THIS_ LPDIRECT3DTEXTURE9 pTexture, CONST RECT *pSrcRect, CONST D3DXVECTOR3 *pCenter, CONST D3DXVECTOR3 *pPosition, D3DCOLOR Color) PURE;
		//pTexture 精灵  pSrcRect中心点坐标(以该坐标旋转)  pCenter位置坐标  Color颜色
		spriteobj->Draw(bomb_surf, NULL, NULL, &bombxy, D3DCOLOR_XRGB(8, 255, 164));//

		//D3DXVECTOR3 pos2(10, 10, 0);
		D3DXVECTOR3 bucketxy((float)bucket.x, (float)bucket.y, 0);  //x  y  z
		spriteobj->Draw(bucket_surf, NULL, NULL, &bucketxy, D3DCOLOR_XRGB(255, 0, 0));//
		
		
		//spriteobj->Begin(D3DXSPRITE_ALPHABLEND); spriteobj->End(); 一定要在 BeginScene 和 EndScene中间
		spriteobj->End();
		d3ddev->EndScene();
		d3ddev->Present(NULL, NULL, NULL, NULL);
	}

	//escape key exits  
	if (Key_Down(DIK_ESCAPE))
		gameover = true;

	//controller Back button also exits  
	if (controllers[0].wButtons & XINPUT_GAMEPAD_BACK)
		gameover = true;


}

void MouseUpdate() {
	int mx = Mouse_X();
	if (mx < 0) bucket.x -= 6.0f;
	else if (mx > 0) bucket.x += 6.0f;
}
void KeyBoardUpdate() {
	if (Key_Down(DIK_LEFT)|| Key_Down(DIK_A)) bucket.x -= 6.0f;
	else if (Key_Down(DIK_RIGHT)|| Key_Down(DIK_D)) bucket.x += 6.0f;
}
void XInputUpdate() {
	if (XInput_Controller_Found())
	{
		//left analog thumb stick  
		if (controllers[0].sThumbLX < -5000)
			bucket.x -= 6.0f;
		else if (controllers[0].sThumbLX > 5000)
			bucket.x += 6.0f;

		//left and right triggers  
		if (controllers[0].bLeftTrigger > 128)
			bucket.x -= 6.0f;
		else if (controllers[0].bRightTrigger > 128)
			bucket.x += 6.0f;

		//left and right D-PAD  
		if (controllers[0].wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER)
			bucket.x -= 6.0f;
		else if (controllers[0].wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER)
			bucket.x += 6.0f;

		//left and right shoulders  
		if (controllers[0].wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
			bucket.x -= 6.0f;
		else if (controllers[0].wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
			bucket.x += 6.0f;
	}

	//update vibration  
	if (vibrating > 0)
	{
		vibrating++;
		if (vibrating > 20)
		{
			XInput_Vibrate(0, 0);
			vibrating = 0;
		}
	}

}
void Game_End()
{
	if (bomb_surf) bomb_surf->Release();
	if (bucket_surf) bucket_surf->Release();
//	if (bomb_surf1) bomb_surf1->Release();
//	if (bucket_surf1) bucket_surf1->Release();
	DirectInput_Shutdown();
	Direct3D_Shutdown();
}

五、MyWindows.cpp
#include "MyDirectX.h"  
using namespace std;
bool gameover = false;

/**
** Windows event handler
**/
LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_DESTROY:
		gameover = true;
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

/**
** Windows entry point
**/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	//initialize window settings  
	WNDCLASSEX wc;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = (WNDPROC)WinProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = NULL;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = APPTITLE.c_str();
	wc.hIconSm = NULL;
	RegisterClassEx(&wc);

	//create a new window  
	HWND window = CreateWindow(APPTITLE.c_str(), APPTITLE.c_str(),
		WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
		SCREENW, SCREENH, NULL, NULL, hInstance, NULL);
	if (window == 0) return 0;

	//display the window  
	ShowWindow(window, nCmdShow);
	UpdateWindow(window);

	//initialize the game  
	if (!Game_Init(window)) return 0;

	// main message loop  
	MSG message;
	while (!gameover)
	{
		if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&message);
			DispatchMessage(&message);
		}

		//process game loop   
		Game_Run(window);
	}

	//shutdown  
	Game_End();
	return message.wParam;
}


六、效果





评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值