20 марта 2013 в 17:08
Создание космической стрелялки в HGE – часть 3
Добро пожаловать в третью часть!
В этой части мы создадим врагов, сделаем обнаружение столкновений и эффекты.
Начнем с создания класса врага, он похож на класс игрока:
#ifndef C_ENEMY_H #define C_ENEMY_H #pragma once #include#include #include #define ENEMY_FRICTION 0.95 class c_enemy { private: static HGE* hge; hgeVector Position; hgeVector Velocity; hgeAnimation* Sprite; hgeRect BoundingBox; float Speed; float CenterY; float Radius; float Angle; bool bCenterYSet; bool bOscillate; short Health; public: c_enemy(hgeVector Position, hgeVector Velocity, short Health, HTEXTURE Texture); ~c_enemy(); bool Update(float delta); void Render(); short GetHealth() { return Health; }; void SetHealth(short health) { Health = health; }; void SetOscillate(bool Value) { bOscillate = Value; }; float GetSpeed() { return Speed; }; void SetSpeed(float speed) { Speed = speed; }; hgeRect GetBoundingBox() { return BoundingBox; }; hgeVector GetPosition() { return Position; }; }; #endif
Как вы могли заметить, мы заставим врага колебаться позже (менять направление движения), это сделает игру немного сложнее. Перед тем, как создать врага, я хочу отметить, что у нас есть несколько различных цветных текстур врага.
Каждый раз, когда объект врага создается, выберем случайным образом один из этих цветов. Но так как мы собираемся создавать довольно много врагов, мы предварительно загрузим эти текстуры в main.cpp.
Добавим объявление для текстур:
//Enemies HTEXTURE g_tEColors[5] = { 0 };
Загружаем их в память и удаляем их в конце:
//Enemies g_tEColors[0] = hge->Texture_Load("images/eSpritesheet_40x30.png"); g_tEColors[1] = hge->Texture_Load("images/eSpritesheet_40x30_hue1.png"); g_tEColors[2] = hge->Texture_Load("images/eSpritesheet_40x30_hue2.png"); g_tEColors[3] = hge->Texture_Load("images/eSpritesheet_40x30_hue3.png"); g_tEColors[4] = hge->Texture_Load("images/eSpritesheet_40x30_hue4.png"); //... for(short i = 0; i < 5; i++) hge->Texture_Free(g_tEColors[i]);
Хорошо, теперь мы можем приступить к написанию класса врага, мы начнем с конструктора и деструктора:
#include "c_enemy.h" HGE* c_enemy::hge = 0; c_enemy::c_enemy(hgeVector position, hgeVector velocity, short health, HTEXTURE Texture) : Position(position), Velocity(velocity), Health(health) { hge = hgeCreate(HGE_VERSION); Sprite = new hgeAnimation(Texture,6,6,0,0,40,30); Sprite->SetHotSpot(20,15); Sprite->Play(); Speed = 0.030; CenterY = 0; Radius = hge->Random_Float(50.0f,80.0f); Angle = 0.0f; bCenterYSet = false; bOscillate = false; } c_enemy::~c_enemy() { delete Sprite; hge->Release(); }
Теперь создадим функцию кадра, где будет обновляться логика врага:
bool c_enemy::Update(float delta) { Velocity.x *= ENEMY_FRICTION; Velocity.y *= ENEMY_FRICTION; Position.x += Velocity.x; if(!bOscillate) Position.y += Velocity.y; else { if(!bCenterYSet) { if(Velocity.y > -0.000001f && Velocity.y < 0.000001f) { CenterY = Position.y; bCenterYSet = true; } } Position.y = CenterY + sin(Angle) * Radius; Angle += 2 * delta; } Sprite->Update(delta); Velocity.x -= Speed; Sprite->GetBoundingBox(Position.x, Position.y, &BoundingBox); return false; }
Она очень похожа на функцию обновления основных расчетов движения пули, а также добавим возможность колебаться.
Теперь функция рисования на экране:
void c_enemy::Render() { Sprite->Render(Position.x, Position.y); }
Давайте добавим то что у нас получилось в наш main.cpp, мы начинаем включая класс и создавая список:
#include "c_enemy.h" //.. std::listEnemies;
И удаляем врагов в фунции System_Initiate:
for(auto i = Enemies.begin(); i != Enemies.end(); /**/) { delete (*i); i = Enemies.erase(i); }
Внутри функции кадра добавил создание врагов. Сделаем так, чтобы враги создавались, когда их количество меньше 5.
//Enemies if(Enemies.size() < 5) { short Health = hge->Random_Int(50, 100); c_enemy* Enemy = new c_enemy( hgeVector(830, hge->Random_Int(50,550)), hgeVector(-hge->Random_Int(2,8), hge->Random_Int(-4,4)), Health, g_tEColors[hge->Random_Int(0,4)]); Enemies.push_back(Enemy); }
Мы задаем случайным образом значение здоровья, возиции, скорости и текстуры, что придает игре более разнообразный геймплей. Так же, если враг улетел за пределы экрана, удаляем его:
for(auto i = Enemies.begin(); i != Enemies.end(); /**/) { if((*i)->GetPosition().x < 0 || (*i)->GetPosition().y > 580 || (*i)->GetPosition().y < 20) { delete (*i); i = Enemies.erase(i); } else { (*i)->Update(delta); i++; } } [.code] И в конце игры удаляем всех врагов. [code]//Enemies for(auto i = Enemies.begin(); i != Enemies.end(); i++) { (*i)->Render(); }
На следующем этапе добавим определение столкновений игрока, врагов и пуль. Используем для этого встроенные в HGE класс:
//Collision Bullet vs Enemy if(!Bullets.empty() && !Enemies.empty()) { for(auto i = Bullets.begin(); i != Bullets.end(); /**/) { bool bHit = false; for(auto x = Enemies.begin(); x != Enemies.end(); x++) { if((*x)->GetBoundingBox().Intersect(&(*i)->GetBoundingBox())) { (*x)->SetHealth((*x)->GetHealth() - (*i)->GetDamage()); delete (*i); i = Bullets.erase(i); bHit = true; break; } } if(!bHit) i++; } }
Тут в цикле мы удаляем врагов, чье здоровье стало меньше 0:
//Check Enemy's health for(auto i = Enemies.begin(); i != Enemies.end(); /**/) { if((*i)->GetHealth() <= 0) { delete (*i); i = Enemies.erase(i); } else i++; }
Здесь проверям столкновение игрока с врагом. Если это произошло, то уничтожаем их с анимацией взрыва и пересоздаем игрока.
//Enemy vs Player for(auto i = Enemies.begin(); i != Enemies.end(); /**/) { if((*i)->GetBoundingBox().Intersect(&Player1->GetBoundingBox())) { delete (*i); i = Enemies.erase(i); Player1->SetPosition(hgeVector(10,268)); Player1->SetVelocity(hgeVector(0,0)); } else i++; }
Теперь создадим эффект взрыва.
Добавим объявления в main.cpp:
HTEXTURE g_tExplosion = 0; HEFFECT g_eExplosion = 0;
Создадим для хранения эфффекта структуру:
struct explosion { hgeAnimation* Animation; hgeVector Position; }; std::listExplosions;
Очевидно, каждый взрыв нуждается в анимации и позиции. Мы сохраняя их в STD :: list. Также подготовим функции, которые мы будем описывать позже: CreateExplosion (hgeVector позиция);
Загрузим текстуры в память и освободим их впоследствии: (Внутри system_initiate)
//Explosion g_tExplosion = hge->Texture_Load("images/Explosion-Sprite-Sheet.png"); g_eExplosion = hge->Effect_Load("sounds/21410__heigh-hoo__blow.aif"); //... hge->Texture_Free(g_tExplosion); hge->Effect_Free(g_eExplosion); for(auto i = Explosions.begin(); i != Explosions.end(); /**/) { delete (*i).Animation; i = Explosions.erase(i); }
Пока все хорошо, давайте продолжим с создания функции взрыва:
void CreateExplosion(hgeVector Position) { explosion exp; exp.Animation = new hgeAnimation(g_tExplosion,5,10,0,0,118,118); exp.Animation->SetHotSpot(59,59); exp.Animation->Play(); exp.Position = Position; Explosions.push_back(exp); hge->Effect_PlayEx(g_eExplosion,100,0,hge->Random_Float(1,3)); }
Как вы можете видеть, мы создаем новый объект нашего взрыва и добавляем его в список. Мы также возпроизводим звук, который мы только что добавили в случайном поле, чтобы получить отличаются звуки. Мы не должны забывать, что необходимо обновить нашы взрывы в и функциях обновления и рендеринга:
for(auto i = Explosions.begin(); i != Explosions.end(); i++) { (*i).Animation->Render((*i).Position.x, (*i).Position.y); } //... for(auto i = Explosions.begin(); i != Explosions.end(); /**/) { if((*i).Animation->GetFrame() == 4) { delete (*i).Animation; i = Explosions.erase(i); } else { (*i).Animation->Update(delta); i++; } }
Вы можете добавить взрыв, куда угодно, как и к игрок против врага или когда здоровье противника равна нулю. Ну вот и все.
Результат части третьей:
22 мая 2013 в 20:34
А как сделать так, что бы игра запускалась на любом пк? Или тут обязательное требование Visual Studio и движка?
22 мая 2013 в 21:46
компилируешь в release моде...а не в debug
23 мая 2013 в 22:15
Спасибо большое за ответ ^^
29 сентября 2016 в 15:07
He bought the coach ofhttp://fastvr4.com/ , for sale vancouver holmes's name.
7 октября 2017 в 06:50
You are a really persuasive writer. I can see this in your writeup. You've a way of writing compelling info that sparks significantly interest.
25 ноября 2017 в 01:10
Thanks for any other informative web site. Where else may just I get that kind of information written in such an ideal way? I have a mission that I am just now operating on, and I have been on the look out for such information.
25 ноября 2017 в 01:11
Thanks for any other informative web site. Where else may just I get that kind of information written in such an ideal way? I have a mission that I am just now operating on, and I have been on the look out for such information.
30 декабря 2017 в 19:03
That alone wwas an egregious oversight on thheir own part, since
12 марта 2018 в 10:00
авторизуйтесь
или войдите через