OOP bei Spiel

JohnnyEnglish

Grünschnabel
Hallo.

Ich habe mir einige Klassen für ein 2D-Jump 'n' Run-Spiel gebastelt. Wie kann das folgende Problem elegant lösen?

Ich habe eine Stammklasse, World, von der ich in WinMain eine Instanz erzeuge. Sie beinhaltet u.a. die Klasse Graphics für Grafikfunktionen, sowie Hero für den Helden und bis zu 1024 andere Objekte. Alles läuft problemlos. Nun aber möchte ich (für jedes Frame) die Objekte bewegen lassen (void Object::Move()). Ich werde noch weitere Kreaturentypen hinzufügen, die dann auch primitive KI haben werden. Doch mein Problem ist: Wie können die Objekte auf die Welt (wo befindet sich was; unsigned long *World::world) zugreifen? Muss ich da für jeden Aufruf von Move() einen Zeiger mitgeben? Oder beim Konstruktor des Objekts einen Zeiger auf *world? Ich möchte dieses Problem so lösen, dass ich immer noch eine objektorientiertheit habe, also nicht etwa mit globalen Vars oder so. Danke.

Anmerkung:
- Ich verwende Polymorphie, d.h. ich werde alle Gegner von Object bzw. Creature ableiten
- TEXTURE, WORLD und ähnliches sind enum's

Code:
class World
{
public:
	World();
	~World();
	void CalcFrame();
	Hero *hero;
private:
	void DrawFrame();
	unsigned long GetAbsoluteX(D3DXVECTOR2 pos);
	unsigned long GetAbsoluteY(D3DXVECTOR2 pos);
	unsigned long GetRelativeX(D3DXVECTOR2 pos);
	unsigned long GetRelativeY(D3DXVECTOR2 pos);
	WORLD GetWorld(unsigned long x, unsigned long y);
	void LoadWorld(unsigned long w);
	Graphics graphics;
	Object *object[1024];
	unsigned long worldSize;
	unsigned long *world;
	float horizScrolling;
	STATUS status;
	unsigned long progress;
};

class Object
{
public:
	Object(D3DXVECTOR2 pos, unsigned long w, unsigned long h);
	~Object();
	virtual void Move() = 0;
	D3DXVECTOR2 pos;
	unsigned long width;
	unsigned long height;
	TEXTURE texture[8];
};

class Item : public Object
{
public:
	Item(D3DXVECTOR2 pos, unsigned long w, unsigned long h, OBJECT t);
	~Item();
	void Move();
	OBJECT type;
};

class Creature : public Object
{
public:
	Creature(D3DXVECTOR2 pos, unsigned long w, unsigned long h);
	~Creature();
};

class Hero : public Creature
{
public:
	Hero(D3DXVECTOR2 pos, unsigned long w, unsigned long h);
	~Hero();
	void Move(WORLD (*world)(unsigned long, unsigned long));
	void SpacePressed();
	bool jumpActive;
	unsigned long jumpCount;
	bool keyRight;
	bool keyLeft;
};
 
Weder noch. Es handelt sich wie gesagt um ein (Design) Pattern. Ein Singleton ist eine Klasse, die nur ein einziges mal instanziert werden kann. Eine mögliche Implementation könnte so aussehen:

Code:
class Singleton
{
	public:
		static Singleton *getInstance();

	private:
		Singleton() {}
		static Singleton *m_pInstance;
};

Singleton *Singleton::m_pInstance = NULL;

Singleton *Singleton::getInstance()
{
	if (m_pInstance == NULL) {
		m_pInstance = new Singleton();
	}

	return m_pInstance;
}
Durch den privaten Konstruktor wird sicher gestellt, dass „von außerhalb“ keine Instanz der Klasse erzeugt werden kann. Um auf die einzige existierende Instanz zuzugreifen, verwendet man die statische Methode getInstance, die einen Zeiger auf die Instanz zurückgibt. Beispielsweise greift man dann auf die Funktion foobar mit folgendem Aufruf zu: Singleton::getInstance()->foobar()

Somit kannst du an jeder Stelle im Code auf deine Instanz zugreifen, ohne eine globale Variable verwenden zu müssen. Außerdem ist (sinnvollerweise) auch sichergestellt, dass deine World-Klasse nur einmal instanziert werden kann.
 
Zurück