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

Saik0

Treue Seele

  • »Saik0« ist der Autor dieses Themas

Beiträge: 171

Beruf: Anwendungsentwickler

  • Private Nachricht senden

1

11.10.2011, 15:29

Allegro und OOP Pong

Hallo zusammen,

ich hoffe ich habe das richtige Forum erwischt, wenn nicht bitte ich um Pardon ^^ Vor paar Tagen habe ich einen Pong Klon mit C++ und Allegro 5 programmiert. Lief bisher alles gut. Jetzt wollte ich das ganze Zwecks OOP umschreiben und hänge an einer vermutlich banalen Stelle fest. Als Klassen habe ich zunächst nur die Paddle 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
35
36
37
38
39
40
#ifndef PADDLE_H_
#define PADDLE_H_

#include "allegro5/allegro.h"

class Paddle {
public:

    Paddle();
    Paddle(float x, float y, int w, int h);
    virtual ~Paddle();

    int getPaddleH();
    int getPaddleW();
    float getX();
    float getY();

    void setPaddleH(int paddle_h);
    void setPaddleW(int paddle_w);
    void setX(float x);
    void setY(float y);

    void draw();
    void move();

    ALLEGRO_BITMAP *getBitmap();
    void createBitmap(ALLEGRO_BITMAP *image);

private:

    float x;
    float y;
    int paddle_w;
    int paddle_h;

    ALLEGRO_BITMAP *image;

};

#endif /* PADDLE_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
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
#include "Paddle.h"
#include "allegro5/allegro5.h"

Paddle::Paddle() {
    setX(0);
    setY(0);
    setPaddleW(0);
    setPaddleH(0);
}

Paddle::~Paddle() {
}

Paddle::Paddle(float x, float y, int w, int h) {
    setX(x);
    setY(y);
    setPaddleW(w);
    setPaddleH(h);

    //create the Bitmap for the paddle
    createBitmap(al_create_bitmap(getPaddleW(), getPaddleH()));
}

int Paddle::getPaddleH() {
    return this->paddle_h;
}

int Paddle::getPaddleW() {
    return this->paddle_w;
}

float Paddle::getX() {
    return this->x;
}

float Paddle::getY() {
    return this->y;
}

void Paddle::setPaddleH(int paddle_h) {
    this->paddle_h = paddle_h;
}

void Paddle::setPaddleW(int paddle_w) {
    this->paddle_w = paddle_w;
}

void Paddle::setX(float x) {
    this->x = x;
}

void Paddle::setY(float y) {
    this->y = y;
}

void Paddle::draw() {
    al_set_target_bitmap(getBitmap());
    al_clear_to_color(al_map_rgb_f(200, 0, 200));
}

void Paddle::move() {

}

ALLEGRO_BITMAP *Paddle::getBitmap() {
    return image;
}

void Paddle::createBitmap(ALLEGRO_BITMAP *image) {
    this->image = image;
}


So.. jetzt erzeuge ich in der main Klasse das Paddle Objekt:

C-/C++-Quelltext

1
    Paddle *paddle = new Paddle(paddle_y, paddle_x, PADDLE_SIZE_W, PADDLE_SIZE_H); 


Das Problem besteht darin, dass das Erzeugen des Objektes nun fehl schlägt. Der Debugger springt in den Konstruktor der Paddle Klasse bis zur Zeile wo

C-/C++-Quelltext

1
createBitmap(al_create_bitmap(getPaddleW(), getPaddleH()));
ausgeführt wird und beendet das ganze ohne irgend eine Meldung. Debugge ich weiter, komme ich zur eigentlichen Allegro Funktion, die mir ein Bitmap erzeugen sollte. Ich befürchte, dass ich die Pointer falsch verwende. Bin mir aber nicht sicher und wollte euch fragen, ob ihr irgendwas erkennen könnt, was ich falsch mache. Sehe praktisch den Wald vor lauter Bäumen nicht mehr :-\

grüße
Saik0

XelVair

Frischling

Beiträge: 46

Beruf: Student

  • Private Nachricht senden

2

11.10.2011, 16:57

Hmm, kenne mich zwar selber nicht so gut aus, aber ich glaube zu wissen dass du innerhalb der klasse normal mit dem punkt-operator arbeitest, egal ob das Objekt später über einen Pointer oder direkt aufgerufen wird. //Falsch, tut mir leid. "this" gibt in der Tat einen Pointer auf das eigene Objekt zurück.

Desweiteren würde ich private Funktionen und Variablen beispielsweise mit "_" oder "My" am Anfang kennzeichnen, dann kannst du dir das "this" komplett sparen ;)

Hoffe ich konnte helfen,
~Xelvair
Ich bin eine Siegnatur, ihr kriegt mich nicht unter!

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »XelVair« (11.10.2011, 17:03)


3

11.10.2011, 20:42

Desweiteren würde ich private Funktionen und Variablen beispielsweise mit "_" oder "My" am Anfang kennzeichnen, dann kannst du dir das "this" komplett sparen ;)

Das mit dem _ und dem My ist in Python gebräuchlich, in C++ aber eher nicht. Mach es ruhig so wie bisher. Das this-> kannst du dir bei den Gettermethoden sowieso sparen, wenn es dich stört.

XelVair

Frischling

Beiträge: 46

Beruf: Student

  • Private Nachricht senden

4

12.10.2011, 07:53

Desweiteren würde ich private Funktionen und Variablen beispielsweise mit "_" oder "My" am Anfang kennzeichnen, dann kannst du dir das "this" komplett sparen ;)

Das mit dem _ und dem My ist in Python gebräuchlich, in C++ aber eher nicht. Mach es ruhig so wie bisher. Das this-> kannst du dir bei den Gettermethoden sowieso sparen, wenn es dich stört.
hmm.. mir leuchtet nicht ein, warum das nur in Python angebracht sein soll. Solange es zur Ordnung beiträgt ist doch nichts falsch daran, derartige Notierungen auch in anderen Sprachen zu verwenden.. Darüber hinaus bin ich mir ziemlich sicher dass Klassen in der SFML auch Private Memberfunktionen- und Variablen mit "My" am Anfang haben ;)
Ich bin eine Siegnatur, ihr kriegt mich nicht unter!

idontknow

unregistriert

5

12.10.2011, 09:14

Nur Membervariablen, aber keine Methoden (zur SFML).
Dass benutzen von "_" und "My" oder "m_" in Membervariablen ist wohl ziemlich gebräuchlich, bei Methoden kenne ich jetzt nichts was so "verbreitet" ist, wobei es da auch weniger Sinn macht. Generell braucht man sowas aber alles nicht wenn man seine Klasse ordentlich durchstrukturiert, nicht zuviel in eine Klasse packt und ordentliche Namen vergibt ;). Das is aber auch mehr win Wunschtraum :P

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

6

12.10.2011, 10:32

Ich meine dass es zu Problem kommt, wenn man in C++ this im Konstruktor benutzt, da dass Objekt ja noch nicht komplett initialisiert ist. Du benutzt es zwar nicht direkt, aber indirekt bei den Settern und Gettern. Vielleicht liegt das Problem ja da.
„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.“

Saik0

Treue Seele

  • »Saik0« ist der Autor dieses Themas

Beiträge: 171

Beruf: Anwendungsentwickler

  • Private Nachricht senden

7

12.10.2011, 11:01

Danke für eure Antworten. Das Problem konnte ich heute lösen. Es lag mehr bei Allegro. Bevor man eine Bitmap erstellen kann, muss das Objekt erst nach der Initialisierung des Fensters erfolgen und da ich mein Paddle Objekt am Anfang erstellen wollte, kam es zu diesem Fehler. Eigentlich trivial aber man muss erst einmal darauf kommen.. aber auch lehrreich das ganze. Desweiteren werde ich meinen Stil ein wenig ändern, denk ich ^^

grüße
Saik0

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

12.10.2011, 12:49

Desweiteren würde ich private Funktionen und Variablen beispielsweise mit "_" oder "My" am Anfang kennzeichnen, dann kannst du dir das "this" komplett sparen ;)

Das mit dem _ und dem My ist in Python gebräuchlich, in C++ aber eher nicht. Mach es ruhig so wie bisher. Das this-> kannst du dir bei den Gettermethoden sowieso sparen, wenn es dich stört.
hmm.. mir leuchtet nicht ein, warum das nur in Python angebracht sein soll. Solange es zur Ordnung beiträgt ist doch nichts falsch daran, derartige Notierungen auch in anderen Sprachen zu verwenden.. Darüber hinaus bin ich mir ziemlich sicher dass Klassen in der SFML auch Private Memberfunktionen- und Variablen mit "My" am Anfang haben ;)

Das ist eben Geschmackssache. Meiner Meinung nach ist sowas in gutem Code überflüssig. Ich würde sogar soweit gehen, es als eine Eigenschaft von gutem Code zu sehen, dass er ohne sowas auskommt. Aber unabhängig von geschmacklichen Fragen, sollte man mit '_' am Anfang von Namen in C++ sehr vorsichtig sein. Alle Namen die mit einem '_' gefolgt von einem Großbuchstaben beginnen, sind, gleich wie alle Namen die "__" enthalten, für den Compiler reserviert, sollte man also nicht verwenden. D.h. '_' gefolgt von Kleinbuchstabe geht, aber nur für Member oder lokale Variablen. Im global namespace ist sogar jeder Name der mit einem '_' beginnt reserviert.

Ich meine dass es zu Problem kommt, wenn man in C++ this im Konstruktor benutzt, da dass Objekt ja noch nicht komplett initialisiert ist. Du benutzt es zwar nicht direkt, aber indirekt bei den Settern und Gettern. Vielleicht liegt das Problem ja da.

Hängt davon ab wie man this benutzt. Zugriff auf Membervariablen im Körper des Konstruktors funktioniert garantiert immer, da die dort schon alle konstruiert sind. In der Initialisierungsliste ist etwas Vorsicht geboten, was die Initialisierungsreihenfolge angeht. Und mit virtuellen Methoden gibts auch ein paar Fallstricke.

buggypixels

Treue Seele

Beiträge: 125

Wohnort: Meerbusch

Beruf: Programmierer

  • Private Nachricht senden

9

12.10.2011, 13:29

Bezüglich der beiden Konstruktoren sollte Du Deinen Code ändern:

C-/C++-Quelltext

1
2
3
4
5
6
Paddle::Paddle() {
    setX(0);
    setY(0);
    setPaddleW(0);
    setPaddleH(0);
}


sollte eher

C-/C++-Quelltext

1
2
Paddle::Paddle() : x(0) , y(0) , paddle_w(0), paddle_h(0) {
}


sein.
Es ist übrigens sehr verbreitet private Variablen mit m_ zu beginnen. Eine Namenskonvention bei Funktionen ergeben meiner Meinung nach keinen Sinn.
Gleichzeitig könntest Du die getter und setter Methoden auch direkt inline machen. Die getter Methode würde ich noch als const deklarieren. Das zeigt
deutlich nach außen, dass die Methode NICHT den inneren Zustand des Objektes ändert.
Die getBitmap Methode scheint auch völlig überflüssig zu sein.

Naja, da ich etwas Zeit habe, fangen wir doch mal eine OOP Diskussion an.
Also: Warum ist in der Paddle Klasse eine draw Methode? Sie ändert ja keine Daten in der Instanz, also warum hast Du sie in der Klasse?
Streng nach OOP Regeln sollte man diese Methode eher auslagern:

C-/C++-Quelltext

1
void draw(....)

Damit man weiß, wozu diese Methode gehört, kannst Du sie in einen Namespace verpacken:

C-/C++-Quelltext

1
2
3
4
5
namespace render {

void draw(....);

}

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

10

12.10.2011, 13:42

in Python ist es üblich, protected Variablen mit einem "_" und private Variablen mit einem "__" zu kennzeichnen
das hat aber auch den Grund, dass es in Python keine Möglichkeit gibt, die Variablen effektiv vor Zugriffen zu schützen (es ist einfach üblich, von außen nicht auf diese Variablen zuzugreifen)
eine Besonderheit sind Variablen mit "__" am Anfang, da aus dem "__" ein "_<Klassenname>_" gemacht wird (für Zugriffe von außen muss man also den Klassennamen kennen)

außerdem möchte ich noch den Begriff "Namenskonvention" in den Raum stellen
beispielsweise werden private Membervariablen in C# mit einem kleinen Buchstaben angefangen, Properties (beispielsweise zum Zugriff auf die private Membervariablen) aber werden mit einem großen Buchstaben angefangen (meist ist das der einzige Unterschied zwischen Membervariable und Property)

Edit: warum benötige ich immer so lange zum Antworten? v.v

Edit2:
streng nach OOP gibt es keine Funktionen, sondern nur Methoden
in welche Klasse sollte die Methode draw() also?
auch die Getter verändern das Objekt nicht, aber diese können drin bleiben?
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Werbeanzeige