Как стать автором
Обновить

Игровое меню SFML C++

Время на прочтение 7 мин
Количество просмотров 11K

Предыдущая тема

Следующая тема

Меню один из неотъемлемых элементов игровой разработки. Благодаря ему мы можем насытить игру множественными разделами такими важными как настройка игры или смена пользователя.  Без игрового меню, проект выглядит путешествием через туннель, в котором есть вход и есть выход, а между ними игровой процесс без права выбора.

В этой статье я познакомлю Вас с моей разработкой простого игрового меню на базе мультимедийной библиотеки SFML и языка программирования С++.

Инструментарий разработчика

Перед тем как я познакомлю Вас с прототипом моего игрового меню. Я обязан посвятить Вас в перечень софта, который использовался мною для данной разработки.

Для разработки кода я использовал:

Интегрированную среду разработки Visual Studio 2022 c установленной рабочей нагрузкой "Разработка классических приложений на С++".

Язык программирования С++14

Свободная кроссплатформенная мультимедийная библиотека 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++ ".

Клонировать репозиторий

Телеграмм канал "Программирование игр С++ / С#"

Предыдущая тема

Следующая тема

Теги:
Хабы:
+1
Комментарии 3
Комментарии Комментарии 3

Публикации

Истории

Работа

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн