이젠, 우리는 저번시간에 배운 SDL 초기화를 각 함수로 나누고 클래스화 시킬 수 있다.

 

다음과 같이 Game Class를 만들 수 있다.

 

 

<Game.h>

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
33
34
35
#ifndef __GAME__
#define __GAME__
#include <SDL.h>
 
class Game
{
public:
    Game();
    ~Game();
 
    // 전체 파라미터를 받아서 초기화, 마지막 파라미터는 SDL_CreateWindow()의 Flag이다.
    bool Init(const char* parTitle, int parXPos, int parYpos, int parWidth, int parHeight, int parFlags);
    // 마지막 파라미터를 전체화면을 나타내는 bool값으로 바꾼 Init function.
    bool Init(const char* parTitle, int parXPos, int parYpos, int parWidth, int parHeight, bool parFullscreen);
 
 
    void Render();
    void Update();
    void HandleEvents();
    void Clean();
 
 
    // a function to access the private running variable
    bool isRunning();
 
private:
 
    SDL_Window* m_pWindow;
    SDL_Renderer* m_pRenderer;
 
    bool m_bRunning;
};
 
#endif // !__GAME__
 
cs

<Game.cpp>

 

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "Game.h"
#include <iostream>
 
// 생성자와 소멸자는 C++ 기초임으로 설명하지 않는다.
// Constructor
Game::Game()
{
}
// Destructor
Game::~Game()
{
}
 
bool Game::Init(const char* parTitle, int parXPos, int parYpos, int parWidth, int parHeight, int parFlags)
{
    // attempt to initialize SDL
    if (SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
        std::cout << "SDL init success\n";
        // init the window
        m_pWindow = SDL_CreateWindow(parTitle, parXPos, parYpos,
            parWidth, parHeight, parFlags);
        if (m_pWindow != 0// window init success
        {
            std::cout << "window creation success\n";
            m_pRenderer = SDL_CreateRenderer(m_pWindow, -10);
            if (m_pRenderer != 0// renderer init success
            {
                std::cout << "renderer creation success\n";
                // 파란색 화면.
                SDL_SetRenderDrawColor(m_pRenderer, 00255255);
            }
            else
            {
                std::cout << "renderer init fail\n";
                return false// renderer init fail
            }
        }
        else
        {
            std::cout << "window init fail\n";
            return false// window init fail
        }
    }
    else
    {
        std::cout << "SDL init fail\n";
        return false// SDL init fail
    }
 
    std::cout << "init success\n";
    m_bRunning = true// everything inited successfully, start the main loop
    return true;
}
 
bool Game::Init(const char* parTitle, int parXPos, int parYpos, int parWidth, int parHeight, bool parFullscreen)
{
    int flags = 0;
    if (parFullscreen)
    {
        flags = SDL_WINDOW_FULLSCREEN;
    }
 
    return Init(parTitle, parXPos, parYpos, parWidth, parHeight, flags);
}
 
void Game::Render()
{
    SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
 
    // RenderClear 와 RenderPresent 사이에 렌더링 할 부분을 넣는다.
 
 
    SDL_RenderPresent(m_pRenderer); // draw to the screen
}
 
void Game::Update()
{
    // 이번 단원에서는 update할 것이 없다.
}
 
void Game::HandleEvents()
{
    SDL_Event event;
    if (SDL_PollEvent(&event))
    {
        switch (event.type)
        {
            case SDL_QUIT:
                m_bRunning = false;
                break;
            default:
                break;
        }
    }
}
 
void Game::Clean()
{
    std::cout << "cleaning game\n";
    SDL_DestroyWindow(m_pWindow);
    SDL_DestroyRenderer(m_pRenderer);
    SDL_Quit();
}
 
bool Game::isRunning()
{
    return m_bRunning;
}
 
cs

 

<Main Fucntion>

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "Game.h"
 
int main(int argc, char* args[])
{
    // 게임 객체 생성
    Game* game = new Game();
 
    if (game->Init("SDL TEST"100100640480false))
    {
        while (game->isRunning())
        {
            game->HandleEvents();
            game->Update();
            game->Render();
        }
        game->Clean();
    }
    return 0;
}
cs

 

실행하면 다음과 같은 결과를 얻는다.

 

 

 

 

 

게임의 기본적임 메커니즘(mechanics)은 다음과 같다.

Game Mechanics

그래서 초기화 이후 반복문을 이용하여, Input, Update, Render를 반복한다.

 

 

 

다음은 SDL_CreateWindow(title, xpos, ypos, width, height, flags); 의 Flags이다.

 

 

출처: SDL Game Development  Shaun Ross Mitchell 

'C++ > SDL' 카테고리의 다른 글

4. SDL TextureManager 만들기(Singleton, 이미지 그리기)  (0) 2021.03.03
3. SDL 에서 그림 그리기.  (0) 2021.03.01
1. Hello SDL (SDL 초기화)  (0) 2021.03.01

SDL 링크 설정을 한 후 다음과 같이 코딩한다.

 

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <SDL.h>
 
SDL_Window *g_pWindow = 0;
SDL_Renderer* g_pRenderer = 0;
 
int main(int argc, char* args[])
{
    // initialize SDL
    if (SDL_Init(SDL_INIT_EVERYTHING) >= 0)
    {
        // if succeeded create our window, 윈도우 생성
 
        // SDL_CreateWindow(윈도우창 제목, 좌표x, 좌표y, width 크기, height 크기, flags)
        g_pWindow = SDL_CreateWindow("Chapter 1: Setting up SDL",
            SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
            640480,
            SDL_WINDOW_SHOWN);
 
        // if the window creation succeeded create our renderer
        if (g_pWindow != 0)
        {
            // 랜더러 생성
            // 랜더러 생성
            g_pRenderer = SDL_CreateRenderer(g_pWindow, -10);
        }
    }
    else
    {
        return 1// sdl could not initialize, 초기화 실패시
    }
 
    // everything succeeded lets draw the window, 모두 성공적이라면,
 
    // set to black // This function expects Red, Green, Blue and
    // Alpha as color values , 빨간색, 초록색, 파란색, 알파(투명도)
    SDL_SetRenderDrawColor(g_pRenderer, 000255);
 
    // clear the window to black,
    SDL_RenderClear(g_pRenderer);
 
    // show the window 윈도우 보여주기
    SDL_RenderPresent(g_pRenderer);
 
    // set a delay before quitting 딜레이 5초
    SDL_Delay(5000);
 
    // clean up SDL, SDL 종료
    SDL_Quit();
 
    return 0;
}
cs

이후, 디버깅은 모드는 32비트와 64비트가 있지만,

일반적으로 32비트로 빌드 한다.

 

실행을 시켜보면 다음과 같은 에러가 발생한다.

 

말그대로 SDL2.dll 이 없어서 발생한 에러임으로 해당 dll을 추가 시켜준다.

해당 파일은 SDL 라이브러리에 포함되어 있다.

 

 

 

SDL_Init Function에는 다음과 같은 플레그를 사용 할 수 있다.

 

물론 다음과 같이 사용 할 수 있다.

 

SDL이 Init이 되었는지 안되었는지 다음 Function으로 확인 가능하다.

 

 

 

다음은 SDL_Renderer Flag 이다.

 

 

 

출처: SDL Game Development  Shaun Ross Mitchell 

우리는 다음과 같이 키 페드를 다음과 설정할 수 있다.

 

위 Function은 매 프레임마다 불리울 수 있다.

 

하지만 많은 게임들이 유저에게 키 설정을 제공하기 때문에 위와 같이 코딩한다면 키 설정을 제공 하기 어렵다.

 

그래서

 

아래와 같이 Interface를 클래스를 사용할 수 있다.

그리고 이것을 Command 패턴이라 부른다.

 

그 다음

Subclass를 만들어 준다.

 

 

우리의 InputHandler에서 우리는 각 커맨드 버튼 객체에 포인트를 저장 할 수 있다.

 

이제, 우리의 HandleInput function은 다음과 같다.

NULL 채크는 각자의 몫이다.

 

 

하지만

 

위의 방식은 어느정도의 제약이 있을 수 있다.

 

위는 오직 플레이어의 움직이만 제어할 수 있다.

만약, 플레이어 외에 적들이라던지 다른 객체의 움직임을 위해서는 다음과 같이 수정한다.

 

단순히 함수를 부르는것 대신, 우리가 움직이기 원하는 객체를 넣는다.

 

GameActor를 매개변수로 넣어서 제어한다.

 

 

 

이제는, 우리의 HandlerInput()은 Command를 리턴한다.

 

그다음, 우리는 Command를 실행시키는 코드가 필요한다.

 

 

이제 우리는 플레이어가 어떤 Actor든지 넣을 Actor를 변경시키으로써 제어할 수 있다.

 

 

 

 

출저: Game Programming Patters, Robert Nystrom

 

 

+ Recent posts