Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

11

09.03.2016, 06:56

Die getFont Funktion gibt eigentlich nur den Font des Textes zurück (*m_text.getFont()).
m_text = otherButton.text würde doch alle Attribute von sf::Text kopieren, ich brauche aber nur diese wenigen.
Das sollte doch das Problem lösen, oder?

Wenn nicht, wie könnte ich sonst noch vorgehen?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

12

09.03.2016, 07:14

Nein, getFont löst das Problem keinesfalls. Du bekommst da ja nur einen Pointer zurück und packst diesen Pointer in den Font des neuen Buttons. Wird der alte Button zerstört, wird auch der Font zerstört und damit ungültig. Bitte beschäftige Dich wie gesagt mit Pointern und Referenzen. Ohne dieses Wissen, ist das Problem nicht sauber lösbar.
Auch m_text = otherButton.text löst das Problem nicht, weil der Text nur einen Pointer auf den Font hält. Dieser wird aber wie gesagt ungültig, wenn der Button, der den Font geladen hat, zerstört wird. Wie das Problem sauber gelöst werden kann, steht in dem von mir verlinkten Wiki-Artikel. Da geht es zwar um Textures und Sprites, ist aber für Font und Text dasselbe Problem. Bitte lies ihn, dafür habe ich ihn geschrieben.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

13

09.03.2016, 19:45

Ich habe mir nun eine FontManager Klasse erstellt, inder alle Fonts geladen werden:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class FontManager
{
public:
    FontManager();
    ~FontManager();

    void setFont(std::string p_direction, int p_index);

    sf::Font FM_getFont(int p_index) const;

private:

    sf::Font m_font[3]; // 1: Cabin, 2: Berlin Sans, 3: arial 
};

Meine Button Klasse erbt von dieser und den KopierKonstruktor habe ich angepasst:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Button::Button(const Button &otherButton)
    :active(otherButton.getActive())
{
    if (&otherButton.getFont() == nullptr)
    {
        m_text.setFont(FM_getFont(0));
    }
    else
    {
        m_text.setFont(otherButton.getFont());
    }
    m_text.setCharacterSize(otherButton.getSize());
    m_text.setPosition(otherButton.getPos());
    m_text.setString(otherButton.getString());
    m_text.setColor(otherButton.getColor());
}

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

14

09.03.2016, 19:58

1) &otherButton.getFont() ist ziemlich sicher Unfug und bei manchen Compilern sogar ein Error
2) FM_getFont liefert Font-Kopien. Damit hast Du dasselbe Problem wieder.

Hast Du mittlerweile in einem Buch über Pointer und Referenzen gelesen? Denn der Code wirkt etwas "geraten".
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

15

09.03.2016, 20:22

Die Idee eines Font-Manager ist erstmal eine gute Idee, aber die Ausführung ist nicht Optimal.

Vererbung bedeutet "ist ein", also jeder Button ist ein Font-Manager, was eben nicht der Fall ist.
Das Problem ist auch für jeden Button hast du trotzdem wieder jeden Font und sogar mehrere Fonts pro Button.

Das ganze als Member zu Impementieren ist auch nicht Optimal, weil da auch wieder die Fonts mehrfach geladen werden.

Was bei einer Managerklasse immer sinn macht, ist diese nur einmal im Projekt an Zentraller stelle zu implementieren (Und ich rede jetzt nicht von Static).
Diese Managerklasse sollte eine get-Funktion haben die eine Refernez oder einen Pointer auf das zu Managende Objekt zurück gibt.
Ein "normales" Array ist da auch etwas schwach auf der Brust, wenn man über einen (integer) Index arbeiten möchte würde sich ein std::vector anbieten. Ich persönlich bevorzuge da lieber eine std::(unordered_)map um mit einem std::string anstelle eines integer Index zu arbeiten, macht den Code etwas übersichtlicher und besser lesbar als eine abstrakte Zahl.

Natürlich gehört zu einer Managerklasse noch mehr, wie z.B. eine Lade-Funktion oder eine Add-Funktion um diese zu "befüllen".

C-/C++-Quelltext

1
2
3
4
// Konstruktor Button
Button(const sf::font& font, ...);

Button newButton(ManagerKlasse.getManagedObject("Arial"), ...);


Übrigens google mal nach "Kopierkonstruktor und Tiefenkopie" dann könnte man das auch über den Kopierkonstruktor lösen, aber hier hast du eben den Nachteil, dass ein und der selbe Font öfter existiert. Schöner wird es mit der Managerklasse.
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

16

10.03.2016, 14:45

Meine FontManager Klasse sieht jetzt folgendermaßen aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#pragma once
#include "Game.h"

class FontManager
{
public:
    FontManager();
    ~FontManager();

    void setFont(std::string p_direction, int p_index);
    void addFont(std::string p_dircetion);

    sf::Font FM_getFont(int p_index) const;

private:

    std::vector<sf::Font> m_font; // 1: Cabin, 2: Berlin Sans, 3: arial 
};


Ein Objekt dieser Klasse ist jetzt außerdem an zentraler Stelle im Projekt erstellt, von der Vererbung habe ich mich getrennt. Damit komme ich aber gleich zum nächsten Problem: Und zwar wird der Fehler
game.h(47): error C2079: "Game::m_FontManager" verwendet undefiniertes class "FontManager"
angezeigt, was ich eigentlich nicht verstehe, da ich diese Klasse ganz normal eingebunden habe und sogar in game.h vorwärtsdeklariert habe. Ich schätze dennoch, dass es etwas mit der einbindung der Klasse zu tun hat .
Hier die Hirarchie der relevanten Klassen :

main
.-Game (steuert alle verwendeten States)
.-FontManager (Basisklasse für Fonts)
..-MainMenuState (managed alle im MainMenu relevanten Aktionen / Objekte)
...-Button (Basisklasse für Buttons)

Desweiteren habe ich nach der Integration des FontManager-Objekts in game.h den Konstruktor der Buttonklasse soweit angepasst, damit er jetzt mit dem Objekt aus der game-Klasse zurecht kommt.

Beim Thema Tiefenkopie hats "klick" gemacht :thumbsup:
Daher habe ich mir eine neue Variable in Button erstellt (FM_font_used), um immer zu wissen, welcher Font von meiner FontManager-Klasse benutzt wird, diese könnte man dann ja auch im Kopierkonstruktor als indikator verwenden.
Aber das führt wiederum zu meinem nächsten Problem. Ich übergebe ja nur im Konstruktor eine Referenz von game.m_FontManager, im Kopierkonstruktor kann ich diese aber nicht verwenden. Wie löse ich das am besten?

Hier das ganze auf Git: TowerDefense

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

17

10.03.2016, 16:44

Der Manager liefert noch immer Kopien von Fonts aus. Genau das soll verhindert werden. Das steht alles im verlinkten Wiki-Artikel.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

18

10.03.2016, 23:24

Ab jetzt gibt dieser nur noch pointer auf das Font zurück.
Allerdings bleiben oben genannte Probleme bestehen

Tobiking

1x Rätselkönig

  • Private Nachricht senden

19

11.03.2016, 06:39


angezeigt, was ich eigentlich nicht verstehe, da ich diese Klasse ganz normal eingebunden habe und sogar in game.h vorwärtsdeklariert habe.

Eine Vorwärtsdeklaration ist sowas wie "class XYZ;", das was du machst ist game.h zu inkludieren. Und da ist auch schon der Fehler. Wenn Header sich gegenseitig Inkludieren hast du eine zyklische Abhängigkeit die nicht aufgelöst werden kann. Wenn der FontManager nichts aus game.h braucht, was für mich auf Anhieb so aussieht, lass das Include raus. Wenn der FontManager einen Pointer auf einer Klasse aus game.h hat, machst du eine Vorwärtsdeklaration für diese Klasse.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

20

11.03.2016, 08:53

Wenn der FontManager einen Pointer auf einer Klasse aus game.h hat, machst du eine Vorwärtsdeklaration für diese Klasse.
Oder noch besser, Du baust das Ganze so um, dass der FontManager überhaupt nichts aus game.h braucht. Wozu sollte er auch, er ist doch in sich abgeschlossen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Werbeanzeige