Пишем собственный игровой движок с помощью C++
С нуля создадим собственный игровой движок с помощью библиотеки SFML и C++, чтобы разобраться, как происходит создание ядра.
В этом проекте мы создадим собственный игровой движок на C++. Движок будет очень простым, но готовым к расширению возможностей. Конечная игра с использованием этого кода тоже крайне проста: наш персонаж сможет перемещаться влево и право, а из графики – только бэкграунд и фигурка персонажа.
Подготовка Visual Studio
Создадим новый проект в Visual Studio. Обратите внимание, что проект требует библиотеку SFML , поэтому если вы не настраивали окружение для нее, прочтите сначала небольшое руководство по настройке.
- Откройте Visual Studio и выберите File | New Project. В левом меню отметьте язык C++ и шаблон HelloSFML. Назовите проект Simple Game Engine.
- Выберите правой кнопкой мыши файл HelloSFML.cpp в окне Solution Explorer (под Source Files), далее – Rename и назовите файл Main. Это подходящее имя, так как файл будет содержать основную функцию.
- Откройте Main.cpp, удалите все содержимое файла.
- Переместите файл библиотеки SFML.dll из каталога Диск:\SFML\bin в Диск:\Visual Studio Stuff\Projects\Simple Game Engine\Simple Game Engine. Если названия в путях отличаются, вероятно, вы сделали отличную от руководства настройку.
Теперь можно приступить к коду. Исходный код и дополнительные ресурсы будут доступны на этой странице.
Проектируем собственный игровой движок
Самое важное – запуск движка, который будет происходить в файле Main.cpp, но им мы займемся немного позже.
Класс персонажа
Bob – простой класс для представления фигурки персонажа, управляемой игроком. Код класса будет легко расширяться, а что самое главное – его несложно переписать под любой другой игровой объект, который вы захотите добавить. Для этого потребуется заменить текстуру и описать поведение нового объекта в методе update().
Займемся заголовками класса. Выберите правой кнопкой Header Files в Solution Explorer и нажмите Add | New Item. В окне Add New Item выберите Header File (.h), затем в поле Name введите Bob. Нажмите Add и добавьте код заголовка класса:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849#pragma once#include using namespace sf; class Bob <// Все private переменные могут быть доступны только внутри объектаprivate: // Позиция Боба Vector2f m_Position; // Объявляем объект Sprite Sprite m_Sprite; // Добавдяем текстуру Texture m_Texture; // Логические переменные для отслеживания направления движения bool m_LeftPressed; bool m_RightPressed; // Скорость Боба в пикселях в секунду float m_Speed; // Открытые методыpublic: // Настраиваем Боба в конструкторе Bob(); // Для отправки спрайта в главную функцию Sprite getSprite(); // Для движения Боба void moveLeft(); void moveRight(); // Прекращение движения void stopLeft(); void stopRight(); // Эта функция будет вызываться на каждый кадр void update(float elapsedTime); >;
Здесь мы объявили объекты типа Texture и Sprite. Дальше мы свяжем эти объекты и любое действие на экране с объектом Sprite будет сопровождаться изображением Боба:
Кликните правой кнопкой, чтобы сохранить
Bob.cpp
Теперь приступим к описанию методов.
Выберите правой кнопкой мыши Source Files в Solution Explorer и откройте Add | New Item. В окне Add New Item кликните по C++ File (.cpp), а в поле Name укажите Bob.cpp. Теперь добавьте в файл код:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162#include «stdafx.h»#include «bob.h» Bob::Bob() <// Вписываем в переменную скорость Боба m_Speed = 400; // Связываем текстуру и спрайт m_Texture.loadFromFile(«bob.png»); m_Sprite.setTexture(m_Texture); // Устанавливаем начальную позицию Боба в пикселях m_Position.x = 500; m_Position.y = 800; > // Делаем приватный спрайт доступным для функции draw()Sprite Bob::getSprite() <return m_Sprite;> void Bob::moveLeft() <m_LeftPressed = true;> void Bob::moveRight() <m_RightPressed = true;> void Bob::stopLeft() <m_LeftPressed = false;> void Bob::stopRight() <m_RightPressed = false;> // Двигаем Боба на основании пользовательского ввода в этом кадре,// прошедшего времени и скоростиvoid Bob::update(float elapsedTime) <if (m_RightPressed) <m_Position.x += m_Speed * elapsedTime; > if (m_LeftPressed) <m_Position.x -= m_Speed * elapsedTime; > // Теперь сдвигаем спрайт на новую позицию m_Sprite.setPosition(m_Position); >
В конструкторе мы установили значение переменной m_Speed на 400. Это значит, что Боб пересечет экран шириной в 1920 пикселей за 5 секунд. Также мы загрузили файл Bob.png в Texture и связали его с объектом Sprite. В переменных m_Position.x и m_Position.y установлено начальное положение Боба.
Функция update обрабатывает два If. Первое If проверяет, нажата ли правая кнопка (m_RightPressed), а второе следит за левой (m_LeftPressed). В каждом If скорость (m_Speed) умножается на elapsedTime. Переменная elapsedTime рассчитывается в функции Start движка (класс Engine). Им мы и займемся далее.
Пишем класс Engine
Класс Engine будет контролировать все остальное.
Engine.h
Добавим заголовок. Откройте окно Add New Item (так же, как для класса Bob), выберите Header File (.h) и в поле Name введите Engine.h. Добавьте в файл следующий код:
12345678910111213141516171819202122232425262728293031#pragma once#include #include «Bob.h»; using namespace sf; class Engine
Класс библиотеки SFML, RenderWIndow, используется для рендера всего, что есть на экране. Переменные Sprite и Texture нужны для создания фона. Также в заголовке мы создали экземпляр класса Bob.
Engine.cpp
В Engine.cpp мы опишем конструктор и функцию start. Создайте файл класса так же, как для Bob.cpp, и добавьте в него код:
12345678910111213141516171819202122232425262728293031323334353637383940#include «stdafx.h»#include «Engine.h» Engine::Engine() <// Получаем разрешение экрана, создаем окно SFML и View Vector2f resolution; resolution.x = VideoMode::getDesktopMode().width; resolution.y = VideoMode::getDesktopMode().height; m_Window.create(VideoMode(resolution.x, resolution.y), «Simple Game Engine», Style::Fullscreen); // Загружаем фон в текстуру // Подготовьте изображение под ваш размер экрана в редакторе m_BackgroundTexture.loadFromFile(«background.jpg»); // Связываем спрайт и текстуру m_BackgroundSprite.setTexture(m_BackgroundTexture); > void Engine::start() <// Расчет времени Clock clock; while (m_Window.isOpen()) <// Перезапускаем таймер и записываем отмеренное время в dt Time dt = clock.restart(); float dtAsSeconds = dt.asSeconds(); input(); update(dtAsSeconds); draw(); >>
Функция конструктора получает разрешение экрана и разворачивает игру на весь экран с помощью m_Window.create. В конструкторе же загружается Texture и связывается с объектом Sprite.
Пример фонового изображения
Скачайте пример изображения или используйте любое другое на свое усмотрение. Переименуйте файл в background.jpg и поместите в каталог Simple Game Engine/Simple Game Engine.
Игровой цикл
Следующие три функции будут описаны каждая в своем файле, но при этом они должны быть частью Engine.h. Поэтому в начале каждого файла укажем директиву #include «Engine.h», так что Visual Studio будет знать, что мы делаем.
Обрабатываем пользовательский ввод
Создайте файл Input.cpp и добавьте в него код:
12345678910111213141516171819202122232425262728293031#include «stdafx.h»#include «Engine.h» void Engine::input() <// Обрабатываем нажатие Escape if (Keyboard::isKeyPressed(Keyboard::Escape)) <m_Window.close(); > // Обрабатываем нажатие клавиш движения if (Keyboard::isKeyPressed(Keyboard::A)) <m_Bob.moveLeft(); > else <m_Bob.stopLeft(); > if (Keyboard::isKeyPressed(Keyboard::D)) <m_Bob.moveRight(); > else <m_Bob.stopRight(); > >
Функция input обрабатывает нажатия клавиш через константу Keyboard::isKeyPressed, предоставляемую SFML. При нажатии Escape m_Window будет закрыто. Для клавиш A и D вызывается соответствующая функция движения.
Обновляем игровые объекты
Теперь опишем простую функцию update. Каждый игровой объект будет иметь собственную функцию update.
Создайте файл Update.cpp и добавьте в него код:
123456789#include «stdafx.h»#include «Engine.h» using namespace sf; void Engine::update(float dtAsSeconds) <m_Bob.update(dtAsSeconds);>
Поскольку у нас пока только один объект «Боб», мы вызываем только функцию m_Bob.update.
Отрисовка сцены
Это последняя функция класса Engine. Создайте файл Draw.cpp и добавьте в него код:
123456789101112131415#include «stdafx.h»#include «Engine.h» void Engine::draw() <// Стираем предыдущий кадр m_Window.clear(Color::White); // Отрисовываем фон m_Window.draw(m_BackgroundSprite); m_Window.draw(m_Bob.getSprite()); // Отображаем все, что нарисовали m_Window.display();>
Экран очищается методом clear, затем отрисовывается фон. Первым делом должен быть отрисован фон, чтобы потом поверх него можно было отрисовать Боба.
Запускаем движок в main()
Теперь вернемся к нашему Main.cpp. Время добавить в него немного кода:
1234567891011121314#include «stdafx.h»#include «Engine.h» int main() <// Объявляем экземпляр класса Engine Engine engine; // Вызываем функцию start engine.start(); // Останавливаем программу программу, когда движок остановлен return 0;>
Несколько слов в конце
Наш собственный игровой движок получился очень простым: он умеет только двигать главный объект и закрывать программу. Он не умеет обрабатывать столкновения, работать с интерфейсом и еще много чего. Однако он отлично описывает то, как строится ядро игрового проекта с нуля. К тому же, как мы уже выяснили, класс Bob расширяется и адаптируется под другие объекты, так что дайте волю фантазии и попробуйте поэкспериментировать с окружением.
Источник статьи: http://zen.yandex.ru/media/id/5cc85a99178ebe00b3e6ee65/pishem-sobstvennyi-igrovoi-dvijok-s-pomosciu-c-5ccf4562a8ac8300b3497c9f
Пишем собственный игровой движок с помощью C++
С нуля создадим собственный игровой движок с помощью библиотеки SFML и C++, чтобы разобраться, как происходит создание ядра.
В этом проекте мы создадим собственный игровой движок на C++. Движок будет очень простым, но готовым к расширению возможностей. Конечная игра с использованием этого кода тоже крайне проста: наш персонаж сможет перемещаться влево и право, а из графики – только бэкграунд и фигурка персонажа.
Подготовка Visual Studio
Создадим новый проект в Visual Studio. Обратите внимание, что проект требует библиотеку SFML, поэтому если вы не настраивали окружение для нее, прочтите сначала небольшое руководство по настройке.
- Откройте Visual Studio и выберите File | New Project. В левом меню отметьте язык C++ и шаблон HelloSFML. Назовите проект Simple Game Engine.
- Выберите правой кнопкой мыши файл HelloSFML.cpp в окне Solution Explorer (под Source Files), далее – Rename и назовите файл Main. Это подходящее имя, так как файл будет содержать основную функцию.
- Откройте Main.cpp, удалите все содержимое файла.
- Переместите файл библиотеки SFML.dll из каталога Диск:\SFML\bin в Диск:\Visual Studio Stuff\Projects\Simple Game Engine\Simple Game Engine. Если названия в путях отличаются, вероятно, вы сделали отличную от руководства настройку.
Теперь можно приступить к коду. Исходный код и дополнительные ресурсы будут доступны на этой странице.
Проектируем собственный игровой движок
Самое важное – запуск движка, который будет происходить в файле Main.cpp, но им мы займемся немного позже.
Класс персонажа
Bob – простой класс для представления фигурки персонажа, управляемой игроком. Код класса будет легко расширяться, а что самое главное – его несложно переписать под любой другой игровой объект, который вы захотите добавить. Для этого потребуется заменить текстуру и описать поведение нового объекта в методе update().
Займемся заголовками класса. Выберите правой кнопкой Header Files в Solution Explorer и нажмите Add | New Item. В окне Add New Item выберите Header File (.h), затем в поле Name введите Bob. Нажмите Add и добавьте код заголовка класса:
Здесь мы объявили объекты типа Texture и Sprite. Дальше мы свяжем эти объекты и любое действие на экране с объектом Sprite будет сопровождаться изображением Боба:
Кликните правой кнопкой, чтобы сохранить
Bob.cpp
Теперь приступим к описанию методов.
Выберите правой кнопкой мыши Source Files в Solution Explorer и откройте Add | New Item. В окне Add New Item кликните по C++ File (.cpp), а в поле Name укажите Bob.cpp. Теперь добавьте в файл код:
В конструкторе мы установили значение переменной m_Speed на 400. Это значит, что Боб пересечет экран шириной в 1920 пикселей за 5 секунд. Также мы загрузили файл Bob.png в Texture и связали его с объектом Sprite. В переменных m_Position.x и m_Position.y установлено начальное положение Боба.
Функция update обрабатывает два If. Первое If проверяет, нажата ли правая кнопка (m_RightPressed), а второе следит за левой (m_LeftPressed). В каждом If скорость (m_Speed) умножается на elapsedTime. Переменная elapsedTime рассчитывается в функции Start движка (класс Engine). Им мы и займемся далее.
Пишем класс Engine
Класс Engine будет контролировать все остальное.
Engine.h
Добавим заголовок. Откройте окно Add New Item (так же, как для класса Bob), выберите Header File (.h) и в поле Name введите Engine.h. Добавьте в файл следующий код:
Класс библиотеки SFML, RenderWIndow, используется для рендера всего, что есть на экране. Переменные Sprite и Texture нужны для создания фона. Также в заголовке мы создали экземпляр класса Bob.
Engine.cpp
В Engine.cpp мы опишем конструктор и функцию start. Создайте файл класса так же, как для Bob.cpp, и добавьте в него код:
Функция конструктора получает разрешение экрана и разворачивает игру на весь экран с помощью m_Window.create. В конструкторе же загружается Texture и связывается с объектом Sprite.
Пример фонового изображения
Скачайте пример изображения или используйте любое другое на свое усмотрение. Переименуйте файл в background.jpg и поместите в каталог Simple Game Engine/Simple Game Engine.
Игровой цикл
Следующие три функции будут описаны каждая в своем файле, но при этом они должны быть частью Engine.h. Поэтому в начале каждого файла укажем директиву #include «Engine.h», так что Visual Studio будет знать, что мы делаем.
Обрабатываем пользовательский ввод
Создайте файл Input.cpp и добавьте в него код:
Функция input обрабатывает нажатия клавиш через константу Keyboard::isKeyPressed, предоставляемую SFML. При нажатии Escape m_Window будет закрыто. Для клавиш A и D вызывается соответствующая функция движения.
Обновляем игровые объекты
Теперь опишем простую функцию update. Каждый игровой объект будет иметь собственную функцию update.
Создайте файл Update.cpp и добавьте в него код:
Поскольку у нас пока только один объект «Боб», мы вызываем только функцию m_Bob.update.
Отрисовка сцены
Это последняя функция класса Engine. Создайте файл Draw.cpp и добавьте в него код:
Экран очищается методом clear, затем отрисовывается фон. Первым делом должен быть отрисован фон, чтобы потом поверх него можно было отрисовать Боба.
Запускаем движок в main()
Теперь вернемся к нашему Main.cpp. Время добавить в него немного кода:
Несколько слов в конце
Наш собственный игровой движок получился очень простым: он умеет только двигать главный объект и закрывать программу. Он не умеет обрабатывать столкновения, работать с интерфейсом и еще много чего. Однако он отлично описывает то, как строится ядро игрового проекта с нуля. К тому же, как мы уже выяснили, класс Bob расширяется и адаптируется под другие объекты, так что дайте волю фантазии и попробуйте поэкспериментировать с окружением.
Источник статьи: http://proglib.io/p/cpp-game-engine/