CHƯƠNG III. SPRITE

Link Source code HD không che: https://goo.gl/zK4qhK
Các bạn nên mở sources code vừa đọc vừa so sánh với tut này vì mình sẽ giải thích những gì trong sources code.

1. Sơ lược về Sprite

  • Sprite có thể hiểu là 1 ảnh 2D dùng để vẽ lên màn hình game. Theo định nghĩa của wikipedia: Trong đồ họa máy tính, sprite là một hình ảnh hai chiều hoặc hình ảnh động được tích hợp vào một cảnh lớn hơn. Ban đầu nó chỉ bao gồm đối tượng đồ họa xử lý riêng lẻ với bộ nhớ bitmap của một màn hình video, nhưng hiện nay nó bao gồm nhiều lớp đồ họa với các sắc thái khác nhau.
  • Túm váy lại là class Sprite này sẽ giúp bạn vẽ hình ảnh lên màn hình game.

2. Class Sprite

  • Mình thêm class Sprite vào folder GameComponents. Và tạo thêm folder Resources để chứa các resources (hình ảnh, âm thanh,…) của game. Mình sẽ phân chia các folder ra để cho dễ quản lý.
  • Mình có chỉnh sửa lại chút tí ở main.cpp đó là SCREEN_WIDTH SCREEN_HEIGHT mình sẽ xóa bỏ và thay bằng GameGlobal::GetWidth() và GameGlobal::GetHeight(). Nếu bạn muốn thay đổi size của cửa sổ thì thay đổi trong file cpp của class GameGlobal.


HINSTANCE GameGlobal::mHInstance = NULL;
HWND GameGlobal::mHwnd = NULL;
LPD3DXSPRITE GameGlobal::mSpriteHandler = NULL;
int GameGlobal::mWidth = 600;
int GameGlobal::mHeight = 600;
LPDIRECT3DDEVICE9 GameGlobal::mDevice = nullptr;
bool GameGlobal::isGameRunning = true;
IDirect3DSurface9GameGlobal::backSurface = nullptr;


  • Trong các tài liệu của Clb thì có chỉ chi tiết cách để vẽ 1 texture lên màn hình, thì class Sprite sẽ chứa một texture cũng như thông tin của tấm hình nó cần vẽ lên. Trong class Sprite này mình sẽ thêm một số thuộc tính và hàm để hỗ trợ việc vẽ texture lên. Dưới đây mình sẽ giải thích 1 số thuộc tính quan trọng.
  • LPD3DXSPRITE mSpriteHandler: dùng để lấy device và vẽ sprite lên màn hình.
  • D3DXVECTOR3 mPosition: Đây là tọa độ của hình ảnh khi được vẽ lên, Sprite sẽ lấy tâm của nó làm điểm mốc (Anchor point).
                                  C:\Users\locth\AppData\Local\Microsoft\Windows\INetCacheContent.Word\PositionCenter.png

  • RECT mSourceRect: Đây là vùng chữ nhật sẽ chọn để vẽ Texture lên màn hình.
C:\Users\locth\AppData\Local\Microsoft\Windows\INetCacheContent.Word\SourceRect.png


  • D3DXIMAGE_INFO mImageInfo: thông tin của texture chủ yếu mình sẽ lấy thông tin Width và Hieght của Texture.
typedef struct _D3DXIMAGE_INFO
{
    UINT                    Width;
    UINT                    Height;
    UINT                    Depth;
    UINT                    MipLevels;
    D3DFORMAT               Format;
    D3DRESOURCETYPE         ResourceType;
    D3DXIMAGE_FILEFORMAT    ImageFileFormat;
D3DXIMAGE_INFO;


  • D3DXVECTOR2 mScale: độ phóng đại của hình nó là 1 Vector2 vì sẽ phóng đại theo chiều rộng và theo chiều dài, mặc định là (1, 1). Nếu giá trị âm nó sẽ lật hình ngược lại.


C:\Users\locth\AppData\Local\Microsoft\Windows\INetCacheContent.Word\scale.png

  • float mRotation: góc xoay tính theo đơn vị radian.
  • D3DXVECTOR2 mRotationCenter: vị trí xoay, để bằng position của Sprite thì sẽ quay quanh tâm.
  • D3DXVECTOR2 mTranslation: phép tịnh tiến, tịnh tiến sprite thêm 1 đoạn bằng vector.
  • bool mIsFlipVertical, mIsFlipHorizontal: tương ứng là lật hình theo trục dọc và trục ngang, có hàm set cho 2 thuộc tính này thuật toán thì chỉ là set Scale tương ứng bằng âm. Các bạn xem trong source code để rõ hơn.
  • D3DXMATRIX mMatrix: là 1 ma trận 4 x 4 giúp trong việc vẽ màn Texture lên màn hình thông qua các tham số như position, scale (tỉ lệ), rotation (xoay hình), translate (phép dời hình).
  • Bạn nào muốn hiểu quy trình này hơn có thể search google về pipeline render cái này dùng trong kĩ thuật 3D. thì 2D cũng là 1 dạng của 3D khi bỏ cmn trục z đi hoy. Ở ma trận trên với x, y , z là tọa độ của sprite ban đầu và x’, y’, z’ là tọa độ sau khi nhân ma trận (transform) nhiều bạn băn khoăn sao có 3 tọa độ mà làm lol gì cần tới ma trận 4x4 cho rắc rối thì nhìn vào kết quả của x’, y’, z’ bạn sẽ thấy các số ở hàng cuối sẽ sử dụng trong việc tính tiến hình ảnh. Nhân ma trận này sẽ tạo ra 1 ràng buộc quan hệ giữa x, y, z cho nên có thể thực hiện được các phép biến hình cơ bản scale (tỉ lệ), rotation (xoay hình), translate (tịnh tiến). Sau quá trình cuối của Piple line thì các tọa độ sẽ được chem chia cho w’ cái này thì mình không cần quan tâm lắm trong framework này.

  • Trên là các thuộc tính cơ bản và cần thiết, mỗi thuộc tính đề có hàm get, set tương ứng để gán và lấy giá trị cho nó. Tiếp đến mình sẽ giải thích thêm 1 số hàm cần thiết.

  • void InitWithSprite(const char* filePath, RECT sourceRect = RECT(), int width = NULL, int height = NULL, D3DCOLOR colorKey = NULL)  hàm này được dùng để khởi tạo Sprite và cũng dùng cho các class kế thừa. đây là kiểu hàm có kèm tham số mặc nhiên nghĩa là bạn có thể chỉ cần truyền mỗi tên đường dẫn của sprite hoặc truyền đầy đủ các tham số trên. Trong hàm chú yếu là khởi tạo các tham số cần thiết ở trên và tạo texture.
  • bool isRect(RECT rect): hàm này kiểm tra xem tham số rect truyền vào có phải là hình chữ nhật không (left != right và top != bottom).

  • void Draw(D3DXVECTOR3 position = D3DXVECTOR3(),RECT sourceRect = RECT(), D3DXVECTOR2 scale = D3DXVECTOR2(), D3DXVECTOR2 transform = D3DXVECTOR2(), float angle = 0, D3DXVECTOR2 rotationCenter = D3DXVECTOR2(), D3DXCOLOR colorKey = D3DCOLOR_XRGB(255, 255, 255)): đây là hàm dài và fứck tạp nhất ☹ . Cái này khởi tạo với full time số mặc nhiên nên không muốn thay đổi gì lúc vẽ (như position, scale, ….) thì chỉ cần gọi hàm Draw(). Trong hàm trước khi vẽ sẽ truyền các tham số cần thiết cho phép biến hình và nhân ma nhận như nói ở trên. Tuy nhiên có đoạn này:

D3DXMATRIX oldMatrix;
mSpriteHandler->GetTransform(&oldMatrix);
mSpriteHandler->SetTransform(&mMatrix);
……
mSpriteHandler->SetTransform(&oldMatrix);

Mình chỉ muốn áp ụng các phép biến hình cho chính Sprite này thôi nên sẽ dùng đoạn này  lấy matrix trước đó, dùng matrix mới sau đó gán lại để chỉ áp dụng cho chính sprite này.
  • Tiếp đến hàm dùng Sprite của DirectX để vẽ thì các tham số truyền vào là Texture cần vẽ, SourceRect (vùng cần vẽ), center vị trí tâm (Anchor Point) mình vẽ ở giữa Texture nên sẽ lấy nó bằng chiều dài và chiều rộng của Texture chia 2 (xem trong source code), Position là vị trí vẽ lên màn hình, và Color là để xóa vùng màu.
mSpriteHandler->Draw(mTexture,
        &inSourceRect,
        &center,
        &inPosition,
        D3DCOLOR_ARGB(255, 255, 255, 255));

3. Vẽ Sprite lên màn hình

  • Trong Source code mình có vẽ 1 sprite lên trong file Game.cpp.
Sprite  *sprite;
…….
sprite = new Sprite("Resources/loctho.png");
sprite->SetPosition(GameGlobal::GetWidth() / 2, GameGlobal::GetHeight() / 2
……..
sprite->Draw();
  • Hàm draw sẽ được gọi trong hàm render của class Game.

Tổng kết

Class Sprite có thể hiểu là class hỗ trợ việc vẽ 1 tấm hình lên màn hình với nhiều tùy chỉnh như vẽ phần nào, vẽ ở đâu, phóng to thu nhỏ (Scale) ra sao xoay góc (Rotation) thế nào,…. Các bạn tham khảo thêm source code vì mình cũng có comment code trong đó giúp các bạn dễ tiếp cận code hơn.

Share on Google Plus

About Lộc Thọ

This is a short description in the author block about the author. You edit it by entering text in the "Biographical Info" field in the user admin panel.
    Blogger Comment
    Facebook Comment

0 Comment:

Post a Comment