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

1

02.04.2017, 15:07

[C++] Bewegung einer Spielfigur für Sokoban-Klon

Hallöchen,

ich sitze jetzt schon eine ziemlich lange Weile an einem Sokoban-Projekt. Das Spiel funktioniert grundsätzlich sehr gut, alles bewegt sich, Grenzen werden eingehalten usw. Jetzt ergeben sich aber zwei Probleme: Bisher kann ich nur eine Kiste implementieren und verschieben und ich habe die Bewegung ziemlich kompliziert gelöst. Also hab ich mir gedacht, ich versuche mal das auseinander zu wurschteln.
Nach meinen Änderungen wird das Programm zwar kompiliert, hängt sich aber mehr oder weniger sofort auf, wenn ich es starte. Ich vermute mal, dass die Idee vielleicht grundsätzlich gar nicht falsch ist, die Umsetzung aber zu viel Rechenleistung erfordert? Vielleicht habe ich auch einfach immer noch viel zu kompliziert gedacht und es geht viel leichter^^ es wäre toll, wenn mir jemand helfen könnte. :)

Ich hab SDL2 benutzt, aber ich bin mir ziemlich sicher, dass es nicht daran liegt, sondern dass es eher ein logischer Fehler von mir ist :)


Hier mal ein Code-Schnipsel vom Bewegungsmechanismus:
('F' ist ein freies Feld, 'K' eine Kiste, 'A' und 'B' sind Hindernisse)

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
if (SDL_PollEvent(&e) != 0) {
                    if (e.type == SDL_KEYDOWN) {
                        taste = e.key.keysym.sym;
                        if (taste == SDLK_ESCAPE) {
                            ende = true;
                        }



                        if (taste == SDLK_UP) {
                            
                            ziel_y = -1;
                            bewegung(figur_y, figur_x, ziel_y, ziel_x, map);
                            schieben(figur_y, figur_x, ziel_y, ziel_x, map);
                            
                            if(bewegung(figur_y, figur_x, ziel_y, ziel_x, map)){
                                figur_y -=1;
                            }
                            
                            if(schieben(figur_y, figur_x, ziel_y, ziel_x, map)){
                                map[figur_y+ziel_y][figur_x+ziel_x] = 'F';
                                map[figur_y+(ziel_y*2)][figur_x+(ziel_x*2)] = 'K';
                            }
                            
                        }
                        else if (taste == SDLK_DOWN) {
                            
                            ziel_y = 1;
                            bewegung(figur_y, figur_x, ziel_y, ziel_x, map);
                            schieben(figur_y, figur_x, ziel_y, ziel_x, map);
                            
                            if(bewegung(figur_y, figur_x, ziel_y, ziel_x, map)){
                                figur_y +=1;
                            }
                            
                            if(schieben(figur_y, figur_x, ziel_y, ziel_x, map)){
                                map[figur_y+ziel_y][figur_x+ziel_x] = 'F';
                                map[figur_y+(ziel_y*2)][figur_x+(ziel_x*2)] = 'K';
                            }

                        }
                        else if (taste == SDLK_RIGHT) {
                            
                            ziel_x = 1;
                            bewegung(figur_y, figur_x, ziel_y, ziel_x, map);
                            schieben(figur_y, figur_x, ziel_y, ziel_x, map);
                            
                            if(bewegung(figur_y, figur_x, ziel_y, ziel_x, map)){
                                figur_x +=1;
                            }
                            
                            if(schieben(figur_y, figur_x, ziel_y, ziel_x, map)){
                                map[figur_y+ziel_y][figur_x+ziel_x] = 'F';
                                map[figur_y+(ziel_y*2)][figur_x+(ziel_x*2)] = 'K';
                            }
                            
                        }
                        else if (taste == SDLK_LEFT) {
                            
                            ziel_x = -1;
                            bewegung(figur_y, figur_x, ziel_y, ziel_x, map);
                            schieben(figur_y, figur_x, ziel_y, ziel_x, map);
                            
                            if(bewegung(figur_y, figur_x, ziel_y, ziel_x, map)){
                                figur_x -=1;
                            }
                            
                            if(schieben(figur_y, figur_x, ziel_y, ziel_x, map)){
                                map[figur_y+ziel_y][figur_x+ziel_x] = 'F';
                                map[figur_y+(ziel_y*2)][figur_x+(ziel_x*2)] = 'K';
                            }
                        }
                        else if (taste == SDLK_SPACE) {
                            figur_x = start_figur_x;
                            figur_y = start_figur_y;
                            }
                        }

                    }

                }


Und hier der Code für die beiden Bool-Funktionen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool bewegung(int figur_y, int figur_x, int ziel_y, int ziel_x, Spielfeld_Vektor aktuelleMap) {
                    
                    if(aktuelleMap[figur_y+ziel_y][figur_x+ziel_x] == 'A' || aktuelleMap[figur_y+ziel_y][figur_x+ziel_x] == 'B'){
                        return false;
                    } 
                    if(aktuelleMap[figur_y+ziel_y][figur_x+ziel_x] == 'K'){
                            if(aktuelleMap[figur_y+(ziel_y*2)][figur_x+(ziel_x*2)] == 'K' || aktuelleMap[figur_y+(ziel_y*2)][figur_x+(ziel_x*2)] == 'A' || aktuelleMap[figur_y+(ziel_y*2)][figur_x+(ziel_x*2)] == 'B'){
                                return false;
                    }}
                     
                     else{ 
                            return true;
                     }  
                };


C-/C++-Quelltext

1
2
3
4
5
bool schieben(int figur_y, int figur_x, int ziel_y, int ziel_x, Spielfeld_Vektor aktuelleMap) {
                        if(aktuelleMap[figur_y+ziel_y][figur_x+ziel_x] == 'K' && aktuelleMap[figur_y+(ziel_y*2)][figur_x+(ziel_x*2)] == 'F'){
                            return true;
                }
};



Vielen Dank schonmal und euch einen schönen Sonntag,
Arriey :)

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

02.04.2017, 16:00

Dein Compiler sollte dir eigentlich eine Warnung geben, weil die Funktion schieben nicht für alle Pfade einen Wert zurückliefert. Da fehlt ein return für den Fall, dass die Bedingung nicht zutrifft. Das gilt übrigens auch für die Funktion bewegung. Auch hier liefert nicht jeder Pfad einen Wert zurück. Das erzeugt undefiniertes Verhalten.

Wenn sich dein Programm aufhängt, hast du wohl eine Endlosschleife programmiert. Das ist die perfekte Gelegenheit, dich mit dem Debugger zu beschäftigen. Der hilft dir bei solchen "trivialen" Problemen, indem er dir erlaubt, Schritt für Schritt durch das Programm zu "steppen", die Werte von Variablen anzuschauen uvm.

PS: Statt if (x) return true; else return false; geht auch einfach return x;.