Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Kết quả 1 đến 9 của 9
  1. #1

    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(){ }
    Trong hàm WinMain ta thiết kế như sau:

    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(&currentTime);                              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;}
    II. Sơ lược về bộ thư việc directx:
    - 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ột số kiểu dữ liệu hay/luôn dùng:


    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
    III. Xây dựng một framework:
    - 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);}
    Class MContent:

    <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){    }
    Class MKeyboard:</font>

    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){} };
    Class MSound:

    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ã:
     
    <font size="4">Tính thời gian trong game:

    - 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
    Code mẫu:

    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;}
    <font color="#0000FF">IV. Bắt tay vào làm game:

    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){}
    <font color="#FF0000">2. Xây dựng class Bat:

    -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));}
    IV. Demo:
    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
    </font></font>

  2. #2
    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

  3. #3
    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.

  4. #4
    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.

  5. #5
    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]

  6. #6
    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]

  7. #7
    Good job. Hi vọng bạn sẽ chia sẻ thêm nhiều kinh nghiệm cho mọi người.

  8. #8
    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.

  9. #9
    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

 

 

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •