Seite 1 von 1

Anfängerfragen Klassendesign & SFML

Verfasst: 15.03.2012, 22:33
von nerem
Hallo zusammen :)

Nach langer Zeit hab ich mal wieder Visual C++ installiert und versuche langsam aber sicher wieder reinzukommen. Derzeit schau ich mir die SFML ein wenig an und dabei tun sich mir zwei Fragen auf:

1. Designfragen
Ich möchte gerade ganz einfach ein Sprite über den Bildschirm bewegen. So weit klappt das auch. Nun möchte ich eine Klasse "CGameObject" erstellen, die Spielobjekte repräsentiert. Also ein Spielobjekt ist nachher zB. der Spieler, ein Gegner, ein PowerUp...
Meine Klassendefinition sieht wie folgt aus:

Code: Alles auswählen

class CGameObject
{
	public:

		// Konstruktoren / Destruktor
		CGameObject();
		CGameObject(sf::Vector2f pos, sf::Image im);
		CGameObject(float x, float y, sf::Image im);
		~CGameObject();

		// Getter / Setter
		void SetImage(sf::Image& im);							// Grafik
		sf::Sprite GetSprite(void);

		void SetType(int type);									// Objektidentifikation
		int GetType(void);

		void SetPosition(sf::Vector2f pos);						// Position
		void SetPosition(float x, float y);
		sf::Vector2f GetPosition(void);
		void SetCenterPosition(sf::Vector2f pos);
		sf::Vector2f GetCenterPosition(void);

		void SetSize(int width, int height);					// Größe
		void SetScale(float scale_x, float scale_y);
		float GetWidth(void);
		float GetHeight(void);
		sf::Vector2f GetScale(void);

		void SetMovement(sf::Vector2f mov);						// Bewegungsrichtung
		void SetMovement(sf::Vector2f mov, bool jumping);		// Bewegung mit Angabe des Sprungzustandes
		void SetMovement(float mov_x, float mov_y, bool jumping);
		void SetMovement(float mov_x, float mov_y);

		void SetJump(float jump);								// Sprunggeschwindigkeit
		float GetJump(void);
		

		// Objekt befindet sich in der Luft
		bool IsJumping(void);

		// Springen
		void Jump(void);

		// Bewegen
		void Move(void);
		void Move(DIRECTION dir);

	

	protected:

		sf::Vector2f m_vMovement;								// Bewegungsrichtung
		int m_iType;											// Objekttyp
		bool m_bJumping;										// Sprungzustand
		float m_fJump;											// Sprungkraft
		sf::Sprite m_sSprite;									// Sprite
};
Dadurch dass meine Klasse ein Sprite enthält habe ich jetzt das Problem, dass ich Getter und Setter benötige um Objekt und damit dem Sprite Position, Größe etc. zuweisen kann. In diesen Settern werden einfach die entsprechenden Methoden von sf::Sprite aufgerufen, zB.

Code: Alles auswählen

void CGameObject::SetPosition(sf::Vector2f pos)
{
	m_sSprite.SetPosition(pos);
}
oder

Code: Alles auswählen

sf::Vector2f CGameObject::GetPosition(void)
{
	return m_sSprite.GetPosition();
}
Irgendwie kommt mir das nicht wirklich geschickt vor, da ich ja nun ständig Sachen extra aufrufen muss, die sf::Sprite schon bietet.
Trotzdem möchte ich so eine Klasse haben, schließlich sollen die Objekte auch mal noch Leben, Waffen oä bekommen, das heißt ich benötige eine Klasse, die das bewerkstelligt.
Die Frage ist nun: Mach ich das richtig? Soll ich völlig anders vorgehen? Für Tips wäre ich dankbar.
Am allerwenigsten gefällt mir das Zeichen meines Objekts, das wie folgt bewerkstelligt wird:

Code: Alles auswählen

sf::Sprite CGameObject::GetSprite(void)
{
	return m_sSprite;
}
Und dann wird in der main wie folgt gezeichnet:

Code: Alles auswählen

App.Draw(Player.GetSprite());
Also für Tips zum Klassendesign etc. wäre ich sehr dankbar.

2. Fiepen
Dann hab ich noch ein technisches Problem. Mit obiger Klasse habe ich ein Objekt erstellt, ein Bild reingeladen und dies dann (im Fenstermodus) zeichnen lassen. Sobald das Programm startet, fiept mein Rechner, was nervt. Maximiere ich das Fenster wird das Fiepen leiser, weg ist es allerdings nicht. Weiß jemand woran das liegen könnte?

Vielen Dank erst mal, fürs bis hier her durchlesen.

Lg, nerem

Re: Anfängerfragen Klassendesign & SFML

Verfasst: 16.03.2012, 08:51
von pUnkOuter
Wenn du schon eine getSprite hast, warum machst du dann nicht player.getSprite().setPosition(100, 200)? Gibt eigentlich keinen Grund, warum du da im GameObject extra Methoden für bereitstellen solltest.

Eigentlich hast du sogar intuitiv den richtigen Ansatz gewählt. Viele versuchen zuerst mal, so was über Vererbung hinzukriegen, also z.B. ein Actor als allgemeine Klasse ohne Sprite, dann ein SpriteActor, usw., was sehr schnell ein fragiles Design bewirkt, bei dem du dann jedesmal zig Klassen im Vererbungsbaum anfassen musst bei der kleinsten Änderung.

Ein Komponenten-basiertes Design, wie du es gewählt hast, ist in dieser Hinsicht viel besser.

Re: Anfängerfragen Klassendesign & SFML

Verfasst: 16.03.2012, 09:03
von joggel
Hallo,
habe mir nicht alles genau angeschaut, aber etwas kann ich dazu sagen.
nerem hat geschrieben: Dadurch dass meine Klasse ein Sprite enthält habe ich jetzt das Problem, dass ich Getter und Setter benötige um Objekt und damit dem Sprite Position, Größe etc. zuweisen kann. In diesen Settern werden einfach die entsprechenden Methoden von sf::Sprite aufgerufen, zB.

Code: Alles auswählen

void CGameObject::SetPosition(sf::Vector2f pos)
{
	m_sSprite.SetPosition(pos);
}
oder

Code: Alles auswählen

sf::Vector2f CGameObject::GetPosition(void)
{
	return m_sSprite.GetPosition();
}
Irgendwie kommt mir das nicht wirklich geschickt vor, da ich ja nun ständig Sachen extra aufrufen muss, die sf::Sprite schon bietet.
Trotzdem möchte ich so eine Klasse haben, schließlich sollen die Objekte auch mal noch Leben, Waffen oä bekommen, das heißt ich benötige eine Klasse, die das bewerkstelligt.
Die Frage ist nun: Mach ich das richtig? Soll ich völlig anders vorgehen? Für Tips wäre ich dankbar.
Nein, ich denke das passt schon. Es geht ja auch kaum anderes, oder besser. Was noch ginge, ist die sf::Sprite public machen und die Position und was sonst noch direkt von außen zu setzen, aber das finde ich nicht so toll und entspricht nicht der Idee der Kapselung.

[Edit]
Oder was eben pUnkOuter geschrieben hat. Ist vlt. sogar noch besser!

Am allerwenigsten gefällt mir das Zeichen meines Objekts, das wie folgt bewerkstelligt wird:

Code: Alles auswählen

sf::Sprite CGameObject::GetSprite(void)
{
	return m_sSprite;
}
Und dann wird in der main wie folgt gezeichnet:

Code: Alles auswählen

App.Draw(Player.GetSprite());
Also, du musst bedenken, das du bei deiner "GetSprite"-Funktion eine Kopie rausgiebst.
Und das ist nicht sehr performant, da bei dem Aufruf jedesmal sämtliche Daten kopiert werden.
Und:
Du kannst dann natürlich nicht sowas machen:
player.getSprite().setPosition(100, 200)!!
Weil du dann setPosition(100, 200) eben auf die Kopie anwendest ;)
Nimm eine Referenz oder einen Zeiger!
zB so:

Code: Alles auswählen

sf::Sprite& CGameObject::GetSprite(void) 
{
	return m_sSprite;
}
2. Fiepen
Dann hab ich noch ein technisches Problem. Mit obiger Klasse habe ich ein Objekt erstellt, ein Bild reingeladen und dies dann (im Fenstermodus) zeichnen lassen. Sobald das Programm startet, fiept mein Rechner, was nervt. Maximiere ich das Fenster wird das Fiepen leiser, weg ist es allerdings nicht. Weiß jemand woran das liegen könnte?
Das klingt nicht gesund... weiß auch nicht woran das liegen könnte!

Gruß

Re: Anfängerfragen Klassendesign & SFML

Verfasst: 16.03.2012, 09:33
von Schrompf
War das Fiepen nicht mal ein "Fehler" einer bestimmten Grafikkarten-Sorte bei sehr hohen Framerates? Falls ja, dann aktivere mal VerticalSync und es müsste weg sein.

Re: Anfängerfragen Klassendesign & SFML

Verfasst: 16.03.2012, 12:37
von nerem
Vielen Dank für die guten Antworten :) Dann werd ich das heute abend entsprechend anpassen.
Und mit dem fiepen mal sehn, ich werds auf alle Fälle versuchen mit dem vsync. Da ihr gesagt habt, das wäre bei bestimmten Grafikkarten der Fall:
Ich hab eine 8800 GT von Gainward, vielleicht sagt das ja jemandem was in dem Bezug.

Also nochmal vielen Dank :)

edit: vsync anschalten hat funktioniert, herzlichen Dank!