[C/C++, graphics] SDL Tutorial Basics

 

These tutorials are meant to teach someone with some experience using C++, or perhaps another programming language. If you have a hard time following certain ideas related to the code itself and not conceptual ideas (those relating to games), then I urge you to first read our tutorials that explain the C++ programming language. It's not vital to understand everything about C++, but every little bit will help later on.

In these tutorials we will be referncing to CodeBlocks as our IDE of choice, with gcc and mingw for compilation. If you wish to use another IDE and compiler that is up to you, but it may be harder to follow along if you have limited experience with linking libraries. If you wish to download CodeBlocks, you can do so for free at http://www.codeblocks.org (download the one including the mingw package). We recommend you use the stable version, unless you want to spend the extra time and use the nightly builds.

These tutorials will be heavily centered around SDL (Simple DirectMedia Layer), a 2D cross-platform graphics library. This library is going to allow us to draw fancy graphics to the screen, and do all sorts of fun stuff that allows us to make a game. You're going to need to download this library at http://www.libsdl.org; be sure to download the Mingw32 tar file under "Development Libraries" and "Win32" and the zip file under "Runtime Libraries" and "Win32." If you are using Visual Studio download the appropriate version instead of the Mingw32 file. Once downloaded, we recommend you put the .dll found in the zip in your system32 folder. This way whenever we open an SDL application it can find the dll file it needs.

Open the tar file now (the one that was listed under "Development Libraries") and decompress the contents to a folder (such as C:\SDL). Now, open up CodeBlocks so we can change some settings. Click "Settings" on the menu bar, and then click "Search Directories" tab. You'll need to add C:\SDL\include to the "Compiler" tab, and C:\SDL\lib to the "Linker" tab (change C:\SDL to wherever you decompressed the files to). Once done, click Okay.
 

Important Note: I use #include <SDL.h> below (and in all other tutorials), when it really should be #include <SDL/SDL.h>. I moved all of my header files up a directory. So, if you want to follow my code exactly, move all your header files up a directory so they are in the include folder, not the SDL folder. Otherwise, use #include instead. Sorry for all the confusion this has caused.



Start a new "blank" project, calling it whatever you want. Save it some place. Click on "Project" on the menu bar, and then click on "Properties." A dialog will open; click on the "Project's build options..." button on the bottom right. Click on the "Linker Settings" tab and add the following to the list under "Link libraries":

mingw32
SDLmain
SDL


The order is important, so use the arrows to rearrange the list until it matches what is shown above. If you are having a little trouble figuring out what we are doing, we're simply "linking" code together, or, in other words, we're taking the SDL code and combining it with our own. We do this by using the include files to compile, and the lib files to link. And once done, our code is put together to make one application.

Click Ok twice, and you should be all set to go!

Let's create two new files called CApp.h, and CApp.cpp; these will serve as the core for our program. First, open CApp.h and add the following code, in here is where our tutorial will really begin:
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef _CAPP_H_
    #define _CAPP_H_
 
#include <SDL.h>
 
class CApp {
 
    public:
 
        CApp();
 
        int OnExecute();
 
};
 
#endif

Now, open up CApp.cpp and add the following code:
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "CApp.h"
 
CApp::CApp() {
}
 
int CApp::OnExecute() {
    return 0;
}
 
int main(int argc, char* argv[]) {
    CApp theApp;
 
    return theApp.OnExecute();
}

The CApp class is setting the stage for our entire program. Let me step aside to take special note of how games are typically setup. Most games consist of 5 functions that handle how the game processes. These processes are typically:

Initialize
This function handles all the loading of data, whether it be textures, maps, NPCs, or whatever.

Event
This function handles all input events from the mouse, keyboard, joysticks, or other devices.

Loop
This function handles all the data updates, such as a NPCs moving across the screen, decreasing your health bar, or whatever

Render
This function handles all the rendering of anything that shows up on the screen. It does NOT handle data manipulation, as this is what the Loop function is supposed to handle.

Cleanup
This function simply cleans up any resources loaded, and insures a peaceful quitting of the game.

It's important to understand that games are one gigantic loop. Within this loop we find events, update data, and render pictures. Thus, the basic structure could be thought of as:
 

1
2
3
4
5
6
7
8
9
Initialize();
 
while(true) {
    Events();
    Loop();
    Render();
}
 
Cleanup();

Each iteration of the loop we do something with data, and render accordingly. Events are extra, as a means for the user to manipulate data as well. In that sense, Events aren't required to make a game, but are needed when you want the user to be able to manipulate data (such as move a NPC to the left).

Let's clarify this idea with an example. Say we have our Knight, the hero of the game. All we want to do is simply have him move around. If I press left, he goes left. We need to figure out how to do this within a loop. Firstly, we know we want to check for events (keyboard events). Since Events are a means to manipulate data, we also know we'll need some sort of variables to modify. Then we can use these variables to render our Knight appropriatly on the screen. We could have:
 

1
2
3
4
5
6
if(Key == LEFT) X--;
if(Key == RIGHT) X++;
if(Key == UP) Y--;
if(Key == DOWN) Y++;//... somewhere else in our code ...
 
RenderImage(KnightImage, X, Y);

This works because each loop it checks if the key is LEFT, RIGHT, etc., and if so, we decrease or increase a variable. So, if our game is running at 30 frames per second and we press LEFT, then our guy would move to the left 30 pixels per second. If you don't understand the game loop, you soon will. Games need them to function correctly.

Going back to our conceptual code (the 5 functions), we can add these additional pages to our project:

CApp_OnInit.cpp CApp_OnEvent.cpp CApp_OnLoop.cpp CApp_OnRender.cpp CApp_OnCleanup.cpp

Go back to CApp.h, and add the following functions and variables:
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef _CAPP_H_
    #define _CAPP_H_
 
#include <SDL.h>
 
class CApp {
    private:
        bool    Running;
 
    public:
        CApp();
 
        int OnExecute();
 
    public:
 
        bool OnInit();
 
        void OnEvent(SDL_Event* Event);
 
        void OnLoop();
 
        void OnRender();
 
        void OnCleanup();
};
 
#endif

Go through each of the 5 files we just created and create the function themselves:
 

1
2
3
4
5
#include "CApp.h"
 
bool CApp::OnInit() {
    return true;
}
1
2
3
4
#include "CApp.h"
 
void CApp::OnEvent(SDL_Event* Event) {
}
1
2
3
4
#include "CApp.h"
 
void CApp::OnLoop() {
}
1
2
3
4
#include "CApp.h"
 
void CApp::OnRender() {
}
1
2
3
4
#include "CApp.h"
 
void CApp::OnCleanup() {
}



Now lets go back to our CApp.cpp code to link all of these functions together:
 

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "CApp.h"
 
CApp::CApp() {
    Running = true;
}
 
int CApp::OnExecute() {
    if(OnInit() == false) {
        return -1;
    }
 
    SDL_Event Event;
 
    while(Running) {
        while(SDL_PollEvent(&Event)) {
            OnEvent(&Event);
        }
 
        OnLoop();
        OnRender();
    }
 
    OnCleanup();
 
    return 0;
}
 
int main(int argc, char* argv[]) {
    CApp theApp;
 
    return theApp.OnExecute();
}

You'll notice some new variables, but let's look at what is happening first. First, we try to Initialize our game, if it fails we return -1 (an error code), thus closing our program. If everything is good, we continue on to the game loop. Within the game loop we use SDL_PollEvent to check for events, and pass them one at a time to OnEvent. Once done with Events, we go to OnLoop for move data around and what not, and then render our game. We repeat this indefinitly. If the user exits the game, we proceed to OnCleanup cleaning up any resources. Simple enough.

Now, lets look at SDL_Event and SDL_PollEvent. The first is a structure that holds information about events. The second is a function that will grab any events waiting in the queue. This queue can have any number of events, which is the reason why we have to loop through them. So, for example, lets say the user presses A and moves the mouse during the OnRender() function. SDL will detect this and put two events in the queue, one for a key press and one for a mouse move. We can grab this event from the queue by using the SDL_PollEvent, and then passing it to OnEvent to handle it accordingly. Once there are no more events in the queue, SDL_PollEvent will return false, thus exiting out of the Event queue loop.

The other variable added, Running, is our own. This is our exit out of the game loop. When this is set to false, it will end the program, and in turn exit the program. So, for example, if the user presses the Escape key we can set this variable to false, quitting the game.

You should be able to compile everything so far just fine, but you may notice you can't exit out. You'll probably have to use the task manager to end the program.

Now that everything is setup, let's start by creating the window our game will be drawn in. Jump over to CApp.h and add a SDL surface variable to the code:
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef _CAPP_H_
    #define _CAPP_H_
 
#include <SDL.h>
 
class CApp {
    private:
        bool            Running;
 
        SDL_Surface*    Surf_Display;
 
    public:
        CApp();
 
        int OnExecute();
 
    public:
        bool OnInit();
 
        void OnEvent(SDL_Event* Event);
 
        void OnLoop();
 
        void OnRender();
 
        void OnCleanup();
};
 
#endif

I suppose now would be a good time to explain exactly what a SDL Surface is. An SDL Surface is anything that can be drawn, or drawn to. Say we have a blank piece of paper, a pencil, and some stickers; this paper could be called our display "surface." We can draw to it, put stickers on it, or whatever. The stickers we have are also surfaces; we can draw on them and put other stickers on them as well. So, Surf_Display is simply our "piece of blank paper" that we will draw all our stuff on.

Now, lets jump on over to CApp_OnInit to actually create this surface:
 

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "CApp.h"
 
bool CApp::OnInit() {
    if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
        return false;
    }
 
    if((Surf_Display = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL) {
        return false;
    }
 
    return true;
}

The first thing we need to do is start up SDL itself, so we can access its functions. We are telling SDL to Initialize everything it has; there are other parameters you can pass, but understanding them at this point is not important. The next function we use is SDL_SetVideoMode. This bad boy is what creates our window, and our surface. It takes 4 parameters: The width of the window, the height of the window, the bit resolution of the window (recommended to be 16 or 32), and then display flags. There are quite a few display flags, but the ones shown above are fine for now. The first flag tells SDL to use hardware memory for storing our images and such, and the second flag tells SDL to use double buffering (which is important if you don't want flickering on your screen). Another flag that may interest you now is SDL_FULLSCREEN, which makes the window go fullscreen.

Now that our display is setup, lets cleanup a little bit to make sure everything works smoothly. Open up CApp_OnCleanup.cpp and add the following:
 

1
2
3
4
5
#include "CApp.h"
 
void CApp::OnCleanup() {
    SDL_Quit();
}

We basically quit out of SDL. You should take note that in this function is where you would free other surfaces as well. This keeps all your code centralized to the function its performing.

To keep things tidy, lets also set the Surf_Display pointer to NULL on the class constructor. Open up CApp.cpp and add the following:
 

1
2
3
4
5
CApp::CApp() {
    Surf_Display = NULL;
 
    Running = true;
}

Try compiling your code, and watching it work. You should have a nice blank window popup. You'll notice you can't close it though, so you'll need to use the task manager to do so.

Now that we have a window all setup, we're going to need a way to close it. Open up the CApp_OnEvent.cpp file, add the following:
 

1
2
3
4
5
6
7
#include "CApp.h"
 
void CApp::OnEvent(SDL_Event* Event) {
    if(Event->type == SDL_QUIT) {
        Running = false;
    }
}

The SDL event structure is broken down into types. These types can range from keypresses, to mouse movements; what we simply are doing here is checking the event type. The type above we are looking for is the request to close the window (i.e., when the user clicks the X button). If that event happens to take place, we set Running to false, thus ending our program. Simple enough. We'll look more into events in a later lesson.

Now, you should everything setup, and a good structure to work with later. It may be a good idea to take this project and turn it into an "SDL template" within CodeBlocks. I won't go over how to do that, but feel free to Google it.

Once you have a good idea what's going on with the code we covered in this lesson, jump over to the next game tutorial lesson to learn more about SDL surfaces.

 

[출처] http://www.sdltutorials.com/sdl-tutorial-basics

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
206 [MSA][Docker][Kubernetes] [Kubernetes] 윈도우10에 도커, 쿠버네티스 설치 (docker desktop) file 졸리운_곰 2021.05.23 32
» [C/C++, graphics] SDL Tutorial Basics 졸리운_곰 2021.05.15 51
204 C++ Simple BOOST Asynchronous ASIO Reverse Proxy file 졸리운_곰 2021.05.10 21
203 [MSA] [Docker] Docker File을 이용하여 Docker Image만들기 file 졸리운_곰 2021.04.27 25
202 [MSA][Docker] Docker 개념, 관리, 이미지생성까지 한번에!! file 졸리운_곰 2021.04.27 64
201 [죽기전에 경험해봐야 하는 미니 코어 리눅스 5가지] 5 tiny Linux distros to try before you die file 졸리운_곰 2021.04.25 14
200 [C/C++ 자료구조] 5일만에 뚝딱 스크립트 언어 만들기 PGLight (1/5) file 졸리운_곰 2021.04.12 23
199 [linux] vi 단축키 정리 / vim 학습자료 file 졸리운_곰 2021.04.04 42
198 [linux] VIM Editor 단축키 / 명령어 모음 졸리운_곰 2021.04.04 44
197 [MSA] 서비스 경량화를 위한 MSA 설계 시 고려사항 file 졸리운_곰 2021.03.21 72
196 [MSA][Docker] 효율적인 도커 이미지 만들기 #2 - 도커 레이어 캐슁을 통한 빌드/배포 속도 높이기 file 졸리운_곰 2021.03.21 22
195 [MSA][Docker] 효율적인 도커 이미지 만들기 #1 - 작은 도커 이미지 file 졸리운_곰 2021.03.21 25
194 [MSA] 오픈소스 모니터링 툴 - Prometheus #3 그라파나를 이용한 시각화 file 졸리운_곰 2021.03.21 185
193 [MSA] 오픈소스 모니터링 툴 - Prometheus #2 Hello Prometheus file 졸리운_곰 2021.03.21 27
192 [MSA] 오픈소스 모니터링툴 - Prometheus #1 기본 개념과 구조 file 졸리운_곰 2021.03.21 68
191 [MSA] API 게이트 웨이 & Google Cloud Endpoints file 졸리운_곰 2021.03.21 26
190 [MSA] Kong API gateway #3 - Kong on Kubernetes file 졸리운_곰 2021.03.21 45
189 [MSA] Kong API gateway #2 - 간단한 아키텍쳐와 API 테스트 file 졸리운_곰 2021.03.21 34
188 [MSA] Kong API gateway #1 - 설치와 둘러보기 file 졸리운_곰 2021.03.21 164
187 [MSA] Istio Traffic management file 졸리운_곰 2021.03.21 24
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED