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

Sp3iky

Treue Seele

Beiträge: 232

Beruf: Entwicklungsingenieur

  • Private Nachricht senden

11

11.04.2013, 23:22

Nimelrian nennt die einfache Variante, wo du einfach einen festen Wert davon abziehst. Ansonsten könntest du dir den Wert auch über die Kollision berechnen. Je nach Winkel und Geschwindigkeit der Kollision wird dann mehr oder weniger "Leben" abgezogen.

Und um nochmal den Unterschied klar zu machen: Du darfst natürlich Variablen in deiner cGame haben, aber eine Membervariable (eine Variable der Klasse, die in der Headerdatei definiert ist) ist etwas anderes als eine temporäre Variable. Wie gesagt, ich würde dir vorschlagen, die Grundlagen der objektorientierten Programmierung nochmal durchzugehen. Es gibt ein paar Konzepte, die man auf jeden Fall kennen sollte, um viele Fehler gleich vom Anfang an zu vermeiden.

TigerClaw25

unregistriert

12

12.04.2013, 07:41

Ok, ich wErde mir das Ganze nochmal genauer anschauen.

Aber eine Zwischenvariable und eine FUnktion, die mir von CPlayer den Wert zurückgibt, brauche ich dennoch. Sonst kann ich mir das Ganze nicht anzeigen lassen. Wenn ich nur eine Funktion Health habe, die meine Lebensenergie inkrementiert oder dekrementiert kann mir diese ja nicht anzeigen.


Kurz nochmal zur Animation. Habe jetzt die Asteroidenklasse soweit umgeschrieben bzw. in Explosion umbenannt .

Dann habe ich in meiner if Schleife, die eine Kollision prüft, folgendes eingefügt:

// Explosion animieren
CExplosion Explosion;
Explosion.Init(m_pSpriteExplosion, 300, 400);
Explosion.Render();

Brauche ja keine Listen oder? Es gibt ja nur eine Explosion pro zerstörtem Asteroiden oder sehe ich das falsch? Das blöde daran ist, dass ich die Animation nur wenige millisekunden zu Gesicht bekomme!

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »TigerClaw25« (12.04.2013, 11:46)


TigerClaw25

unregistriert

13

12.04.2013, 12:09

Mittlerweile hängt sich das Spiel sogar auf, obwohl ich nichts geändert habe ...

Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

14

12.04.2013, 12:52


// Explosion animieren
CExplosion Explosion;
Explosion.Init(m_pSpriteExplosion, 300, 400);
Explosion.Render();

Brauche ja keine Listen oder? Es gibt ja nur eine Explosion pro zerstörtem Asteroiden oder sehe ich das falsch? Das blöde daran ist, dass ich die Animation nur wenige millisekunden zu Gesicht bekomme!


Holy...

Ich überlege gerade wirklich, ob es überhaupt Sinn macht, dir helfen zu wollen, denn du hast das Prinzip nicht verstanden.
Kleiner Tipp: Du brauchst Listen (Allein die Behauptung, du bräuchtest keine, zeugt von Unwissen pur!)
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

15

12.04.2013, 13:14

in meiner if Schleife, die eine Kollision prüft

Nein.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Fred

Supermoderator

Beiträge: 2 121

Beruf: Softwareentwickler

  • Private Nachricht senden

16

12.04.2013, 13:23

Lass dich erst mal nicht von irgendwelchen Design-Aspekten ablenken. Ich persönlich finde es nicht verkehrt, in diesem Fall mit Gettern und Settern zu arbeiten. Denn Code-Design zu verbessern ist in der Regel kein einfaches hinzufügen von einer Funktion, sondern man muss sich dann grundlegende Gedanken machen, um was sich welche Klasse zu kümmern hat und wie diese aufgerufen wird. In deinem Fall könnte man sich beispielsweise überlegen, die Spiellogik zu kapseln und die Game-Klasse könnte nur noch als Vermittler agieren, die Objekte auf Kollisionen prüft und dann für alle kollidierenden Objekte eine Kollsions-Methode aufruft, für jedes Objekt eine render-Methode aufruft und dergleichen mehr. Man könnte sich aber auch beispielsweise ein System ausdenken, was auf Nachrichten basiert und wo bei besonderen Ereignissen Nachrichten an die entspechenden Objekte gesendet werden, die diese dann handhaben. Es gibt viele Möglichkeiten ein Spielsystem umzusetzen und für den Anfang reicht deines vollkommen aus. Es ist von Design-Gesichtspunkt nicht unbedingt optimal, aber man kann sich auch tot-designen. Vor allem wenn sich der Fokus deiner Frage um etwas ganz anderes dreht.


// Explosion animieren
CExplosion Explosion;
Explosion.Init(m_pSpriteExplosion, 300, 400);
Explosion.Render();

Wenn du das in jeder If-Anweisung(wichtig keine Schleife) schreibst, dann wird jedes Mal ein neues temporäres Objekt erstellt und beim Verlassen der If-Anweisung wieder zerstört. Darum siehst du die Explosion nur so kurz. Deswegen ist die Idee eine Liste für Explosionen zu verwenden nicht verkehrt, weil du zwar nur eine Explosion für ein Objekt brauchst, diese Explosion muss aber über einen längeren Zeitraum existieren und es ist ja nicht klar, wie viele Objekte letztlich existieren, die explodieren können.

EDIT: Ach ja und bitte lest euch nochmal den Thread durch. Lest euch seine Fragen und die entsprechenden Antworten durch und dann stellt euch die Frage: Haben wir ihm egtl. bei seinem Problem geholfen? Und wenn ihr ihm nicht helfen wollt, dann lasst es doch einfach sein und spart euch unnötige Kommentare. Es ist kein Fehler Anfänger zu sein und bei bestimmten Punkten Verständnisprobleme zu haben. Dafür ist dieses Forum doch da.

TigerClaw25

unregistriert

17

12.04.2013, 13:55

@Fred

Vielen Dank. Dein Beitrag hilft mir weiter. Mir ging es ja in erster Linie nur darum, ueberhaupt eine Lebenanzeige auf den Bildschirm zu bringen. Habe mittlerweile das so gemacht, dass ich Get und Set Funktionen in CSpieler habe und diese ueber meine Spielerinstanz in CGame Aufrufe. Ueber eine zwischenvarable gebe ich diese in CGame dann aus.

Zum Thema Explosionen habe ich auch gemerkt, dass bei einfachen Instanzen, also ohne Listen, die Zeit eine Rolle spielt. Aber ich dachte, dass meine Updatefunktion dieses Problem uebernimmt. Hat sie aber nicht.

Ich glaube, dass ich nicht verkehrt gearbeitet habe. Ich erzeuge mir eine Instanz, schiebe diese aBer anders als oben gepostet, in eine Liste und gebe dann ueber diese Liste die Explosionen aus. Muss dann nur noch herausfinden, wie ich feststelle, dass die CheckCollision mir einen Wert zurueckgibt, den ich in eine if Abfrage packe.

TigerClaw25

unregistriert

18

13.04.2013, 17:29

So, hab es jetzt über die Listen hinbekommen.

Und zwar erstelle ich mir, sobald eine Kollision stattgefunden hat eine Instanz der Klasse CExplosion, die ich dann in eine Liste schiebe. Über diese Liste gebe ich das Teil dann in der Game::Run aus. Leider läuft die Animation in einer Schleife munter weiter, verschwindet also nicht vom Bildschirm:

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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
#include "Game.hpp"

// Konstruktor
//
// Aufgabe: Allgemeine Initialisierungen
//
CGame::CGame ()
{
    m_pPlayer = NULL;
    m_pSpriteBackground = NULL;
    m_pSpriteAsteroid = NULL;
    m_pSpriteExplosion = NULL;
} // Konstruktor

// Init
//
// Aufgabe: Spieler, Hintergrund und Asteroid initialisieren
//
void CGame::Init ()
{
    // Neuen Spieler initialisieren
    m_pPlayer = new CPlayer;
    m_pPlayer->Init ();
    m_pPlayer->Reset ();

    /* Neuen Gegner initialisieren
    m_pOpponent = new COpponent;
    m_pOpponent->Init ();
    m_pOpponent->Reset ();
*/
    // Hintergrundbild (Sprite) laden
    m_pSpriteBackground = new CSprite;
    m_pSpriteBackground->Load ("Data/Background.bmp");

    // Sprite für Asteroiden laden
    m_pSpriteAsteroid = new CSprite;
    m_pSpriteAsteroid->Load ("Data/Asteroid.bmp", 20, 64, 64);
    m_pSpriteAsteroid->SetColorKey (255, 0, 255);

    // Sprite für Explosion laden
    m_pSpriteExplosion = new CSprite;
    m_pSpriteExplosion->Load ("Data/Asteroid.bmp", 20, 64, 64);
    m_pSpriteExplosion->SetColorKey (255, 0, 255);

    // Sound laden
    m_pMusic = NULL; 
    m_pMusic = new CSound (44100, AUDIO_S16SYS, 2, 4096);
    m_pMusic->LoadMusic("Data/test.wav",100);
    m_pMusic->PlayMusic();

    // Sound für Asteroiden-Explosion laden
    m_pSoundAsteroid = NULL;
    m_pSoundAsteroid = new CSound (44100, AUDIO_S16SYS, 2, 4096);
    m_pSoundAsteroid->LoadSound("Data/Asteroid_Explosion.wav", 100);

    // Font Lebensenergie
    m_pFontLive = NULL;
    m_pFontLive = new CFont();
    m_pFontLive->LoadFont("Data/sfd/FreeMono.ttf", 15);

    // Font Lebensenergie - Anzahl
    m_pFontNumb = NULL;
    m_pFontNumb = new CFont();
    m_pFontNumb->LoadFont("Data/sfd/FreeMono.ttf", 15);

    // Timer für Asteroiden zurücksetzen
    m_fAsteroidTimer = 0.0f;

    // Spiel läuft
    m_bGameRun = true;
} // Init

// Quit
//
// Aufgabe: Instanzen freigeben
//
void CGame::Quit ()
{
    // Spieler freigeben
    if (m_pPlayer != NULL)
    {
        m_pPlayer->Quit ();
        delete (m_pPlayer);
        m_pPlayer = NULL ;
    }

    /* Spieler freigeben
    if (m_pOpponent != NULL)
    {
        m_pOpponent->Quit ();
        delete (m_pOpponent);
        m_pOpponent = NULL ;
    }*/


    // Hintergrundsprite freigeben
    if (m_pSpriteBackground != NULL)
    {
        delete (m_pSpriteBackground);
        m_pSpriteBackground = NULL;
    }

    // Asteroidensprite freigeben
    if (m_pSpriteAsteroid != NULL)
    {
        delete (m_pSpriteAsteroid);
        m_pSpriteAsteroid = NULL;
    }

        // Explosionssprite freigeben
    if (m_pSpriteExplosion != NULL)
    {
        delete (m_pSpriteExplosion);
        m_pSpriteExplosion = NULL;
    }

    // Hintergrundmusik freigeben
    if (m_pMusic != NULL)
    {
        delete (m_pMusic);
        m_pMusic = NULL;
    }

    // Sound für Asteroiden-Explosion freigeben
    if (m_pSoundAsteroid != NULL)
    {
        delete (m_pSoundAsteroid);
        m_pSoundAsteroid = NULL;
    }

    // Lebensenergie freigeben
    if (m_pFontLive != NULL)
    {
        delete (m_pFontLive);
        m_pFontLive = NULL;
    }

    // Lebenspunkte freigeben
    if (m_pFontNumb != NULL)
    {
        delete (m_pFontNumb);
        m_pFontNumb = NULL;
    }


} // Quit

// Run
//
// Aufgabe: Hauptschleife des Spiels
//
void CGame::Run ()
{
    // Zerstörte Asteroiden (Anzahl)
    m_AsteroidDestroy = 0;

    // Hauptschleife des Spiels durchlaufen
    //
    while (m_bGameRun == true)
    {
        // Events bearbeiten
        ProcessEvents ();

        // Framework updaten und Buffer löschen
        g_pFramework->Update ();
        g_pFramework->Clear ();

        // Hintergrundbild rendern
        m_pSpriteBackground->Render ();

        // Spieler updaten und rendern
        m_pPlayer->Update ();
        m_pPlayer->Render ();
        
        // Gegner updaten und rendern
        //m_pOpponent->Update ();
        //m_pOpponent->Render ();

        // Lebensenergie anzeigen
        int m_HitCount = m_pPlayer->GetHealth();
        
        if (m_HitCount>=5)
        {       
            m_pFontNumb->WriteFont("Energie: ", 530, 550, 255, 20, 50);
            m_pFontNumb->WriteNumber(m_HitCount, 610, 550, 255, 20, 50);
        }
        else if (m_HitCount<=5)
        {
            m_pFontNumb->WriteFont("Energie: ", 530, 550, 255, 20, 50);
            m_pFontNumb->WriteFont("Kritischer Zustand", 610, 550, 255, 20, 50);
        }
            
        // Neue Asteroiden hinzufügen
        SpawnAsteroids ();

        // Kollisionen prüfen
        CheckCollisions ();

        // Asteroiden zerstört (Anzahl)
        if (m_AsteroidDestroy <= 20)
        {
            m_pFontLive->WriteFont("Asteroiden:", 10, 550, 255, 20, 50);
            m_pFontNumb->WriteNumber(m_AsteroidDestroy, 120, 550, 255, 20, 50);
        }
        else
        {
            m_pFontLive->WriteFont("Ziel erreicht!", 10, 550, 255, 20, 50);
        }       

        // Explosion rendern
        RenderExplosion ();
        
        // Asteroiden rendern
        RenderAsteroids ();

        // Buffer flippen
        g_pFramework->Flip ();
    }

} // Run

// ProcessEvents
//
// Aufgabe: Events bearbeiten
//
void CGame::ProcessEvents ()
{
    SDL_Event Event;

    // Gab es ein Event?
    if (SDL_PollEvent (&Event))
    {
        // Ja, also schauen welches
        switch (Event.type)
        {
            // Beenden?
        case (SDL_QUIT):
            {
                m_bGameRun = false;

            } break;


            // Wurde eine Taste gedrückt?
        case (SDL_KEYDOWN):
            {
                switch (Event.key.keysym.sym)
                {
                case (SDLK_ESCAPE):
                    {
                        // Ja, also Spiel beenden
                        m_bGameRun = false;

                    } break;
                }
            } break;
        }
    }

} // ProcessEvents

// SpawnAsteroids
//
// Aufgabe: Nach Ablauf einer bestimmten Zeit neuen Asteroiden erzeugen
//
void CGame::SpawnAsteroids ()
{
    // Timer für nächsten Asteroiden erhöhen
    m_fAsteroidTimer += g_pTimer->GetElapsed ();

    // Wenn eine halbe Sekunde vergangen ist,
    // dann einen neuen Asteroiden erzeugen
    if (m_fAsteroidTimer >= 0.5)
    {
        // Neuer Asteroid
        CAsteroid Asteroid;

        // Zufällige X-Position
        int XPos = rand()%736;

        // Asteroid initialisieren
        Asteroid.Init (m_pSpriteAsteroid, static_cast<float>(XPos), -60.0f);

        // Asteroid in Liste einfügen
        m_AsteroidList.push_back (Asteroid);

        // Zeitgeber wieder zurücksetzen
        m_fAsteroidTimer = 0.0f;
    }

} // SpawnAsteroids


// SpawnExplosion
//
// Aufgabe: Explosion nach einer Kollision erzeugen
//
void CGame::SpawnExplosion ()
{
        // Explosion hinzufügen
        CExplosion Explosion;
        // Asteroid initialisieren
        Explosion.Init (m_pSpriteExplosion, 300.0f, 300.f);

        // Asteroid in Liste einfügen
        m_ExplosionList.push_back (Explosion);          

} // SpawnExplosion

// CheckCollisions
//
// Aufgabe: Kollisionen zwischen Asteroiden und Schüssen prüfen
//
void CGame::CheckCollisions ()
{
    // Schussliste des Spielers holen
    list<CShot> *ShotList = m_pPlayer->GetShotList ();

    // Iteratoren für Asteroiden- und Schussliste sowie Explosionsliste
    list<CAsteroid>::iterator ItAsteroid = m_AsteroidList.begin ();
    list<CShot>::iterator ItShot;
    list<CExplosion>::iterator ItExplosion = m_ExplosionList.begin ();

    // Rects für Asteroiden und Schüsse sowie Spieler
    SDL_Rect RectAsteroid;
    SDL_Rect RectShot;
    SDL_Rect RectPlayer;
    

    // Alle Asteroiden durchlaufen
    while (ItAsteroid != m_AsteroidList.end () )
    {
        // Rect des Asteroiden holen
        RectAsteroid = ItAsteroid->GetRect ();

        // Rect des Spielers holen (Erweitert)
        RectPlayer = m_pPlayer->GetRect();

        // Alle Schüsse durchlaufen
        for (ItShot = ShotList->begin ();
            ItShot != ShotList->end ();
            ++ItShot)
        {
            // Rect des Schusses holen
            RectShot = ItShot->GetRect ();

            // Überschneiden sich die Rects?
            if (RectShot.y < RectAsteroid.y + RectAsteroid.h &&
                RectShot.y + RectShot.h > RectAsteroid.y &&
                RectShot.x < RectAsteroid.x + RectAsteroid.w &&
                RectShot.x + RectShot.w > RectAsteroid.x)
            {       
                // Ja, also gab es eine Kollision. Somit Schuss und
                // Asteroid deaktivieren
                ItAsteroid->SetAlive (false);
                ItShot->SetAlive (false);
                m_AsteroidDestroy++;            // Wieviele Asteroiden zerstört?
                m_pSoundAsteroid->PlaySound();  // Asteriod explodiert -> Soundeffekt   

                SpawnExplosion ();              // Explosion erstellen und in Liste schieben
                
            }

        }

        // Kollision zwischen Asteroid und Spieler prüfen          
            if (RectPlayer.y < RectAsteroid.y + RectAsteroid.h &&
                RectPlayer.y + RectPlayer.h > RectAsteroid.y &&
                RectPlayer.x < RectAsteroid.x + RectAsteroid.w &&
                RectPlayer.x + RectPlayer.w > RectAsteroid.x)
            {
                // Ja, also gab es eine Kollision. Somit Spieler und
                // Asteroid deaktivieren
                ItAsteroid->SetAlive (false);
                m_pPlayer->SetHealth();
                m_pPlayer->Reset();
                // Asteriod explodiert -> Soundeffekt
                m_pSoundAsteroid->PlaySound();
                            
            }

        // Asteroid löschen, falls deaktiviert
        if (ItAsteroid->IsAlive () )
            ItAsteroid++;
        else
            ItAsteroid = m_AsteroidList.erase (ItAsteroid);
        
    }

} // CheckCollision

// RenderAsteroids
//
// Aufgabe: Alle Asteroiden rendern und updaten
//
void CGame::RenderAsteroids ()
{
    // Iterator für die Asteroiden-Liste
    list<CAsteroid>::iterator It;

    // Asteroiden-Liste durchlaufen
    for (It = m_AsteroidList.begin (); It != m_AsteroidList.end (); ++It)
    {
        // Asteroid rendern
        It->Render ();

        // Asteroid updaten
        It->Update ();

    }

} // RenderAsteroids

// RenderAsteroids
//
// Aufgabe: Alle Explosion rendern und updaten
//
void CGame::RenderExplosion ()
{
    // Iterator für die Explosion-Liste
    list<CExplosion>::iterator It;

    // Explosion-Liste durchlaufen
    for (It = m_ExplosionList.begin (); It != m_ExplosionList.end (); ++It)
    {
        // Explosion rendern
        It->Render ();

        // Explosion updaten
        It->Update ();

    }

} // RenderExplosion

19

13.04.2013, 19:08

Du musst isAlive auf false setzen sobalt die Animation einmal durchlaufen wurde und die Explosion dann aus der Liste entfernen. Tust du das?

TigerClaw25

unregistriert

20

13.04.2013, 21:58

darauf bin ich schon gekommen, aber das Spiel bricht direkt nach dem Start ab. Hab ueber den Iterator und SetAlive die Variable auf false gesetzt und dann eventuell auch per erase loeschen, aBer mit oder ohne erase, es geht nicht.

Werbeanzeige