Game Menu SFML C++

Previous topic

The menu is one of the integral elements of game development. Thanks to him, we can saturate the game with multiple sections as important as setting up the game or changing the user. Without the game menu, the project looks like a journey through a tunnel with an entrance and an exit, and between them there is a game process without the right to choose.

In this article, I will introduce you to my development of a simple game menu based on the SFML multimedia library and the C++ programming language.

Developer Toolkit

Before I introduce you to the prototype of my game menu. I am obliged to dedicate you to the list of software that I used for this development.

For code development I used:

Visual Studio 2022 IDE with the “Desktop C++ Development” workload installed.

C++14 programming language

Free cross-platform multimedia library SFML 2.5.1 version for Visual C++ 15 (2017) – 64-bit (Instructions for connecting the SFML library.)

Graphics and working materials (telegram channel).

Clone the repository of the full version of the game menu project (github).

Getting Started

Writing a game menu class

GameMenu.h file

#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;
		}
	};
}

File GameMenu.cpp

#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 file

#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);
}

You can get more detailed instructions by watching the video “Game Menu SFML C++ “.

Clone repository

Telegram channel “Programming games C++ / C#”

Previous topic

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *