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

Meai

Frischling

  • »Meai« ist der Autor dieses Themas
  • Private Nachricht senden

1

29.07.2008, 19:01

SDL:Meine tolle 2D Kollisionserkennung funktioniert nicht :(

Mein Spiel ist eine Pong Variante..
Erstmal will ich nur gegen das Fenster testen.
Mein Ball:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const unsigned char ball[]={
    0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
    0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,
    0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
    0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
    0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
    0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
    0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
    0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
    0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
    0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,
    0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0

};



move Methode des Balles:
ballVektor[0]=x Koordinate des Richtungsvektors
ballVektor[1]=y Koordinate des Richtungsvektors
..am Anfang beide 10.

ballX= x Koordinate des Balles
ballY= y Koordinate des Balles

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
void moveBall(){
    double winkel=atan2(static_cast<double>(ballVektor[1]),static_cast<double>(ballVektor[0]));

    double dCos = cos(winkel), dSin = sin(winkel); 
    double x,y;
    x=0;
    y=0;

       //nicht über die seltsamen Zahlen wundern, der Sprite wird von  eben links abgeprüft statt von der Mitte


    if (ballX+17 > SCREEN_WIDTH || ballX-17<0 || ballY+21 >SCREEN_HEIGHT || ballY-1 < 0){
        x = ballVektor[0] * dCos - ballVektor[1] * dSin;
        y = ballVektor[0] * dSin + ballVektor[1] * dCos; 
        
        ballVektor[0]=x;
        ballVektor[1]=y;
    }
    
    int i, j, c, yofs;
    ballX=ballX+ballVektor[0];
    ballY=ballY+ballVektor[1];

        //Ball wird gezeichnet

    yofs = ballY * (screen->pitch / 4) + ballX;
    for (i = 0, c = 0; i < 16; i++)
    {
        for (j = 0; j < 16; j++, c++)
        {
            if (ball[c])
            {
                ((unsigned int*)screen->pixels)[yofs + j] = 0xFFFFFF;
            }
        }
        yofs += (screen->pitch / 4);
    }

}

Formel müsste stimmen, ich hab schon soviel ausprobiert dass ich langsam total verwirrt bin. Mein Winkel, muss der eigentlich nicht immer 90 sein um jeweils einen Austrittswinkel von 45° zu garantieren?

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

2

29.07.2008, 21:50

1. Warum nimmst du keine Bitmap?!
2. In einer move Funktion sollte nicht gerendert werden.
3. Wo genau ist dein Problem?

Wenn du nur auf die Wände reagieren willst, schaust eu hald einfach, ob der Ball.x kleiner 0 ist (natürlich noch Breite einberechnen) oder Ball.y grösser die Breite sein soll. (Dasselbe natürlich auch noch für y-Richtung).

Oder ist das abprallen, also die Richtungsänderung dein Problem?

Meai

Frischling

  • »Meai« ist der Autor dieses Themas
  • Private Nachricht senden

3

30.07.2008, 09:59

1,
Ich sehe jetzt keinen Vorteil mit einer Bitmap, außerdem wollte ich ein klassiches "Pixel"spiel machen, da sollte man natürlich mit Pixeln arbeiten :)
Bei einer Bitmap müsste ich auch jeden Pixel auf Kollision überprüfen, und wüsste jetzt spontan nichtmal wie ich auf die Pixel der Bitmap zugreife.
Der einzige Vorteil wäre vielleicht dass ich die Bitmap automatisch am Mittelpunkt anfasse, was nicht nen großen Unterschied macht.
2,
Stimmt, im Moment ist mein Code hässlich weil ich viel zu viele Sachen ausprobieren muss und ständig umschreibe. Da wäre der Zeitaufwand unproportional groß alles schön zu coden. (zb. sind meine Variablen auch nicht in ungarischer Notation was ich noch machen will)
3,
Naja sobald der Ball an die Wand gelangt fliegt er raus und erzeugt natürlich nen Absturz. Ich habs schon probiert die Formel umzukehren (mit der Begründung mir gegenüber dass das Koordinatensystem schließlich auch umgedreht ist).
Der Ball prallt zwar ab, das Programm stürzt trotzdem ab. (obwohl er abprallt). Soweit ich das im Debugger feststellen konnte waren die nächsten durch die Formel berechneten Werte für ballX, ballY außerhalb des screens.

C-/C++-Quelltext

1
Wenn du nur auf die Wände reagieren willst, schaust eu hald einfach, ob der Ball.x kleiner 0 ist (natürlich noch Breite einberechnen) oder Ball.y grösser die Breite sein soll. (Dasselbe natürlich auch noch für y-Richtung). 

Das mach ich ja schon, in der if-Abfrage. Wie gesagt funktioniert das aber nicht aus irgendeinem Grund. (der aus der Formel berechnete neue Richtungsvektor beim Aufprall ist falsch,warum?)

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

4

30.07.2008, 19:53

Zitat

Ich sehe jetzt keinen Vorteil mit einer Bitmap, außerdem wollte ich ein klassiches "Pixel"spiel machen, da sollte man natürlich mit Pixeln arbeiten

:lol:
Naja. Auch klasische Pixelspiele verwenden Bitmaps die zeichen ihre Figuren nicht im Code in Arrays. ;)
Im übrigen kannst du die Kollision genau so perfekt machen, wenn du einfach den Mittelpunkt nimmst und dann mit dem Radius rechnest.

Wenn du nämlich mit Bitmaps arbeitest, hast du deine anderen Probleme auch nicht mehr. Ich verstehe auch nicht, warum etwas abstürzen sollte, nur weil es nicht mehr in DEINEM Spielfeld ist. Wenn ich etwas rendere, dann kann das sein, wo es will, das gibt mir nie irgend einen Fehler. Das schlimmste, was passiert ist, dass du einfach nichts siehst, weil es zu weit Weg (oder seitlich) ist.

Aber da du da anscheinend in einen anderen Buffer schreibst, würde ich mal davon ausgehen, dass du auf Speicher zugreifst, wo du nicht darfst.

C-/C++-Quelltext

1
screen->pixels)[yofs + j]

Hier wird das Problem sein. Aber was genau das Problem ist, kann ich nicht sagen, solange ich nicht weiss, was screen und pixels ist.

Auch deine for Schleifen sehen seehr merkwürdig aus und verwirren nur zusätzlich.

Ich würde zuerst mal das Problem lösen und dich dann an das korrekte apprallen wagen. ;)

(mal vorweg: Seitlich verhält es sich so, dass du den Eintrittswinkel *180 rechnest und dann das ganze mal -1. Oben und unten reicht, wenn du nur *-1 machst.

fkrauthan

Supermoderator

Beiträge: 979

Wohnort: Vancouver

Beruf: Software engineer

  • Private Nachricht senden

5

30.07.2008, 20:25

Hä was hast du für probleme bei einer Bitmap? das Abprallen vom Rand kannste da genauso leicht machen. Und es ist weniger aufwand und leichter zu warten. Aber letztendlich ist es deine entscheidung. Was mich aber auch wundert ist, warum dein programm abstürzt sobald du den Rand verlässt.
Homepage: fkrauthan.de | Browser-game: flowergame.net

Meai

Frischling

  • »Meai« ist der Autor dieses Themas
  • Private Nachricht senden

6

30.07.2008, 23:07

Danke für eure Antworten,
screen ist mein SDL_Surface
screen->pixels greift somit auf meine "Zeichenfläche" zu. (also auf meine Pixel meine ich)

Zitat


Wenn du nämlich mit Bitmaps arbeitest, hast du deine anderen Probleme auch nicht mehr. Ich verstehe auch nicht, warum etwas abstürzen sollte, nur weil es nicht mehr in DEINEM Spielfeld ist. Wenn ich etwas rendere, dann kann das sein, wo es will, das gibt mir nie irgend einen Fehler. Das schlimmste, was passiert ist, dass du einfach nichts siehst, weil es zu weit Weg (oder seitlich) ist.

Ok ich probiers morgen mal mit Bitmaps, deine Erklärungen scheinen logisch zu sein. Ich habe die Formel testweise einfach mal umgekehrt, Vorzeichen verändert..und siehe da, das Verhalten ist seltsamer als zuvor. Der Ball prallt erfolgreich mehrmals von den Wänden ab bis er plötzlich trotzdem auf der einen Seite verschwindet, auf der anderen wieder auftaucht..und einen Speicherfehler verursacht.

Zitat

Aber da du da anscheinend in einen anderen Buffer schreibst, würde ich mal davon ausgehen, dass du auf Speicher zugreifst, wo du nicht darfst.

Also buffer benutze ich keinen (noch nicht rausgefunden wie das geht, deswegen flimmert auch alles leicht). Die Formel sollte stimmen, hab sie mir selbst auch nochmal durchgedacht. (fairerweise muss ich sagen dass die Formel und die Sprite Idee aus diesem Tutorial sind: http://sol.gfxile.net/gp/ch03.html )
Wollte einfach mal ausprobieren ob ich ein kleines Spiel schaffe...prompt gescheitert. Ok, also morgen gehts mit Bitmaps los.

edit: mit klassischen Pixelspielen meinte ich die richtig alten Spiele auf den Konsolen. Also wo sich einzelne Pixel herumbewegten.

Meai

Frischling

  • »Meai« ist der Autor dieses Themas
  • Private Nachricht senden

7

31.07.2008, 10:48

Okay habe den Ball jetzt als Bitmap importiert, mein Abprallproblem besteht aber immer noch zu einem nur geringfügig geringerem Ausmaß. Der Ball prallt ab, jedoch nicht immer im gewünschten Winkel. (der Ball sollte ja immer in Richtung des größeren Winkels abprallen nicht in die Richtung von wo er gekommen ist)
Außerdem wird anscheinend allzu oft der Richtungsvektor 2mal berechnet, das zu einem Ruckeln am Rand führt bzw. wiederum falscher Richtung. Bin eigentlich immer noch nicht klüger geworden.
Warum muss man überhaupt separat oben/unten und rechts/links prüfen? Die Drehungsmatrix sollte den Winkel erfolgreich in beiden Fällen drehen.
Hier meine move Methode:

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
//for constant velocity

    if (xVel>0)
    xVel=static_cast<int>(xVel/xVel) *10;
    if (yVel>0)
    yVel=static_cast<int>(yVel/yVel) *10;
    
    //If the dot went too far to the left or right

if( ( x < 0 ) || ( x + DOT_WIDTH > SCREEN_WIDTH ) ){
        double winkel=atan2(static_cast<double>(ballVektor[1]),static_cast<double>(ballVektor[0]))+90; 
        double dCos = cos(winkel), dSin = sin(winkel); 
        double x1,y1;
        x1=0;
        y1=0;

        x1 = xVel * dCos - yVel * dSin;
        y1 = xVel * dSin + yVel * dCos; 
        xVel=x1;
        yVel=y1;

    }
        if( ( y < 0 ) || ( y + DOT_HEIGHT > SCREEN_HEIGHT )){
        double winkel=atan2(static_cast<double>(ballVektor[1]),static_cast<double>(ballVektor[0]))+90; 
        double dCos = cos(winkel), dSin = sin(winkel); 
        double x1,y1;
        x1=0;
        y1=0;

        x1 = xVel * dCos - yVel * dSin;
        y1 = xVel * dSin + yVel * dCos; 
        xVel=x1;
        yVel=y1;

    }
    //Move the dot left or right

    x += xVel;
    //Move the dot up or down

    y += yVel;
    
    

8

31.07.2008, 10:55

Sorry dass ich dir jetzt nich direkt helfen kann, aber:
Wieso berechnest du die Geschwindigkeiten nach dem Winkel des Balles? Mit dem Winkel ist ja sicherlich die Drehung gemeint, und die macht bei einem Ball keinen Sinn. Ich glaub die ganze Move-Funktion könnte viel einfacher gemacht werden!

Meai

Frischling

  • »Meai« ist der Autor dieses Themas
  • Private Nachricht senden

9

31.07.2008, 13:27

Ok so macht programmieren keinen Spaß, ich habe nach wie vor keine Ahnung warum die Lösung mit den Drehmatrizen nicht funktioniert hat. Tja jetzt hab ichs mit Trial und Error irgendwie hingepflastert.
Hier die Lösung für Mitleser oder wen's interessiert:

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
void Dot::move()
{
    //If the dot went too far to the left or right

    if( ( x + DOT_WIDTH > SCREEN_WIDTH ) ){
        
        if (Flugwinkel>=40){
            xDirection*=1;
            yDirection*=-1;
        }else{
            xDirection*=-1;
            yDirection*=+1;
        }   
    }
    if (( x < 0 )){
        
        if (Flugwinkel<=40){
            xDirection*=1;
            yDirection*=-1;
        }else{
            xDirection*=-1;
            yDirection*=+1;
        }
    }
    //if the dot went too far up or down

    if( ( y + DOT_HEIGHT > SCREEN_HEIGHT )){
        
        if (Flugwinkel>=40){
        xDirection*=1;
        yDirection*=-1;
        }else{
            xDirection*=-1;
            yDirection*=+1;
        }
    }
    if (( y< 0 ) ){
        
        if (Flugwinkel<=40){
            xDirection*=1;
            yDirection*=-1;
        }else{
            xDirection*=-1;
            yDirection*=+1;
        }
    }
    //Move the dot left or right

    x += xVel*xDirection;
    //Move the dot up or down

    y += yVel*yDirection;

    Flugwinkel=atan2(static_cast<double>(y),static_cast<double>(x))*180/PI ;

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

10

31.07.2008, 22:57

Ich habe dir doch das abprallverlaten bereits beschrieben. :roll:

Wenn der Ball links, oder rechts ankommt, dann machst du einfach den Winkel (in Grad) + 180, dann *-1. Und wenn er oben/unten ankommt, machst du einfach einfach nur *-1.

Werbeanzeige