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

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

31

27.05.2013, 11:14

Warum willst du die Kollisionsprüfung überhaupt in Schleifen einbauen. Du meinst, dass du alle Tiles durchläufst und dann prüfst ob der Spieler damit kollidiert, oder nicht? Du kennst ja die Position des Spielers (oder der Figur, welche du mit der Map kollidieren lassen möchtest). Durch die Position kannst du die Kacheln unter dem Spieler relativ einfach bestimmen. Du weißt wie groß ein Tile ist, wie groß der Spieler ist und an welcher Position der Spieler ist. Wenn du jetzt überlegst mit welchen Kacheln der Spieler theoretisch kollidieren könnte, dann weißt du auch welche Kacheln du auf Kollision prüfen musst. Je nach Größe des Spielers können das verschieden viele Kacheln sein die du prüfen musst. Du kannst dich ja einfach mal mit einem Schachbrett und einer Schachfigur hinsetzen. Jetzt bewegst du die Figur über das Schachbrett. Bewege sie genau so wie die Figuren sich in deinem Spiel bewegen können. Können sie sich in deinem Spiel frei bewegen und sich nicht fest an die Kacheln gebunden, so bewege die Schachfigur genau so. Jetzt legst du dir Münzen (oder was auch immer) auf die Felder mit denen der Spieler kollidieren soll. Versuch damit einfach mal rum zuspielen und das was du siehst auf dein Spiel zu übertragen. Viel aufmalen hilft auch weiter.
„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.“

TigerClaw25

unregistriert

32

27.05.2013, 17:21

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
// CheckCollisions
//
// Aufgabe: Kollisionen überprüfen
//
void CGame::CheckCollisions ()
{
    
    SDL_Rect Player;
    SDL_Rect Tile;
    
        for (int j = 0; j<map_hoehe; j++)
        {
            for (int k = 0; k<map_breite; k++)
            {                       
        Player = m_pPlayer->GetRect();
        Tile = p_Spritemap[0].GetRect();
                        
                if (Tile.y < Player.y + Player.h &&
                    Tile.y + Tile.h > Player.y &&
                    Tile.x < Player.x + Player.w &&
                    Tile.x + Tile.w > Player.x)
                {
                    m_bGameRun = false;
                }
            }
        }

} // CheckCollisions


Wenn ich die if-Abfrage direkt oben beim Darstellen der Tiles innerhalb der for-Schleifen einbaue, läuft alles. Wenn ich es aber so wie jetzt getrennt mache, funktioniert es nicht ...

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

33

27.05.2013, 17:46

Du holst dir auch jedes mal das selbe Tile und prüfst damit auf Kollision.

C-/C++-Quelltext

1
Tile = p_Spritemap[0].GetRect();

Das kannst du noch so oft aufrufen, da bekommst du immer das selbe Objekt.
„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.“

TigerClaw25

unregistriert

34

27.05.2013, 18:26

Wenn ich das aber in den Block, wo die Tiles gesetzt werden, einfüge, dann funktioniert es, also hier in der innersten for-Schleife:

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
/ Run
//
// Aufgabe: Hauptschleife des Spiels
//
void CGame::Run ()
{
    // Hauptschleife des Spiels durchlaufen
    //
    while (m_bGameRun == true)
    {
    
        // Events bearbeiten
        ProcessEvents ();
        
        // Framework updaten und Buffer löschen
        g_pFramework->Update ();
        g_pFramework->Clear ();

        int byte_nr = 0;
        for (int j = 0; j<map_hoehe; j++)
        {
            for (int k = 0; k<map_breite; k++)
            {
                tilemap[j][k] = level_1[byte_nr];
                p_Spritemap[tilemap[j][k]].SetPos(k*TILE_HEIGHT, j*TILE_WIDTH);
                p_Spritemap[tilemap[j][k]].Render();
                byte_nr++;
            }
        }

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

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


} // Run


Normalerweise würde ich loigisch gesehen die map durchlaufen und prüfen, ob das Objekt 0 (steht für rot) an der Stelle ist:

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
//
// Aufgabe: Kollisionen überprüfen
//
void CGame::CheckCollisions ()
{
        SDL_Rect Player;
        SDL_Rect Tile;

        Player = m_pPlayer->GetRect();
        

        for (int j = 0; j<map_hoehe; j++)
        {
            for (int k = 0; k<map_breite; k++)
            {
                if (tilemap[j][k] == 0)         
                Tile = p_Spritemap[0].GetRect();
                                            
                if (Tile.y < Player.y + Player.h &&
                    Tile.y + Tile.h > Player.y &&
                    Tile.x < Player.x + Player.w &&
                    Tile.x + Tile.w > Player.x)
                {
                    m_bGameRun = false;
                }
            }
        }

} // CheckCollisions

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »TigerClaw25« (27.05.2013, 18:31)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

35

27.05.2013, 18:43

Du holst dir da trotzdem jedes mal das selbe Rect. Das Rect hat jedes mal die selben Koordinaten. Wenn du dir ein Schachbrett nimmst dann prüfst du die ganze Zeit nur die Kollision mit einer Kachel vom Schachbrett. Und dein neuer Code sollte so nicht funktionieren, es sei denn in TileMap ist jeder Wert 0. Ansonsten hat Tile nämlich einfach die Standadwerte von einem SDL_Rect. Auf Kollision prüfen tust du da schon mal nirgendwo. Wenn du die Kollision über die Rects machen möchtest, was meiner Meinung nach eh Unsinn ist, dann muss jedes Tile ein eigenes Rect kriegen. Allein die Position ist ja bei jeden Tile anders.
„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.“

TigerClaw25

unregistriert

36

04.07.2013, 11:10

Hab eine Frage zu Tilemaps. Hab in der Kollision-Funktion eine Überprüfung eingebaut, die schauen soll, ob es eine Kollision gibt bzw an der Stelle 0 (=Wand) gibt. Als TEst soll das Spiel dabei beendet werden. Klappt aber leider nicht, kann mir da jemand helfen? Komme einfach nicht drauf ...

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
#include "Game.hpp"

// Tiles - Konstanten
const unsigned int TILE_WIDTH = 80;
const unsigned int TILE_HEIGHT = 80;
const int TOTAL_TILES = 64;
const int TILES_SPRITES = 4;
    
// Map Größe
const unsigned int map_breite = 16;
const unsigned int map_hoehe = 4;

// Map selbst
unsigned int level_1[map_breite*map_hoehe] =  
  { 0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,
  3,2,1,0,0,1,2,3,0,1,2,3,0,1,2,3,
  0,0,0,0,0,1,2,3,0,1,2,3,0,1,2,3,
  3,3,3,3,0,1,2,3,0,1,2,3,0,1,2,3
};
unsigned int tilemap[map_breite][map_hoehe];
// Konstruktor
//
// Aufgabe: Allgemeine Initialisierungen
//
CGame::CGame ()
{
    m_pPlayer = NULL;
    p_Spritemap = NULL;

} // Konstruktor


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

    // Hintergrundbild (Sprite) laden
    p_Spritemap = new CSprite [TILES_SPRITES];

    p_Spritemap[0].Load ("Data/red.bmp");
    p_Spritemap[1].Load ("Data/green.bmp");
    p_Spritemap[2].Load ("Data/yellow.bmp");
    p_Spritemap[3].Load ("Data/blue.bmp");

    
    

    // Spiel läuft
    m_bGameRun = true;

} // Init

// Quit
//
// Aufgabe: Instanzen freigeben
//
void CGame::Quit ()
{
        // Hintergrundsprite freigeben

    if (p_Spritemap != NULL)
    {
        delete[] p_Spritemap;
        p_Spritemap = NULL;
    }

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

} // Quit

// Run
//
// Aufgabe: Hauptschleife des Spiels
//
void CGame::Run ()
{
    // Hauptschleife des Spiels durchlaufen
    //
    while (m_bGameRun == true)
    {
    
        // Events bearbeiten
        ProcessEvents ();
        
        // Framework updaten und Buffer löschen
        g_pFramework->Update ();
        g_pFramework->Clear ();

        int byte_nr = 0;
        for (int j = 0; j<map_hoehe; j++)
        {
            for (int k = 0; k<map_breite; k++)
            {
                tilemap[j][k] = level_1[byte_nr];
                p_Spritemap[tilemap[j][k]].SetPos(k*TILE_HEIGHT, j*TILE_WIDTH);
                p_Spritemap[tilemap[j][k]].Render();
                byte_nr++;
            }
        }

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

        // 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


// CheckCollisions
//
// Aufgabe: Kollisionen überprüfen
//
void CGame::CheckCollisions ()
{
        SDL_Rect Player;


        Player = m_pPlayer->GetRect();
        

        for (int j = 0; j<map_hoehe; j++)
        {
            for (int k = 0; k<map_breite; k++)
            {
                SDL_Rect Tile[map_breite][map_hoehe];
                    
                Tile[j][k] = p_Spritemap[tilemap[j][k]].GetRect();
                                            
                if (Tile[j][k].y < Player.y + Player.h &&
                    Tile[j][k].y + Tile[j][k].h > Player.y &&
                    Tile[j][k].x < Player.x + Player.w &&
                    Tile[j][k].x + Tile[j][k].w > Player.x)
                {
                    m_bGameRun = false;
                }
        
            }
        }

} // CheckCollisions

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »TigerClaw25« (04.07.2013, 11:29)


37

04.07.2013, 12:58

Findest du nicht, das ein "Spiel beenden" Test eine ziemlich schlechte Methode ist, um sowas zu überprüfen?
Warum setzt du keine Breakpoints und nutzt den debugger?

TigerClaw25

unregistriert

38

04.07.2013, 13:12

Wollte auch nur prüfen, ob es überhaupt funktioniert, aber es tut sich ja nichts.

Breakpoint würde ich machen, aber es dauert ziemlich lange, bis sich im Hintergrund etwas tut ...


EDIT: Hab den Code oben in die ersten Schleifen gepackt, es funktioniert. Möchte es aber in verschiedene Funktionen, das scheint aber nicht zu funktionieren

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
        // Framework updaten und Buffer löschen
        g_pFramework->Update ();
        g_pFramework->Clear ();

        SDL_Rect Player;
        SDL_Rect Tile[map_breite][map_hoehe];
        Player = m_pPlayer->GetRect();

        int byte_nr = 0;
        for (int j = 0; j<map_hoehe; j++)
        {
            for (int k = 0; k<map_breite; k++)
            {
                tilemap[j][k] = level_1[byte_nr];
                p_Spritemap[tilemap[j][k]].SetPos(k*TILE_HEIGHT, j*TILE_WIDTH);
                p_Spritemap[tilemap[j][k]].Render();
                
                Tile[j][k] = p_Spritemap[tilemap[j][k]].GetRect();
                if (tilemap[j][k] == 0){    
                if (Tile[j][k].y < Player.y + Player.h &&
                    Tile[j][k].y + Tile[j][k].h > Player.y &&
                    Tile[j][k].x < Player.x + Player.w &&
                    Tile[j][k].x + Tile[j][k].w > Player.x)
                {
                    m_bGameRun = false;
                }
                }

                byte_nr++;
            }
        }


Aber von der Überlegung her bin ich doch auf dem richtigen weg oder? Über Rects bräuchte ich eigentlich nicht gehen, diese ändern sich ja nicht, aber komme da irgendwie jetzt nicht weiter

Wenn ich nämlich den Teil statt oben einzeln in eine Funktion packe, dann klappt es nicht.

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
// CheckCollisions
//
// Aufgabe: Kollisionen überprüfen
//
void CGame::CheckCollisions ()
{
        SDL_Rect Player;
        SDL_Rect Tile[map_breite][map_hoehe];
        Player = m_pPlayer->GetRect();
        
            for (int j = 0; j<map_hoehe; j++)
        {
            for (int k = 0; k<map_breite; k++)
            {
                Tile[j][k] = p_Spritemap[tilemap[j][k]].GetRect();
                if (tilemap[j][k] == 0){
                    m_bGameRun = false;
                if (Tile[j][k].y < Player.y + Player.h &&
                    Tile[j][k].y + Tile[j][k].h > Player.y &&
                    Tile[j][k].x < Player.x + Player.w &&
                    Tile[j][k].x + Tile[j][k].w > Player.x)
                {
                    m_bGameRun = false;
                }
                }
            }
            }


} // CheckCollisions

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »TigerClaw25« (04.07.2013, 13:47)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

39

04.07.2013, 17:44

Du musst nicht mit jedem Tile auf Kollision prüfen. Das ist totaler Unsinn. Das ist ja einer der vielen Vorteile bei solchen Datenstrukturen. Man teilt sich die Welt so ein, dass man sinnvoll damit arbeiten kann. Hatte ich soweit ich es im Kopf habe sogar mehr als ein mal in diesem Thread erklärt. Weiterhin habe ich zum Beispiel wenig lust mir deine ganzen Zeilen anzugucken;) Vor allem weil keine Erklärung dazu vorhanden ist. Wenn ich dein Projekt hätte könnte ich es mir angucken und dann selbst mit dem Debugger durchsteppen. Vorher müsste ich aber vermutlich Stundenlang Code lesen. Also setz du dich einfach mit dem Debugger hin. Sollte ja nicht so schwer sein da Breakpoints vor die Funktion zu setzen.
„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.“

TigerClaw25

unregistriert

40

04.07.2013, 20:59

Nun ja, mit dem Debugger habe ich zumindest herausgefunden, dass das erste Rect, dass ich mir hole an der Position x = 960 und y = 240 liegen soll. Alle anderen Positionen sind -132000.

Was ich da genau falsch mache, sehe ich einfach nicht ...

Werbeanzeige