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

24.02.2013, 15:24

Entities "spezialisieren"

Guten Tag zusammen,

ich arbeite immer noch an meinen Entities ;-). Ich habe mir nun den Anfang eines Systems in Anlehnung an dieses Tutorial geschaffen: http://www.sdltutorials.com/sdl-entities.
Nun habe ich eine Klasse die die grundsätzlichsten funktionen beinhaltet, diese habe ich per Vererbung an meine spezialisierte Klasse weitergegeben. Bsp: Mein Entity enthält die position die größe sowie das Aussehen ("SDLSurface"). Die Klasse "Box" enthält diese dann als Basisklasse. Mein Problem ist nun dass die Entity-Klasse eine Funktion "OnLoop" enthält, die bei jedem Durchgang aufgerufen wird. Nun benötige ich allerding in meiner Klasse Box zum Beispiel eine Klasse "Gravitation". Diese sollte zum ändern der Koordinaten bei jedem Loop aufgerufen werden. Doch wie kann ich dies erreichen? Aus dem Loop der Basisklasse ein "Unter"-Loop in der Box-Klasse (bzw. jeder anderen) aufrufen?

Sollte der Code nochvon Nutzen sein kann ich ihn natürlich noch hinzufügen, ist derzeit aber leicht unübersichtlich und in viele Files aufgeteilt :D

MfG Pat711

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Pat711« (25.02.2013, 15:18)


2

25.02.2013, 15:19

Sry wegen des Doppelposts aber ich war mir nicht sicher ob des sonst jemand mitbekommt ;-)

Ich hab das ganze nun mal so probiert, dass ich in der Entity-Klasse eine Funktion erstelle, die TypeLoop heißt und je nach typ etwas anderes ausführen soll. Die Entity-Klasse soll dann an die Typen-Klassen vererbt werden, die dann die Funktion "TypeLoop" ersetzen durch die von ihnen benötigte. Mein Problem besteht nun darin dass ich sobald ich das versuche die Fehlermeldung

Zitat

error: expected class-name before '{' token|
bekomme. (In der Datei "CBox.h" bei {)


CBox.h

C-/C++-Quelltext

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

#include "CEntity.h"

#define DROP_SPEED 100

//class CEntity;

class CBox:public CEntity
{
public:
    void gravity(/*CEntity *BoxEntity*/);
    void TypesLoop() const;
    CBox();
    ~CBox();
};

#endif // CBOX_H_INCLUDED


CBox.cpp

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
#include "CBox.h"

/*
bool CBox::OnLoop()
{
   AnimControl.OnAnimate();
   return 1;
}
*/

void CBox::gravity(/*CEntity *BoxEntity*/)
{
    if(true/*!(collision)*/) //Kollisionskontrolle noch aktivieren
    {
        /*
        if(DROP_SPEED <= drop_counter)
        {
                BoxEntity->pos.y ++;
                drop_counter = 0;
        }
        drop_counter ++;*/
    }
}

void CBox::TypesLoop() const
{

}

CBox::CBox()
{

}

CBox::~CBox()
{

}


CEntity.h

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
#ifndef CENTITY_H_INCLUDED
#define CENTITY_H_INCLUDED

#include <SDL.h>
#include <vector>

#include "types.h"
#include "CAnimationControl.h"
#include "CSurface.h"

// Entity - Typen:
#define TYPE_BOX 1

class CEntity
{
public:
    static std::vector<CEntity*> EntityList;    // Liste der Entities

    position pos;   // Position
    int width; // Breite
    int height; // Höhe

    CEntity();
    virtual ~CEntity();

    //Animation
    int AnimState;  // Aktuelles Bild

    // Funktionen
    virtual bool OnLoad(std::string file,int Width, int Height, int MaxFrames); // Erstellen
    virtual void OnLoop();          // Refresh
    virtual void OnRender(SDL_Surface* Surf_Display,SDL_Surface* Surf_Background);       // Rendern
    virtual void OnCleanup();       // Löschen
    virtual void SetType(int newtype);
    virtual int GetType();

    virtual void TypesLoop() const;

private:
    SDL_Surface* Surf_Entity;   // Surface des Entities
    CAnimControl AnimControl;
    int type;
    position old_pos; // alte Position
};

#endif // CENTITY_H_INCLUDED




CEntity.cpp

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
#include "CEntity.h"

std::vector<CEntity*> CEntity::EntityList;

CEntity::CEntity()
{
    Surf_Entity = NULL;

    pos.x = 0;
    pos.y = 0;

    width = 0;
    height = 0;
    AnimState = 0;
}

CEntity::~CEntity()
{

}

bool CEntity::OnLoad(std::string file, int Width, int Height, int MaxFrames)
{
    Surf_Entity = CSurface::load_image(file);
    this->width = Width;
    this->height = Height;
    AnimControl.SetFrameRate(24);
    if(Surf_Entity == NULL)
    {
        return false;
    }
    return true;
}

void CEntity::OnLoop()
{
    AnimControl.OnAnimate();
}

void CEntity::OnRender(SDL_Surface* Surf_Display,SDL_Surface* Surf_Background)
{
    if(Surf_Entity == NULL || Surf_Display == NULL) return;
    if((pos.x != old_pos.y)||(pos.y != old_pos.y))
    {
        CSurface::OnDraw(Surf_Display, Surf_Background, old_pos.x, old_pos.y, 0, 0, width, height);
        old_pos.x = pos.x;
        old_pos.y = pos.y;
    }
    CSurface::OnDraw(Surf_Display, Surf_Entity, pos.x, pos.y, AnimState * width, AnimControl.GetCurrentFrame() * height, width, height);
}

void CEntity::SetType(int newtype)
{
    type = newtype;
}
int CEntity::GetType()
{
    return type;
}

void TypesLoop()
{

}

void CEntity::OnCleanup()
{

}




MfG Pat711

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

3

25.02.2013, 15:56

Ich kann so auf die schnelle nichts finden, mein C++ ist aber auch schon extrem eingerostet. Da findet jemand anderes sicherlich mehr. Im Prinzip möchtest du ja nur, dass die abgeleiteten Klassen eine Funktion der Basisklasse überschreibt bzw allgemein implementiert. Virtuelle Methoden wären da ein Ansatz. Normalerweise würde ich für sowas aber eine abstrakte Klasse anlegen. Die Basisklasse soll ja normal nicht erstellt werden, sondern nur die abgeleiteten Entitäten und dort muss die Methode dann halt überschrieben werden. Wenn du in einer abgeleiteten Klasse noch andere Objekte benötigst, dann musst du der Instanz diese halt mitgeben. Warum übergibst du deiner Box Klasse die Gravity Instanz nicht einfach im Konstruktor. Ich denke du solltest dir Vererbung noch mal genauer anschauen und dann noch mal versuchen das Prinzip hinter Polymorphie zu verstehen.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

4

27.02.2013, 18:28

Vielen Dank für deine Antwort.

Zitat

Im Prinzip möchtest du ja nur, dass die abgeleiteten Klassen eine Funktion der Basisklasse überschreibt bzw allgemein implementiert.
Genau das hatte ich versucht. Ich habe nun das ganze nochmal in einem extra Projekt probiert allerdings kam ich zum selben Ergebnis: error: expected class-name before '{' token|

Der Fehler trat aber nur auch, wenn ich meine abgeleitete Klasse in einem anderen Dokument hatte.(hier auskommentiert).
Wenn die Klasse im selben File (hier recht unschön in der .h) ist funktioniert alles bestens o.O

Irgendwo hab ich da doch nen einfachen Denkfehler oder?

hier mal mein neues Programm:

main.cpp:

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
#include <iostream>
#include "stdlib.h"

#include "CHandler.h"

class CApp
{
private:

public:
    int OnExecute();
};

int CApp::OnExecute()
{
    std::cout << "---Start---\n";
    CHandler::NewBase();    // 0
    CHandler::NewChild();   // 1
    CHandler::NewBase();    // 2
    CHandler::NewBase();    // 3
    CHandler::NewChild();   // 4
    CHandler::NewChild();   // 5
    CHandler::NewChild();   // 6

    for(unsigned int i= 0; i < CBase::BaseList.size(); i++)
    {
        std::cout <<" -------" << i << "------- \n";
        CBase::BaseList[i]->output();
    }
    return 0;
}

int main()
{
    CApp theApp;
    return theApp.OnExecute();
}

CBase.h:

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
#ifndef CBASE_H_INCLUDED
#define CBASE_H_INCLUDED

#include <iostream>
#include <vector>

class CBase
{
public:
    static std::vector<CBase*> BaseList;

    virtual void output();

    CBase();

private:

};

class CChild2: public CBase
{
public:
    void output()
    {
        std::cout << "Hi, I'm Child-class\n";
        ChildExtra();
    }
    void ChildExtra()
    {
        std::cout << "Child extra!\n";
    }
    CChild2()
    {

    }
private:

};

#endif // CBASE_H_INCLUDED

CBase.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "CBase.h"

std::vector<CBase*> CBase::BaseList;

void CBase::output()
{
    std::cout << "Hi, I'm Base-class\n";
}

CBase::CBase()
{

}

CChild.h:

C-/C++-Quelltext

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

#include <iostream>

/*
class CChild: public CBase
{
public:
    void output();
    void ChildExtra();
    CChild();
private:

};
*/
#endif // CCHILD_H_INCLUDED

CChild.cpp:

C-/C++-Quelltext

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

/*
void CChild::output()
{
    std::cout << "Hi, I'm Child-class\n";
    ChildExtra();
}

void CChild::ChildExtra()
{
    std::cout << "Child extra!\n";
}

CChild::CChild()
{

}
*/

CHandler.h:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef CHANDLER_H_INCLUDED
#define CHANDLER_H_INCLUDED

#include "CBase.h"

class CHandler
{
public:
    static void NewBase();
    static void NewChild();
};

#endif // CHANDLER_H_INCLUDED

CHandler.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "CHandler.h"

void CHandler::NewBase()
{
    CBase *object = new CBase;
    CBase::BaseList.push_back(object);
}

void CHandler::NewChild()
{
    CBase *object = new CChild2;
    CBase::BaseList.push_back(object);
}




Mit Freundlichen Grüßen,



Pat711

H5::

Treue Seele

Beiträge: 368

Wohnort: Kiel

  • Private Nachricht senden

5

27.02.2013, 21:09

Also so auf die Schnell sind mir erst mal ein paar Dinge auf gefallen.

Post1:

CEntity.cpp

C-/C++-Quelltext

1
2
3
4
void TypesLoop() // << void CEntity::TypesLoop() 
{

}


Post2:
CChild.h, Fehlt ein #include "CBase.h"

Edit:
Als Tipp sofern dein Compiler es schon unterstützt, benutze die neuen Spezial Identifiier override und final. Speziell override ist sehr nützlich um Fehler zu vermeiden.
:love: := Go;

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »H5::« (27.02.2013, 21:19)


6

28.02.2013, 18:42

Vielen Dank für deine Antwort, ich habe die Änderungen mal vorgenommen. In dem in File aus Post 1 (das eigentliche , richtige und wichtige Programm ;-) ) habe ich noch das CEntity:: hinzugefügt.

In dem Programm aus dem 2. Post, das eigentlich nur zum Finden des Fehlers gedacht war hab ich noch das "#include "CBase.h" " eingefügt. Und siehe da... es funktioniert!!! Mist.. denn das eigentliche mag immer noch nicht.. immer noch der gleiche Fehler. Ich habe nun schon einige unnötige #include 's bereinigt, was aber auch nichts geändert hat.

An was kann denn ein "expected class-name before '{' token|" noch liegen?

Das mit dem override scheint zwar Code::Blocks zu kennen aber mein Compiler nicht ;-)


MfG Pat711

H5::

Treue Seele

Beiträge: 368

Wohnort: Kiel

  • Private Nachricht senden

7

28.02.2013, 20:10

Du must die ganze Signatur einhalten, auch das const.

C-/C++-Quelltext

1
void TypesLoop() const



Der Fehler kann auch auftreten wenn ein Header der in CEntity.h eingebunden ist wiederum zuvor CBox.h einbindet. ( Zirkuläre Abhängigkeit ) Soetwas gillt es zu vermeiden. Dazu gibt es mehrere Möglichkeiten z.B. Forward Declaration, andere Abängigkeitenstruktur. usw.
:love: := Go;

8

01.03.2013, 15:26

Ja soetwas hatte ich auch vermutet, allerding habe ich nun mittlerweile die #include 's so weit minimiert, dass mein Entity-Manager mein #CBox includiert und CBox dann CEntity, jeweils Cbox und der manager includieren jeweils auch nichts anderes.

Das mit dem cont habe ich bereits abgeändert, ich habs einfach mal rausgeworfen, da ich nicht genau wusste was des soll und des andere Programm auch ohne funktioniert ;-)


Das mit der forward-declaration hatte ich auch angeschaut, muss ich aber vmtl. noch mal genauer anschaun.

MfG Pat711

H5::

Treue Seele

Beiträge: 368

Wohnort: Kiel

  • Private Nachricht senden

9

01.03.2013, 16:10

... dass mein Entity-Manager mein #CBox includiert und CBox dann CEntity, jeweils Cbox und der manager includieren jeweils auch nichts anderes.
Sofern ich dich jetzt richtig verstanden habe ist es Entity-Manager.h -> CBox -> CEntity.h? Das schaut so erst mal nicht falsch aus. Wenn du magst kann ich mir mal dein gesamtes Projekt ansehen, wenn du es mir schickst.

Für die Funktion ist es nicht wichtig, aber es ist eigentlich nicht mehr üblich Namen wie CBox zu vergeben… Einfach Box das reicht, auch wenn man es noch viel anders liest.

Zu dem const:
Das sagt in dem Fall (also hinter der Methode), das die Methode keine member der verändert. Sprich, dass die Methode keine Änderungen an dem Objekt vornehmen kann. Die Folge ist, die Methode kann auch benutzt werden wenn das Object selbst konstant ist.

Const correctness
:love: := Go;

10

02.03.2013, 17:19

Dank der freundlichen Unterstützuung von H5:: hat sich das Problem gelöst. Er hat noch ein paar Funktions-Leichen aus früheren Versuchen entfernt ;-) und die gesuchte zirkuläre Abhängigkeit gefunden. Allerdings in einem ganz anderen Dokument als die oben aufgeführten und wo ich das Problem auch nie vermutet hatte. Das Problem war, dass ich eine Header-Datei in einem Header eingebunden hatte, die aber erst in der zugehörigen *.cpp genutzt wurde. Dadurch entstand folgendes Problem: CSurface.h -> CApp.h -> CSurface.h. (CSurface dient zur ausgabe CApp ist die "Haupt"-klasse.

Vielen Dank nochmal an H5::

MfG Pat711

Werbeanzeige