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

AyJay

Frischling

  • »AyJay« ist der Autor dieses Themas

Beiträge: 67

Beruf: Schule, Hobbys :D

  • Private Nachricht senden

1

03.10.2011, 19:51

SFML TileMap Collision problem

Hallo leute,
Also die Collision funktioniert super doch das Problem liegt darin wenn ich jetzt irgendwelche Doppelten Tasten habe wie z.b dort 13,23,14,24(W & A oder W & D oder sonstiges)
und ich an einer Wand stehe (mit Rücken zur Wand) und dann zur Wand hin und nach rechtes gehe (zum Beispiel nur) bewegt er sich garnicht. Logischer weise sollte er sich dann doch trotzdem nach rechts bewegen leicht und nicht so stark wie sonst weil er ja an der Wand leicht schrammt.

Gemeint sind Zeilen:
129-138 // Hier wird Do gesetzt also welche die Letzte Bewegung war.
157-179 // Hier wird die Bewegung zurück gesetzt wenn diese zur einer Collision geführt hat.

Alle Png's sind 32x32px
wall.png player.png sand.png und walledge.png

Wall = Wand Collidiert
Sand = Sand Collidiert nicht
Walledge = WandEcke Collidiert
Player = Spieler Collidiert

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
#include <SFML/Graphics.hpp>
#include "collision.h"
#include <sstream>
#include <list>
#include <string>
#include <iostream>
#include <fstream>

using namespace std;

template<class T> inline std::string toStr(T x)
{
    std::stringstream type;
    type << x;
    return type.str();
};

class Tile {
public:
    float X, Y, Rotation;
    bool Collision;
    sf::Sprite sTile;
    sf::Image iTile;
    Tile::Tile(std::string Path, float X, float Y, float Rotation, bool bCollision){
        iTile.LoadFromFile(Path);
        std::cout << Path << std::endl;
        iTile.SetSmooth(false);
        sTile.SetImage(iTile);
        sTile.SetRotation(Rotation);
        sTile.Move(X,Y);
        sTile.SetCenter(16,16);
        Collision = bCollision;
    }
};

float rad2deg(float x){
    return x*360.0f/(2.0f*3.14f);
} 

std::list<Tile> Tiles;

int main(){
    sf::RenderWindow App(sf::VideoMode(800, 600, 32), "Square Fighter");

    App.UseVerticalSync(true);

    Tile TempTile1("./data/sand.png",32.0f,32.0f,0.0f,false);
    Tile TempTile2("./data/sand.png",64.0f,32.0f,0.0f,false);
    Tile TempTile3("./data/sand.png",96.0f,32.0f,0.0f,false);
    Tile TempTile4("./data/sand.png",128.0f,32.0f,0.0f,false);
    Tile TempTile5("./data/sand.png",32.0f,64.0f,0.0f,false);
    Tile TempTile6("./data/sand.png",64.0f,64.0f,0.0f,false);
    Tile TempTile7("./data/sand.png",96.0f,64.0f,0.0f,false);
    Tile TempTile8("./data/sand.png",128.0f,64.0f,0.0f,false);

    Tiles.push_back(TempTile1);
    Tiles.push_back(TempTile2);
    Tiles.push_back(TempTile3);
    Tiles.push_back(TempTile4);
    Tiles.push_back(TempTile5);
    Tiles.push_back(TempTile6);
    Tiles.push_back(TempTile7);
    Tiles.push_back(TempTile8);

    Tile TempTile9("./data/wall.png",32.0f,0.0f,0.0f,true);
    Tile TempTile10("./data/wall.png",64.0f,0.0f,0.0f,true);
    Tile TempTile11("./data/wall.png",96.0f,0.0f,0.0f,true);
    Tile TempTile12("./data/wall.png",128.0f,0.0f,0.0f,true);
    Tile TempTile13("./data/wall.png",32.0f,96.0f,180.0f,true);
    Tile TempTile14("./data/wall.png",64.0f,96.0f,180.0f,true);
    Tile TempTile15("./data/wall.png",96.0f,96.0f,180.0f,true);
    Tile TempTile16("./data/wall.png",128.0f,96.0f,180.0f,true);
    Tile TempTile17("./data/wall.png",0.0f,32.0f,90.0f,true);
    Tile TempTile18("./data/wall.png",0.0f,64.0f,90.0f,true);
    Tile TempTile19("./data/wall.png",160.0f,32.0f,270.0f,true);
    Tile TempTile20("./data/wall.png",160.0f,64.0f,270.0f,true);

    Tiles.push_back(TempTile9);
    Tiles.push_back(TempTile10);
    Tiles.push_back(TempTile11);
    Tiles.push_back(TempTile12);
    Tiles.push_back(TempTile13);
    Tiles.push_back(TempTile14);
    Tiles.push_back(TempTile15);
    Tiles.push_back(TempTile16);
    Tiles.push_back(TempTile17);
    Tiles.push_back(TempTile18);
    Tiles.push_back(TempTile19);
    Tiles.push_back(TempTile20);

    Tile TempTile21("./data/walledge.png",0.0f,0.0f,90.0f,true);
    Tile TempTile22("./data/walledge.png",160.0f,0.0f,0.0f,true);
    Tile TempTile23("./data/walledge.png",160.0f,96.0f,270.0f,true);
    Tile TempTile24("./data/walledge.png",0.0f,96.0f,180.0f,true);

    Tiles.push_back(TempTile21);
    Tiles.push_back(TempTile22);
    Tiles.push_back(TempTile23);
    Tiles.push_back(TempTile24);

    sf::Image iPlayer;
    iPlayer.LoadFromFile("./data/player-both-u.png");
    sf::Sprite sPlayer(iPlayer);
    sPlayer.SetCenter(16.0f,16.0f);
    sPlayer.Move(64.0f,32.0f);

    sf::Vector2f Center(0, 0);
    sf::Vector2f HalfSize(400, 300);
    sf::View Camera(Center, HalfSize);
    App.SetView(Camera);

    sf::Font Font;
    Font.LoadFromFile("arial.ttf", 16);
    sf::String Text("Hello", Font, 16);
    Text.SetPosition(-100.0f,-100.0f);
    std::string Do = "0";
    while (App.IsOpened()){
        sf::Event Event;
        while (App.GetEvent(Event)){
            if (Event.Type == sf::Event::Closed){
                App.Close();
            }
        }

        float ElapsedTime = App.GetFrameTime();
        Do = "";

        //Player Bewegung
        if(App.GetInput().IsKeyDown(sf::Key::A)){ sPlayer.Move(-100 * ElapsedTime, 0); Do += "1";}
        if(App.GetInput().IsKeyDown(sf::Key::D)){ sPlayer.Move( 100 * ElapsedTime, 0); Do += "2";}
        if(App.GetInput().IsKeyDown(sf::Key::W)){ sPlayer.Move(0, -100 * ElapsedTime); Do += "3";}
        if(App.GetInput().IsKeyDown(sf::Key::S)){ sPlayer.Move(0,  100 * ElapsedTime); Do += "4";}
        if((!App.GetInput().IsKeyDown(sf::Key::A)) &&
           (!App.GetInput().IsKeyDown(sf::Key::D)) &&
           (!App.GetInput().IsKeyDown(sf::Key::W)) &&
           (!App.GetInput().IsKeyDown(sf::Key::S))){
                Do = "";
        }
        //Player Blickrichtung Maus berechnung
        sf::Vector2f Diff, MausPos, SpielerPos;
        MausPos = App.ConvertCoords(App.GetInput().GetMouseX(),App.GetInput().GetMouseY());
        SpielerPos = sPlayer.GetPosition();
        float Grad = rad2deg(atan2((MausPos.x-SpielerPos.x),(MausPos.y-SpielerPos.y)));
        sPlayer.SetRotation(Grad);

        //Camera
        if (App.GetInput().IsKeyDown(sf::Key::Left))    { Camera.Move(-100 * ElapsedTime, 0);}
        if (App.GetInput().IsKeyDown(sf::Key::Right))   { Camera.Move( 100 * ElapsedTime, 0);}
        if (App.GetInput().IsKeyDown(sf::Key::Up))      { Camera.Move(0, -100 * ElapsedTime);}
        if (App.GetInput().IsKeyDown(sf::Key::Down))    { Camera.Move(0,  100 * ElapsedTime);}

        App.Clear();
        //Draw Alle Tiles, Text &' Player.
        for(std::list<Tile>::iterator iT = Tiles.begin(); iT != Tiles.end(); ++iT){
            App.Draw((*iT).sTile);
            if((*iT).Collision == true){
                if(Collision::PixelPerfectTest(sPlayer,(*iT).sTile)){
                    if(Do == "1"){
                        sPlayer.Move(100 * ElapsedTime, 0);
                    }else if(Do == "2"){
                        sPlayer.Move(-100 * ElapsedTime, 0);
                    }else if(Do == "3"){
                        sPlayer.Move(0, 100 * ElapsedTime);
                    }else if(Do == "4"){
                        sPlayer.Move(0, -100 * ElapsedTime);
                    }else if(Do == "13"){
                        sPlayer.Move(100 * ElapsedTime, 0);
                        sPlayer.Move(0, 100 * ElapsedTime);
                    }else if(Do == "23"){
                        sPlayer.Move(-100 * ElapsedTime, 0);
                        sPlayer.Move(0, 100 * ElapsedTime);
                    }else if(Do == "14"){
                        sPlayer.Move(100 * ElapsedTime, 0);
                        sPlayer.Move(0, -100 * ElapsedTime);
                    }else if(Do == "24"){
                        sPlayer.Move(-100 * ElapsedTime, 0);
                        sPlayer.Move(0, -100 * ElapsedTime);
                    }
                }
            }
        }
        Text.SetText(toStr(Do));
        App.Draw(Text);
        App.Draw(sPlayer);

        App.Display();
    }
    return EXIT_SUCCESS;
}



Schonmal vielen Dank für die Hilfe.
LG,
Jason.

C-/C++-Quelltext

1
2
3
While(!asleep){
    sheep++;
}

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »AyJay« (03.10.2011, 20:01)


Werwofl

Treue Seele

Beiträge: 100

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

2

04.10.2011, 12:22

Sehe ich das richtig das du das Sprite immer ziehen lässt, und wenn eine Kollision aufgetreten ist, das Sprite wieder zurücksetzt?
Edit: Nein, hab mich verguck das ist dei Kamera.

Kann das Sprite sich denn noch in irgendeine Richtung bewegen wenn es an einem Tile kollidiert?
Prüfst du denn auch das nächste Tile auf das der Player zugeht oder alle Tile's in der Umgebung?

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Werwofl« (04.10.2011, 12:29)


AyJay

Frischling

  • »AyJay« ist der Autor dieses Themas

Beiträge: 67

Beruf: Schule, Hobbys :D

  • Private Nachricht senden

3

04.10.2011, 17:51

Man sieht direkt eigendlich das ich denn Player mit jedem Tile das mit Colide true bestückt ist prüfe

C-/C++-Quelltext

1
if(Collision::PixelPerfectTest(sPlayer,(*iT).sTile))

und ich setze es dann sofort zurück wenn er colidiert. das problem liegt ja daran das wenn ich mit rücken zur wand stehe nicht nach recht bewegen kann nach vorne geht ja dann natürlich und nur nach rechts aber wenn ich jetzt z.b rückwerts und rechts habe sollte er sich auch nach rechts bischen bewegen aber das tut er nicht.

also nochmal zusammen gefaßt
ich stehe an der wand mit rücken
W: Geht
S: Geht nicht Colidiert ja
A: Geht
D: Geht
S & D: Geht nicht weil colidiert

WASD die steuerung eigendlich sollte er bei S & D nach rechts dann gehen oder nicht ?

C-/C++-Quelltext

1
2
3
While(!asleep){
    sheep++;
}

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

4

04.10.2011, 18:05

Weiß garnicht was du da vor hast.
Du brauchst nicht für jedes Sprite das Image neu laden.
Du könntest auch einfach die alte Position des Spielers speichern, wenn du ihn später wieder zurücksetzen willst.
Speichert man Tiles nicht in einem 2D-Array bzw. einem Vector oder ähnlichem? Eine List ist dafür absolut nicht geeignet.
Dann benötigst du auch keine Schleife für Spieler-Tilekollision.

Wenn du das alles geändert hast, hast du nurnoch ein drittel bis die hälfte des Codes und kannst dir überlegen, wieso die Spielfigur sich so verhält.
Ausserdem wird es auch für uns einfacher dir zu helfen, weil wir uns besser die Position der Tiles vorstellen können. ;)

edit: Achja, wie war das nochmal mit der Übergabe von Strings(oder anderen zusammengesetzten Objekten) als Wert? ?(
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

AyJay

Frischling

  • »AyJay« ist der Autor dieses Themas

Beiträge: 67

Beruf: Schule, Hobbys :D

  • Private Nachricht senden

5

04.10.2011, 18:15

Hier ein Bild mit Beschreibung was was ist.
Was soll ich denn sonst benutzen als eine List ?
Und wieso soll ich das nicht durchlaufen dann weiss ich ja garnicht ob es Colidiert ? oô
Klingt mir jetzt etwas komisch.
»AyJay« hat folgendes Bild angehängt:
  • SquareFighter.png

C-/C++-Quelltext

1
2
3
While(!asleep){
    sheep++;
}

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

6

04.10.2011, 18:31

Was soll ich denn sonst benutzen als eine List ?

Hab ich schon erwähnt.
Und wieso soll ich das nicht durchlaufen dann weiss ich ja garnicht ob es Colidiert ? oô

Du musst in einer Tilemap sehr oft direkt auf ein bestimmtes Tile zugreifen. Stell dir vor du hast 200 Tiles und 10 Objekte die damit Kollidieren können. Dann musst du deine Liste bis zu 200*10 mal pro Frame durchlaufen.
In einem std::Vector hast du die Möglichkeit direkt auf das Xte Tile zuzugreifen und sparst dir die Sucherei.
Aus der Position und Größe des Spieler(z.B.) kannst du die Positionen, der Sprites, auf denen er steht berechnen. Steckt halt etwas Mathematik drin, die du aber sowieso beherrschen musst.

Stell dir vor du hast eine unsortierte Liste mit 100 Wörtern und müsstest "Hund" raus suchen und jemand anders hat eine sortierte durchnummerierte Tabelle und muss das Wort mit der Nummer 23 raus suchen.(Die Nummer 23 ist hier mal die Nummer von "Hund")
Wer ist wohl schneller? ;)
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »NachoMan« (04.10.2011, 18:39)


Werwofl

Treue Seele

Beiträge: 100

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

7

04.10.2011, 18:45

Zitat

WASD die steuerung eigendlich sollte er bei S & D nach rechts dann gehen oder nicht ?

Nein wieso du machst zwei if Abfragen heißt er wird (solange die Flags richtig gesetzt werden), geht er nach Rechts-Unten. und wenn unten eine Kollision auftritt soll er ja gar nich hingehen oder wie bei dir das Sprite zurücksetzen(Das solltest du übrigens mal überdenken).

Ich würd sagen dur solltest den ganzen Code aufräumen und nochmal überdenken und NachoMan's Ratschläge beherzigen, weil so findet man da nur schwer durch.

AyJay

Frischling

  • »AyJay« ist der Autor dieses Themas

Beiträge: 67

Beruf: Schule, Hobbys :D

  • Private Nachricht senden

8

04.10.2011, 18:48

Auf welchem er steht würde ich ja hinbekommen und mit Vector da hast du recht und stimmt du hast es schon gesagt.
Doch wie soll mir das bei dem Problem helfen ?

//Edit
Und ich muss ja trotzdem dem ganzen vector durchlaufen um alles zu Drawn?

C-/C++-Quelltext

1
2
3
While(!asleep){
    sheep++;
}

Werwofl

Treue Seele

Beiträge: 100

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

9

04.10.2011, 18:54

Auf welchem er steht würde ich ja hinbekommen und mit Vector da hast du recht und stimmt du hast es schon gesagt.
Doch wie soll mir das bei dem Problem helfen ?

//Edit
Und ich muss ja trotzdem dem ganzen vector durchlaufen um alles zu Drawn?


Nein musst du nicht wieso?

Du gehst nach unten und weißt auf welchem Tile der Player steht. Heißt du musst nur:

C-/C++-Quelltext

1
Tile[x][y-1].istBegehbar();

prüfen.

Dein Problem löst das insofern, dass du offensichtlich ein logisches Problem hast und wir jetzt deinen ganzen Code durchwhlen müssen um herszufinden, wo du was falsch gemacht hast.Siehe Post von ebend der Auf NachoMan's Post verweist:P.
z.B. nutzt man auch kein Strings für Flags, du nutzt ja selbst schon Ganzzahlen bloß in string Form.

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

10

04.10.2011, 19:00

Probiers doch einfach mal alles umzusetzen. Das hat höhere Priorität als, dass es einfach irgendwie funktioniert.

Das:
Du könntest auch einfach die alte Position des Spielers speichern, wenn du ihn später wieder zurücksetzen willst.

...könnte das beschriebene Problem zumindest teilweise lösen oder wenigstens das Lösen des Problems wesentlich vereinfachen.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Werbeanzeige

Ähnliche Themen