Anfängerfragen Klassendesign & SFML

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
nerem
Beiträge: 15
Registriert: 15.03.2012, 22:18

Anfängerfragen Klassendesign & SFML

Beitrag 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
pUnkOuter
Establishment
Beiträge: 303
Registriert: 15.04.2002, 15:59

Re: Anfängerfragen Klassendesign & SFML

Beitrag 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.
Ein Zeiger ins Blaue ist wie ein Wegweiser nach <SEGFAULT>. Wenn du denkst, mein Name hat was mit abgefuckter Kleidung und bunten Haaren zu tun, dann kehr besser um.
joggel

Re: Anfängerfragen Klassendesign & SFML

Beitrag 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ß
Benutzeravatar
Schrompf
Moderator
Beiträge: 4869
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Anfängerfragen Klassendesign & SFML

Beitrag 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.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
nerem
Beiträge: 15
Registriert: 15.03.2012, 22:18

Re: Anfängerfragen Klassendesign & SFML

Beitrag 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!
Antworten