Игры и движки2.1 SystemCore - Application


2.1 SystemCore — Application

Думаю из названия понятно, что в этом уроке будет рассматриваться системное ядро, а конкретнее его составляющая — приложение.
В этом уроке начнем писать движок и разработаем класс приложения.

Писать все я буду в своем любимом Code::Blocks 10.05

(сейчас будет пояснение о том как сделать все с самих азов, позже сделаю урок по разным IDE)

2.1.1 Подготовка

И так запускаем IDE, создаем новый проект (там есть кнопочка Create New Project), выбираем Empty project, потом next, указываем название проекту (я указал New_Engine_v0.1), указываем компилятор — GNU GCC Compiler и жмем Finish.

этот двиг почему то я назвал FEngine, называйте как хотите, я выбрал такое название

Теперь надо создать следующие файлы — main.cpp FEngine.h SystemCore.h cApplication.cpp cApplication.h Public.h Public.cpp

main.cpp — в этом файле будем тестировать наш движок

FEngine.h — этот файл у меня содержит линковку всех библиотек, всех ядер и других фалов

SystemCore.h — этот файл линкует все составляющие системного ядра

cApplication.h
cApplication.cpp
— эти файлы содержат класс для работы приложения

Public.h
Public.cpp
— этот файл я сделал для того что бы ложить туда разные переменные которые не относятся к какому либо классу и они требуются для работы юзера

2.1.2 Разбираемся и пишем код

И так, в main.cpp нам нужно написать только

#include "FEngine.h" //линкуем наш диг

using namespace FEngine; //используем пространство имен нашего движка

int main()//эээ..всем ясно =))
{
}


Тут все предельно просто

дальше пишем FEngine.h

#ifndef ENGINE_H //это сделано для того что бы имена не повторялись
#define ENGINE_H

#include <GL/gl.h> //линки библиотек с которыми мы будем работать
#include <GL/glu.h> //..
#include <SDL/SDL.h> //..

#include "Public.h" //линкем наш файл с переменными

#include "SystemCore.h" //линкуем наше системное ядро

#endif


все предельно просто =)

теперь SystemCore.h

#ifndef SYSTEMCORE_H
#define SYSTEMCORE_H

//все тоже самое
#include "FEngine.h"
#include "cApplication.h"

#endif


кто то может сказать что я делаю лишнее создавая отдельные файлы для каждого ядра, но блин и классы ведь все можно в одном файле записать, по моему так красивее будет, и удобнее

в Public.h и Public.cpp сейчас лежит только переменная хранящая в себе клавиши, но не все, все было лень писать, вы и сами сможете дописать остальные.

Public.h

//тут тоже все предельно просто
#ifndef PUBLIC_H
#define PUBLIC_H

#include "FEngine.h"

namespace systemCore //указываем в какому пространству имен принадлежит все что ниже
{

enum keydown { //создаем перечисление keydown в котором хранятся названия клавиш
//так сказать сделали свою переменную
    EK0, EK_1, EK_2, EK_3, EK_4, EK_5, EK_6, EK_7, EK_8, EK_9, EK_0,

    EK_F1, EK_F2, EK_F3, EK_F4, EK_F5, EK_F6, EK_F7, EK_F8, EK_F9, EK_F10, EK_F11, EK_F12,

    EK_CAPSLOCK, EK_SPACE, EK_ESCAPE,

    EK_Q, EK_W, EK_E, EK_R, EK_T, EK_Y, EK_U, EK_I, EK_O, EK_P, EK_A, EK_S, EK_D,
        EK_F, EK_G, EK_H, EK_J, EK_K, EK_L, EK_Z, EK_X, EK_C, EK_V, EK_B, EK_N, EK_M, null
    };
extern keydown KeyDown; //делаем глобальной переменную KeyDown

};

#endif


Public.cpp

#include "Public.h"

namespace systemCore
{

keydown             KeyDown; //указываем что переменная KeyDown имеет тип keydown
//позже мы сможем смотреть какая клавиша нажата через переменную KeyDown

};


Ну вот и подошли мы к тому что будем писать класс приложения.

Заходим в файл cApplication.h ну и пишем:

#ifndef APPLICATION_H //все как обычно
#define APPLICATION_H

#include "SystemCore.h"

namespace systemCore
{

enum state_cursore {SHOW, HIDE}; //этот тип хранит скрыть или показать, 
//позже пригодится

class cApplication //создаем класс
{
public:
    cApplication();//конструктор
    ~cApplication();//деструктор
};

};
#endif


но это как вы поняли это еще не весь код =))
будем ити медленно
что нам нужно сначала написать?
конечно переменные, какие переменные нам понадобятся?


public:
    bool Runing; //если true то приложение работает

private:
    int Width; //ширина приложения
    int Height; // высота приложения
    int BPP; // это показывает какое количество цветов будет 32 или 16

    bool Fullscreen; //полноэкранный режим или нет

    char* Caption; //название окна
    SDL_Surface* Icon; //иконка

    SDL_Surface* Surface; //это область окна
    SDL_Event    Event; //это переменная событий


думаю все ясно =)

в спп файле пишем следующее:

cApplication::cApplication()
{
    Runing              = true;

    Fullscreen          = false;

    Caption             = "FEngine";
    Icon                = NULL;

    Surface             = NULL;
}

cApplication::~cApplication()
{
}


тут мы просто указываем какие значения должны быть когда программа запустится

теперь будем писать методы, все методы у нас публичные

и так нам в начале главным образом надо вот эти 4 метода:

bool Init();//в принципе тут тоже самое что и в конструкторе
bool Run();//тут будет обработка клавиш и проверка на выход из программы
bool Reset();//этим мы будем перезагружать программу, например изменив некоторые 
//параметры запустив этот метод они будут применены, вы  наверное выдели такое в 
//настройках какой нить игры, там есть такая кнопочка применить, после нажатия все 
//параметры которые вы ставили применяются
void Shutdown()//метод завершения программы
;

реализуем эти методы(cApplication.cpp):

bool cApplication::Init()
{
    bool Runing             = true;

    bool Fullscreen         = false;

    Caption                 = "FEngine";
    SDL_Surface* Icon       = NULL;

    SDL_Surface* Surface    = NULL;
}

bool cApplication::Reset()
{
    SDL_WM_SetCaption(Caption, NULL);
    SDL_WM_SetIcon(Icon, NULL);

    if(Fullscreen == true)
    {
        if((Surface = SDL_SetVideoMode(Width, Height, BPP, SDL_OPENGL | SDL_FULLSCREEN)) == NULL)
            return false;
    }
    else
    {
        if((Surface = SDL_SetVideoMode(Width, Height, BPP, SDL_OPENGL)) == NULL)
            return false;
    }
}

void cApplication::Shutdown()
{
    SDL_Quit();
    delete this;
}


Я думаю тут пояснять ничего не надо, и так все понятно из кода

а теперь метод Run

bool cApplication::Run()
{
    SDL_PollEvent(&Event);//тут мы обрабатываем события

    KeyDown = null; //устанавливаем что не нажата никакая клавиша

    switch(Event.type) //смотрим какие события сейчас происходят
    {
        case SDL_QUIT: {return false;}break; //события закрытия программы, как 
//только оно то мы сразу завершаем работу

        case SDL_KEYDOWN: //нажатие клавиш
        {
            switch(Event.key.keysym.sym) //смотрим какая клавиша нажата
            {//если нажата клавиша то мы переменной KeyDown передаем эту клавишу
//в итоге у нас переменная KeyDown хранит нажатую клавишу
                case SDLK_0:            KeyDown = EK_0;             break;
                case SDLK_1:            KeyDown = EK_1;             break;
                case SDLK_2:            KeyDown = EK_2;             break;
                case SDLK_3:            KeyDown = EK_3;             break;
                case SDLK_4:            KeyDown = EK_4;             break;
                case SDLK_5:            KeyDown = EK_5;             break;
                case SDLK_6:            KeyDown = EK_6;             break;
                case SDLK_7:            KeyDown = EK_7;             break;
                case SDLK_8:            KeyDown = EK_8;             break;
                case SDLK_9:            KeyDown = EK_9;             break;

                case SDLK_F1:           KeyDown = EK_F1;            break;
                case SDLK_F2:           KeyDown = EK_F2;            break;
                case SDLK_F3:           KeyDown = EK_F3;            break;
                case SDLK_F4:           KeyDown = EK_F4;            break;
                case SDLK_F5:           KeyDown = EK_F5;            break;
                case SDLK_F6:           KeyDown = EK_F6;            break;
                case SDLK_F7:           KeyDown = EK_F7;            break;
                case SDLK_F8:           KeyDown = EK_F8;            break;
                case SDLK_F9:           KeyDown = EK_F9;            break;
                case SDLK_F10:          KeyDown = EK_F10;           break;
                case SDLK_F11:          KeyDown = EK_F11;           break;
                case SDLK_F12:          KeyDown = EK_F12;           break;

                case SDLK_CAPSLOCK:     KeyDown = EK_CAPSLOCK;      break;
                case SDLK_SPACE:        KeyDown = EK_SPACE;         break;
                case SDLK_ESCAPE:       KeyDown = EK_ESCAPE;        break;

                case SDLK_q:            KeyDown = EK_Q;             break;
                case SDLK_w:            KeyDown = EK_W;             break;
                case SDLK_e:            KeyDown = EK_E;             break;
                case SDLK_r:            KeyDown = EK_R;             break;
                case SDLK_t:            KeyDown = EK_T;             break;
                case SDLK_y:            KeyDown = EK_Y;             break;
                case SDLK_u:            KeyDown = EK_U;             break;
                case SDLK_i:            KeyDown = EK_I;             break;
                case SDLK_o:            KeyDown = EK_O;             break;
                case SDLK_p:            KeyDown = EK_P;             break;
                case SDLK_a:            KeyDown = EK_A;             break;
                case SDLK_s:            KeyDown = EK_S;             break;
                case SDLK_d:            KeyDown = EK_D;             break;
                case SDLK_f:            KeyDown = EK_F;             break;
                case SDLK_g:            KeyDown = EK_G;             break;
                case SDLK_h:            KeyDown = EK_H;             break;
                case SDLK_j:            KeyDown = EK_J;             break;
                case SDLK_k:            KeyDown = EK_K;             break;
                case SDLK_l:            KeyDown = EK_L;             break;
                case SDLK_z:            KeyDown = EK_Z;             break;
                case SDLK_x:            KeyDown = EK_X;             break;
                case SDLK_c:            KeyDown = EK_C;             break;
                case SDLK_v:            KeyDown = EK_V;             break;
                case SDLK_b:            KeyDown = EK_B;             break;
                case SDLK_n:            KeyDown = EK_N;             break;
                case SDLK_m:            KeyDown = EK_M;             break;
            }
        }break;
    }

    if(Runing){ return true;} else{ return false}; //смотрим, если программа работает то возвращаем true иначе false 
}


как видите ничего сложного

теперь разберем эти методы:

void SetCaption(char* caption);//вызываем этот метод и указываем 
//какое название будет у окна
    void SetIcon(SDL_Surface* icon); //указываем иконку

    void SetSizeWindow(int width, int height); //указываем размер
    void SetBPP(int bpp); //указываем BPP

    void Cursor(state_cursore state); //можем скрыть или показать курсор
//если передать этому методу HIDE то курсор будет скрыт а если SHOW то показан

    void ToggleFullscreenMode(); //вызываем когда хотим перейти в широкоэкранный
    void ToggleWindowMode();
//оконный режим

реализуем эти методы:

тут все очень просто, мы просто глобальным переменным передаем переданные значения

void cApplication::SetCaption(char* caption)
{
    Caption = caption;
}

void cApplication::SetIcon(SDL_Surface* icon)
{
    Icon = icon;
}

void cApplication::SetSizeWindow(int width, int height)
{
    Width       = width;
    Height      = height;
}

void cApplication::SetBPP(int bpp)
{
    BPP = bpp;
}

void cApplication::Cursor(state_cursore state)
{
    if(state == SHOW)
        SDL_ShowCursor(SDL_ENABLE);
    else if(state == HIDE)
        SDL_ShowCursor(SDL_DISABLE);
}

void cApplication::ToggleFullscreenMode()
{
    Fullscreen = true;
}

void cApplication::ToggleWindowMode()
{
    Fullscreen = false;
}


ну и наконец то последний метод это метод создания окна:

bool CreateWindow(int width, int height, int bpp);


и его реализация:

bool cApplication::CreateWindow(int width, int height, int bpp)
{
    Width     = width;
    Height    = height;
    BPP       = bpp;

    if(SDL_Init(SDL_INIT_VIDEO) < 0)
        return false;

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,    1);

    SDL_WM_SetCaption(Caption, NULL);
    if(Fullscreen == true)
    {
        if((Surface = SDL_SetVideoMode(Width, Height, BPP, SDL_OPENGL | SDL_FULLSCREEN)) == NULL)
            return false;
    }
    else
    {
        if((Surface = SDL_SetVideoMode(Width, Height, BPP, SDL_OPENGL)) == NULL)
            return false;
    }
}


тут все очень просто так что я думаю объяснять не нужно

2.1.3 Итоги
Теперь вы можете в main.cpp
создать приложение очень малым количеством строк, вот пример:

#include "FEngine.h"

using namespace systemCore;

cApplication* app = new cApplication();

void Keydown()
{
    switch(KeyDown)
    {
        case EK_ESCAPE:
        {
            app->Runing = false;
        }break;
    }
}

int main()
{
    app->Init();

    app->CreateWindow(800, 600, 32);

    while(app->Run())
    {
        Keydown();
    }

    app->Shutdown();
}


как видите приложение работает нормально, при нажатии на Esc приложение закрывается

на этом урок закончен, надеюсь он вам помог хоть чем нубуть
  • +5
  • isaer
  • 03 февраля 2011, 02:34

Вставка изображения

Комментарии (5)

rss свернуть / развернуть
  • avatar
  • OniKy
  • 03 февраля 2011, 16:21
  • #
  • 0
а я думал на с# будет код)

свернуть ветку
но все равно) хороший урок)

свернуть ветку
я шарп плохо знаю, но там я понимаю тоже самое, немного изенить придется, главное это сделать ПУСТОЕ приложение

свернуть ветку
Отличный урок!!! Я из него почерпнул много интересного. =)
SDL правда для меня загадка.((

свернуть ветку
рад помоч =))

свернуть ветку
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.