Search…

Khởi Tạo Cửa Sổ với DirectX 9

27/09/20206 min read
Hướng dẫn khởi tạo cửa sổ làm việc với DirectX 9.

Khởi tạo cửa sổ với DirectX 9

Cách để khởi tạo một cửa sổ cũng như các kiến thức liên quan để khởi đầu cho việc lập trình game với DirectX 9.

Nhắc lại kiến thức

Game được hiện thực như 1 đối tượng trong chương trình, đối tượng đó trải qua 3 giai đoạn chính gồm: khởi Tạo (init), chạy (run) và thoát (exit).

Tạo class Game 

#ifndef __GAME_H__
#define __GAME_H__

#include <d3d9.h>

#define WIDTH 800
#define HEIGHT 600

class Game
{
private:
	int			m_Width;
	int			m_Height;
	bool			m_IsWindow;
	
	HINSTANCE		m_HandleInstance;
	HWND			m_HandleWindow;
	LPDIRECT3D9		m_lpDirect3D;
	LPDIRECT3DDEVICE9 	m_lpDirect3DDevice;
	
	static LRESULT CALLBACK WndProceduce(HWND hWnd,	UINT message, WPARAM wParam, LPARAM lParam);
public:
	Game(int scr_Width, int scr_Height, bool isWindow);
	
	bool initHandleWindow();
	bool initDirectX3DEnviroment();
	bool initDirect3DDevice();

	void GameInit();
	void GameRun();
	void GameExit();
};
#endif

Giải thích các thuộc tính

  • m_Width, m_Height: các thuộc tính quy định chiều dài và rộng của cửa sổ Game.
  • m_IsWindow: quy định cửa sổ sẽ hiển thị window hoặc full màn hình.
  • m_HandleInstance: HINSTANCE là 1 thuộc tính đại diện cho ứng dụng / game khi được hệ điều hành chạy.
  • m_HandleWindow: mỗi ứng dụng / game sẽ có thể chứa nhiều cửa sổ, mỗi cửa sổ cần có 1 định danh riêng, định danh đó chính là HWND.
  • m_lpDirect3D: LPDIRECT3D9 là một Direct3D Object, biến này cần thiết cho việc khởi tạo Device để thao tác vẽ trong Game.
  • m_lpDirect3DDevice: LPDIRECT3DDEVICE9 dùng để lưu thông tin của Device sử dụng thao tác vẽ trong chương trình.
  • WndProceduce(...): hàm callback dùng để lắng nghe các sự kiện của cửa sổ Game khi người dùng tương tác.
  • Game(...): hàm tạo của GameObject.
  • initHandleWindow(...): khởi tạo các thuộc tính cần thiết cho cửa sổ.
  • initDirectX3DEnviroment(...): khởi tạo môi trường lập trìn DirectX.
  • initDirect3DDevice(...): Khởi tạo thiết bị DirectX.
  • GameInit(...): đặt tất cả các hàm khởi tạo cần thiết trước lúc chương trình chạy.
  • GameRun(...): update Game.
  • GameExit(...): giải phóng các tài nguyên cần được giải phóng trước lúc chương trình thoát.

Hiện thực các phương thức

Hàm tạo

Khởi tạo các giá trị ban đầu cho ứng dụng.

Game::Game(int scr_Width, int scr_Height, bool isWindow) {
	this->m_Width = scr_Width;
	this->m_Height = scr_Height;
	this->m_IsWindow = isWindow;
	this->m_HandleInstance = 0;
	this->m_HandleWindow = 0;
	this->m_lpDirect3D = 0;
	this->m_lpDirect3DDevice = 0;
}

initHandleWindow

Ở class này, khởi tạo các thuộc tính cần thiết cho cửa sổ, giúp cửa sổ hiển thị và đăng ký các sự kiện khi người dùng thao tác với cửa sổ.

bool Game::initHandleWindow()
{
	WNDCLASSEX WndcEx;
	ZeroMemory(&WndcEx, sizeof(WndcEx));
	WndcEx.cbSize = sizeof(WNDCLASSEX);
	WndcEx.hInstance = this->m_HandleInstance;
	WndcEx.lpfnWndProc = (WNDPROC) WndProceduce;
	WndcEx.lpszClassName = "Game";
	if (!RegisterClassEx(&WndcEx))
	{
		return false;
	}
	this->m_HandleWindow = CreateWindow(
		"Game", // đặt trung với WndcEx.lpszClassName
		TITLE, // TITLE của cửa sổ #define TITLE "GAME"
		WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, // style của cửa sổ
		100, // tọa độ x khi cửa sổ xuất hiện
		100, // tọa độ y khi cửa sổ xuất hiện
		this->m_Width, // chiều dài cửa sổ
		this->m_Height, // chiều cao cửa sổ
		0, // handle window parent của của sổ hiện tại. Để là 0
		0, // handle đến Menu. Để là 0
		this->m_HandleInstance, // Handle Instance của ứng dụng
		0); // giữ nguyên theo default là 0
	if (!this->m_HandleWindow) // Kiểm tra tạo thành công.
	{
		return false;
	}
	ShowWindow(m_HandleWindow, SW_SHOW); // show cửa sổ lên màn hình
	UpdateWindow(m_HandleWindow); // Update cửa sổ theo thời gian
	return true;
}

initDirectX3Denviroment

Hàm này tác dụng khởi tạo đối tượng Direct3D, cần đối tượng này để làm việc với DirectX ở các bài viết sau.

bool Game::initDirectX3DEnviroment()
{
	this->m_lpDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
	if (m_lpDirect3D){
		return true;
	}
	return false;
}

initDirect3DDevice

Cần dùng D3DPRESENT_PARAMETERS để thao tác tạo Direct3D Device, dùng vẽ các Game Object lên màn hình sau này.

bool Game::initDirect3DDevice()
{
	D3DPRESENT_PARAMETERS d3dpp; // khai báo biến
	ZeroMemory(&d3dpp, sizeof(d3dpp)); // Khởi tạo vùng nhớ
	d3dpp.BackBufferCount = 1; // Số lượng Back buffer
	d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // Chọn UNKNOW, DirectX sẽ tự chọn 1 định dạng phù hợp cho Device
	d3dpp.BackBufferHeight = HEIGHT; // chiều cao cảu BackBuffer
	d3dpp.BackBufferWidth = WIDTH; // Chiều dài của BackBuffer
	d3dpp.Windowed = true; // Window ở dạng cửa sổ, không phải full màn hình
	d3dpp.hDeviceWindow = this->m_HandleWindow; // Gán HandleWindow cho Device
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // Phương thức swap của Buffer
	m_lpDirect3D->CreateDevice(
		D3DADAPTER_DEFAULT, // Chọn DEFAULT ADAPTER
		D3DDEVTYPE_HAL, // 
		m_HandleWindow, // Handle Window của của sổ
		D3DCREATE_HARDWARE_VERTEXPROCESSING, // Hard ware vertex processing
		&d3dpp,
		&m_lpDirect3DDevice); // Hàm tạo Device
	if(FAILED(m_lpDirect3DDevice))
	{
		return false;
	}
	return true;
}

GameInit

Hàm này lần lượt gọi các khởi tạo đã xây dựng từ trước.

void Game::GameInit()
{
	initHandleWindow();
	initDirectX3DEnviroment();
	initDirect3DDevice();
}

GameRun

Hàm này thực hiện toàn bộ update của Game, sử dụng vòng lặp while để duy trì cửa sổ luôn hoạt động trong quá trình chạy Game.

void Game::GameRun()
{
	MSG msg;
	ZeroMemory(&msg, sizeof(msg)); // Tạo một Mesage để lắng nghe các sự kiện của cửa sổ
	while (true)
	{
		if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) // Lấy message và truyền vào biến msg đã khai báo
		{
			if (msg.message == WM_QUIT) // Kiểm tra nếu msg yêu cầu QUIT ứng dụng thì ứng dụng sẽ thoát
				break;
			TranslateMessage(&msg); // xử lý input và chuyển vào msg
			DispatchMessage(&msg); // gửi message đến hàm WndProceduce để xử lý
		}
		else
		{
			// Begin Draw something in Game
			m_lpDirect3DDevice->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(100, 100, 100), 1.0f, 0); // Clear cửa sổ 1 lần trước khi vẽ lên
			if (m_lpDirect3DDevice->BeginScene())
			{

				// Game Render Here
				m_lpDirect3DDevice->EndScene();
			}
			m_lpDirect3DDevice->Present(0, 0, 0, 0); // Thể hiện tất cả những gì đã vẽ lên màn hình
		}
	}
}

GameExit

Hàm có chức năng giải phóng vùng nhớ không cần dùng đến lúc thoát Game.

void Game::GameExit()
{
	if (this->m_lpDirect3D) {
		this->m_lpDirect3D->Release();
		this->m_lpDirect3D = NULL;
	}
	if (this->m_lpDirect3DDevice) {
		this->m_lpDirect3DDevice->Release();
		this->m_lpDirect3DDevice = NULL;
	}
}

WndProceduce

Hàm nhận các sự kiện của cửa sổ và xử lý ở đây, ví dụ khi nhận sự kiện WM_DESTROY thì cửa sổ sẽ đóng xuống.

LRESULT CALLBACK Game::WndProceduce(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hWnd, message, wParam, lParam);
}

Hàm WinMain

Chương trình của bắt đầu chạy tại đây.

#include<d3d9.h>
#include "Game.h"

int WINAPI WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstace,
	LPSTR lpStrCmdLine,
	int nShowCmd)
{
	Game mygame(WIDTH, HEIGHT, false);
	mygame.GameInit();
	mygame.GameRun();
	mygame.GameExit();
	return 0;
}

Bài chung series

IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024