• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Problem przy ustawianiu napisów w SFML przy użyciu własnej klasy i wskaźnika do oryginalnej czcionki

VPS Starter Arubacloud
0 głosów
598 wizyt
pytanie zadane 30 lipca 2018 w C i C++ przez DarkEliat Bywalec (2,810 p.)

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.

1 odpowiedź

0 głosów
odpowiedź 30 lipca 2018 przez monika90 Pasjonat (22,940 p.)

Jeżeli problem jest spowodowany zbyt późnym ładowaniem czcionki, to spróbuj wymusić wcześniejsze ładowanie, np. zainicjalizuj składową font w ten sposób

    Font font{[]{ Font f; f.loadFromFile("font/iron_man.ttf"); return f; }()};

 

komentarz 23 sierpnia 2018 przez DarkEliat Bywalec (2,810 p.)
Cześć!

Dzięki wielkie za odpowiedź! Wybacz, że tak późno odpisuję, niestety Twój sposób nie działa, wydaje mi się, że problem tkwi w tym, że napisy są tworzone w konstruktorze Menu, który wywołuje się jeszcze przed konstruktorem klasy Controller. Niestety nie bardzo wiem  co na to poradzić :(
komentarz 26 sierpnia 2018 przez monika90 Pasjonat (22,940 p.)
Może wrzuć cały projekt na githuba, żeby można było sobie skompilować i sprawdzić.

Podobne pytania

0 głosów
1 odpowiedź 454 wizyt
0 głosów
2 odpowiedzi 257 wizyt
pytanie zadane 9 marca 2016 w Grafika i multimedia przez Adam Jakś Dyskutant (8,940 p.)
0 głosów
1 odpowiedź 216 wizyt

92,454 zapytań

141,262 odpowiedzi

319,089 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...