Các đối tượng sử dụng trong bài viết
SDL_Window
: struct giữ tất cả các thông tin của cửa sổ được tạo ra, chẳng hạn như size, postion, border, fullscreen.SDL_Renderer
: struct xử lý tất cả các công việc rendering lên cửa sổ.SDL_Surface
: chứa 1 tập hợp các pixel (a collection of pixels) để có thể render lên cửa sổ sử dụng software rendering (CPU).SDL_Texture
: chứa 1 tập hợp các pixel (a collection of pixels) để có thể render lên cửa sổ sử dụng hardware rendering (GPU).SDL_Rect
: struct đại diện cho 1 hình chữ nhật gồm có các thông tin làx
,y
,w
,h
.
Tạo đối tượng SDL_Texuture
Sử dụng project ở bài viết Xử Lý Sự Kiện trong SDL nhưng giữ lại main loop và main event, tiếp tục khai báo thêm 1 số biến sử dụng trong chương trình là renderer
, tempSurface
, texture
, sourceRect
, desRect
.
int main() { SDL_Window* window = NULL; SDL_Renderer* renderer = NULL; SDL_Surface* tempSurface = NULL; SDL_Texture* texture = NULL; SDL_Event mainEvent; SDL_Rect sourceRect; SDL_Rect desRect; bool isRunning = true; //initializes the subsystems if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { printf("Unable to initialize SDL %s\n", SDL_GetError()); return -1; } //Create window window = SDL_CreateWindow("Stdio.vn - SDL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 640, SDL_WINDOW_SHOWN); if (window == NULL) { printf("Could not create window %s", SDL_GetError()); return -1; } //main loop while (isRunning) { //main event while (SDL_PollEvent(&mainEvent)) { switch (mainEvent.type) { //User - requested quit case SDL_QUIT: { isRunning = false; break; } default: { break; } } } } //Destroy a window. SDL_DestroyWindow(window); //cleans up all initialized subsystems SDL_Quit(); return 0; }
Tạo đối tượng renderer
để có thể render lên cửa sổ bằng cách:
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if (renderer == NULL) { printf("Could not create render %s", SDL_GetError()); return -1; }
Tiếp theo tạo tempSurface
từ 1 file hình có đuôi mở rộng là .bmp và tạo texture
từ tempSurface
đó. Sau đó hủy tempSurface
. Ở đây, file hình ảnh có tên là texture_demo.bmp được đặt trong thư mục gốc của solution.
tempSurface = SDL_LoadBMP("texture_demo.bmp"); texture = SDL_CreateTextureFromSurface(renderer, tempSurface); SDL_FreeSurface(tempSurface);
* Hàm SDL_LoadBMP()
chỉ nhận được hình ảnh có đuôi mở rộng là .bmp.
Sử dụng hàm SDL_QueryTexture()
để lấy ra thông tin chiều rộng và chiều cao của texture
.
SDL_QueryTexture(texture, NULL, NULL, &sourceRect.w, &sourceRect.h);
Đoạn code trên có khai báo đối tượng SDL_Rect
với 2 biến là sourceRect
và desRect
, chức năng của chúng như sau:
sourceRect
: sử dụng để thông tin về chiều cao, chiều rộng củatexture
muốn vẽ. Ví dụ có 1texture
được load lên, để vẽ 1 phần nào đó củatexture
thay vì vẽ toàn bộtexture
đó lên mà hình, sử dụng đối tượng hình chữ nhật này để fix lại x, y, w, h.desRect
: sử dụng để xác định tọa độ củatexture
muốn vẽ trên màn hình.
Vẽ Texture lên màn hình
Lấy thông tin về chiều cao và chiều rộng của texture
sau khi texure
được tạo:
SDL_QueryTexture(texture, NULL, NULL, &sourceRect.w, &sourceRect.h); sourceRect.x = desRect.x = 0; sourceRect.y = desRect.y = 0; desRect.w = sourceRect.w; desRect.h = sourceRect.h;
Set background màu đen cho cửa sổ sử dụng hàm:
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
Với tham số thứ nhất chính là đối tượng renderer
, 3 tham số tiếp theo lần lượt là các giá trị màu r, g, b, a.
Trong main loop, tiến hành vẽ texture
lên cửa sổ:
//main loop while (isRunning) { SDL_RenderClear(renderer); //main event while (SDL_PollEvent(&mainEvent)) { switch (mainEvent.type) { //User - requested quit case SDL_QUIT: { isRunning = false; break; } default: { break; } } } SDL_RenderCopy(renderer, texture, &sourceRect, &desRect); SDL_RenderPresent(renderer); }
SDL_RenderClear()
: xóa màn hình sau mỗi frame với màu của background được set.SDL_RenderCopy()
: hàm sử dụng để render texture với các tham số:renderer
: đối tượng được sử dụng để render.texture
: đối tượng texture muốn render.sourceRect
: 1 phần nào đó của texture muốn render. Nếu để NULL nó sẽ render toàn bộ texture.desRect
: hình chữ nhật xác đinh tọa độ mà texture muốn vẽ trên cửa sổ. Nếu chiều rộng và chiều cao lớn hơn hoặc nhỏ hơn texture muốn vẽ thì texture sẽ bị scale theo hình chữ nhật này. Nếu để NULL texture sẽ được vẽ full màn hình.
SDL_RenderPresent()
: cập nhập, vẽ lên cửa sổ.
Kết quả sau khi chạy chương trình:
Bây giờ, thay đổi các thông số của sourceRect
và desSource
để có thể vẽ được 1/4 hình ảnh ở vị trí x= 200, y = 200 trên màn hình:
sourceRect.x = 0; sourceRect.y = 0; sourceRect.w = sourceRect.w / 2; sourceRect.h = sourceRect.h / 2; desRect.x = 200; desRect.y = 200; desRect.w = sourceRect.w; desRect.h = sourceRect.h;
Source code toàn bộ chương trình
#include <stdio.h> #include <SDL.h> #undef main int main() { SDL_Window* window = NULL; SDL_Renderer* renderer = NULL; SDL_Surface* tempSurface = NULL; SDL_Texture* texture = NULL; SDL_Event mainEvent; SDL_Rect sourceRect; SDL_Rect desRect; bool isRunning = true; //initializes the subsystems if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { printf("Unable to initialize SDL %s\n", SDL_GetError()); return -1; } //Create window window = SDL_CreateWindow("Stdio.vn - SDL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 640, SDL_WINDOW_SHOWN); if (window == NULL) { printf("Could not create window %s", SDL_GetError()); return -1; } //create a renderer renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if (renderer == NULL) { printf("Could not create render %s", SDL_GetError()); return -1; } //create a tempSurface tempSurface = SDL_LoadBMP("texture_demo.bmp"); //create a texutre from surface texture = SDL_CreateTextureFromSurface(renderer, tempSurface); //free surface SDL_FreeSurface(tempSurface); SDL_QueryTexture(texture, NULL, NULL, &sourceRect.w, &sourceRect.h); sourceRect.x = 0; sourceRect.y = 0; sourceRect.w = sourceRect.w / 2; sourceRect.h = sourceRect.h / 2; desRect.x = 200; desRect.y = 200; desRect.w = sourceRect.w; desRect.h = sourceRect.h; //set background color SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); //main loop while (isRunning) { // clear the window to black SDL_RenderClear(renderer); //main event while (SDL_PollEvent(&mainEvent)) { switch (mainEvent.type) { //User - requested quit case SDL_QUIT: { isRunning = false; break; } default: { break; } } } // copy a portion of the texture to the current rendering target. SDL_RenderCopy(renderer, texture, &sourceRect, NULL); //draw to the screen SDL_RenderPresent(renderer); } //Destroy a window. SDL_DestroyWindow(window); //Destroy a renderer SDL_DestroyRenderer(renderer); //cleans up all initialized subsystems SDL_Quit(); return 0; }