Dzień Dobry.
Pisze symulacje ruchu 1000 dysków przy wykorzystaniu metody Eulera ( wyliczenie Pos i y). Mam problem z kolizją.
Mam napisany prosty kod wykrywania kolizji (collision), ale niektóre dyski mogą przeniknąć i wypaść poza okno.
Zasugerowano mi abym podzielił krok czasowy (dt) na 2 cześć (do kolizji i po kolizji). Próbowałem np. dt = 0 , gdy wykrywa kolizje lub t1 = 0 i t0 = 0 gdy wykrywa kolizje , ale nie przynosi to pozytywnych skutków. Chciałbym aby ktoś mi wskazał jak powinienem podzielić dt aby uzyskać prawidłową kolizje 1000 dysków.
Podrzucam kod trzech plików:
Disc.h
#include <iostream>
#include <math.h>
#include <SFML/Graphics.hpp>
class Disc
{
private:
sf::CircleShape disc;
sf::Color color;
sf::Vector2f PosXY;
sf::Vector2f V;
float mass;
float diameter;
float g;
clock_t t0;
clock_t t1;
float dt;
public:
Disc(float m, float d, sf::RenderWindow &W, int R, int G, int B, float X, float Y);
Disc();
~Disc();
void setup();
void move();
void collision(sf::RenderWindow& W);
void draw(sf::RenderWindow& W);
};
Disc.cpp
Disc::Disc(float m, float d, sf::RenderWindow &W, int R, int G, int B, float X, float Y)
{
color.r = R;
color.g = G;
color.b = B;
PosXY.x = X;
PosXY.y = Y;
V.x = 0.f;
V.y = 0.f;
mass = m;
diameter = d;
g = 9.81f;
t0 = 0;
t1 = clock();
dt = 0.0f;
}
Disc::Disc()
{
color.r = 0;
color.g = 0;
color.b = 0;
PosXY.x = 0.f;
PosXY.y = 0.f;
V.x = 0.f;
V.y = 0.f;
mass = 0;
diameter = 0;
g = 9.81f;
t0 = 0;
t1 = clock();
dt = 0.0f;
}
Disc::~Disc()
{ }
void Disc::setup()
{
disc.setRadius(diameter/2);
disc.setFillColor(color);
}
void Disc::move()
{
t0 = t1;
t1 = clock();
dt = ((float)t1) / CLOCKS_PER_SEC - ((float)t0) / CLOCKS_PER_SEC;
PosXY.x = PosXY.x + V.x * dt;
PosXY.y = PosXY.y + V.y * dt;
V.x = V.x + g * dt;
V.y = V.y + g * dt;
disc.setPosition(PosXY);
}
void Disc::collision(sf::RenderWindow& W)
{
if (PosXY.y + diameter >= W.getSize().y || PosXY.y + diameter <= 0)
V.y = -V.y;
if (PosXY.x + diameter >= W.getSize().x || PosXY.x + diameter <= 0)
V.x = -V.x;
}
void Disc::draw(sf::RenderWindow &W)
{
W.draw(disc);
}
main.cpp
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <string>
#include <SFML/Graphics.hpp>
#include "Disc.h"
struct DATA
{
float mass;
float diameter;
int Red;
int Green;
int Blue;
float PosX;
float PosY;
} DataDisc;
int main()
{
int width = 600;
int height = 600;
const int count_disc = 200;
int len_tab_disc = count_disc;
sf::RenderWindow window(sf::VideoMode(width, height), "SFML works!");
srand(time(NULL));
Disc D[count_disc];
for (int i = 0; i < len_tab_disc; i++)
{
DataDisc.mass = rand()%10+1;
DataDisc.diameter = 10.f;
DataDisc.Red = rand()%256+1;
DataDisc.Green = rand()%256+1;
DataDisc.Blue = rand()%256+1;
DataDisc.PosX = rand() % width/2;
DataDisc.PosY = rand() % height/2;
D[i] = { DataDisc.mass, DataDisc.diameter,window,DataDisc.Red,DataDisc.Green,DataDisc.Blue,DataDisc.PosX ,DataDisc.PosY};
//D[i] = { 20.0f,10.0f,window,23,53,83,300.f+10.f*i,300.f };
D[i].setup();
}
while (window.isOpen())
{
for (int i = 0; i < len_tab_disc; i++)
{
D[i].move();
D[i].collision(window);
}
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
for (int i = 0; i < len_tab_disc; i++)
{
D[i].draw(window);
}
window.display();
}
return 0;
}