一个简单的2D小球碰撞模拟程序,代码不长主程序90多行。
全部用c++实现,借助easyx绘图,同时实现简单向量类便于计算 (默认小球质量相同 大小相同)。
#include <iostream>
#include <easyx.h>
#include <conio.h>
#include <algorithm>
#include <vector>
#include <cmath>
#include <stdlib.h>
#include <time.h>
#include "Vector2D.h"
#include "CollisionBox.h"
using namespace std;
const int WIDTH = 1100;
const int HEIGHT = 600;
void CollisionCheck(vector<Ball> &v) {
for (int i = 0; i < v.size(); i++) {
for (int j = i + 1; j < v.size(); j++) {
if (pow(v[i].x - v[j].x, 2) + pow(v[i].y - v[j].y, 2) <= 4.0 * v[i].r*v[i].r) {
Vector2D vv(v[i].vx - v[j].vx, v[i].vy - v[j].vy);
Vector2D v1, v2;
Vector2D t1(v[i].x, v[i].y), t2(v[j].x, v[j].y);
v2 = t2 - t1;
double angle = Angle(vv, v2);
double k = Len(vv)*cos(Rad(angle)) / Len(v2);
v2.x *= k;
v2.y *= k;
v1 = vv - v2;
v[i].vx = v1.x + v[j].vx;
v[i].vy = v1.y + v[j].vy;
v[j].vx += v2.x;
v[j].vy += v2.y;
}
}
}
}
void WallCheck(vector<Ball> &v) {
for (int i = 0; i < v.size(); i++) {
if (v[i].x + v[i].r >= WIDTH) v[i].vx *= -1;
else if (v[i].y - v[i].r <= 0) v[i].vy *= -1;
else if (v[i].x - v[i].r <= 0) v[i].vx *= -1;
else if (v[i].y + v[i].r >= HEIGHT) v[i].vy *= -1;
}
}
void CreatBall(vector<Ball> &v) {
srand((unsigned int)time(NULL));
for (int i = 0; i < 10; i++) {
double x, y, r = 20, vx, vy;
bool f = 1;
while (f) {
f = 0;
x = (rand() % (WIDTH - 2 * (int)r))*1.0 + r;
y = (rand() % (HEIGHT - 2 * (int)r))*1.0 + r;
for (int j = 0; j < v.size(); j++) {
if (pow(v[j].x - x, 2) + pow(v[j].y - y, 2) <= 4.0 * pow(v[j].r, 2)) {
f = 1;
}
}
if (!f) {
vx = rand() % 6;
vy = rand() % 6;
Ball t(x, y, r, vx, vy);
v.push_back(t);
}
}
}
}
int main() {
initgraph(WIDTH, HEIGHT);
vector<Ball> v;
CreatBall(v);
while (1) {
BeginBatchDraw();
for (int i = 0; i < v.size(); i++) solidcircle(v[i].x, v[i].y, v[i].r);
CollisionCheck(v);
WallCheck(v);
for (int i = 0; i <= 10000000; i++);
EndBatchDraw();
cleardevice();
for (int i = 0; i < v.size(); i++) {
v[i].x += v[i].vx;
v[i].y += v[i].vy;
}
}
closegraph();
return 0;
}
头文件: Vector2D.h
#pragma once
#include<cmath>
const double PI = 3.1415926;
double Deg(double rad) { return rad * 180.0 / PI; }
double Rad(double deg) { return deg / 180.0 * PI; }
struct Vector2D {
Vector2D() :x(), y() {};
Vector2D(double px, double py) :x(px), y(py) {};
double x, y;
Vector2D operator + (const Vector2D &b)const {
return Vector2D(this->x + b.x, this->y + b.y);
}
Vector2D operator - (const Vector2D &b)const {
return Vector2D(this->x - b.x, this->y - b.y);
}
Vector2D operator () (double px, double py) {
this->x = px, this->y = py;
return *this;
}
double operator * (const Vector2D &b)const {
return (this->x * b.x + this->y * b.y);
}
};
double Len(const Vector2D &a) {
return sqrt(a.x*a.x + a.y*a.y);
}
double Angle(const Vector2D &a, const Vector2D &b) {
return Deg(acos(a*b / (Len(a)*Len(b))));
}
CollisionBox.h
#pragma once
struct Ball {
double x, y, r;
double vx, vy;
Ball() :x(), y(), r(), vx(), vy() {}
Ball(double sx, double sy, double sr = 30.0, double svx = 3.0, double svy = 0.0):
x(sx), y(sy), r(sr), vx(svx), vy(svy) {}
};
|