Создание космической стрелялки в  HGE – часть 1

Создание космической стрелялки в HGE – часть 1

Для создания подобной игры необходимы базовые знания c++.

Часть 1 включает:
-Создание проекта
-Создание окна
-Создание прокрутки фона

За 3 урока мы создадим целую игру, видео ниже:
http://www.youtube.com/

Прежде чем мы сможем начать, мы должны установить проект. Я буду использовать Microsoft Visual Studio 2012 во время этого урока.
1) Скачать полный HGE 1,81 отсюда.
2) Извлечь файлы из архива.
3) Запустите Visual Studio, выберите File -> New -> Project -> Templates -> Visual C + + -> Win32 Project -> нажмите OK
Фото
New project dialog

4) Now the Win32 Application Wizard will popup, click next, select “Empty project” and deselect “Security Development Lifecycle (SDL) checks” and press Finish. A new project should be created now.
Сейчас мастер приложений Win32 откроет всплывающее окно, нажмите кнопку Далее, выберите "Empty project" и снимите флажок "Security Development Lifecycle (SDL) checks" и нажмите кнопку Finish. Новый проект должен быть создан.
Фото
Application Wizard

Next, we need to include HGE into our project. Go into the Solution Explorer, right-click on the project and select properties. Inside the property pages navigate to VC++ Directories and edit the Include Directories. Add the path to HGE’s include files here “ \hge181\include”, do the same for library directories and add the path to HGE’s library’s: “ \hge181\lib\vc”. Press apply but keep the dialog open.

5) Далее, мы должны подключить HGE к нашему проекту. Идите в Solution Explorer, щелкните правой кнопкой мыши на проекте и выберите Свойства. Внутри страницы свойств перейдите на VC++ Directories и отредактируйте Include Directories. Добавьте путь к заголовочным HGE файлам, лежат здесь "<путь куда распаковали>\hge181\include", сделать то же самое для библиотечных каталогов и добавить путь к HGE библиотеке: "<путь куда распаковали>\hge181\lib\vc". Нажмите кнопку Применить, но не закрывайте окно.
Фото
Include + Lib directories

Then, we include the library’s in the linking process. Navigate to Linker -> Input -> Additional Dependencies, add “hge.lib” and “hgehelp.lib”. You also have to add “libc.lib” to the ignore list (Ignore specific default libraries) press apply, again keep the dialog open.
6) Затем мы подключим библиотеки в процесс связывания. Перейдите к Linker -> Input -> Additional Dependencies и добавить "hge.lib" и "hgehelp.lib". Вы также должны добавить "libc.lib" в список игнорирования (Ignore specific default libraries) нажмите Применить, но не закрывайте окно.
Фото
Library dependencies

7) В качестве последнего шага, перейдите к General and set the character и установить набор символов Multi-Byte. Нажмите Применить. Теперь мы закончили создание проекта!
Фото
Multi-byte character set

Создание окна приложения
Мы собираемся создать основное окно с черным фоном, на следующем этапе мы будем наполнять ее чем-нибудь полезным. Во-первых, мы должны включить заголовк hge.h, создать указатель, чтобы сохранить его интерфейс и инициализировать его нулем:

#include 
 
HGE*    hge = NULL;

Затем мы создаем наши функции кадра и рендеринга, в функции кадра мы будем обрабатывать нашу логику. Функции рендеринга предназначена для рисования вещей на экране, она всегда должна возвращать ложь. 
Функция кадра должна возвращать логическое значение, если возвращает истину - HGE остановит выполнение цикла игры. Если ложь - игровой цикл будет продолжен.

bool FrameFunc()
{
    //Check whether escape has been pressed or not
    if (hge->Input_GetKeyState(HGEK_ESCAPE)) return true;
    return false;
}
 
bool RenderFunc()
{
    hge->Gfx_BeginScene();
    hge->Gfx_Clear(0);
    //..
    hge->Gfx_EndScene();
    return false;
}

Давайте в функции WinMain мы получим указатель на интерфейс HGE.

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    hge = hgeCreate(HGE_VERSION);

Затем мы устанавливаем в HGE настройки среды, большинство из этих состояний системы имеют соответствующие значения по умолчанию, мы должны установить по крайней мере, HGE_FRAMEFUNC и HGE_RENDERFUNC, чтобы движок работал и рисовал что то.

    hge->System_SetState(HGE_FRAMEFUNC, FrameFunc);
    hge->System_SetState(HGE_RENDERFUNC, RenderFunc);
    hge->System_SetState(HGE_WINDOWED, true);
    hge->System_SetState(HGE_USESOUND, false);
    hge->System_SetState(HGE_FPS, HGEFPS_VSYNC);
    hge->System_SetState(HGE_TITLE, "Spaceshooter Tutorial");

Сейчас мы инициируем HGE, функция System_Initiate вернет ложь, если что-то пойдет не так. Более конкретные описания того, что пошло не так, может быть получено функцией System_GetErrorMessage. После успешного старта HGE мы начинаем цикл игры функцией System_Start.

if(hge->System_Initiate())
{
    hge->System_Start();
}
else
{
    MessageBox(NULL, hge->System_GetErrorMessage(), "Error", MB_OK | MB_ICONERROR | MB_APPLMODAL);
}

Если клавиша ESC была нажата, или окно было закрыто, то цикл игры завершится. Это означает, что мы должны освободить все занятые ресурсы и HGE интерфейс:

    hge->System_Shutdown();
    hge->Release();
 
    return 0;
}

Теперь вы готовы к компиляции кода, чтобы запустить его нужно скопировать и hge.dll и bass.dll из " \hge181\" в исполняемого каталог.

Вывод прокручивающегося фона
Итак, давайте взглянем на наш фон, он состоит из двух частей

Фото
Подложка

Фото
Звезды

Мы хотим, чтобы "Подложка" бесконечно повторялась, чтобы создать иллюзию бесконечного пространства. Мы просто будем рисовать наш фон два раза и поиграем с координатами. Красная площадь является видимой областью фона.
Фото
Scrolling Background sketch

Приступим к реализации. Мы начнем с добавления двух заголовочных файлов (hgesprite.h и hgevector.h) и несколько глобальных переменных.

#include 
#include 
#include 
 
HGE*    hge = NULL;
 
//Background
HTEXTURE    g_tBackground       = 0;
HTEXTURE    g_tStars            = 0;
 
hgeSprite*  g_sBackground       = NULL;
hgeSprite*  g_sStars            = NULL;
 
hgeVector   g_vBGPosition       = hgeVector(0,0);


//Внутри WinMain, прямо  под hge->System_Initiate мы будем инициализировать эти переменные
if(hge->System_Initiate())
{
    //Background
    g_tBackground   = hge->Texture_Load("images/farback.jpg");
    g_tStars        = hge->Texture_Load("images/starfield.png");
 
    g_sBackground   = new hgeSprite(g_tBackground, 0, 0, 1782, 600);
    g_sStars        = new hgeSprite(g_tStars, 0, 0, 800, 600);
 
    g_vBGPosition   = hgeVector(-982, 0);
 
    hge->System_Start();


//И, конечно, удалять их после
//Cleanup..
    hge->Texture_Free(g_tBackground);
    hge->Texture_Free(g_tStars);
 
    delete g_sBackground;
    delete g_sStars;
}

Мы инициализируем положение фона (g_vBGPosition) с координатой х -982, это потому, что мы начинаем с правой стороны, а прокрутку будем осуществлять вправо. (Фон 1782px шириной и наше окно 800px, 1782 - 800 = 982)Давайте отобразим его, в функции рендеринга мы добавляем этот код между Gfx_Clear и Gfx_EndScene

g_sBackground->Render(g_vBGPosition.x,g_vBGPosition.y);
g_sStars->Render(0,0);

Вы должны поместить изображение "farback.jpg" и "starfield.png" в директории вашего приложения в "

images\", как только вы это сделали, вы можете запустить игру и должны увидеть это
Фото
Static background

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

#define BACKGROUND_SCROLLING_SPEED  0.105f

Мы также должны изменить функцию кадра, так как наша логика работает там. Добавьте следующий код над Input_GetKeyState

//Background
if(g_vBGPosition.x < 800) g_vBGPosition.x += BACKGROUND_SCROLLING_SPEED;
else g_vBGPosition  = hgeVector(-982,0);

Добавьте следующий код в функции кадра после g_sBackground->Render():

if(g_vBGPosition.x > -1)     g_sBackground->Render(g_vBGPosition.x - 982 - 800, 0);

Что мы здесь делаем? Вы должны видеть, что мы рисуем фон дважды теперь, как только его позиция становится больше -1. Мы рисуем второй фон справа после первого (первый с-982px смещением, мы просто добавим -800px). Т.е. мы крутим фон постоянно, сначала 1, потом 2, потом снова 1.
Фото
Background gap

Разрыв Фона
Как вы заметили,у нас есть небольшая разница в цвете на обоих концах при прокрутке страницы, чтобы исправить это необходимо следующее изображение: (bg_gapfix.jpg, переместить его в \images\)
Фото
Gapfix

Мы нарисуем эту картинку выше, чтобы скрыть дефекты. Итак, давайте добавим еще две переменные для этого

HTEXTURE    g_tBGGapFix         = 0;
hgeSprite*  g_sBGGapFix         = NULL;


//Инициализация  и удаление их  в WinMain:
g_tBGGapFix     = hge->Texture_Load("images/bg_gapfix.jpg");
g_sBGGapFix     = new hgeSprite(g_tBGGapFix, 0, 0, 64, 600);
 
//...
 
hge->Texture_Free(g_tBGGapFix);
delete g_sBGGapFix;

И, конечно, применим это в функций рендеринга

g_sBGGapFix->Render(g_vBGPosition.x - 28, 0);

-28 Это смещение точно скрывает цветовые различия.

Когда вы запустите игру, увидите, что есть гладкий фон без пробелов или цветовых различий.
Но прежде чем мы закончим эту часть, давайте добавим некоторые эффекты к звездам, они должны исчезать и дать ему хороший внешний вид. Добавим три переменные и два определения

bool        g_bBGFadeIn         = false;
bool        g_bBGFadeOut        = true;
short       g_nBGAlpha          = 255;
#define BACKGROUND_ALPHA_MIN        50
#define BACKGROUND_ALPHA_MAX        255

А в кадре мы добавим это, для контроля fade эффекта.

if(g_bBGFadeOut)
{
    g_nBGAlpha -= 2;
 
    if(g_nBGAlpha <= BACKGROUND_ALPHA_MIN)
    {
        g_bBGFadeOut = false;
        g_bBGFadeIn  = true;
    }
}
else if(g_bBGFadeIn)
{
    g_nBGAlpha += 2;
 
    if(g_nBGAlpha >= BACKGROUND_ALPHA_MAX)
    {
        g_bBGFadeOut = true;
        g_bBGFadeIn  = false;
    }
}
g_sStars->SetColor(ARGB(g_nBGAlpha,255,255,255));

Вот и все.

Полный исходный код:

Full source code of this tutorial part:

//========= Tutorial: Creating a spaceshooter in HGE – Part 1 ============//
 
#include 
#include 
#include 
 
HGE*    hge = NULL;
 
#define BACKGROUND_SCROLLING_SPEED  0.105f
#define BACKGROUND_ALPHA_MIN        50
#define BACKGROUND_ALPHA_MAX        255
 
//Background
HTEXTURE    g_tBackground       = 0;
HTEXTURE    g_tBGGapFix         = 0;
HTEXTURE    g_tStars            = 0;
 
hgeSprite*  g_sBackground       = NULL;
hgeSprite*  g_sBGGapFix         = NULL;
hgeSprite*  g_sStars            = NULL;
 
hgeVector   g_vBGPosition       = hgeVector(0,0);
 
bool        g_bBGFadeIn         = false;
bool        g_bBGFadeOut        = true;
short       g_nBGAlpha          = 255;
 
bool FrameFunc()
{
    //Background
    if(g_vBGPosition.x < 800) g_vBGPosition.x += BACKGROUND_SCROLLING_SPEED;
    else g_vBGPosition  = hgeVector(-982,0);
 
    if(g_bBGFadeOut)
    {
        g_nBGAlpha -= 2;
 
        if(g_nBGAlpha <= BACKGROUND_ALPHA_MIN)
        {
            g_bBGFadeOut = false;
            g_bBGFadeIn  = true;
        }
    }
    else if(g_bBGFadeIn)
    {
        g_nBGAlpha += 2;
 
        if(g_nBGAlpha >= BACKGROUND_ALPHA_MAX)
        {
            g_bBGFadeOut = true;
            g_bBGFadeIn  = false;
        }
    }
    g_sStars->SetColor(ARGB(g_nBGAlpha,255,255,255));
 
    if (hge->Input_GetKeyState(HGEK_ESCAPE)) return true;
    return false;
}
 
bool RenderFunc()
{
    hge->Gfx_BeginScene();
    hge->Gfx_Clear(0);
 
    g_sBackground->Render(g_vBGPosition.x,g_vBGPosition.y);
    if(g_vBGPosition.x > -1)     g_sBackground->Render(g_vBGPosition.x - 982 - 800, 0);
    g_sBGGapFix->Render(g_vBGPosition.x - 28, 0);
 
    g_sStars->Render(0,0);
 
    //..
 
    hge->Gfx_EndScene();
    return false;
}
 
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    hge = hgeCreate(HGE_VERSION);
    hge->System_SetState(HGE_FRAMEFUNC, FrameFunc);
    hge->System_SetState(HGE_RENDERFUNC, RenderFunc);
    hge->System_SetState(HGE_WINDOWED, true);
    hge->System_SetState(HGE_USESOUND, false);
    hge->System_SetState(HGE_FPS, HGEFPS_VSYNC);
    hge->System_SetState(HGE_TITLE, "Spaceshooter Tutorial");
 
    if(hge->System_Initiate())
    {
        //Background
        g_tBackground   = hge->Texture_Load("images/farback.jpg");
        g_tBGGapFix     = hge->Texture_Load("images/bg_gapfix.jpg");
        g_tStars        = hge->Texture_Load("images/starfield.png");
 
        g_sBackground   = new hgeSprite(g_tBackground, 0, 0, 1782, 600);
        g_sBGGapFix     = new hgeSprite(g_tBGGapFix, 0, 0, 64, 600);
        g_sStars        = new hgeSprite(g_tStars, 0, 0, 800, 600);
 
        g_vBGPosition   = hgeVector(-982, 0);
 
        hge->System_Start();
 
        //Cleanup..
        hge->Texture_Free(g_tBackground);
        hge->Texture_Free(g_tBGGapFix);
        hge->Texture_Free(g_tStars);
 
        delete g_sBackground;
        delete g_sBGGapFix;
        delete g_sStars;
    }
    else
    {
      MessageBox(NULL, hge->System_GetErrorMessage(), "Error", MB_OK | MB_ICONERROR | MB_APPLMODAL);
    }
 
    hge->System_Shutdown();
    hge->Release();
 
    return 0;
}