Witam!
Do tworzenia napisów w SFML używam własnej klasy (większość podanych niżej funkcji nie ma nic wspólnego z tym pytaniem):
// Caption.h
#pragma once
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <sstream>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <Windows.h>
using namespace sf;
using namespace std;
void loadFont(Font &font, string path); // Ładowanie czcionki
string intToString(int number);
int stringToInt(string text);
string convertToPolishChars(string text);
void setColorConsoleFont(unsigned int color);
bool isNumeric(string number); // Zwraca true jeśli cały napis jest liczbą całkowitą i nie posiada liter ani znaków specjalnych
bool isNumeric(char number); // Zwraca true jeśli dany znak jest liczbą
class Caption : public Text
{
public:
Caption();
Caption(Font & font, string text = "", float x = 0, float y = 0, int size = 20);
~Caption();
//void setCaptionOptions()
};
// Caption.cpp
#include "Caption.h"
Caption::Caption()
{
this->setCharacterSize(20);
}
Caption::Caption(Font & font, string text, float x, float y, int size)
{
this->setFont(font);
if (text != "") this->setString(text);
if (size != 20) this->setCharacterSize(size);
if (x != 0) this->setPosition(x, this->getPosition().y);
if (y != 0) this->setPosition(this->getPosition().x, y);
}
Caption::~Caption()
{
}
void loadFont(Font & font, string path)
{
font.loadFromFile(path);
}
string intToString(int number)
{
ostringstream ss; // Obiekt do konwersji "int to string"
ss << number;
string text = ss.str(); // Łączenie członów napisu
return text;
}
int stringToInt(string text)
{
int number = atoi(text.c_str());
return number;
}
string convertToPolishChars(string text)
{
string convertedText = "";
for (int i = 0; i < text.length(); i++)
{
switch (text[i])
{
/*case 'ą': convertedText += "\245"; break;
case 'ć': convertedText += "\206"; break;
case 'ę': convertedText += "\251"; break;
case 'ł': convertedText += "\210"; break;
case 'ń': convertedText += "\344"; break;
case 'ó': convertedText += "\242"; break;
case 'ś': convertedText += "\230"; break;
case 'ź': convertedText += "\253"; break;
case 'ż': convertedText += "\256"; break; // Żadna z tych linii nie działa w prawidłowy sposób
case 'Ą': convertedText += "\143"; break; // Użyłem różnych zestawów liczb mających odpowiadać znakom w tablicy ASCII
case 'Ć': convertedText += "\149"; break; // Ale żaden nie zamienia poprawnie pojawiających się krzaczków (np. ten poniżej)
case 'Ę': convertedText += "\144"; break;
case 'Ł': convertedText += "\157"; break;
case 'Ń': convertedText += "\165"; break;
case 'Ó': convertedText += "\163"; break;
case 'Ś': convertedText += "\152"; break;
case 'Ź': convertedText += "\160"; break;
case 'Ż': convertedText += "\161"; break;
case '°': convertedText += "\248"; break;
default: convertedText += text[i]; break;*/
/*206 - ć
210 - ł
230 - ś
242 - ó
245 - ą
251 - ę
253 - ź
276 - ż
344 - ń*/
case 'ą': convertedText += static_cast<char>(165); break;
case 'ć': convertedText += static_cast<char>(134); break;
case 'ę': convertedText += static_cast<char>(169); break;
case 'ł': convertedText += static_cast<char>(136); break;
case 'ń': convertedText += static_cast<char>(228); break;
case 'ó': convertedText += static_cast<char>(162); break;
case 'ś': convertedText += static_cast<char>(152); break;
case 'ź': convertedText += static_cast<char>(171); break;
case 'ż': convertedText += static_cast<char>(190); break;
case 'Ą': convertedText += static_cast<char>(164); break;
case 'Ć': convertedText += static_cast<char>(143); break;
case 'Ę': convertedText += static_cast<char>(168); break;
case 'Ł': convertedText += static_cast<char>(157); break;
case 'Ń': convertedText += static_cast<char>(227); break;
case 'Ó': convertedText += static_cast<char>(224); break;
case 'Ś': convertedText += static_cast<char>(151); break;
case 'Ź': convertedText += static_cast<char>(141); break;
case 'Ż': convertedText += static_cast<char>(189); break;
case '°': convertedText += static_cast<char>(248); break;
default: convertedText += text[i]; break;
}
}
return convertedText;
}
void setColorConsoleFont(unsigned int color)
{
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut, color);
}
bool isNumeric(string number)
{
bool isNumeric = false;
for (int i = 0; i < number.length(); i++)
{
if (number[i] == '1' || number[i] == '2' || number[i] == '3' || number[i] == '4' ||
number[i] == '5' || number[i] == '6' || number[i] == '7' || number[i] == '8' ||
number[i] == '9' || number[i] == '0')
{
isNumeric = true;
continue;
}
else
{
isNumeric = false;
break;
}
}
if(isNumeric == true) return true;
else return false;
}
bool isNumeric(char number)
{
if (number == '1' || number == '2' || number == '3' || number == '4' || number == '5' ||
number == '6' || number == '7' || number == '8' || number == '9' || number == '0')
return true;
else
return false;
}
Główny Kontroler gry przechowuje wiele informacji, które później są przekazywane to takich klas jak: Menu czy Game. Tu właśnie pojawia się problem, ponieważ zastosowałem składnię dostępną dopiero od C++11 - klamerki, które mają zastępować nawiasy okrągłe w klasie w pliku .h do tworzenia obiektów z podaniem argumentów. Konstruktory tak utworzonych obiektów zostają wywołane przed konstruktorem Kontrolera co staje się problemem. Wszystko dlatego, że obiekty klasy Menu dostają w argumentach konstruktora referencję do oryginalnej czcionki (myślałem, że takie coś załatwi sprawę) i już w konstruktorze są tworzone wszystkie potrzebne napisy (KTÓRE W TYM MOMENCIE NIE MAJĄ JESZCZE PODANEJ ŚCIEŻKI DO CZCIONKI - TO DZIEJE SIĘ DOPIERO W KONSTRUKTORZE KLASY CONTROLLER), które jak się okazuje nie wyświetlają się na ekranie, chyba z powodu nieznajomości ścieżki do czcionki na dysku. W kodzie wygląda to następująco:
// Controller.h
#ifndef CONTROLLER_H_INCLUDED
#define CONTROLLER_H_INCLUDED
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include "GameInfo.h"
#include "Game.h"
#include "Menu.h"
using namespace std;
using namespace sf;
class Controller
{
private:
Controller();
Controller(const Controller &);
public:
void run();
static Controller &getReference();
RenderWindow *getRenderWindow();
Graphics *getGraphicsController();
Audio *getAudioController();
GameInfo *getGameInfo();
Game *getGameObject();
Menu *getMenuObject();
Font *getFont();
private:
RenderWindow window;
Graphics graphicsController;
Audio audioController;
GameInfo gameInfo;
Font font;
// Te klamerki {} to specjalny zapis działający jak () tylko, że w pliku nagłówkowym (dostępne od C++11)
Game game{ window, graphicsController, audioController, font, gameInfo }; // Klasa Game nie tworzy napisów w konstruktorze dlatego tutaj nie występują te problemy
Menu menu{ window, graphicsController, audioController, font, gameInfo }; // Problem zaczyna się w tym obiekcie
void runGame();
void showFinalScore();
void showMenu();
};
#endif // CONTROLLER_H_INCLUDED
// Controller.cpp
#include "Controller.h"
#include <conio.h>
Controller::Controller()
{
window.create(VideoMode(GameInfo::widthWindow, GameInfo::heightWindow, 32), GameInfo::gameName, Style::Titlebar | Style::Close);
loadFont(font, "font/iron_man.ttf"); // O tę linijkę chodzi, wywołuje się ona po stworzeniu wszystkich napisów
gameInfo.state = GameInfo::MENU;
cout << "'1' ";
}
// Menu.cpp
#include "Menu.h"
Menu::Menu()
{
loadedData = false;
}
Menu::Menu(RenderWindow &window, Graphics &graphicsController, Audio &audioController, Font &font, GameInfo &gameInfo)
{
this->window = &window;
this->graphicsController = &graphicsController;
this->audioController = &audioController;
this->font = &font; // Tutaj ustawiam wskaźnik na oryginalną czcionkę
this->gameInfo = &gameInfo;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Ustawianie wartości napisów w menu głównym
mainOptions.push_back(Caption(font, "Start Gry!"));
mainOptions.push_back(Caption(font, "Ustawienia"));
mainOptions.push_back(Caption(font, "Info"));
mainOptions.push_back(Caption(font, "Wyjscie"));
for (int i = 0; i < mainOptions.size(); i++)
{
mainOptions[i].setCharacterSize(30);
mainOptions[i].setPosition(Graphics::centerPosition(mainOptions[i]), (295 + i * (mainOptions[i].getGlobalBounds().height + 50))); // Ustawianie pozycji każdego z napisów
}
currentOptions = mainOptions;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Ustawianie napisów w menu ustawień
settingsHeader = Caption(font, "Dzwiek");
settingsHeader.setCharacterSize(60);
settingsHeader.setPosition(Graphics::centerPosition(settingsHeader), 25);
settingsOptions.push_back(Caption(font, "Glosnosc muzyki: "));
settingsOptions.push_back(Caption(font, "Glosnosc dzwiekow: "));
settingsOptions.push_back(Caption(font, "Powrot"));
for (int i = 0; i < settingsOptions.size(); i++)
{
settingsOptions[i].setCharacterSize(30);
settingsOptions[i].setPosition(100, (120 + i * (settingsOptions[i].getGlobalBounds().height + 50))); // Ustawianie pozycji każdego z napisów
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Ustawianei napisów z menu informacji
infoHeader = Caption(font, "Informacje");
infoHeader.setCharacterSize(60);
infoHeader.setPosition(Graphics::centerPosition(infoHeader), 25);
gameInformations.push_back(Caption(font, "Wersja aplikacji: 1.0"));
gameInformations.push_back(Caption(font, "Autor gry: Ce Pe U"));
gameInformations.push_back(Caption(font, "Autor czesci grafiki: Ce Pe U"));
gameInformations.push_back(Caption(font, "Muzyka z menu: SnD Nero v7 All Product Keygen"));
gameInformations.push_back(Caption(font, "Muzyka z gry: MP2k - UltraEdit11"));
for (int i = 0; i < gameInformations.size(); i++)
{
gameInformations[i].setCharacterSize(30);
gameInformations[i].setPosition(Graphics::centerPosition(gameInformations[i]), (120 + i * (gameInformations[i].getGlobalBounds().height + 20))); // Ustawianie pozycji każdego z napisów
}
infoOptions.push_back(Caption(font, "Powrot"));
for (int i = 0; i < infoOptions.size(); i++)
{
infoOptions[i].setCharacterSize(30);
infoOptions[i].setPosition(Graphics::centerPosition(infoOptions[i]), (500 + i * (infoOptions[i].getGlobalBounds().height + 20))); // Ustawianie pozycji każdego z napisów
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Ustawianie suwaków głośności
sliderBar1.setSize(Vector2f(205, 20));
sliderBar1.setPosition(GameInfo::widthWindow / 2 + 50, settingsOptions[0].getPosition().y + 9);
sliderBar2.setSize(Vector2f(205, 20));
sliderBar2.setPosition(GameInfo::widthWindow / 2 + 50, settingsOptions[1].getPosition().y + 9);
sliderMovingVol1.setSize(Vector2f(5, 30));
sliderMovingVol1.setPosition(sliderBar1.getPosition().x + audioController.volumeMusic * 2, Graphics::centerPosition(sliderMovingVol1, sliderBar1, false));
sliderMovingVol1.setFillColor(Color::Red);
sliderMovingVol2.setSize(Vector2f(5, 30));
sliderMovingVol2.setPosition(sliderBar2.getPosition().x + audioController.volumeSound * 2, Graphics::centerPosition(sliderMovingVol2, sliderBar2, false));
sliderMovingVol2.setFillColor(Color::Red);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
selectedOption = 1;
loadedData = false;
clickedButton = false;
loadData();
}
Czy jest jakieś rozwiązanie oprócz tworzenia oddzielnej funkcji, która będzie wszystko później ustawiała? Oraz dlaczego to nie działa? Podczas sprawdzania poprawności tworzenia napisów w innych miejscach (wraz z tą zasadą ich tworzenia - wskaźnik na czcionkę itd.) wszystko działało idealnie.