SDL 2 Pelajaran: Pelajaran 3 - Acara

Halo semuanya! Ini adalah pelajaran ketiga dalam SDL 2. Informasi diambil dari sumber ini . Saya tidak suka tutorial penanganan acara Lasy Foo, jadi saya akan menulis sendiri, tetapi materinya dapat ditemukan di sini dan di sini .

Dan kita mulai, selamat datang di pelajaran

Acara


Hari ini kita akan mengajarkan program kita untuk menanggapi peristiwa dengan bantuan John .

Jadi mari kita mulai. hubungkan SDL 2 dan buat 3 variabel global dan 2 konstanta.

#include <SDL2/SDL.h> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *john = NULL; 

Selanjutnya, kita menulis 3 fungsi yang sudah diketahui dari pelajaran terakhir:

Init
 int init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init: " << SDL_GetError() << std::endl; system("pause"); return 1; } win = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; system("pause"); return 1; } scr = SDL_GetWindowSurface(win); return 0; } 

Muat
 int load() { john = SDL_LoadBMP("john.bmp"); if (john == NULL) { std::cout << "Can't load image: " << SDL_GetError() << std::endl; system("pause"); return 1; } return 0; } 

Berhenti
 int quit() { SDL_FreeSurface(john); SDL_DestroyWindow(win); SDL_Quit(); return 0; } 


Perhatian (!), Jika Anda menyalin kode dari pelajaran sebelumnya, jangan lupa untuk mengubah senyum menjadi john .

Semua itu harus dikatakan: Saya memutuskan untuk menunjukkan kesalahan pada tahap inisialisasi dan pemuatan gambar.

Jadi, mari kita lanjutkan. buka main dan panggil fungsi Init and Load .

 int main (int argc, char ** args) { if (init() == 1) { return 1; } if (load() == 1) { return 1; } } 

Sekarang mari kita lihat bagaimana aplikasi bekerja. Program apa pun yang Anda jalankan (Google Chrome, Paint, Minecraft) memiliki loop utama yang menjalankan sejumlah besar kali. Ini penting untuk dinamisme. Sebelumnya, kami menulis sebuah program yang hanya menunjukkan senyum selama 2 detik, tetapi agar program tersebut dapat belajar bagaimana menanggapi tindakan pengguna (atau setidaknya menampilkan gambar tanpa henti), diperlukan loop Sementara .

Itu akan terus diulang dan di dalamnya kita sudah bisa melakukan apa yang kita inginkan, misalnya, proses peristiwa. Tetapi sebelum Anda memulai siklus glan, mari kita buat beberapa variabel.

  bool run = true; SDL_Event e; SDL_Rect r; int x = 0; int y = 0; rx = x; ry = y; 

Kami akan menganalisis semuanya sekarang. Pertama, buat variabel run dari tipe boolean . Variabel ini bertanggung jawab atas eksekusi loop: ketika program sedang berjalan, itu benar , jika kita ingin menghentikan eksekusi, maka setel variabel ini menjadi false . Selanjutnya, buat objek e dari kelas SDL_Event . Properti dari objek ini akan berisi data dari peristiwa yang diterima, selanjutnya akan lebih rinci. Setelah itu kita membuat objek r dari kelas SDL_Rect . Ini adalah persegi panjang yang diperlukan untuk menggambar objek dengan beberapa koordinat yang kita butuhkan. Kemudian kita membuat variabel x dan y dari tipe int . Segera tetapkan nilainya ke nol. Ini akan menjadi koordinat karakter kita. Item berikutnya, kami menetapkan variabel rx dan ry nilai x dan y, masing-masing. rx dan ry adalah koordinat persegi panjang r .

Saatnya untuk membuka siklus utama.

  while (run) { while(SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { run = false; } if (e.type == SDL_KEYDOWN) { if (e.key.keysym.sym == SDLK_UP) { y -= 1; } if (e.key.keysym.sym == SDLK_DOWN) { y += 1; } if (e.key.keysym.sym == SDLK_RIGHT) { x += 1; } if (e.key.keysym.sym == SDLK_LEFT) { x -= 1; } } } rx = x; ry = y; SDL_FillRect(scr, NULL, SDL_MapRGB(scr -> format, 255, 255, 255)); SDL_BlitSurface(john, NULL, scr, &r); SDL_UpdateWindowSurface(win); } 

Mari kita uraikan kode ini. Kami memiliki dua siklus. Yang utama pertama adalah yang utama, yang bekerja dengan menjalankan variabel, seperti yang disebutkan sebelumnya. Loop kedua bertanggung jawab untuk menangani acara.

Fungsi SDL_PollEvent () membuka antrian acara yang diterima dalam satu eksekusi dari loop utama, menghapus acara terakhir dan menulis data tentang peristiwa ini ke variabel objek yang kami lewatkan ke fungsi ini, kami memiliki ini e . Fungsi ini mengembalikan 0, NULL atau false jika semua peristiwa dari antrian telah dihapus, jadi kami menulis kondisi while (SDL_PollEvent (& e)! = NULL) .

Kami melihat lebih jauh: cek pertama yang kami miliki adalah mengklik tanda silang di bingkai jendela. Jika kita klik itu, maka variabel tipe objek e diberi nilai SDL_QUIT . Jika ini terjadi, maka kami menetapkan false ke variabel run dan loop berakhir.

Selanjutnya, saya menulis tes keyboard keystroke. Jika tombol ditekan, maka variabel e.type sama dengan SDL_KEYDOWN . Selanjutnya, periksa nilai-nilai kunci. variabel e.key.keysym.sym menyimpan nilai tombol. Kami membandingkan nilai ini dengan yang diinginkan dan melakukan tindakan tertentu. Kami akan mengubah koordinat John. Jika panah atas ditekan, maka y berkurang sebesar 1, jika turun, itu meningkat, dll. Intinya, saya pikir, Anda mengerti.

Setelah memproses peristiwa, tetapkan kembali rx dan ry untuk memperbarui koordinat Manusia. Selanjutnya, kita menulis fungsi SDL_FilRect yang sudah dikenal, ia memiliki peran yang sangat besar. Jika kita tidak menulisnya, maka John akan meninggalkan tanda jelek pada gerakan, dan setiap frame kita menggambar latar belakang putih dan menggambar sprite di atasnya. Setelah itu, kita menggambar pahlawan kita dengan fungsi SDL_BlitSurface . Di sini kita akan menggunakan r persegi panjang kita, atau lebih tepatnya variabelnya x dan y , untuk menggambar tidak hanya di kiri atas, tetapi dengan beberapa koordinat yang diperlukan. Selanjutnya, cukup perbarui jendela.

Setelah loop utama, tulis kembali berhenti (); untuk menyelesaikan program.

Itu saja, pelajaran ini selesai. Ini kode seperti itu:

Kode
 #include <SDL2/SDL.h> #include <iostream> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *john = NULL; int init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init: " << SDL_GetError() << std::endl; system("pause"); return 1; } win = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; system("pause"); return 1; } scr = SDL_GetWindowSurface(win); return 0; } int load() { john = SDL_LoadBMP("john.bmp"); if (john == NULL) { std::cout << "Can't load image: " << SDL_GetError() << std::endl; system("pause"); return 1; } return 0; } int quit() { SDL_FreeSurface(john); SDL_DestroyWindow(win); SDL_Quit(); return 0; } int main (int argc, char ** args) { if (init() == 1) { return 1; } if (load() == 1) { return 1; } bool run = true; SDL_Event e; SDL_Rect r; int x = 0; int y = 0; rx = x; ry = y; while (run) { while(SDL_PollEvent(&e) != NULL) { if (e.type == SDL_QUIT) { run = false; } if (e.type == SDL_KEYDOWN) { if (e.key.keysym.sym == SDLK_UP) { y -= 1; } if (e.key.keysym.sym == SDLK_DOWN) { y += 1; } if (e.key.keysym.sym == SDLK_RIGHT) { x += 1; } if (e.key.keysym.sym == SDLK_LEFT) { x -= 1; } } } rx = x; ry = y; SDL_FillRect(scr, NULL, SDL_MapRGB(scr -> format, 255, 255, 255)); SDL_BlitSurface(john, NULL, scr, &r); SDL_UpdateWindowSurface(win); } return quit(); } 


Dan saya mengucapkan selamat tinggal kepada Anda, selamat tinggal semuanya!

<< Pelajaran sebelumnya || Pelajaran selanjutnya >>

Source: https://habr.com/ru/post/id455577/


All Articles