1. Trang chủ
  2. » Công Nghệ Thông Tin

Bài giảng Lập trình nâng cao: Đồ hoạ với SDL - Trần Quốc Long

93 135 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 93
Dung lượng 3,77 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Bài giảng Lập trình nâng cao: Đồ hoạ với SDL cung cấp cho người học các kiến thức: Thư viện SDL, xây dựng API vẽ, vẽ hình bằng bút vẽ, vẽ hình fractal. Mời các bạn cùng tham khảo nội dung chi tiết.

Trang 1

7&8 - Đồ hoạ với SDL

https://github.com/tqlong/advprogram

Trang 2

● Vẽ hình fractal

Trang 3

Đồ họa với SDL

● https://www.libsdl.org/

● Hướng dẫn: http://wiki.libsdl.org/FrontPage

● SDL có thể phát triển trò chơi chuyên nghiệp

● SDL dễ dàng kết nối với CodeBlocks

● SDL chạy trên nhiều nền tảng (Windows,

Linux, Android, iOS …)

Trang 4

Lựa chọn thư viện

Thường cần thư viện (bên thứ 3 - third party library) ngoài tính

năng của ngôn ngữ và thư viện chuẩn của C++

○ https://en.wikipedia.org/wiki/List_of_game_engines

Trang 6

Cài đặt SDL với CodeBlocks-MinGW

trong thư mục này có 4 thư mục bin, include, lib, share

mã nguồn project )

6 / 15

Trang 7

Cấu hình CodeBlocks

Settings / Compiler

Trang 8

Cấu hình CodeBlocks

Liên kết thư viện:

Linker settings: -lmingw32 -lSDL2main -lSDL2

8 / 15

Trang 9

Cấu hình CodeBlocks

Vị trí thư mục include và lib: Search directories | Compilers

Đường dẫn đến thư

mục chứa SDL

Trang 10

Cấu hình CodeBlocks

Vị trí thư mục include và lib: Search directories | Linker

10 / 15

Trang 12

Khởi tạo SDL

# include < iostream >

# include < SD L.h>

usin g n am esp ace std;

in t m ain(in t argc, char* argv[])

{

return ;

}

sử dụng thư viện SDL2

Trang 13

Báo lỗi SDL

void logS D LError(std::ostream & os,

con st std::string & m sg, b ool fatal = false);

void logS D LError(std::ostream & os,

con st std::string & m sg, b ool fatal)

Trang 14

Khởi tạo SDL

con st int SCREEN _W ID TH = 800;

con st int SCREEN _H EIG H T = 600;

con st string W IN D O W _TITLE = "An Im plem entation of Code.org Painter";

void in itS D L(SD L_W indow * & w indow , SD L_Renderer* & renderer);

Đại diện cho cửa sổ vẽ Đại diện cho bút vẽ

Trang 15

Khởi tạo SDL

con st int SCREEN _W ID TH = 800;

con st int SCREEN _H EIG H T = 600;

con st string W IN D O W _TITLE = "An Im plem entation of Code.org Painter";

void in itS D L(SD L_W indow * & w indow , SD L_Renderer* & renderer);

void initS D L(SD L_W indow * & w indow , SD L_Renderer* & renderer)

{

if (SD L_Init(SD L_IN IT_EVERYTH IN G ) != 0)

logSD LError(std::cout, "SD L_Init", true );

w indow = SD L_CreateW indow (W IN D O W _TITLE.c_str(), SD L_W IN D O W PO S_CEN TERED ,

SD L_W IN D O W PO S_CEN TERED , SCREEN _W ID TH , SCREEN _H EIG H T, SD L_W IN D O W _SH O W N ); //w indow = SD L_CreateW indow (W IN D O W _TITLE.c_str(), SD L_W IN D O W PO S_CEN TERED ,

SD L_W IN D O W PO S_CEN TERED , SCREEN _W ID TH , SCREEN _H EIG H T,

SD L_W IN D O W _FU LLSCREEN _D ESKTO P);

if (w indow = = nullptr)

logSD LError(std::cout, "CreateW indow ", true );

renderer = SD L_CreateRenderer(w indow , -1, SD L_REN D ERER_ACCELERATED |

SD L_REN D ERER_PRESEN TVSYN C);

//SD L_Renderer *renderer = SD L_CreateSoftw areRenderer(SD L_G etW indow Surface(w indow ));

if (renderer = = nullptr)

logSD LError(std::cout, "CreateRenderer", true );

SD L_SetH int(SD L_H IN T_REN D ER_SCALE_Q U ALITY, "linear");

SD L_RenderSetLogicalSize(renderer, SCREEN _W ID TH , SCREEN _H EIG H T);

Mở cửa sổ vẽ theo kích thước

đã chọn

Lấy bút vẽ

Trang 16

Giải phóng SDL

void q uitSD L(SD L_W indow * w indow , SD L_Renderer* renderer);

void q uitSD L(SD L_W indow * w indow , SD L_Renderer* renderer){

Trang 17

Đợi 1 phím để thoát

void w aitU n tilK eyP ressed();

void w aitU n tilK eyP ressed()

{

SD L_Event e;

w h ile (true) {

if ( SD L_W aitEvent(& e) != 0 & &

(e.type = = SD L_KEYD O W N || e.type = = SD L_Q U IT) )

return;

SD L_D elay(100);

}

Xác định sự kiện bàn phím

Trang 18

initSD L(w indow , renderer);

// Your draw ing code here

// use SD L_RenderPresent(renderer) to show it

w aitU ntilKeyPressed();

quitSD L(w indow , renderer);

return ;}

https://github.com/tqlong/advprogram/raw/6f01f8f6f96afe0aa9e107d65dcde17802f1e1e3/lec10-sdl/main.cpp

Trang 19

Cửa sổ trắng,

ấn 1 phím bất

kỳ để thoát

Trang 20

● Vẽ hình fractal

Trang 21

Vẽ hình với SDL

● SDL đã cung cấp hàm

● Ta cũng có thể xây dựng thư viện riêng

Vẽ hình theo phong cách của riêng chúng ta

Trang 22

Lớp Painter

● API vẽ ( Application Program Interface )

● Cách vẽ

độ), màu vẽ trắng, màu nền xanh

Trang 23

void setP osition(f l oat x, f l oat y);

f l oat getX() con st { return x; }

f l oat getY() const { return y; }

void setAngle(f l oat angle);

f l oat getAngle() con st { return angle; }

in t getW idth() con st { return w idth; }

in t getH eight() con st { return height; }

void setColor(SD L_Color color);

SD L_Color getColor() const { return color; } void clearW ithBgColor(SD L_Color color);

SD L_Renderer* getRenderer() con st

{ return renderer; }

Trang 24

Một số màu hay dùng

con st SD L_Color CYAN _CO LO R = {0, 255, 255};

con st SD L_Color BLU E_CO LO R = {0, 0, 255};

con st SD L_Color O RAN G E_CO LO R = {255, 165, 0};

con st SD L_Color YELLO W _CO LO R = {255, 255, 0};

con st SD L_Color LIM E_CO LO R = {0, 255, 0};

con st SD L_Color PU RPLE_CO LO R = {128, 0, 128};

con st SD L_Color RED _CO LO R = {255, 0, 0};

con st SD L_Color W H ITE_CO LO R = {255, 255, 255};

con st SD L_Color BLACK_CO LO R = {0, 0, 0};

con st SD L_Color G REEN _CO LO R = {0, 128, 0};

con st SD L_Color D EFAU LT_CO LO R = BLACK_CO LO R;

Nên đặt đoạn

mã này ở đâu ?

http://stackoverflow com/questions/23870 83/where-should-you- put-global-constants -in-a-c-program

Trang 25

Lớp Painter: Hàm khởi tạo

Painter::Painter(SD L_W indow * w indow , SD L_Renderer* renderer_)

: renderer(renderer_)

{

SD L_RenderG etLogicalSize(renderer, & w idth, & height);

if (w idth = = 0 & & height = = 0)

SD L_G etW indow Size(w indow , & w idth, & height);

setPosition(w idth/2, height/2);

setAngle(0);

setColor(W H ITE_CO LO R);

clearW ithBgColor(BLU E_CO LO R);

Khởi tạo tọa độ, màu và hướng ban đầu của bút vẽ, tô nền bằng màu xanh

Lấy kích thước cửa sổ

Trang 26

void Painter::setPosition(f l oat x, f l oat y)

SD L_SetRenderD raw Color(

renderer, color.r, color.g, color.b, 0);

vẽ và tô màu nền

Trang 27

Đi tới vẽ đoạn thẳng

p ub lic:

// basic draw ing functions

void m oveForw ard(f l oat length);

void jum p Forw ard(f l oat length);

void Painter::m oveForw ard(f l oat length){

f l oat prevX = x, prevY = y;

jum pForw ard(length);

SD L_RenderD raw Line(renderer, (in t)prevX, (in t)prevY,

và vẽ đoạn thẳng

Trang 28

Đi lùi, nhảy lùi

jum pForw ard(-length);

}

Trang 29

Quay trái, quay phải

turnLeft(-angle);

}

Trang 30

f l oat length = generateRandom N um ber() * M AX_LEN G TH ;

painter.m oveForw ard(length);

f l oat angle = generateRandom N um ber() * 360;

initSD L(w indow , renderer);

Painter painter(w indow , renderer); random W alk(painter);

SD L_RenderPresent(renderer);

}

Chọn độ dài bước và hướng đi ngẫu nhiên

Trang 32

Chọn màu ngẫu nhiên

void Painter::setRandom Color()

}

Trang 34

Đường thẳng, hình vuông, tam giác …

Phối hợp tạo thành các hình tuyệt đẹp

Vẽ ảnh JPG, PNG

● Vẽ hình fractal

Trang 35

11: nhiều đường kẻ 12: hình thoi

13: nhiều hình tròn lồng nhau 14: bông tuyết tám cánh

15: đi dạo (ngẫu nhiên)

Trang 36

Hình vuông

in t figN um ber = argc > 1 ? atoi(argv[1]) : 0;

sw itch (figN um ber)

Trang 40

Tô kín tam giác

for (in t j = 0; j < 3; + + j) {

painter.turnLeft(120);

painter.m oveForw ard(size - i); }

painter.setPosition(curX, curY); painter.jum pBackw ard(i+ 1); }

painter.setPosition(curX, curY); break;

} // case 2

Vẽ các tam giác có kích thước nhỏ dần

Trang 42

Hình bát giác

/* O ctagon */

case : painter.setPosition(350, 500);

painter.setColor(YELLO W _CO LO R);

for (in t i = 0; i < 8; + + i) {

painter.m oveForw ard(150);

painter.turnLeft(45);

} break;

Quay 45 độ 8 lần và

đi tới

Trang 44

Sao năm cánh

/* Star of fives */

case : painter.setPosition(350, 200);

painter.setColor(YELLO W _CO LO R);

for (int i = 0; i < 5; + + i) {

painter.m oveForw ard(200);

Trang 46

painter.m oveForw ard(150); painter.turnLeft(120);

}

b reak;

Vẽ 2 tam giác đều

Trang 48

Nhím 8 gai

/* Eight lines crossing at center*/

case : painter.setColor(W H ITE_CO LO R);

for (in t i = 0; i < 8; + + i) {

painter.m oveForw ard(100);

painter.m oveBackw ard(100);

Trang 50

Sáu hình vuông

/* Six squares */

case : for (in t i = 0; i < 6; + + i) {

for (in t j = 0; j < 4; + + j) {

painter.m oveForw ard(100);

painter.turnRight(90);

} painter.turnLeft(60);

}

b reak;

Vẽ một hình vuông

Quay 60 độ, vẽ tiếp hình vuông tất cả 6 lần

Trang 52

Hình tròn

● Giải thuật vẽ hình tròn

■ https://en.wikipedia.org/wiki/Midpoint_circle_algo rithm

Trang 53

Hình tròn

void Painter::createCircle(f l oat radius){

d oub le rad = (angle / 180) * M _PI;

in t centerX = x + cos(rad) * radius;

in t centerY = y - sin(rad) * radius;

in t dx = radius;

in t dy = 0;

in t err = 0;

Trang 54

Hình tròn

void Painter::createCircle(f l oat radius)

{

d oub le rad = (angle / 180) * M _PI;

in t centerX = x + cos(rad) * radius;

in t centerY = y - sin(rad) * radius;

in t dx = radius;

in t dy = 0;

in t err = 0;

w h ile (dx > = dy) {

SD L_RenderD raw Point(renderer, centerX + dx, centerY + dy);

SD L_RenderD raw Point(renderer, centerX + dy, centerY + dx);

SD L_RenderD raw Point(renderer, centerX - dy, centerY + dx);

SD L_RenderD raw Point(renderer, centerX - dx, centerY + dy);

SD L_RenderD raw Point(renderer, centerX - dx, centerY - dy);

SD L_RenderD raw Point(renderer, centerX - dy, centerY - dx);

SD L_RenderD raw Point(renderer, centerX + dy, centerY - dx);

SD L_RenderD raw Point(renderer, centerX + dx, centerY - dy);

if (err < = 0) {

dy + = 1; err + = 2*dy + 1; }

if (err > 0) {

dx -= 1; err -= 2*dx + 1; }

} // w hile} // createCircle()

● Từ 1 điểm suy ra 7 điểm khác bằng tính đối xứng của hình tròn

● Tính điểm kế tiếp (tăng dy

hoặc giảm dx 1 điểm ảnh) bằng cách kiểm tra err

Chi tiết thuật toán

https://en.wikipedia.org/wiki/Midpoint_circle_algorithm

Trang 55

30 điểm ảnh

Trang 57

Đi tới 50 điểm ảnh, xoay hướng 18 độ

18 x 20 lần = 360 độ

Trang 59

{ //painter.random Color();

painter.createSquare(100); painter.turnRight(36);

}

b reak;

Trang 61

painter.m oveForw ard(150);

painter.jum pBackw ard(150);

painter.turnRight(4);

}

b reak;

Trang 63

Hình thoi

/* Pattern of Ten parallelogram s */

case 12: painter.setColor(W H ITE_CO LO R); for (in t i = 0; i < 10; + + i)

{ painter.createParallelogram (100); painter.turnRight(36);

Trang 65

Nhiều hình tròn lồng nhau

/* Five and five cirles */

//*

case 13: painter.setColor(W H ITE_CO LO R);

painter.clearW ithBgColor(G REEN _CO LO R);

for (int i = 0; i < 5; + + i) {

painter.createCircle(100);

painter.createCircle(50);

painter.turnRight(72);

}

Trang 67

painter.turnLeft(45);

painter.m oveForw ard(size);

painter.jum pBackw ard(size);

painter.turnRight(90);

painter.m oveForw ard(size);

painter.jum pBackw ard(size);

painter.turnLeft(45);

painter.m oveForw ard(size);

https://github.com/tqlong/advprogram/archive/3677695699840c851d6e22972eb4ff7353540e00.zip

Trang 69

● Đọc ảnh vào SDL_Surface (bitmap)

● Chuyển sang SDL_Texture (phụ thuộc driver)

● Dùng SDL_RenderCopy() vẽ SDL_Texture

● Giải phóng SDL_Texture

Trang 70

Chuẩn bị SDL_Texture

SD L_Texture* Painter::loadTexture( string path )

{

SD L_Texture* new Texture = N U LL;

SD L_Surface* loadedSurface = IM G _Load( path.c_str() );

Trang 71

Vẽ ảnh

b ool Painter::createIm age( SD L_Texture* texture )

{

if( texture = = N U LL ) return false;

SD L_RenderCopy( renderer, texture, N U LL, N U LL );

return true;

case 16: {

if (argc < = 2) { cout < < "Please provide im age fi le path" < < endl; break;

} texture = painter.loadTexture(argv[2]);

painter.createIm age(texture);

} break;

Trang 73

Vẽ hình fractal

Kỹ thuật đệ quy

Trang 75

● Nếu dãy phân kì thì c không thuộc tập hợp

○ Tô màu với số n mà |zn|2 = xn2 + yn2 ≥ 4 (phân kì)

● Nếu n > MAX_ITERATION, coi c thuộc tập

hợp (tô màu đen)

Trang 76

Thuật toán điểm thoát (escape)

For each pixel (Px, Py) on the screen, do:

{

x0 = scaled x coordinate of pixel (scaled to lie in the Mandelbrot X scale (-2, 1.5))

y0 = scaled y coordinate of pixel (scaled to lie in the Mandelbrot Y scale (-2, 1.5))

Trang 77

Chuyển đổi tọa độ

Tọa độ hiển thị tọa độ trên mặt phẳng phức ⇔

Trang 78

void draw M andelb rot(Painter& painter, f l oat xm in, f l oat ym in, f l oat xm ax, f l oat ym ax)

{

int w idth = painter.getW idth(), height = painter.getH eight();

const int M AX_ITERATIO N = 1000;

for (int px = 0; px < w idth; px+ + ) {

for (int py = 0; py < painter.getH eight(); py+ + ) {

f l oat x0 = (f l oat)px / w idth * (xm ax-xm in) + xm in, x = 0;

f l oat y0 = (f l oat)py / height * (ym ax-ym in) + ym in, y = 0;

int iteration = 0;

w hile (x*x+ y*y < 2 & & iteration < M AX_ITERATIO N ) {

f l oat xtem p = x*x-y*y+ x0;

y = 2*x*y+ y0;

x = xtem p;

iteration+ + ;

}

SD L_Color color = iteration < M AX_ITERATIO N ?

PALLETTE[iteration % PALETTE_CO UN T] : BLACK_CO LO R;

Tính điểm thoát của

c = (x0,y0)

Chuyển đổi tọa độ từ (px,py) qua

(x0,y0)

Sử dụng

SDL_RenderDrawPoint(renderer, px, py)

cài đặt hàm này

Trang 79

Bảng màu

http://stackoverflow.com/questions/16500656/which-color-gradient-is-used-to-color-mandel brot-in-wikipedia

con st SD L_Color PALLETTE[] = {

Trang 80

https://github.com/tqlong/advprogram/archive/9d8e1a0d5aed0f94e1095d89813cf0b2ee99bb21.zip

Trang 81

Zoom in

(0, 0, 2*0.5, 1.5*0.5) (2*0.17, 1.5*0.17, 2*0.25,1.5*0.25)

Trang 82

Fractal đệ quy

● Khái niệm đệ quy trong toán học / lập trình

qua chính nó với tham số khác (thường nhỏ hơn)

○ Giai thừa: factorial(n) = n * factorial(n-1)

○ Fibonaci: fibo(n) = fibo(n-1) + fibo(n-2)

● Hình fractal đệ quy

○ http://natureofcode.com/book/chapter-8-fractals/

Trang 83

Tính giai thừa

in t factorial(in t n) {

if (n = = 1) { return ; } else { return n * factorial(n-1);

}}

Điều kiện dừng đệ quy

Trang 84

painter.jum pForw ard(radius*0.25f);

draw RecursiveCircle(painter, radius*0.75f);

painter.jum pBackw ard(radius*0.25f);

}

}

Điều kiện đệ quy (bán kính lớn hơn 2)

Trang 86

Vẽ 2 hình tròn bên trái, phải

void d raw R ecursiveC ircle2(Painter& painter, f l oat radius)

{

painter.createCircle(radius);

if(radius > 2) {

painter.jum pBackw ard(radius / 2);

draw RecursiveCircle2(painter, radius / 2);

painter.jum pForw ard(radius * 2);

draw RecursiveCircle2(painter, radius / 2);

painter.jum pBackw ard(radius*3/ );

}

}

Trang 88

Thêm 2 hình tròn trên, dưới

void d raw R ecursiveC ircle4(Painter& painter, f l oat radius)

draw RecursiveCircle4(painter, radius / 2);

painter.setPosition(x+ radius/2,y-radius);

draw RecursiveCircle4(painter, radius / 2);

painter.setPosition(x+ radius*3/ ,y);

draw RecursiveCircle4(painter, radius / 2);

painter.setPosition(x+ radius/2,y+ radius);

draw RecursiveCircle4(painter, radius / 2);

painter.setPosition(x,y);

}

}

Ngày đăng: 08/05/2021, 12:19

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w