-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit bae9271
Showing
18 changed files
with
1,745 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
lib/* | ||
Box2D* | ||
*.user | ||
*~* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
Carbox2d - симулятор эволюции машинок | ||
Идея взята с сайта http://boxcar2d.com | ||
|
||
СБОРКА | ||
1. Скачайте и распакуйте физический движок с сайта http://box2d.org/. В данной версии carbox2d используется box2d 2.2.1 | ||
2. Соберите движок box2d по инструкции в файле Building.txt | ||
3. Создайте в каталоге с проектом каталог lib и скопируйте в него полученный файл $BOX2DPATH/Build/Box2D/libBox2D.a | ||
4. Скопируйте в каталог с проектом директорию Box2D, содержащую заголовочные файлы от физического движка | ||
5. Теперь проект можно открыть и собрать в Qt Creator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,305 @@ | ||
#include <qmath.h> | ||
|
||
#include "car.h" | ||
|
||
Car::Car(GeneticAlgorithm *pAlghorithm, b2World *world): | ||
algorithm (pAlghorithm), | ||
b2world(world) { | ||
b2BodyDef bodyDef; | ||
init(bodyDef); | ||
createCart(); | ||
createWheels(bodyDef); | ||
updateTorque(); | ||
baseSpringForce = 7.5*carBody->GetMass(); | ||
update(); | ||
} | ||
|
||
Car::~Car() { | ||
QColor *color; | ||
for (int i = 0; i < 8; i++) { | ||
if (wheelOn[i] != NO_WHEELS || wheelOn[i] == BROKEN_WHEELS) { | ||
if (wheelOn[i] != BROKEN_WHEELS) | ||
b2world->DestroyJoint(spring[i]); | ||
b2world->DestroyJoint(motor[i]); | ||
for (b2Fixture *f = axle[i]->GetFixtureList(); f; | ||
f = f->GetNext()) { | ||
if (f->GetUserData()) | ||
delete (QColor *)f->GetUserData(); | ||
} | ||
b2world->DestroyBody(axle[i]); | ||
color = (QColor *)wheel[i]->GetUserData(); | ||
delete color; | ||
b2world->DestroyBody(wheel[i]->GetBody()); | ||
} | ||
} | ||
for (b2Fixture *f = carBody->GetFixtureList(); f; f = f->GetNext()) { | ||
if (f->GetUserData()) | ||
delete (QColor *)f->GetUserData(); | ||
} | ||
b2world->DestroyBody(carBody); | ||
QVectorIterator<b2Fixture *> piece(pieces); | ||
while (piece.hasNext()) { | ||
b2Fixture *p = piece.next(); | ||
color = (QColor *)p->GetUserData(); | ||
delete color; | ||
b2world->DestroyBody(p->GetBody()); | ||
} | ||
} | ||
|
||
void Car::breakFixture(const int index) { | ||
breakCartFixture[index] = false; | ||
int i = index%8; | ||
if (index < 8) { | ||
QColor *color = (QColor *)cartFixture[i]->GetUserData(); | ||
carBody->DestroyFixture(cartFixture[i]); | ||
cartFixture[i] = NULL; | ||
b2BodyDef bodyDef; | ||
bodyDef.type = b2_dynamicBody; | ||
bodyDef.position = carBody->GetPosition(); | ||
bodyDef.angle = carBody->GetAngle(); | ||
b2Body *piece = b2world->CreateBody(&bodyDef); | ||
b2Fixture *f = piece->CreateFixture(&cartShapes[i], 2); | ||
f->SetUserData(color); | ||
pieces.push_back(f); | ||
} else { | ||
QColor *color = (QColor *)axleFixture[i]->GetUserData(); | ||
carBody->DestroyFixture(axleFixture[i]); | ||
axleFixture[i] = NULL; | ||
b2Fixture *f = axle[i]->CreateFixture(&axleShapes[i], 2); | ||
f->SetUserData(color); | ||
wheelOn[i] = BROKEN_WHEELS; | ||
wheelsCount--; | ||
} | ||
} | ||
|
||
|
||
b2Body *Car::getAxleBody(const int index) { | ||
return wheelOn[index] == NO_WHEELS? NULL: axle[index]; | ||
} | ||
|
||
b2Fixture *Car::getAxleFixture(const int index) { | ||
return wheelOn[index] == NO_WHEELS? NULL: axleFixture[index]; | ||
} | ||
|
||
b2Body *Car::getBody() { | ||
return carBody; | ||
} | ||
|
||
b2Fixture *Car::getCartFixture(const int index) { | ||
return cartFixture[index]; | ||
} | ||
|
||
b2Body *Car::getWheel(const int index) { | ||
return wheelOn[index] == NO_WHEELS? NULL: wheel[index]->GetBody(); | ||
} | ||
|
||
float Car::getMaxPossition() { | ||
return TRACK_LENGTH < maxPossition? TRACK_LENGTH: maxPossition; | ||
} | ||
|
||
b2Body *Car::getPiece(const int index) { | ||
return pieces[index]->GetBody(); | ||
} | ||
|
||
int Car::getPiecesCount() { | ||
return pieces.size(); | ||
} | ||
|
||
b2Vec2 Car::getPossition() { | ||
return carBody->GetPosition(); | ||
} | ||
|
||
int Car::getRemainingTime() { | ||
return (MAX_ITTERATION - itteration)/60; | ||
} | ||
|
||
float Car::getSpeed() { | ||
b2Vec2 vel = carBody->GetLinearVelocity(); | ||
return qSqrt(qPow(vel.x, 2) + qPow(vel.y, 2)); | ||
} | ||
|
||
float Car::getTime() { | ||
return itteration/60.0f; | ||
} | ||
|
||
float Car::getTorque() { | ||
return torque; | ||
} | ||
|
||
bool Car::isStoped() { | ||
return stoped; | ||
} | ||
|
||
void Car::setBreakFixture(const int index, const bool val) { | ||
breakCartFixture[index] = val; | ||
} | ||
|
||
void Car::update() { | ||
for (int i = 0; i < 8; i++) { | ||
if (wheelOn[i] >= 0) { | ||
spring[i]->SetMaxMotorForce(baseSpringForce + 40*baseSpringForce* | ||
qPow(spring[i]->GetJointTranslation(), | ||
2)); | ||
spring[i]->SetMotorSpeed(-20*spring[i]->GetJointTranslation()); | ||
} | ||
if (brokeNum < 7 && breakCartFixture[i]) { | ||
brokeNum++; | ||
breakFixture(i); | ||
for (int j = 0; j < 8; j++) { | ||
if (wheelOn[j] == i) { | ||
b2world->DestroyJoint(spring[j]); | ||
breakFixture(8 + j); | ||
motor[j]->SetMotorSpeed(0); | ||
motor[j]->SetMaxMotorTorque(0); | ||
} | ||
} | ||
updateTorque(); | ||
} | ||
if (breakCartFixture[i + 8]) { | ||
b2world->DestroyJoint(spring[i]); | ||
breakFixture(i+8); | ||
motor[i]->SetMotorSpeed(0); | ||
motor[i]->SetMaxMotorTorque(0); | ||
updateTorque(); | ||
} | ||
} | ||
itteration++; | ||
float possition = carBody->GetPosition().x; | ||
maxPossition = qMax(maxPossition, possition); | ||
if (maxPossition - prevPossition > 1) { | ||
slow = 0; | ||
prevPossition = maxPossition; | ||
} else { | ||
if (carBody->GetLinearVelocity().x < 1) | ||
slow++; | ||
} | ||
float maxSlow = possition > 10? 300: 180; | ||
if (slow >= maxSlow || possition >= TRACK_LENGTH || | ||
itteration > MAX_ITTERATION || possition < -10 || brokeNum >= 7) | ||
stoped = true; | ||
} | ||
|
||
void Car::updateTorque() { | ||
float totalMass = carBody->GetMass(); | ||
torque = wheelsCount? totalMass*MASS_MULT*15/qPow(2,float(wheelsCount) - 1): | ||
0; | ||
for (int i = 0; i < 8; i++) { | ||
if (wheelOn[i] >= 0) { | ||
motor[i]->SetMaxMotorTorque(torque); | ||
} | ||
} | ||
} | ||
|
||
void Car::createCart() { | ||
b2Vec2 triangle[3]; | ||
triangle[0].Set(0,0); | ||
for (int i = 0; i < 8; i++) { | ||
float angle = algorithm->getCartAngle(i); | ||
float magnitude = algorithm->getMagnitude(i); | ||
float x = magnitude*qCos(angle); | ||
float y = magnitude*qSin(angle); | ||
float nextMagnitude = algorithm->getMagnitude((i + 1)%8); | ||
float nextAngle = algorithm->getCartAngle((i + 1)%8); | ||
float nextX = nextMagnitude*qCos(nextAngle); | ||
float nextY = nextMagnitude*qSin(nextAngle); | ||
triangle[0].Set(0 ,0); | ||
triangle[1].Set(x, y); | ||
triangle[2].Set(nextX, nextY); | ||
cartShapes[i].Set(triangle, 3); | ||
b2FixtureDef fixtureDef; | ||
fixtureDef.shape = &cartShapes[i]; | ||
fixtureDef.density = 2; | ||
fixtureDef.friction = 10; | ||
fixtureDef.restitution = 0.05; | ||
fixtureDef.filter.groupIndex = -1; | ||
cartFixture[i] = createFixture(&fixtureDef, carBody, | ||
algorithm->getColorCart(i)); | ||
setBreakFixture(i, false); | ||
} | ||
} | ||
|
||
b2Fixture *Car::createFixture(const b2FixtureDef* def, b2Body *body, | ||
const QColor color) { | ||
b2Fixture *fixture = body->CreateFixture(def); | ||
QColor *c = new QColor(color); | ||
fixture->SetUserData(c); | ||
return fixture; | ||
} | ||
|
||
void Car::createWheels(b2BodyDef &bodyDef) { | ||
b2PrismaticJointDef prismaticJointDef; | ||
prismaticJointDef.lowerTranslation = -0.1; | ||
prismaticJointDef.upperTranslation = 0.25; | ||
prismaticJointDef.enableLimit = true; | ||
prismaticJointDef.enableMotor = true; | ||
for (int i = 0; i < 8; i++) { | ||
wheelOn[i] = algorithm->getWheelOn(i); | ||
setBreakFixture(8 + i, false); | ||
if (wheelOn[i] == NO_WHEELS) | ||
continue; | ||
wheelsCount++; | ||
float angle = algorithm->getCartAngle(wheelOn[i]); | ||
float magnitude = algorithm->getMagnitude(wheelOn[i]); | ||
float x = magnitude*qCos(angle); | ||
float y = magnitude*qSin(angle); | ||
float axleAngle = algorithm->getAxleAngle(i); | ||
axleShapes[i].SetAsBox(0.2, 0.1, b2Vec2(x, y), axleAngle); | ||
b2FixtureDef fixtureDef; | ||
fixtureDef.shape = &axleShapes[i]; | ||
fixtureDef.density = 2; | ||
fixtureDef.friction = 10; | ||
fixtureDef.restitution = 0.05; | ||
fixtureDef.filter.groupIndex = -1; | ||
axleFixture[i] = createFixture(&fixtureDef, carBody, | ||
algorithm->getColorAxle(i)); | ||
axle[i] = b2world->CreateBody(&bodyDef); | ||
b2PolygonShape polygonShape; | ||
polygonShape.SetAsBox(0.2, 0.05, b2Vec2(x - 0.3*qCos(axleAngle), | ||
y - 0.3*qSin(axleAngle)), axleAngle); | ||
fixtureDef.shape = &polygonShape; | ||
fixtureDef.density = 20; | ||
createFixture(&fixtureDef, axle[i], algorithm->getColorAxle(i)); | ||
prismaticJointDef.Initialize(carBody, axle[i], | ||
axle[i]->GetWorldCenter(), | ||
b2Vec2(qCos(axleAngle), qSin(axleAngle))); | ||
spring[i] = (b2PrismaticJoint *) | ||
b2world->CreateJoint(&prismaticJointDef); | ||
b2CircleShape circleShape; | ||
circleShape.m_radius = algorithm->getWheelRadius(i); | ||
b2FixtureDef wheelFixtureDef; | ||
wheelFixtureDef.shape = &circleShape; | ||
wheelFixtureDef.density = 0.5; | ||
wheelFixtureDef.friction = 10; | ||
wheelFixtureDef.restitution = 0.1; | ||
wheelFixtureDef.filter.groupIndex = -1; | ||
b2BodyDef wheelBodyDef; | ||
wheelBodyDef.position.Set(carBody->GetPosition().x + x - | ||
qCos(axleAngle)/2, carBody->GetPosition().y + | ||
y - qSin(axleAngle)/2); | ||
wheelBodyDef.allowSleep = false; | ||
wheelBodyDef.type = b2_dynamicBody; | ||
b2Body *bodyWheel = b2world->CreateBody(&wheelBodyDef); | ||
wheel[i] = createFixture(&wheelFixtureDef, bodyWheel, Qt::black); | ||
b2RevoluteJointDef revoluteJointDef; | ||
revoluteJointDef.enableMotor = true; | ||
revoluteJointDef.Initialize(axle[i], bodyWheel, | ||
bodyWheel->GetWorldCenter()); | ||
motor[i] = (b2RevoluteJoint *)b2world->CreateJoint(&revoluteJointDef); | ||
motor[i]->SetMotorSpeed(-6*M_PI); | ||
} | ||
} | ||
|
||
void Car::init(b2BodyDef &bodyDef) { | ||
stoped = false; | ||
bodyDef.position.Set(0, 4); | ||
bodyDef.angle = 0; | ||
bodyDef.type = b2_dynamicBody; | ||
carBody = b2world->CreateBody(&bodyDef); | ||
brokeNum = 0; | ||
wheelsCount = 0; | ||
maxPossition = 0; | ||
prevPossition = 0; | ||
itteration = 0; | ||
slow = 0; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
#ifndef CAR_H | ||
#define CAR_H | ||
|
||
#include <QVector> | ||
#include "Box2D.h" | ||
#include "geneticalgorithm.h" | ||
|
||
class Car { | ||
public: | ||
Car(GeneticAlgorithm *pAlghorithm, b2World *world); | ||
~Car(); | ||
|
||
void breakFixture(const int index); | ||
b2Body *getAxleBody(const int index); | ||
b2Fixture *getAxleFixture(const int index); | ||
b2Body *getBody(); | ||
b2Fixture *getCartFixture(const int index); | ||
b2Body *getWheel(const int index); | ||
float getMaxPossition(); | ||
b2Body *getPiece(const int index); | ||
int getPiecesCount(); | ||
b2Vec2 getPossition(); | ||
int getRemainingTime(); | ||
float getSpeed(); | ||
float getTime(); | ||
float getTorque(); | ||
bool isStoped(); | ||
void setBreakFixture(const int index, const bool val); | ||
void update(); | ||
void updateTorque(); | ||
|
||
private: | ||
static const float MASS_MULT = 1.5; | ||
static const int MAX_ITTERATION = 5*60*60; | ||
static const float TRACK_LENGTH = 1500.0f; | ||
static const int NO_WHEELS = -1; | ||
static const int BROKEN_WHEELS = -2; | ||
|
||
void createCart(); | ||
b2Fixture *createFixture(const b2FixtureDef* def, b2Body *body, | ||
const QColor color); | ||
void createWheels(b2BodyDef &bodyDef); | ||
void init(b2BodyDef &bodyDef); | ||
|
||
GeneticAlgorithm *algorithm; | ||
b2Body *axle[8]; | ||
b2Fixture *axleFixture[8]; | ||
b2PolygonShape axleShapes[8]; | ||
float baseSpringForce; | ||
b2World *b2world; | ||
bool breakCartFixture[16]; | ||
int brokeNum; | ||
b2Body *carBody; | ||
b2Fixture *cartFixture[8]; | ||
b2PolygonShape cartShapes[8]; | ||
int itteration; | ||
float maxPossition; | ||
b2RevoluteJoint *motor[8]; | ||
float prevPossition; | ||
int slow; | ||
bool stoped; | ||
b2PrismaticJoint *spring[8]; | ||
float torque; | ||
b2Fixture *wheel[8]; | ||
int wheelsCount; | ||
int wheelOn[8]; | ||
QVector<b2Fixture *> pieces; | ||
}; | ||
|
||
#endif // CAR_H |
Oops, something went wrong.