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

1

02.09.2017, 09:18

[C++|SFML] Klasse "Player" in mehreren gamestates benutzen

Hey, ich bin am Programmieren eines Textadventures. Dabei benutze ich für die Story zwischen jeder Entscheidung GameStates, also immer den gleichen Aufbau.
Jetzt habe ich eine Klasse "Player" geschrieben, die bestimmte Attribute hat, die dann durch die Events verändert werden sollen. Allerdings
weiß ich überhaupt nicht, wie ich ein Objekt der Klasse erstellen kann, dass dann in den verschiedenen GameStates immer wiederverwendet wird.
Oder irgendeine andere Lösung, bei der Attribute und Name des einen Spielers in jedem GameState übernommen werden.

Vielleicht hat ja jemand eine Lösung parat :)
Hier nochmal die Player Klasse:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#pragma once
#ifndef PLAYER_HPP
#define PLAYER_HPP

#include "Game.h"

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

    std::string Spielername;

    enum class Attribute {STAERKE, SCHNELLIGKEIT, SCHOENHEIT, INTELLIGENZ, GLAUBEN, LEBENSPUNKTE};

    void changeAttribut(Attribute, int);
    void setSpielername(std::string);
    std::string getSpielername();
    std::int16_t getAttributWert(Attribute);


private:
    std::int16_t Staerke = 0;
    std::int16_t Schnelligkeit = 0;
    std::int16_t Schoenheit = 0;
    std::int16_t Intelligenz = 0;
    std::int16_t Glauben = 0;
    std::int16_t Lebenspunkte = 10;

};


#endif


Die cpp-datei:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include "Player.h"

Player::Player()
{
    std::cout << "Spieler-Konstruktor aufgerufen!" << std::endl;
}

void Player::changeAttribut(Attribute attribut, int x)
{
    switch (attribut)
    {
    case Attribute::GLAUBEN:
        Glauben += x;
        break;

    case Attribute::INTELLIGENZ:
        Intelligenz += x;
        break;

    case Attribute::SCHNELLIGKEIT:
        Schnelligkeit += x;
        break;

    case Attribute::SCHOENHEIT:
        Schoenheit += x;
        break;

    case Attribute::STAERKE:
        Staerke += x;
        break;

    case Attribute::LEBENSPUNKTE:
        Lebenspunkte += x;
        break;
    }
}

std::int16_t Player::getAttributWert(Attribute attribut)
{
    switch (attribut)
    {
    case Attribute::GLAUBEN:
        return Glauben;
        break;

    case Attribute::INTELLIGENZ:
        return Intelligenz;
        break;

    case Attribute::SCHNELLIGKEIT:
        return Schnelligkeit;
        break;

    case Attribute::SCHOENHEIT:
        return Schoenheit;
        break;

    case Attribute::STAERKE:
        return Staerke;
        break;

    case Attribute::LEBENSPUNKTE:
        return Lebenspunkte;
        break;
    }
}

void Player::setSpielername(std::string string)
{
    Spielername = string;
}

std::string Player::getSpielername()
{
    return Spielername;
}

Player::~Player()
{
    std::cout << "Spieler-Destruktor aufgerufen!" << std::endl;
}


Und das sind die GameStates:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef GAMESTATE_HPP
#define GAMESTATE_HPP

class Game;
class Player;

class Gamestate
{
public:
    virtual void HandleEvents(Game& game) = 0;
    virtual void Update(Game& game) = 0;
    virtual void Draw(Game& game) = 0;
    virtual void Spieler(Player& player) = 0;
    virtual      ~Gamestate() {};
};
#endif


Vielen Dank schonmal im Voraus!

buggypixels

Treue Seele

Beiträge: 125

Wohnort: Meerbusch

Beruf: Programmierer

  • Private Nachricht senden

2

02.09.2017, 11:40

Hier eine ganz einfache Möglichkeit:

C-/C++-Quelltext

1
2
3
4
5
6
7
class Gamestate {

public:
  Gamestate(Player* player) : _player(player) {}
protected:
  Player* _player;
};

Damit hat jede konkrete Implementierung von Gamestate Zugriff auf das eine Player Objekt.

3

02.09.2017, 14:25

Ich glaube, das würde ganz gut funktionieren, allerdings mache ich irgendwo noch einen Fehler, denn er sagt mir, in Gamestate ist kein Standardkonstruktor vorhanden... Was ja eigentlich auch stimmt.
Aber wie kann man das beheben?

4

02.09.2017, 14:39

Ruf nicht den NICHT MEHR vorhandenen Standardkonstruktor auf, sondern den neuen bei dem du Player übergibst.

GameState gameState(myPlayer); statt GameState gameState();

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

5

02.09.2017, 15:35

Hier eine ganz einfache Möglichkeit:
Wieso Player*? Ist der denn optional? Wenn nicht, wäre Player& wohl besser. Wenn du nur davon lesen willst, dann const Player&.


Außerdem ist mir nicht klar wieso std::int16_t und warum nicht einfach nur int?
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]

6

02.09.2017, 17:59

Irgendwie hat das alles nicht funktioniert. Ich habe den Konstruktor eines Gamestates auf zahlreiche verschiedene Möglichkeiten verändert (auch mit Player& player), aber nein. Irgendetwas mache ich da falsch.
Jedenfalls habe ich eine andere Methode gefunden. Eventuell ist euch die Zeile Code schon aufgefallen:

Zitat

virtual void Spieler(Player& player) = 0;

Da habe ich vorher einmal versucht, das ganze über eine Funktion zu lösen. Das habe ich jetzt ein wenig abgeändert und zwar so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef GAMESTATE_HPP
#define GAMESTATE_HPP

class Game;
class Player;

class Gamestate
{
public:
    virtual void HandleEvents(Game& game) = 0;
    virtual void Update(Game& game) = 0;
    virtual void Draw(Game& game) = 0;
    virtual void Spieler(Player* _player) = 0;
    virtual      ~Gamestate() {};

protected:
    Player* _player;
};
#endif

Also die Zeiger-Idee hab ich übernommen. Und so funktioniert das. Innerhalb von

C-/C++-Quelltext

1
void Beispielstate::Spieler(Player* player) {}

kann ich dann _player von der Gamestate-Klasse aufrufen und die Funktionen aus der class Player benutzen.

Außerdem ist mir nicht klar wieso std::int16_t und warum nicht einfach nur int?

Ich habe das jetzt noch auf std::int8_t geändert. Ich brauche einfach nicht so große Werte, für die Attribute reichen die kleinen völlig aus. Events werden ja jetzt nicht mehrere Millionen Stärke geben... als Beispiel.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

02.09.2017, 18:06

Ich habe das jetzt noch auf std::int8_t geändert. Ich brauche einfach nicht so große Werte, für die Attribute reichen die kleinen völlig aus.
Und welchen Vorteil versprichst du dir davon im Gegensatz zu einem normalen int?
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]

8

02.09.2017, 18:19

Ich habe das jetzt noch auf std::int8_t geändert. Ich brauche einfach nicht so große Werte, für die Attribute reichen die kleinen völlig aus.
Und welchen Vorteil versprichst du dir davon im Gegensatz zu einem normalen int?

Das Problem war, dass int aus irgend einem seltsamen grund genau an der Stelle nicht akzeptiert wurde. Also wirklich nur da im Private-Teil der Klasse. Ich weiß nicht warum, aber das wird schon seine Gründe haben. Und dann standen mir halt noch die verschiedenen intxy_t frei und da habe ich dann das kleinste genommen, da ich denke, dass dies ein ganz klein wenig effizienter ist.
Berichtige mich, falls dem nicht so ist :)

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

9

02.09.2017, 18:57

Genau deswegen frage ich. Das Gegenteil ist nämlich der Fall. Und ich kann mir nicht vorstellen, dass aus irgendeinem obskuren Grund der Compiler einen normalen int nicht akzeptiert.
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]

10

02.09.2017, 19:11

Fehler C2589 "int": Ungültiges Token auf der rechten Seite von "::" Projekt-A (Pfad) 24

Das ist die Fehlermeldung (Projekt-A heißt es bislang). Mit auf der rechten Seite von :: ist gemeint von std::
siehe:

C-/C++-Quelltext

1
2
private:
    std::int Staerke = 0;


Und dürfte ich fragen, warum ein intx_t ineffizienter als ein normaler int ist? Schließlich beinhaltet dieser doch weniger Zeichen oder liege ich da jetzt komplett falsch?

Werbeanzeige