Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Ball simulation - Bälle werden immer langsamer, Hilfe!

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
08.06.2012, 09:02 Uhr
~Crymes
Gast


Hallo, ich hab ein Programm geschrieben, dass 2 Bälle kollidieren lässt.
Das funktioniert soweit auch fehlerfrei, nur bewegen sie sich mit der Zeit immer langsamer.
Ich denke das Problem liegt in der Funktion kollisionball(), bin mir aber nicht sicher.

Könnt ihr mir bitte helfen?

Hier ist der Code:


C++:

// Ball Simulation.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
//
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <Windows.h>
#include <GL/glew.h>
#include <GL/freeglut.h>

#define Pi 3.14159265358979323846

using namespace std;

//Bildschirmauflösung ermitteln
unsigned int blänge = GetSystemMetrics(SM_CXSCREEN), bbreite = GetSystemMetrics(SM_CYSCREEN);    

struct kugel
    {
        float position[2];
        float geschwindigkeit[2];
        float radius;

    }ball1, ball2;
void ballinit()
{    //Klasse initialisieren Ball1    
    ball1.position[0]=110;
    ball1.position[1]=110;
    ball1.geschwindigkeit[0]=31;
    ball1.geschwindigkeit[1]=6;
    ball1.radius=100;

    //Ball2
    ball2.position[0]=500;
    ball2.position[1]=500;
    ball2.geschwindigkeit[0]=3;
    ball2.geschwindigkeit[1]=9;
    ball2.radius=100 ;
};
void ballupdate()
{    
    for(int stelle = 0; stelle<=1; stelle++)
    {
        ball1.position[stelle] = ball1.position[stelle] + ball1.geschwindigkeit[stelle];
        ball2.position[stelle] = ball2.position[stelle] + ball2.geschwindigkeit[stelle];
    }        
}
void kollisionrand()
{        
    //Nicht über Rand hinaus oben/unten
    if(ball1.position[1] + ball1.geschwindigkeit[1] < ball1.radius)
    {
        ball1.position[1] = ball1.radius;
    }
    
    if(ball1.position[1] + ball1.geschwindigkeit[1] > bbreite - ball1.radius)
    {
        ball1.position[1] = bbreite - ball1.radius;
    }

    //links rechts
    if(ball1.position[0] + ball1.geschwindigkeit[0] < ball1.radius)
    {
        ball1.position[0] = ball1.radius;
    }

    if(ball1.position[0] + ball1.geschwindigkeit[0] > blänge - ball1.radius)
    {
        ball1.position[0] = blänge - ball1.radius;
    }

    //Ball1
    //rechts /links kollidieren
    if( (ball1.position[0] >= (blänge-ball1.radius)) || (ball1.position[0] <= ball1.radius) )
    {
        ball1.geschwindigkeit[0] = ball1.geschwindigkeit[0] * (-1);        
    }

    //oben /unten
    else if( (ball1.position[1] >= (bbreite-ball1.radius)) || (ball1.position[1] <= ball1.radius) )
    {
        ball1.geschwindigkeit[1] = ball1.geschwindigkeit[1] * (-1);
    }

    //Nicht über den Rand hinaus fliegen oben/unten
    if(ball2.position[1] + ball2.geschwindigkeit[1] < ball2.radius)
    {
        ball2.position[1] = ball2.radius;
    }
    
    if(ball2.position[1] + ball2.geschwindigkeit[1] > bbreite - ball2.radius)
    {
        ball2.position[1] = bbreite - ball2.radius;
    }

    //links/rechts
    if(ball2.position[0] + ball2.geschwindigkeit[0] < ball2.radius)
    {
        ball2.position[0] = ball2.radius;
    }

    if(ball2.position[0] + ball2.geschwindigkeit[0] > blänge - ball2.radius)
    {
        ball2.position[0] = blänge - ball2.radius;
    }

    //Ball2
    //rechts /links
    if( (ball2.position[0] >= (blänge-ball2.radius)) || (ball2.position[0] <= ball2.radius) )
    {
        ball2.geschwindigkeit[0] = ball2.geschwindigkeit[0] * (-1);
    }

    
    //oben /unten
    else if( (ball2.position[1] >= (bbreite-ball2.radius)) || (ball2.position[1] <= ball2.radius) )
    {
        ball2.geschwindigkeit[1] = ball2.geschwindigkeit[1] * (-1);
    }    
}
void kollisionball()
{
    //Gewicht der Bälle errechnen
    float gball1 = 0, gball2 = 0;
    gball1 = (ball1.radius*ball1.radius) * Pi;
    gball2 = (ball2.radius*ball2.radius) * Pi;

    //Abstand ausrechnen
    if( sqrt( pow( ball2.position[0]-ball1.position[0], 2) + pow( ball2.position[1]-ball1.position[1], 2) ) <= (ball1.radius+ball2.radius) )
    {
        //Bälle dürfen sich nicht schneiden        
        if(sqrt( pow( ball2.position[0]-ball1.position[0], 2) + pow( ball2.position[1]-ball1.position[1], 2) ) < (ball1.radius+ball2.radius) )
        {        
            do
            {
                for(int c=0;c<=1;c++)
                {
                    ball1.position[c] = ball1.position[c] - 0.01 * ball1.geschwindigkeit[c];
                    ball2.position[c] = ball2.position[c] - 0.01 * ball2.geschwindigkeit[c];
                }
            }
            while(sqrt( pow( ball2.position[0]-ball1.position[0], 2) + pow( ball2.position[1]-ball1.position[1], 2) ) < (ball1.radius+ball2.radius) );
        }

        //Linie zwischen den Mittelpunkten (Zentralvektor)
        float vlinie[2];
        vlinie[0] = ball2.position[0] - ball1.position[1];
        vlinie[1] = ball2.position[1] - ball1.position[1];

        //Linie auf Einheitsvektor nominieren: vlinie / bertag(vlinie)
        float vliniee[2];
        vliniee[0] = vlinie[0]/sqrt(vlinie[0] * vlinie[0] + vlinie[1] * vlinie[1]);
        vliniee[1] = vlinie[1]/sqrt(vlinie[0] * vlinie[0] + vlinie[1] * vlinie[1]);
        
        //Tangentialvektor errechnen: vt = (-vliniee(y), vliniee(x) )
        float vtan[2];
        vtan[0] = -1 * vliniee[1];
        vtan[1] =      vliniee[0];

        //Geschwindigkeitsvektoren zerlegen (tangential, normal Richtung), es kommen Skalare raus
        float gnormb1, gnormb2, gtanb1, gtanb2;
        gnormb1 = (vliniee[0] * ball1.geschwindigkeit[0]) + (vliniee[1] * ball1.geschwindigkeit[1]);  
        gnormb2 = (vliniee[0] * ball2.geschwindigkeit[0]) + (vliniee[1] * ball2.geschwindigkeit[1]);
        gtanb1  = (vtan[0] * ball1.geschwindigkeit[0]) + (vtan[1] + ball1.geschwindigkeit[1]);
        gtanb2  = (vtan[0] * ball2.geschwindigkeit[0]) + (vtan[1] + ball2.geschwindigkeit[1]);

        //Neue Geschwindigkeit errechnen
        //tangentiale Geschwindigkeiten verändern sich nicht!
        //Geschwindigkeitsvektoren nach Kollision
        //Masse ist Radius!
        float gnormb1n, gnormb2n;
        /*gnormb1n = ( (gnormb1*(gball1 - gball2) + ((2*gball2) * gnormb2))) / (gball1 + gball2);
        gnormb2n = ( (gnormb2*(gball2 - gball1) + ((2*gball1) * gnormb1))) / (gball1 + gball2);
        */


        //Ander Formel
        /*gnormb1n = (gball1*gnormb1 + (gball2*(2*gnormb2-gnormb1))) / (gball1 + gball2);
        gnormb2n = (gball2*gnormb2 + (gball1*(2*gnormb1-gnormb2))) / (gball1 + gball2);*/


        //Formel ohne Masse
        gnormb1n =  gnormb2;
        gnormb2n =  gnormb1;

        //Einheitsvektoren zu normalvektoren konvertieren (normal richtung)
        float b1nn[2], b2nn[2], b1tn[2], b2tn[2];
        b1nn[0] = gnormb1n * vliniee[0];
        b1nn[1] = gnormb1n * vliniee[1];
        b2nn[0] = gnormb2n * vliniee[0];
        b2nn[1] = gnormb2n * vliniee[1];
        b1tn[0] = gnormb1n * vtan[0];
        b1tn[1] = gnormb1n * vtan[1];
        b2tn[0] = gnormb2n * vtan[0];
        b2tn[1] = gnormb2n * vtan[1];

        //Finale Geschwindigkeiten ausrechnen
        ball1.geschwindigkeit[0] = b1nn[0] + b1tn[0];
        ball1.geschwindigkeit[1] = b1nn[1] + b1tn[1];
        ball2.geschwindigkeit[0] = b2nn[0] + b2tn[0];
        ball2.geschwindigkeit[1] = b2nn[1] + b2tn[1];
    }        
}
void ball(float x, float y, float radius, float rot, float grün, float blau)
{
    glBegin(GL_LINE_LOOP);
    glColor3d(rot,grün,blau);
    for(float s=0;s<=360;s++)
    {
        glVertex2d( (x + (radius*cos(s*(Pi/180)))), (y + (radius*sin(s*(Pi/180)))) );
    }
    glEnd();
}
void fenster()
{
    //Glut aufrufen und initialisieren    
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(0,0);
    glutInitWindowSize(blänge, bbreite);    
    glutCreateWindow("Ball Simulation");    

    //Farbe fürs löschen festlegen
    glClearColor(0,0,0,0);
}
void zeichnen()
{  
   //Bildschirm bereinigen  
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glLoadIdentity();  

   //Bälle zeichnen
   ball(ball1.position[0],ball1.position[1],ball1.radius,1,0,0);
   ball(ball2.position[0],ball2.position[1],ball2.radius,0,0,1);  

   //Position aktualisieren
   kollisionrand();
   kollisionball();
   ballupdate();

   //Debug in Konsole
   //Bildschirmgröße
   cout << blänge << bbreite << endl;

   //Position der Bälle
   cout << "Ball1: (" << ball1.position[0] << ", " << ball1.position[1] << ")" << endl;  
   cout << "Ball2: (" << ball2.position[0] << ", " << ball2.position[1] << ")" << endl;
   cout << "Geschwindigkeit Ball1: " << ball1.geschwindigkeit[0] << " " << ball1.geschwindigkeit[1] << endl;
   cout << "Geschwindigkeit Ball2: " << ball2.geschwindigkeit[0] << " " << ball2.geschwindigkeit[1] << endl;

   //Alles anzeigen
   glutSwapBuffers();
   glutPostRedisplay();
}
void änderung(int länge, int breite)
{
    double verhältnis;

    //Nicht durch 0 teilen
    if(breite == 0)
    {
        breite = 1;
    }
    verhältnis = 1.0*länge/breite;    

    //Projektionsmodus
    glMatrixMode(GL_PROJECTION);

    //Reset
    glLoadIdentity();    

    //Sichtfeld fürs ganze Fenstere
    glViewport(0,0,länge,breite);

    //Korrekte Perspektive
    gluPerspective(0,verhältnis,1,100);

    //Zeichenbereich an Bildschirm anpassen
    glOrtho(0,blänge,0,bbreite,0,1);

    //Wieder Szene anzeigen
    glMatrixMode(GL_MODELVIEW);
}
int _tmain(int argc, char *argv[])
{    
    //Bälle initialisieren
    ballinit();

    //Glut aufrufen
    glutInit(&argc, argv);

    //Fenster zeichnen
    fenster();

    //Renderfunktion festlegen
    glutDisplayFunc(zeichnen);

    //Fenster darf verändert werden
    glutReshapeFunc(änderung);

    //immer auf neuen Event warten;
    glutMainLoop();
  
    return(0);
}




Danke für eure Hilfe.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
08.06.2012, 15:32 Uhr
~Crymes
Gast


Hat keiner eine Lösung?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
08.06.2012, 20:35 Uhr
TOSHMAX



Ich habe folgende Zeilen an einen Code angepasst, den ich vor einiger Zeit mal für dasselbe Vorhaben verwendet habe. Vielleicht verhalten sich die Bälle jetzt so wie du es dir vorgestellt hast.

C++:
void kollisionball()
{
        ...

        //Linie zwischen den Mittelpunkten (Zentralvektor)
        float vlinie[2];
        vlinie[0] = ball2.position[0] - ball1.position[0]; // [0] statt [1]
        vlinie[1] = ball2.position[1] - ball1.position[1];

        ...
        
        //Geschwindigkeitsvektoren zerlegen (tangential, normal Richtung), es kommen Skalare raus

        float gnormb1, gnormb2, gtanb1, gtanb2;
        gnormb1 = (vliniee[0] * ball1.geschwindigkeit[0]) + (vliniee[1] * ball1.geschwindigkeit[1]);
        gnormb2 = (vliniee[0] * ball2.geschwindigkeit[0]) + (vliniee[1] * ball2.geschwindigkeit[1]);
        gtanb1  = (vtan[0] * ball1.geschwindigkeit[0]) + (vtan[1] * ball1.geschwindigkeit[1]); // * statt +
        gtanb2  = (vtan[0] * ball2.geschwindigkeit[0]) + (vtan[1] * ball2.geschwindigkeit[1]); // * statt +

        ...

        //Einheitsvektoren zu normalvektoren konvertieren (normal richtung)
        float b1nn[2], b2nn[2], b1tn[2], b2tn[2];
        b1nn[0] = gnormb1n * vliniee[0];
        b1nn[1] = gnormb1n * -vtan[0];
        b2nn[0] = gnormb2n * vliniee[0];
        b2nn[1] = gnormb2n * -vtan[0];
        b1tn[0] = gtanb1 * -vliniee[1];
        b1tn[1] = gtanb1 * vtan[1];
        b2tn[0] = gtanb2 * -vliniee[1];
        b2tn[1] = gtanb2 * vtan[1];

        ...
    }
}
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
09.06.2012, 13:03 Uhr
~Crymes
Gast


Ok, Vielen Dank, es funktioniert jetzt wunderbar.

Als nächstes will ich implementieren, dass wenn man einme Taste drückt ein neuer Ball hinzukommt und bei einer anderen Taste ein Ball wieder verschwindet.

Wie mache ich das am Besten?

Kann ich des Ball struct irgendwie variabel verfielfältigen?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
09.06.2012, 15:06 Uhr
TOSHMAX



Verwalten könntest du die Bälle mit einem std::vector, z. B. so:

C++:
#include <vector>

std::vector<kugel> kugeln;

// neue Kugel hinzufügen
kugel neueKugel;
neueKugel.position[0]=110;
neueKugel.position[1]=110;
neueKugel.geschwindigkeit[0]=31;
neueKugel.geschwindigkeit[1]=6;
neueKugel.radius=100;

kugeln.push_back(neueKugel);

// letzte Kugel entfernen
if(!kugeln.empty())
    kugeln.pop_back();

Allerdings musst du mit mehreren Bällen alle Kollisionsüberprüfungen umschreiben, sodass jeder Ball mit jedem anderen kollidieren kann. Auch die Zeichenfunktion sowie die Aktualisierungen der Positionen müssen angepasst werden.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
09.06.2012, 19:28 Uhr
~Crymes
Gast


Wenn das mit der vector Klasse so einfach geht, freue ich mich.
Hatte schon Schiß, mich mit so komischen doppelt verlinkten Listen herumschlagen zu müssen.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
10.06.2012, 10:39 Uhr
~global
Gast



Zitat von ~Crymes:
Ok, Vielen Dank, es funktioniert jetzt wunderbar.

Als nächstes will ich implementieren, dass wenn man einme Taste drückt ein neuer Ball hinzukommt und bei einer anderen Taste ein Ball wieder verschwindet.

Wie mache ich das am Besten?

Kann ich des Ball struct irgendwie variabel verfielfältigen?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
10.06.2012, 10:40 Uhr
~global
Gast



Zitat von ~Crymes:
Kann ich des Ball struct irgendwie variabel verfielfältigen?


Ich würde mir mal Gedanken machen ob da eine Klasse sinvoller wäre, dann könntest du die Initialisierung, kollisionsabfrage, usw gleich in der Ball-klasse behandeln
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: