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

16.06.2012, 17:56

C++ - SFML - 2D - Jump and Run - Kollision in der X-Achse

Hallo Community!
Bin gerade dabei ein kleines Jump 'n Run für mich selbst zu programmieren, um meine Fähigkeiten zu verbessern.
Leider hackt's bei der Kollision in der X-Achse...
Problem: Wenn der Spieler(bzw. das RectShape) in der X-Achse kollidiert, hängt sich das komplette Programm(Fenster) auf, d.h. man kann es nichtmal schließen/verschieben.
Hier mein Code:

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
//Kollision checken
void CMap::UpdatePlayer(CPlayer &Player)
{
    sf::Vector2f *NewPos = Player.getNewPosition();
    unsigned int i, j;

    bool onGround = false;
    for(i = 0; i < MapVector.size(); i++)
    {
        for(j = 0; j < MapVector[i].size(); j++)
        {
            if(MapVector[i][j] == 0)
            {
                while(Collision(j*BLOCKSIZE, i*BLOCKSIZE, BLOCKSIZE, BLOCKSIZE, Player) == true)
                {
                    if(Player.getPosY() < NewPos->y)
                    {
                        onGround = true;
                        Player.MoveBackY(-0.01f);
                    }else
                    {
                        onGround = false;
                        Player.MoveBackY(0.01f);
                    }
                }
            }
        }
    }
    if(onGround)
        Player.setJumping(true);
    else
        Player.setJumping(false);

    for(i = 0; i < MapVector.size(); i++)
    {
        for(j = 0; j < MapVector[i].size(); j++)
        {
            if(MapVector[i][j] == 0)
            {
                while(Collision(j*BLOCKSIZE, i*BLOCKSIZE, BLOCKSIZE, BLOCKSIZE, Player) == true)
                {
                    if(Player.getPosX() < NewPos->x)
                    {
                        Player.MoveBackX(-0.01f);
                    }
                    else
                    {
                        Player.MoveBackX(0.01f);
                    }
                }
            }
        }
    }

    Player.setNewPosition();
}   

//Kollision
bool CMap::Collision(int xPos, int yPos, int width, int height, CPlayer &Player)
{
    return Player.getNewPosition()->x < xPos+width &&
            Player.getNewPosition()->x+Player.getSize().x > xPos &&
            Player.getNewPosition()->y < yPos+height &&
            Player.getNewPosition()->y+Player.getSize().y > yPos;
}


Ich bedanke mich schonmal im voraus bei euch ;)

EDIT: GELÖST!
Only God can judge me.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »denniro« (16.06.2012, 18:16)


2

16.06.2012, 18:16

KANN GESCHLOSSEN WERDEN! GELÖST!
Only God can judge me.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

3

16.06.2012, 22:55

Nur mal so: 40-30 = 10 = 100 * 0.1 = 1000 * 0.01
Anders ausgedrückt: Es macht mehr Sinn und es ist deutlich besser eine Differenz zu benutzen statt in einer Schleife immer kleine Schritte zu machen, speziell dann, wenn sich die Strecke so einfach berechnen lässt.

PS: Zur Hilfe bei ähnlichen Problemen wäre es gut, wenn Du die Lösung ebenfalls präsentieren könntest.
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]

4

17.06.2012, 10:08

So hier ist die gewünschte Lösung:

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
//Spieler updaten
void CMap::UpdatePlayer(CPlayer &Player, sf::View &Camera)
{
    sf::Vector2f *NewPos = Player.getNewPosition();
    unsigned int i, j;

    Player.makeNewPosX();

    for(i = 0; i < MapVector.size(); i++)
    {
        for(j = 0; j < MapVector[i].size(); j++)
        {
            if(MapVector[i][j] == 0)
            {
                if(Collision(j*BLOCKSIZE, i*BLOCKSIZE, BLOCKSIZE, BLOCKSIZE, Player) == true)
                {
                    if(Player.getPosX() < NewPos->x)
                    {
                        Player.SetPosX(j*BLOCKSIZE-Player.getSize().x);
                    }
                    else
                    {
                        Player.SetPosX((j+1)*BLOCKSIZE);
                    }
                }
            }
        }
    }

    Player.makeNewPosY();
    bool onGround = false;
    bool dead = false;
    for(i = 0; i < MapVector.size(); i++)
    {
        for(j = 0; j < MapVector[i].size(); j++)
        {
            if(MapVector[i][j] == 0)
            {
                if(Collision(j*BLOCKSIZE, i*BLOCKSIZE, BLOCKSIZE, BLOCKSIZE, Player) == true)
                {
                    if(Player.getPosY() < NewPos->y)
                    {
                        onGround = true;
                        Player.SetPosY(i*BLOCKSIZE-Player.getSize().y);
                    }else
                    {
                        onGround = false;
                        Player.setVelocityY(0);
                        Player.SetPosY((i+1)*BLOCKSIZE);
                    }
                }
            }else if(MapVector[i][j] == 1)
            {
                if(Collision(j*BLOCKSIZE, i*BLOCKSIZE, BLOCKSIZE, BLOCKSIZE, Player) == true)
                {
                    Player.Restart(Camera);
                    dead = true;
                    break;break;break;
                }
            }
        }
    }
    if(!dead)
    {
        if(onGround)
            Player.setJumping(true);
        else
            Player.setJumping(false);

        Player.setNewPosition();
    }
}   

Das Problem lag daran, dass ich, schon bevor die Kollision in der X-Achse abgefragt wurde, sofort die beiden Werte der neuen Position abgerufen habe(X und Y), statt zuerst X und danach im Laufe der Funktion Y.

lg. denniro
Only God can judge me.

Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von »denniro« (17.06.2012, 11:32)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

5

17.06.2012, 11:09

Eventuell solltest Du nochmal über meinen Einwurf bezüglich der redundanten und unperformanten Schleifen nachdenken.
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]

6

17.06.2012, 11:17

Eventuell solltest Du nochmal über meinen Einwurf bezüglich der redundanten und unperformanten Schleifen nachdenken.

Hab ich gerade getan, ich lade es mal in meinen vorherigen Post hoch, check mal bitte, ob es das ist, was du gemeint hast ;)
Only God can judge me.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

7

17.06.2012, 16:20

Ja, das sieht schon besser aus. Jetzt überleg Dir eventuell mal noch, ob Du Dir die Schleifen mit i und j nicht eventuell auch schenken kannst, denn das behaupte ich ;) Du musst ja schließlich nicht jedes Map-Stück prüfen, sondern nur die, in welchen sich der Spieler überhaupt befindet.
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]

8

18.06.2012, 15:07

Ja, das sieht schon besser aus. Jetzt überleg Dir eventuell mal noch, ob Du Dir die Schleifen mit i und j nicht eventuell auch schenken kannst, denn das behaupte ich ;) Du musst ja schließlich nicht jedes Map-Stück prüfen, sondern nur die, in welchen sich der Spieler überhaupt befindet.

Ja wär auch ne Idee ;) Ich schau mal, was sich machen lässt!
Only God can judge me.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

9

18.06.2012, 20:39

Das ist ja eine der Ideen hinter Tilemaps. Nicht nur dass ich meine Welt aus kleinen Grafiken bauen kann, sondern dass ich Kollisionen etc relativ schnell bestimmen kann. Wenn du nicht drauf kommst, kannst du dich einfach mal mit einem Schachbrett hinsetzen. Nimm dir eine Figur und beweg die über das Schachbrett. Dann überlegst du dir welche Informationen du hast um direkt zu wissen welche Felder überprüft werden müssen.
„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.“

Werbeanzeige