14 февраля 2013 в 12:13
Создание космической стрелялки в HGE – часть 2
В этой части, мы создадим объект игрока, который будет управляемым, а также пули и звуковые эффекты. Давайте подумаем, как создать классы для этого. Для этого мы создам переменные для физики, текстуры и спрайты. Так же напишем класс для обнаружения столкновения.
#ifndef C_PLAYER_H #define C_PLAYER_H #pragma once #include#include #include #define PLAYER_FRICTION 0.95 class c_player { private: static HGE* hge; hgeVector Position; hgeVector Velocity; HTEXTURE Texture; hgeAnimation* Sprite; hgeRect BoundingBox; //необходимо для обнаружения столкновений float Speed;
Нам еще нужно несколько методов доступа к этим значениям:
public: c_player(hgeVector Position, hgeVector Velocity); ~c_player(); bool Update(float delta); void Render(); void SetVelocity(hgeVector velocity) { Velocity = velocity; }; void SetPosition(hgeVector position) { Position = position; }; hgeRect GetBoundingBox() { return BoundingBox; }; hgeVector GetPosition() { return Position; }; }; #endif
Давайте начнем с конструктора и деструктора:
#include "c_player.h" HGE* c_player::hge = 0; c_player::c_player(hgeVector position, hgeVector velocity) : Position(position), Velocity(velocity) { hge = hgeCreate(HGE_VERSION); //Get interface to hge Texture = hge->Texture_Load("images/Spritesheet_64x29.png"); Sprite = new hgeAnimation(Texture,4,4,0,0,64,29); Sprite->SetHotSpot(32,14.5); Sprite->Play(); Speed = 0.15; }
Сначала мы получаем интерфейс HGE, чтобы мы могли загрузить текстуры и прочее. Затем мы создаем анимацию (hgeAnimation) с четырьмя кадрами и четыре кадра в секунду. Затем мы устанавливаем хот-спот точку для анимации, которая является центром для масштабирования, поворота и положения. Напишем Sprite->Play();, чтобы запустить анимацию. Speed - это скорость. Деструктор в значительной степени понятен, все, что мы хотим сделать - это здесь очистить наши ресурсы, которые мы использовали и удалить интерфейс HGE:
c_player::~c_player() { hge->Texture_Free(Texture); delete Sprite; hge->Release(); }
Давайте объявим функцию для обновления расчетов:
(Velocity * Friction && Position * Velocity)
bool c_player::Update(float delta) { Velocity.x *= PLAYER_FRICTION; Velocity.y *= PLAYER_FRICTION; Position.x += Velocity.x; Position.y += Velocity.y;
Далее мы хотим сделать его подвижным для пользователя, мы будем использовать AWSD и клавиши со стрелками для передвижения. Мы проверяем ввод с помощью Input_GetKeyState функции, она возвращает истину, если указанная кнопка нажата, иначе возвращает ложь. Мы также хотим сделать так, чтобы игрок не мог улететь за пределы экрана. Если кнопка нажата, мы будем увеличивать или уменьшать скорость: (Примечание: M_PI является предопределенным значением в hge.h)
if(hge->Input_GetKeyState(HGEK_A) || hge->Input_GetKeyState(HGEK_LEFT) && Position.x > 32) Velocity.x -= (Speed * M_PI) /2; if(hge->Input_GetKeyState(HGEK_D) || hge->Input_GetKeyState(HGEK_RIGHT) && Position.x < 800) Velocity.x += (Speed * M_PI) /2; if(hge->Input_GetKeyState(HGEK_W) || hge->Input_GetKeyState(HGEK_UP) && Position.y > 0) Velocity.y -= (Speed * M_PI) /2; if(hge->Input_GetKeyState(HGEK_S) || hge->Input_GetKeyState(HGEK_DOWN) && Position.y < 600) Velocity.y += (Speed * M_PI) /2;
На следующем шаге мы хотим держать игрока внутри экрана, если он покидает экран - отражаем перемещение в обратную сторону:
if(Position.x > 800) { Position.x -= 1; Velocity.x = -Velocity.x; }; if(Position.x < 0) { Position.x += 1; Velocity.x = -Velocity.x; }; if(Position.y < 0) { Position.y += 1; Velocity.y = -Velocity.y; }; if(Position.y > 600) { Position.y -= 1; Velocity.y = -Velocity.y; };
Теперь мы хотим обновить нашу анимацию и BoundingBox. Функция должна возвращать ложь, иначе игра остановится.
Sprite->Update(delta); Sprite->GetBoundingBox(Position.x, Position.y, &BoundingBox); return false; }
Рисуем игрока на экране:
void c_player::Render() { Sprite->Render(Position.x, Position.y); }
Теперь реалиузем наш класс игрока в main.cpp:
Сначала добавим объявление нашего класса и переменную указатель:
#include "c_player.h" //.. c_player* Player1 = NULL;
В функции кадра добавьте эту строку в самый верх:
(Timer_GetDelta() возвращает время, прошедшее с последнего вызова функции кадра)
float delta = hge->Timer_GetDelta();
а это в нижней части, чтобы обновить логику игрока:
Player1->Update(delta);
Рисуем игрока внутри функции Render:
Player1->Render();
Внутри System_Initiate мы создаем и удаляем наш объект игрока:
Player1 = new c_player(hgeVector(10, 268), hgeVector(5,0)); //... delete Player1;
Вот теперь у нас получился управляемый космический корабль.
Пули
Мы снова начанем с создания нового класса для пули:
#ifndef C_BULLET_H #define C_BULLET_H #pragma once #include#include #include #include #define BULLET_FRICTION 0.99 class c_bullet { private: static HGE* hge; hgeVector Position; hgeVector Velocity; hgeSprite* Sprite; hgeRect BoundingBox; float Speed; short Damage;
почти те же переменные, как указано в класса игрока, в дополнение к ним, мы добавим несколько переменных
float CenterY; float Radius; float Angle; bool bCenterYSet; bool bOscillate; bool bOscillateReverse;
Определим координаты центра пули. Радиус и угол должен быть известен. Давайте добавим несколько методов класса:
public: c_bullet(hgeVector Position, hgeVector Velocity, HTEXTURE &Texture, short Damage); ~c_bullet(); void Update(); void Render(); void SetDamage(short damage) { Damage = damage; }; short GetDamage() { return Damage; }; void SetOscillateReverse(bool Value) { bOscillateReverse = Value; }; void SetOscillate(bool Value) { bOscillate = Value; }; hgeRect GetBoundingBox() { return BoundingBox; }; hgeVector GetPosition() { return Position; }; }; #endif
Так как мы будем использовать много пуль мы не будем создавать текстуру каждый раз, мы ее подгрузим раньше в main.cpp.
c_bullet::c_bullet(hgeVector position, hgeVector velocity,HTEXTURE &Texture, short damage) : Position(position), Velocity(velocity), Damage(damage) { hge = hgeCreate(HGE_VERSION); Sprite = new hgeSprite(Texture,0,0,6,3); Sprite->SetHotSpot(3,1.5); Speed = 0.15; CenterY = 0; Radius = hge->Random_Float(50.0f,80.0f); Angle = 0.0f; bCenterYSet = false; bOscillate = false; bOscillateReverse = true; }
В деструктора удалим используемые ресурсы.
c_bullet::~c_bullet() { delete Sprite; hge->Release(); }
Создадим фуннкцию обновления логики пули:
void c_bullet::Update() { Velocity.x *= BULLET_FRICTION; Velocity.y *= BULLET_FRICTION; Position.x += Velocity.x; if(!bOscillate) Position.y += Velocity.y; else { if(!bCenterYSet) { CenterY = Position.y; bCenterYSet = true; } if(!bOscillateReverse) Position.y = CenterY - sin(Angle) * Radius; else Position.y = CenterY + sin(Angle) * Radius; Angle += 5 * hge->Timer_GetDelta(); } Sprite->GetBoundingBox(Position.x, Position.y, &BoundingBox); }
И функции рисования пули:
void c_bullet::Render() { Sprite->Render(Position.x, Position.y); }
Добавим заголовки класса пули и создадим список указателей на пули.
#include//... #include "c_bullet.h" //... std::list
Bullets; HTEXTURE g_tBullet = 0;
В функции обновления добавим создание выстрела при нажатом пробеле и удаление пуль, если они улетели за пределы экрана.
if(hge->Input_KeyDown(HGEK_SPACE)) { //Single shot c_bullet* Bullet = new c_bullet(Player1->GetPosition() + hgeVector(16,0), hgeVector(15,0), g_tBullet, 10); Bullets.push_back(Bullet); } for(auto i = Bullets.begin(); i != Bullets.end(); /**/) { (*i)->Update(); if((*i)->GetPosition().x > 800 || (*i)->GetPosition().x < 0 || (*i)->GetPosition().y < 0 || (*i)->GetPosition().y > 600) i = Bullets.erase(i); else i++; }
В функции рисования проходимся циклом по списку пуль и русуем их на экране:
for(auto i = Bullets.begin(); i!= Bullets.end(); i++) { (*i)->Render(); }
далее подгружаем текстуры пули и добавим их удалиние внутри System_Initiate:
g_tBullet = hge->Texture_Load("images/bullet.png"); //... hge->Texture_Free(g_tBullet); for(auto i = Bullets.begin(); i != Bullets.end(); /**/) { delete (*i); i = Bullets.erase(i); }
Результат стрельбы
Звук
Таким образом, чтобы добавить звук первое, что вам нужно, сделать, это скопировать bass.dll из
hge->System_SetState(HGE_USESOUND, true);
Для каждого звукака мы будем использовать три отдельных звуковых файла:
внутрь main.cpp добавим:
//Sounds HEFFECT g_eBGMusic = 0; HEFFECT g_eBGMusic2 = 0; HEFFECT g_eBGMusic3 = 0;
Внутри System_Initiate добавим подгрузку и удаление звуков:
//Sounds g_eBGMusic = hge->Effect_Load("sounds/134707__atanasiu__deepspace-sonification.ogg"); g_eBGMusic2 = hge->Effect_Load("sounds/158733__panzertank15__spaceambient.ogg"); g_eBGMusic3 = hge->Effect_Load("sounds/108929__soulman-90__ambience-space.ogg"); hge->Effect_PlayEx(g_eBGMusic, 40, 0, 0, true); hge->Effect_PlayEx(g_eBGMusic2, 100, 0, 0, true); hge->Effect_PlayEx(g_eBGMusic3, 10, 0, 0, true);
Запустим звуки с разной громкостью для создания окружения и зациклим их воспроизведение.
Удаление звуков:
hge->Effect_Free(g_eBGMusic); hge->Effect_Free(g_eBGMusic2); hge->Effect_Free(g_eBGMusic3);
Звук стрельбы попробуйте добавить сами.
Результат части 2:
24 мая 2013 в 22:53
Не удается открыть файл include: c_player.h: No such file or directory
что делать?
24 мая 2013 в 23:03
Configuration -> C++ -> Additional Include Directories -> прописать путь до c_player.h
24 мая 2013 в 23:17
перепроверьте пожалуйста в исходниках код в main.сpp, слишком много ошибок выдаёт... а после ещё раз пройдитесь по уроку.
24 мая 2013 в 23:18
заранее спасибо =^_^=
27 мая 2013 в 12:33
что именно не правильно? через страницу контакты пришли свою версию, заменим)
3 июля 2014 в 18:29
Там ошибка, хотя в исходниках всё правильно, видимо автор просто опечатался:
Вместо std::list Bullets; должно быть std::list<c_bullet*> Bullets;
29 сентября 2016 в 15:32
I may be wrong, but I think that it is to early in the product cycle for there to be generichttp://fastvr4.com/ , .
20 февраля 2017 в 17:27
I'm really impressed with your writing skills as well as with the layout on your blog. Is this a paid theme or did you customize it yourself? Anyway keep up the excellent quality writing, its rare to see a great blog like this one these days..
20 февраля 2017 в 17:42
I'm really impressed with your writing skills as well as with the layout on your blog. Is this a paid theme or did you customize it yourself? Anyway keep up the excellent quality writing, its rare to see a great blog like this one these days..
28 марта 2017 в 13:12
Kegunaan alley chicago order etodolac onlinehttp://buyvia2.com/ , contraindications for use .
6 мая 2017 в 04:13
Ultimately, a dilemma that I'm passionate about. I have looked for data of this caliber for the previous various hours. Your internet site is greatly appreciated.
6 мая 2017 в 04:13
Ultimately, a dilemma that I'm passionate about. I have looked for data of this caliber for the previous various hours. Your internet site is greatly appreciated.
14 октября 2017 в 15:55
Hello, always i used to check blog posts here in the early hours in the daylight,
1 декабря 2017 в 16:07
May work faster, and for men for whomhttp://viagraomz.com/ , failed.
8 января 2018 в 15:41
Pretty great post. I just stumbled upon your blog and wanted
8 января 2018 в 15:42
Pretty great post. I just stumbled upon your blog and wanted
11 апреля 2018 в 12:36
Journeys tohttp://onlineviphs.com/ , , whose generic name for adc restocking processes �provide.
авторизуйтесь
или войдите через