-
12-07-2014, 07:15 PM #1Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Hướng dẫn viết một game đơn giản trong DirectX từ A - Z
Chào mọi người. Hôm nay mình viết bài viết này nhằm củng cố kiến thức đã học và mong muốn của mình là đem kiến thức đến với tất cả mọi người. Đặc biệt là giúp newbie tiếp cận với lĩnh vực làm game. Ngoài ra mình muốn trình bày thật chi tiết, ngắn gọn, đơn giản nhất về bộ thư viện rất là nhức đầu này. Hihi nói nhiều quá rồi. Thôi vào vấn đề chính luôn :v
I. Cấu Hình Visual Studio:
- Cái này là cái cơ bản nhất mà tất cả mọi người phải làm khi lập trình game bằng DirectX.
1. Tạo mới một project và chọn ngôn ngữ Visual C++. Đừng quên chọn Empty project nhé [IMG]images/smilies/biggrin.png[/IMG]
2. Cấu hình lại project:
- Các bạn vào Project -> Properties -> Configuration Properties -> VC++ Directories.
Ở đây chúng ta chỉ quan tâm tới Include Directories và Library Directories.
Chúng ta lần lượt tìm đường dẫn tới thư viện directx được cài trong máy cho mục này. Lưu ý ở thu mục lib chúng ta chọn x86.
(Mình sẽ cập nhật ảnh sau)
II. Sơ lược về lập trình C4W(C for Windows):
- Thật dễ dàng để tìm một cuốn giáo trình về lập trình C trên Windows. Mình sẽ không nhắc lại nhiều về vấn đề này nữa. Hôm nay mình sẽ trình bày nó dưới dạng hướng đối tượng. Đây là cái cơ bản nhất. [IMG]images/smilies/biggrin.png[/IMG] Thực ra copy và paste cũng được. Làm game nên chúng ta không cần đặt nặng điều này. Các bạn chỉ cần nắm được cái cấu trúc này là được rồi.
Mã:class Game{private: //hinstance của chương trình HINSTANCE hInstance; //hwnd của cửa sổ HWND hWnd; //Kích thước cửa sổ int Width; int Height; //Tên cửa sổ char windowName[256]; //Thủ tục xử lý cửa sổ static HRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam); public: //Hàm này dùng để thiết đặt các giá trị cho cửa sổ bool InitWindow(); //Hàm này dùng cho việc load data cho game void InitData(); //Hàm này dùng để update game của chúng ta sau một khoảng gameTime void Update(float gameTime); //dùng để vẽ các đối tượng của game lên màn hình void Render(); // Constructor Game(HINSTANCE hIns,int W,int H,char* name); ~Game(void);}; Game::Game(HINSTANCE hIns,int W,int H,char* name){ this->hInstance = hIns; this->Width = W; this->Height = H; this->hWnd = NULL; strcpy(this->windowName,name);} Game::~Game(void){}//Hàm xử lý cửa sổ. Chúng ta chỉ cần quan tâm tới cái WM_DESTROYLRESULT CALLBACK Game::WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam){ if(message == WM_DESTROY) { PostQuitMessage(0); } return DefWindowProc(hWnd,message,wParam,lParam);}// Tạo cửa sổ game. Cài đặt các đối tượng direct x ở đâybool Game::InitWindow(){ WNDCLASSEX wndclass; wndclass.cbSize = sizeof(WNDCLASSEX); wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hIconSm = 0; wndclass.hIcon = 0; wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); wndclass.hInstance = this->hInstance; wndclass.lpfnWndProc = (WNDPROC)WndProc; wndclass.lpszClassName = "Game"; wndclass.lpszMenuName = NULL; wndclass.style = CS_HREDRAW | CS_VREDRAW; if(!RegisterClassEx(&wndclass)) { return false; } this->hWnd = CreateWindow( "Game", this->windowName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, this->Width, this->Height, NULL, NULL, this->hInstance, NULL); if(!this->hWnd) return false; ShowWindow(this->hWnd,SW_NORMAL); UpdateWindow(this->hWnd); return true;}//Init game datavoid Game::InitData(){ //load dữ liệu ở đây}// Cập nhật gamevoid Game::Update(float gameTime){}// Vẽ các đối tượng trong gamevoid Game::Render(){ }
Mã:#include <Windows.h>#include "Game.h" int WINAPI WinMain(HINSTANCE h, HINSTANCE p, LPTSTR a, int c){ MSG msg; Game game(h,480,600,"Game Dau Tien"); if(!game.Init()) { MessageBox(NULL,"Can't init game","Error",MB_OK); return 0; } // Các biến này dùng để tính toán game time LARGE_INTEGER currentTime; LARGE_INTEGER frequence; float cntPerSecond = 0; float gameTime = 0; LARGE_INTEGER preTime ; float delay = 0; ZeroMemory(&msg,sizeof(msg)); QueryPerformanceFrequency(&frequence); cntPerSecond = 100.0f / (float)frequence.QuadPart; QueryPerformanceCounter(&preTime); while(msg.message != WM_QUIT) { if(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { //phần tính toán game time mình sẽ trình bày sau QueryPerformanceCounter(¤tTime); delay+= gameTime; if(delay > gameTime * 3) { game.Update(delay); game.Render(); delay = 0; } QueryPerformanceCounter(&preTime); gameTime = ((float)preTime.QuadPart - (float)currentTime.QuadPart) * cntPerSecond ; } } return 0;}
- Làm quen với bộ thư viện này không cần đòi hỏi bạn là siêu nhân hay thông minh gì cả. Chỉ cần chịu khó và kiên trì một chút là được. Hồi năm nhất mình vừa nhìn code là vứt nó luôn vì mấy cái kiểu dữ liệu @#$#$%%^$%^ rất khó nhớ. Sau đây mình xin trinh bày một vài tiếp ngữ của các kiểu dữ liệu này(Không hiểu sao khi mình nắm được các cụm từ viết tắt tự dưng thấy nó dễ nhớ hơn rất nhiều):
Mã:D3D: Nghĩa là Direct 3D. Nếu có theo sau số 9 thì mình hiểu nó là Version 9 LPDIRECT3D: Tương tự với cái trên. LP ở đây là Long pointer. Mình cũng chẳng biết nó là gì. Thôi chụi khó hỏi GS gg vậy ^^ D3DX: Tương tự như cái D3D. Chữ X ở đây muốn nói rằng nó thuộc thư viện <d3dx9.h>(d3d là của thư viện <d3d9.h>)
Mã:// Các kiểu dữ liệu hay dùngLPDIRECT3D9 //Đối tượng direct x. Để tạo một game bằng directX thì đầu tiên các bạn phải tạo cục này. Rồi từ cục này tạo ra các cục như cục để vẽ, cục để load //hình ảnh, cục xử lý chuột, bàn phím, cục network...LPDIRECT3DDEVICE9 // Đây là một đối tượng thể hiện cho các thiết bị. Nó cũng là một cục trong số các cục ở trênD3DPRESENT_PARAMETERS // Chứa các thông số về thiết bị sắp được tạoLPD3DXSPRITE //Cục này dùng để vẽ các texture. Nói nôm na là hình ảnhLPDIRECT3DTEXTURE9 // Đây là đối tượng dùng để lưu hình ảnh được load lên. D3DXIMAGE_INFO // Đây là đối tượng dùng để lưu thông tin hình ảnh như dài, rộng ...LPDIRECT3DSURFACE9 // Tương tự như texture. Nhưng nó không có dc hỗ trợ như xoay, zoon....LPDIRECTINPUT8 // Đối tượng bàn phím.LPDIRECTINPUTDEVICE8 // Thiết bị bàn phím//các hằng số thường dùngD3D_OK // Xử lý thành công yêu cầuD3D_SDK_VERSION // Một tham số mặc định khi khởi tạo đối tượng directx// Mình sẽ cập nhật thêm// Các hàm thường dùng:Direct3DCreate9 // Hàm này nhận một đối số mặc định là D3D_SDK_VERSION. Hàm này dùng để tạo đối tượng DirectXZeroMemory // Có chức năng giống tên gọi của nóDirectInput8Create // Tạo đối tượng nhập dữ liệuD3DXCreateSprite // Tạo một đối tượng spriteD3DXGetImageInfoFromFile // Lấy thông tin hình ảnhD3DXCreateTextureFromFileEx // Tạo texture từ một file ảnhD3DXLoadSurfaceFromFile // Tạo một surface từ file ảnhQueryPerformanceFrequency // Trả về số lượng count trong một secondQueryPerformanceCounter // Lấy thời gian tại thời điểm hiện tại
- Nói một cái framework thì thấy nó ghê ghê. Thực ra cái này chỉ nhằm mục đích bao đống lại cái mớ cồng kềnh của thư viện directx bằng các class. Ở đây mình sẽ trình bày một cách thiết kế đơn giản nhất để có thể làm một game.
- Các thành phần:
+ Class MGraphic: Class này dùng để tạo bề mặt đồ họa. Chứa các hàm vẽ các texture, surface.... Đặt chữ M đầu tiên ý cho nó ngầu ngầu [IMG]images/smilies/biggrin.png[/IMG] (M mean Manager)
+ Class MContent: Class này dùng để load texture, surface
+ Class Mkeyboard : Quản lý bàn phím
+ Class MMouse: Quản lý con chuột
+ Class MSound: Lo phần quản lý cái loa :v
Khi cần dùng phần nào ta chỉ việc lấy class quản lý công việc đó ra dùng. Không cần phải viết thêm một đóng lằng nhằng nữa cho nó cực khổ [IMG]images/smilies/biggrin.png[/IMG]
Class MGraphic:
- Graphic là đối tượng không thể thiếu trong game. Mình xin nói sơ qua về phần graphic trong directX như sau:
+ Thứ nhất là về thiết bị vẽ: Có 3 loại thiết bị mà directX cung cấp như sau
D3DDEVTYPE_HAL : Sử dụng phần cứng (card màn hình)
D3DDEVICETYPE_REF: Sử dụng bộ mô phỏng
D3DDEVICETYPE_SW: Sử dụng phần mềm. Các thao tác xử lý hoàn toàn bằng cpu
Khi khởi tạo thiết bị thì chúng ta khởi tạo theo thứ tự. Cái nào được thì dùng cái đó [IMG]images/smilies/biggrin.png[/IMG] Nếu tất cả không được thì bảo người dùng nâng cấp máy ^_^
+ Thứ hai là về buffer:
Trong các ứng dụng đồ họa thì đây là một khái niệm quen thuộc. Mỗi màn hình có một bộ nhớ là front buffer. do tốc độ màn hình chậm hơn so với tốc độ cpu nhiều lần nên khi đồ họa sẽ gây ra hiện tượng giật. Back buffer để khắc phục nhược điểm này. Các thao tac vẽ đều diễn ra trên back buffer. sau đó chuyển dữ liệu vẽ từ back buffer sang front buffer. Thao tác chuyển này được thực hiện bằng phần cứng nên tốc độ rất nhanh nến không gấy ra nháng hình [IMG]images/smilies/biggrin.png[/IMG]
Mã:#pragma once#include <d3d9.h>#include <d3dx9.h>class MGraphic{private : //doi tuong direct x LPDIRECT3D9 d3d; //thiet bi ve LPDIRECT3DDEVICE9 d3ddev; //Ve texture LPD3DXSPRITE d3dxSprite; //hwnd cua cua so ve HWND hWnd; //Kich thuoc cua bộ đệm int Width; int Height;public: //Cài đặt thiết bị vẽ bool InitD3D(); //Constructor MGraphic(HWND,int,int); //Destructor ~MGraphic(void); //Bắt đầu vẽ void Begin(); //Kết thúc vẽ void End(); //Vẽ các hình cơ bản void DrawTexture(LPDIRECT3DTEXTURE9 texture,D3DXVECTOR2 postion,D3DCOLOR color); void DrawTexture(LPDIRECT3DTEXTURE9 texture,RECT source,D3DXVECTOR2 postion,D3DCOLOR color); void DrawTexture(LPDIRECT3DTEXTURE9 texture,D3DXVECTOR2 postion,D3DCOLOR color,float angle); //Vẽ các sufface void DrawSurface(); //Lấy thiết bị vẽ LPDIRECT3DDEVICE9 GetDevice(); }; MGraphic::MGraphic(HWND hwnd,int W,int H){ this->hWnd = hwnd; this->Width = W; this->Height = H; this->d3d = NULL; this->d3ddev = NULL; this->d3dxSprite = NULL; } bool MGraphic::InitD3D(){ //tao mot doi tuong Direct3D this->d3d = Direct3DCreate9(D3D_SDK_VERSION); if(!this->d3d) return false; //tao thiet bi ve D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp,sizeof(d3dpp)); d3dpp.BackBufferCount = 1;// Có một back buffer d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;//Tự tạo format phù hợp d3dpp.BackBufferWidth = this->Width;//Chiều rộng back buffer d3dpp.BackBufferHeight = this->Height;//Chiều cao back buffer d3dpp.hDeviceWindow = this->hWnd;// Handle của cửa sổ mình sẽ vẽ lên d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;// Một tham số hay dùng d3dpp.Windowed = true;// Chế độ có cửa sổ HRESULT hr = this->d3d->CreateDevice(D3DADAPTER_DEFAULT,//chon thiet bi ve mac dinh D3DDEVTYPE_HAL,//su dung ho tro cua phan cung. Có rất nhiều sự lựa chọn. Tham khảo MSDN để biết thêm this->hWnd,// Cửa sổ vẽ D3DCREATE_SOFTWARE_VERTEXPROCESSING,//MSDN không nói rõ. :D &d3dpp,//Các thông số cho back buffer &this->d3ddev//Con trỏ nhận dữ liẹu sau khi tạo devicce ); // Ở đây vì ngắn gọn nên mình chỉ tạo device cho thiết bị có hỗ trợ phần cứng. if(FAILED(hr)) { return false; } Tạo bút vẽ các texture hr = D3DXCreateSprite(this->d3ddev,&this->d3dxSprite); if(FAILED(hr)) return false; return true;} MGraphic::~MGraphic(void){} void MGraphic::Begin(){ // xóa cửa sổ vẽ bằng màu trắng D3DCOLOR_XRGB(255,255,255) this->d3ddev->Clear(1,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(255,255,255),1,NULL); // Bắt đầu vẽ this->d3ddev->BeginScene(); this->d3dxSprite->Begin(D3DXSPRITE_ALPHABLEND);}void MGraphic::End(){ // Kết thúc vẽ this->d3dxSprite->End(); this->d3ddev->EndScene(); // Thể hiện các đối tượng từ back buffer ra ngoài màn hình this->d3ddev->Present(NULL,NULL,NULL,NULL);}void MGraphic::DrawTexture(LPDIRECT3DTEXTURE9 texture,D3DXVECTOR2 postion,D3DCOLOR color){ this->d3dxSprite->Draw( texture,//hình cần vẽ NULL,//khung cắt từ ảnh. Xem thêm các bài viết trên cviet về sprite. Chọn NULL là lấy hết cả texture NULL,//Tâm của texture. Chọn NULL là tọa đọ 0,0 &D3DXVECTOR3(postion.x,postion.y,0),//Tọa đọ của texture trên màn hình đồ họa color//màu của texture );} void MGraphic::DrawTexture(LPDIRECT3DTEXTURE9 texture,RECT source,D3DXVECTOR2 postion,D3DCOLOR color){ // Tương tự this->d3dxSprite->Draw(texture,&source,NULL,&D3DXVECTOR3(postion.x,postion.y,0),color);} void MGraphic::DrawSurface(){ } LPDIRECT3DDEVICE9 MGraphic::GetDevice(){ return this->d3ddev;} void MGraphic::DrawTexture(LPDIRECT3DTEXTURE9 texture,D3DXVECTOR2 postion,D3DCOLOR color,float angle){ // Vừa vẽ vừa xoay, Xem thêm trên msdn. Mình chưa fix bug đoạn code này :D D3DXMATRIX m1,m2,m3; this->d3dxSprite->GetTransform(&m1); D3DXMatrixTransformation2D(&m2,NULL,NULL,NULL,NULL,1,&postion); m3 = m1 * m2; this->d3dxSprite->SetTransform(&m3); this->d3dxSprite->Draw(texture,NULL,NULL,&D3DXVECTOR3(postion.x,postion.y,0),D3DCOLOR_XRGB(255,255,255)); this->d3dxSprite->SetTransform(&m1);}
<font size="3">- Cơ bản cần nắm suface và texture:
+ Hai thằng này cơ bản là một.
+ Texture được tạo ra từ surface.
+ Texture có thể Zoom, Rotate còn surface thi không.
+ Texture được dùng nhiều hơn surface
+ Thao tác trên surface nhanh hơn so với trên texture
Mã:#include <d3dx9.h>#include <string>using namespace std;class MContent{ //thiết bị vẽ này phải được lấy từ lớp graphic LPDIRECT3DDEVICE9 d3ddv;public: // load một texture LPDIRECT3DTEXTURE9 LoadTexture(string path); //load một sufface LPDIRECT3DSURFACE9 LoadSurface(string path); MContent(LPDIRECT3DDEVICE9); ~MContent(void);}; MContent::MContent(LPDIRECT3DDEVICE9 device){ this->d3ddv = device;} LPDIRECT3DTEXTURE9 MContent::LoadTexture(string path){ LPDIRECT3DTEXTURE9 texture = NULL; D3DXIMAGE_INFO info; HRESULT hr; ZeroMemory(&info,sizeof(info)); //lấy thông tin về hình ảnh hr = D3DXGetImageInfoFromFile(path.c_str(),&info); if(hr != D3D_OK) return NULL; //tạo texture hr = D3DXCreateTextureFromFileEx(this->d3ddv, path.c_str(), info.Width, info.Height, 1, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN,// tự động chọn format phù hợp D3DPOOL_DEFAULT, //Chọn bộ nhớ để lưu tự động D3DX_DEFAULT,//Chọn tham số mặc định D3DX_DEFAULT,//Chọn tham số mặc định D3DCOLOR_XRGB(255,255,255), &info,//thông tin hình ảnh NULL, &texture); if(hr != D3D_OK) return 0; return texture;} LPDIRECT3DSURFACE9 MContent::LoadSurface(string path){ LPDIRECT3DSURFACE9 surface = NULL; D3DXIMAGE_INFO info; HRESULT hr; ZeroMemory(&info,sizeof(info)); hr = D3DXGetImageInfoFromFile(path.c_str(),&info); if(hr != D3D_OK) return NULL; hr = this->d3ddv->CreateOffscreenPlainSurface( info.Width, info.Height, D3DFMT_UNKNOWN,//Chọn format tự động D3DPOOL_DEFAULT,//Chọn vùng nhớ tự động &surface,//Con trỏ lưu surface được tạo ra NULL); if(hr != D3D_OK) return 0; //load hình lên surface đã tạo ra hr = D3DXLoadSurfaceFromFile(surface,NULL,NULL,path.c_str(),NULL,D3DX_DEFAULT,D3DCOLOR_XRGB(255,255,255),&info); if(hr != D3D_OK) return 0; return surface;} MContent::~MContent(void){ }
Trong directX bàn phím con chuột hay một thiết bị nhập nào khác đều không được phân biệt rõ ràng. Mình tạo nó là con chuột thì nó sẽ là chuột. Tạo nó là bàn phím thì nó sẽ là phím. Hoặc ngay cả lúc bạn có một thiết bị nhập xuất cho riêng bạn thì nó cũng hiểu được.
Cũng như ban đầu. Để tạo ra một thiết bị gọi là bàn phím dùng trong game thì bạn phải tạo một đối tượng nhập xuất.
Mã:#pragma once#include <dinput.h>class MKeyboard{ //Đối tượng nhập xuất LPDIRECTINPUT8 di8; // thiết bị nhập xuất LPDIRECTINPUTDEVICE8 did8; //buffer lưu dữ liệu lấy được từ thiết bị. // ở đây là bàn phím nên minh dùng mảng char để lưu char key_buffer[256]; // thể hiện của chương trình HINSTANCE hInstance; //handle của cữa sổ vẽ HWND hWnd; public: //cài đặt thiết bị(bàn phím) bool Init(); //Constructor MKeyboard(HINSTANCE hIns,HWND hwnd); //Lấy trạng thái của bàn phím void GetState(); //Nhận diện phím được nhấn bool IsKeyDown(int Key); ~MKeyboard(void); MKeyboard::MKeyboard(HINSTANCE hIns,HWND hwnd){ this->di8 = 0; this->did8 = 0; this->hInstance = hIns; this->hWnd = hwnd; ZeroMemory(&this->key_buffer,sizeof(key_buffer)); } bool MKeyboard::Init(){ HRESULT hr= DirectInput8Create( this->hInstance,//hinstance của chương trình DIRECTINPUT_VERSION,//Tham số mặc định IID_IDirectInput8,//tham số này cũng là defaul (void**)&this->di8,//con trỏ nhận dữ liệu trả về NULL);//tham số dùng thêm if(FAILED(hr)) return false; //tạo bàn phím. GUID_SysKeyboard là chỉ bàn phím. Nếu bạn có một thiết bị cho riêng mình thì bạn phải định nghĩa nó trước hr = this->di8->CreateDevice(GUID_SysKeyboard,&this->did8,NULL); if(FAILED(hr)) return false; //dạng dữ liệu sẽ được nhận hr = this->did8->SetDataFormat(&c_dfDIKeyboard); if(FAILED(hr)) return false; //loại hoạt động. DISCL_FOREGROUND nghĩa là chỉ hoạt động khi của sổ hWnd đang được handle hr = this->did8->SetCooperativeLevel(this->hWnd,DISCL_FOREGROUND| DISCL_NONEXCLUSIVE); if(FAILED(hr)) return false; //Yêu cầu thiết bị hr = this->did8->Acquire(); if(FAILED(hr)) return false; return true;}void MKeyboard::GetState(){ //lấy trạng thái của bàn phím HRESULT hr = this->did8->GetDeviceState(sizeof(this->key_buffer),(LPVOID)&this->key_buffer); if(FAILED(hr)) { /ếu bàn phím đang bị nhả ra thì yêu cầu lại while (this->did8->Acquire() == DIERR_INPUTLOST); }} bool MKeyboard::IsKeyDown(int Key){ //trả về phím có được nhấn hay không. 0x80 nhằm xác định giá trị các bit đàu tiên return key_buffer[Key] & 0x80; } MKeyboard::~MKeyboard(void){} };
Cập nhật sau [IMG]images/smilies/biggrin.png[/IMG]
PS: Cho khuất cái này. Đợi rãnh làm tiếp
Mã:
- Game là một ứng dụng theo thời gian thực. Vì vậy thời gian trong game là rất quan trọng. Thời gian trong game được tính như sau.
Mã:start = GetTime();UpdateGame(gameTime);RenderGame();end = GetTime();gameTime = (end - start) * số xung trong 1 giây; //Hiểu nôm na là vậy
Mã:#include <Windows.h>#include "Game.h"#include "RSManager.h"RSManager* RSManager::instance = NULL;int WINAPI WinMain(HINSTANCE h, HINSTANCE p, LPTSTR a, int c){ MSG msg; Game game(h,1000,600,"Tank"); if(!game.Init()) { MessageBox(NULL,"Can't init game","Error",MB_OK); return 0; } MSG msg; ZeroMemory(&msg,sizeof(MSG)); LARGE_INTEGER clock_cycles_count; QueryPerformanceFrequency(&clock_cycles_count); LARGE_INTEGER start; LARGE_INTEGER end; float cycles_count_per_second = 1000.0f / clock_cycles_count.QuadPart; float gameTime = 0; float frame_rate = 1000.0f / 60.0f; QueryPerformanceCounter(&start); while(msg.message != WM_QUIT) { if(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { QueryPerformanceCounter(&end); gameTime = (end.QuadPart - start.QuadPart) * cycles_count_per_second; if(gameTime >= frame_rate) { start = end; this->Update(gameTime); this->Render(); } } } return 0;}
1. Xây dựng class Ball</font>
Mục đích: Tạo quả bóng biết di chuyển. Mình dùng vợt hứng :v
Mã:#pragma once#include <d3dx9.h>#include "MContent.h"#include "MGraphic.h"class Ball{private: LPDIRECT3DTEXTURE9 img; public: D3DXVECTOR2 position; float speed; int dx, dy; RECT rect; Ball(void); ~Ball(void); //Load data void Init(MContent* content); void Update(float gameTime); void Render(MGraphic* graphic);}; #include "Ball.h" Ball::Ball(void){} void Ball::Init(MContent* content){ this->img = content->LoadTexture("./ball.png"); this->position = D3DXVECTOR2(0,0); dx = dy = 1;}void Ball::Update(float gameTime){ float speed = 5; if(position.x < 0 || position.x + 40.0 > 300) dx = -dx; if(position.y < 0 || position.y + 40.0 > 600) dy = -dy; position.x += dx * speed; position.y += dy * speed; rect.left = position.x; rect.top = position.y; rect.right = 40; rect.bottom = 40;}void Ball::Render(MGraphic* graphic){ graphic->DrawTexture(this->img,this->position,D3DCOLOR_XRGB(255,255,255));} Ball::~Ball(void){}
-Mục đích: Hiển thị cái vợt để đỡ quả bóng [IMG]images/smilies/biggrin.png[/IMG]
Mã:#pragma once#include <d3dx9.h>#include "MContent.h"#include "MGraphic.h"#include "MKeyboard.h"class Bat{ LPDIRECT3DTEXTURE9 img;public: Bat(void); D3DXVECTOR2 position; float speed; RECT rect; ~Bat(void); void Init(MContent* content); void Update(float gameTime,MKeyboard* key); void Render(MGraphic* graphic);}; #include "Bat.h" Bat::Bat(void){} Bat::~Bat(void){} void Bat::Init(MContent* content){ this->img = content->LoadTexture("./bat.png"); this->position = D3DXVECTOR2(200,600 - 30); speed = 3;}void Bat::Update(float gameTime,MKeyboard* key){ if(key->IsKeyDown(DIK_LEFT)) { if(position.x > 0.0f) this->position.x -=speed; } if(key->IsKeyDown(DIK_RIGHT)) { if(position.x + 90.0f < 300.0f ) this->position.x +=speed; } rect.left = position.x; rect.right = rect.left + 90; rect.top = position.y; rect.bottom = 30;}void Bat::Render(MGraphic* graphic){ graphic->DrawTexture(img,position,D3DCOLOR_XRGB(255,255,255));}
Up tạm cái này. Mai sẽ đính kèm vào bài viết sau. Code ẩu nên còn bug một tí [IMG]images/smilies/biggrin.png[/IMG]
Mã:http://www.mediafire.com/download/y4i7ic3ctbgdy8y/PingPong.rar
View more random threads:
- Lập Trình Mạng Với Thư Viện Winsock trên VC++
- Dịch Vụ Cài Phần Mềm AutoCad Nhanh Chóng Quận 2 Tận Nơi
- Hướng Dẫn Viết COM Server bằng VS 2008
- Tiệm Sửa PC Bàn Uy Tín Q. 10 Tại Nhà
- Visual C++ code to play a .WAV file
- Hướng dẫn cách đọc FileName dạng Unicode (16-bit)
- Tạo Thread và đa xử lý trong 1 chương trình
- Một số kĩ thuật cơ bản với Irrlicht
- Một số hàm về Message
- TLS Callback in VC++
-
01-08-2014, 11:07 AM #2Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Tao cũng đang làm lại 1 frw. [IMG]images/smilies/2.gif[/IMG] Cảm ơn bài viết của thím Luận
-
04-08-2014, 09:58 AM #3Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Chào anh! Nếu sau mỗi phần hướng dẫn có một chương trình demo thì quá hay ^^
Em ủng hộ pic này.
-
05-08-2014, 12:31 PM #4Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Sao không tiếp tục đề tài này vậy luanft, anh em ủng hộ bạn.
-
06-08-2014, 02:43 PM #5Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Sorry mọi người. Mấy hôm nay đang đi mhx nên không viết được [IMG]images/smilies/biggrin.png[/IMG]
-
06-08-2014, 03:06 PM #6Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Cho cái demo đi bạn.Thanks [IMG]images/smilies/smile.png[/IMG]
-
27-08-2014, 06:11 PM #7Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Good job. Hi vọng bạn sẽ chia sẻ thêm nhiều kinh nghiệm cho mọi người.
-
23-09-2014, 02:38 PM #8Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Mới xem bài của bạn, bài hay lắm.
-
24-05-2015, 08:07 AM #9Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
topic này hữu ích mà chết yểu thế, tiếc thật
Pallet nhựa Long An đã trở thành một trong những lựa chọn phổ biến cho nhu cầu vận chuyển và lưu trữ hàng hóa trong nhiều ngành công nghiệp. Với đặc tính nhẹ nhàng, chắc chắn và dễ vận chuyển, các...
Thanh lý pallet nhựa Long An giá rẻ