Меню один из неотъемлемых элементов игровой разработки. Благодаря ему мы можем насытить игру множественными разделами такими важными как настройка игры или смена пользователя. Без игрового меню, проект выглядит путешествием через туннель, в котором есть вход и есть выход, а между ними игровой процесс без права выбора.
В этой статье я познакомлю Вас с моей разработкой простого игрового меню на базе мультимедийной библиотеки SFML и языка программирования С++.
Инструментарий разработчика
Перед тем как я познакомлю Вас с прототипом моего игрового меню. Я обязан посвятить Вас в перечень софта, который использовался мною для данной разработки.
Для разработки кода я использовал:
Интегрированную среду разработки Visual Studio 2022 c установленной рабочей нагрузкой "Разработка классических приложений на С++".
Свободная кроссплатформенная мультимедийная библиотека SFML 2.5.1 версия для Visual C++ 15 (2017) - 64-bit (Инструкция подключения библиотеки SFML.)
Графика и рабочие материалы (телеграмм канал).
Клонировать репозиторий полной версии проекта игровое меню (github).
Начинаем работу
Пишем класс игрового меню
Файл GameMenu.h
#pragma once
#include <SFML/Graphics.hpp>
namespace game {
class GameMenu
{
float menu_X; // Координаты меню по X
float menu_Y; // Координаты меню по Y
int menu_Step; // Расстояние между пунктами меню
int max_menu; // Максимальное количество пунктов меню
int size_font; // Размер шрифта
int mainMenuSelected; // Номер текущего пункта меню
sf::Font font; // Шрифт меню
// Динамический массив текстовых объектов названий пунктов меню
sf::Text* mainMenu;
sf::Color menu_text_color = sf::Color::White; // Цвет пунктов меню
sf::Color chose_text_color = sf::Color::Yellow; // Цвет выбора пункта меню
sf::Color border_color = sf::Color::Black; // Цвет обводки текста пунктов меню
// Настройка текста пунктов меню
// Параметры: ссылка на текстовый объект, текст, координаты текста
void setInitText(sf::Text& text, sf::String str, float xpos, float ypos);
// Ссылка на графическое окно
sf::RenderWindow& mywindow;
public:
// Конструктор
// Параметры: ссылка на графическое окно, координаты игрового меню по x и y
// количество пунктов меню, массив названий пунктов меню, размер шрифта, шаг между пунктами меню
GameMenu(sf::RenderWindow& window, float menux, float menuy,
int index, sf::String name[], int sizeFont = 60, int step = 80);
~GameMenu()
{
delete[] mainMenu;
}
void draw(); // Рисуем меню
void MoveUp(); // Перемещение выбора меню вверх
void MoveDown(); // Перемещение выбора меню вниз
// Цвет элементов игрового меню
void setColorTextMenu(sf::Color menColor, sf::Color ChoColor,
sf::Color BordColor);
void AlignMenu(int posx); // Выравнивание положения меню
int getSelectedMenuNumber() // Возвращает номер выбранного элемента меню
{
return mainMenuSelected;
}
};
}
Файл GameMenu.сpp
#include "GameMenu.h"
// метод настройки текстовых объектов пунктов игрового меню
void game::GameMenu::setInitText(sf::Text& text, sf::String str, float xpos, float ypos)
{
text.setFont(font); // шрифт
text.setFillColor(menu_text_color); // цвет
text.setString(str); // текст
text.setCharacterSize(size_font); // размер шрифта
text.setPosition(xpos, ypos); // координаты текстового объекта
text.setOutlineThickness(3); // толщина контура обводки текста
text.setOutlineColor(border_color); // цвет контура обводки текста
}
// Выравнивание пунктов меню по левому по правому по центру
void game::GameMenu::AlignMenu(int posx)
{
float nullx = 0;
for (int i = 0; i < max_menu; i++) {
switch (posx)
{
case 0:
nullx = 0; // выравнивание по правому краю от установленных координат
break;
case 1:
nullx = mainMenu[i].getLocalBounds().width; // по левому краю
break;
case 2:
nullx = nullx = mainMenu[i].getLocalBounds().width / 2; // по центру
break;
}
mainMenu[i].setPosition(mainMenu[i].getPosition().x - nullx, mainMenu[i].getPosition().y);
}
}
// Конструктор
game::GameMenu::GameMenu(sf::RenderWindow& window, float menux, float menuy,
int index, sf::String name[], int sizeFont, int step)
:mywindow(window), menu_X(menux), menu_Y(menuy), size_font(sizeFont), menu_Step(step)
{
// Загрузка шрифта
if (!font.loadFromFile("font/troika.otf")) exit(32);
max_menu = index; // Количество єлементов меню
mainMenu = new sf::Text[max_menu]; // Динамический массив пунктов меню
// Выстраиваем элементы меню
for (int i = 0, ypos = menu_Y; i < max_menu; i++, ypos += menu_Step) setInitText(mainMenu[i], name[i], menu_X, ypos);
mainMenuSelected = 0; // Задаём начальное положения выбраного пункта меню
// цвет выбраного пункта меню
mainMenu[mainMenuSelected].setFillColor(chose_text_color);
}
// перемещение выбора меню вверх
void game::GameMenu::MoveUp()
{
mainMenuSelected--;
// подсвечиваем выбранный пункт меню
if (mainMenuSelected >= 0) {
mainMenu[mainMenuSelected].setFillColor(chose_text_color);
mainMenu[mainMenuSelected + 1].setFillColor(menu_text_color);
}
else
{
mainMenu[0].setFillColor(menu_text_color);
mainMenuSelected = max_menu - 1;
mainMenu[mainMenuSelected].setFillColor(chose_text_color);
}
}
// перемещение выбора меню вниз
void game::GameMenu::MoveDown()
{
mainMenuSelected++;
// подсвечиваем выбранный пункт меню
if (mainMenuSelected < max_menu) {
mainMenu[mainMenuSelected - 1].setFillColor(menu_text_color);
mainMenu[mainMenuSelected].setFillColor(chose_text_color);
}
else
{
mainMenu[max_menu - 1].setFillColor(menu_text_color);
mainMenuSelected = 0;
mainMenu[mainMenuSelected].setFillColor(chose_text_color);
}
}
// рисуем элементы меню в графическом окне
void game::GameMenu::draw()
{
// перебираем для отрисовки существующие текстовые объекты пунктов меню
for (int i = 0; i < max_menu; i++) mywindow.draw(mainMenu[i]);
}
// назначение цвета элементам пунктов меню
void game::GameMenu::setColorTextMenu(sf::Color menColor, sf::Color ChoColor, sf::Color BordColor)
{
menu_text_color = menColor; // цвет пунктов меню
chose_text_color = ChoColor; // цвет выбраного пункта меню
border_color = BordColor; // цвет контура пунктов меню
for (int i = 0; i < max_menu; i++) {
mainMenu[i].setFillColor(menu_text_color);
mainMenu[i].setOutlineColor(border_color);
}
mainMenu[mainMenuSelected].setFillColor(chose_text_color);
}
Файл main.cpp
#include "GameMenu.h"
using namespace sf;
// функция настройки текста
void InitText(Text& mtext, float xpos, float ypos, String str, int size_font = 60,
Color menu_text_color = Color::White, int bord = 0, Color border_color = Color::Black);
// Функция перехода к игре
void GamеStart()
{
RenderWindow Play(VideoMode::getDesktopMode(), L"Уровень 1", Style::Fullscreen);
RectangleShape background_play(Vector2f(1920, 1080));
Texture texture_play;
if (!texture_play.loadFromFile("image/menu4.jpg")) exit(1);
background_play.setTexture(&texture_play);
while (Play.isOpen())
{
Event event_play;
while (Play.pollEvent(event_play))
{
if (event_play.type == Event::KeyPressed)
{
if (event_play.key.code == Keyboard::Escape) { Play.close(); }
}
}
Play.clear();
Play.draw(background_play);
Play.display();
}
}
// Функция настройки игры
void Options()
{
RenderWindow Options(VideoMode::getDesktopMode(), L"Настройки", Style::Fullscreen);
RectangleShape background_opt(Vector2f(1920, 1080));
Texture texture_opt;
if (!texture_opt.loadFromFile("image/menu1.jpg")) exit(2);
background_opt.setTexture(&texture_opt);
while (Options.isOpen())
{
Event event_opt;
while (Options.pollEvent(event_opt))
{
if (event_opt.type == Event::Closed) Options.close();
if (event_opt.type == Event::KeyPressed)
{
if (event_opt.key.code == Keyboard::Escape) Options.close();
}
}
Options.clear();
Options.draw(background_opt);
Options.display();
}
}
// Функция с описанием игры
void About_Game()
{
RenderWindow About(VideoMode::getDesktopMode(), L"О игре", Style::Fullscreen);
RectangleShape background_ab(Vector2f(VideoMode::getDesktopMode().width, VideoMode::getDesktopMode().height));
Texture texture_ab;
if (!texture_ab.loadFromFile("image/menu2.jpg")) exit(3);
background_ab.setTexture(&texture_ab);
while (About.isOpen())
{
Event event_play;
while (About.pollEvent(event_play))
{
if (event_play.type == Event::Closed) About.close();
if (event_play.type == Event::KeyPressed)
{
if (event_play.key.code == Keyboard::Escape) About.close();
}
}
About.clear();
About.draw(background_ab);
About.display();
}
}
int main()
{
// Создаём окно windows
RenderWindow window;
// Параметры: размер окна установить согласно текущему разрешению экрана
// название моя игра, развернуть графическое окно на весь размер экрана
window.create(VideoMode::getDesktopMode(), L"Моя игра", Style::Fullscreen);
//отключаем видимость курсора
window.setMouseCursorVisible(false);
// получаем текущий размер экрана
float width = VideoMode::getDesktopMode().width;
float height = VideoMode::getDesktopMode().height;
// Устанавливаем фон для графического окна
// Создаём прямоугольник
RectangleShape background(Vector2f(width, height));
// Загружаем в прямоугольник текстуру с изображением menu9.jpg
Texture texture_window;
if (!texture_window.loadFromFile("image/menu9.jpg")) return 4;
background.setTexture(&texture_window);
// Устанавливаем шрифт для названия игры
Font font;
if (!font.loadFromFile("font/troika.otf")) return 5;
Text Titul;
Titul.setFont(font);
// Текст с названием игры
InitText(Titul, 480, 50, L"Апокалипсис", 150, Color(237, 147, 0), 3);
// Название пунктов меню
String name_menu[]{ L"Старт",L"Настройки", L"О игре",L"Выход"};
// Объект игровое меню
game::GameMenu mymenu(window, 950, 350, 4, name_menu, 100, 120);
// Установка цвета элементов пунктов меню
mymenu.setColorTextMenu(Color(237, 147, 0), Color::Red, Color::Black);
// выравнивание по центру пунктов меню
mymenu.AlignMenu(2);
while (window.isOpen())
{
Event event;
while (window.pollEvent(event))
{
if (event.type == Event::KeyReleased)
{
// События выбра пунктов меню
// нажати на клавиатуре стрелки вверх
if (event.key.code == Keyboard::Up) { mymenu.MoveUp(); }
// нажати на клавиатуре стрелки вниз
if (event.key.code == Keyboard::Down) { mymenu.MoveDown(); }
// нажати на клавиатуре клавиши Enter
if (event.key.code == Keyboard::Return)
{
// Переходим на выбранный пункт меню
switch (mymenu.getSelectedMenuNumber())
{
case 0:GamеStart(); break;
case 1:Options(); break;
case 2:About_Game(); break;
case 3:window.close(); break;
}
}
}
}
window.clear();
window.draw(background);
window.draw(Titul);
mymenu.draw();
window.display();
}
return 0;
}
// функция настройки текста
void InitText(Text& mtext, float xpos, float ypos, String str, int size_font,
Color menu_text_color, int bord, Color border_color)
{
mtext.setCharacterSize(size_font);
mtext.setPosition(xpos, ypos);
mtext.setString(str);
mtext.setFillColor(menu_text_color);
mtext.setOutlineThickness(bord);
mtext.setOutlineColor(border_color);
}
Более подробную инструкцию вы можете получить посмотрев видео "Игровое меню SFML C++ ".
Комментарии (3)
fire64
12.01.2023 16:27Понятно, что меню написано с использованием библиотеки SFML, но все же ностальгией повеяло, когда люди сами писали игры, а не использовали готовые движки типа Unity, GoDot, Unreal engine и прочих.
podsvirov
12.01.2023 22:40-1Третий пункт мерю для игры Апокалипсис следует исправить на: Об игре. Предлог Об пишется перед словом начинающимися на гласную букву.
Wolf4D
Зачем в статье этот огромный кусок кода, если есть репозиторий? Никакого смысла в нём нет.