• TopDown Car demo


      1 //这个是老外教程附带的文件,直接复制下来放到Testbed例子的目录。你懂得 
      2 /* * Author: Chris Campbell - www.iforce2d.net * * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org *
      3    * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software.
      4    * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions:
      5    * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required.
      6    * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software.
      7    * 3. This notice may not be removed or altered from any source distribution. */
      8 #ifndef IFORCE2D_TOPDOWN_CAR_H
      9 #define IFORCE2D_TOPDOWN_CAR_H
     10 #include #include 
     11 #ifndef DEGTORAD 
     12 #define DEGTORAD 0.0174532925199432957f
     13 #define RADTODEG 57.295779513082320876f
     14 #endif
     15 enum {
     16     TDC_LEFT = 0x1,
     17     TDC_RIGHT = 0x2,
     18     TDC_UP = 0x4,
     19     TDC_DOWN = 0x8
     20 }; //types of fixture user data
     21 enum fixtureUserDataType
     22 {
     23     FUD_CAR_TIRE,
     24     FUD_GROUND_AREA
     25 }; //a class to allow subclassing of different fixture user data
     26 class FixtureUserData {
     27     fixtureUserDataType m_type;
     28 protected:
     29     FixtureUserData(fixtureUserDataType type) : m_type(type) {}
     30 public:
     31     virtual fixtureUserDataType getType() {
     32         return m_type;
     33     }
     34     virtual ~FixtureUserData()
     35     {
     36     }
     37 }; //class to allow marking a fixture as a car tire 
     38 class CarTireFUD : public FixtureUserData
     39 {
     40 public:
     41     CarTireFUD() : FixtureUserData(FUD_CAR_TIRE) {}
     42 };
     43 //class to allow marking a fixture as a ground area 
     44 class GroundAreaFUD : public FixtureUserData {
     45 public:
     46     float frictionModifier;
     47     bool outOfCourse;
     48     GroundAreaFUD(float fm, bool ooc) : FixtureUserData(FUD_GROUND_AREA)
     49     {
     50         frictionModifier = fm; outOfCourse = ooc;
     51     }
     52 };
     53 class TDTire
     54 {
     55 public:
     56     b2Body* m_body;
     57     float m_maxForwardSpeed;
     58     float m_maxBackwardSpeed;
     59     float m_maxDriveForce;
     60     float m_maxLateralImpulse;
     61     std::set m_groundAreas;
     62     float m_currentTraction;
     63     TDTire(b2World* world) {
     64         b2BodyDef bodyDef;
     65         bodyDef.type = b2_dynamicBody;
     66         m_body = world->CreateBody(&bodyDef);
     67         b2PolygonShape polygonShape;
     68         polygonShape.SetAsBox(0.5f, 1.25f);
     69         b2Fixture* fixture = m_body->CreateFixture(&polygonShape, 1);//shape, density 
     70         fixture->SetUserData(new CarTireFUD());
     71         m_body->SetUserData(this);
     72         m_currentTraction = 1;
     73     }
     74     ~TDTire() { m_body->GetWorld()->DestroyBody(m_body); }
     75     void setCharacteristics(float maxForwardSpeed, float maxBackwardSpeed, float maxDriveForce, float maxLateralImpulse)
     76     {
     77         m_maxForwardSpeed = maxForwardSpeed; m_maxBackwardSpeed = maxBackwardSpeed; m_maxDriveForce = maxDriveForce;
     78         m_maxLateralImpulse = maxLateralImpulse;
     79     }
     80     void addGroundArea(GroundAreaFUD* ga) {
     81         m_groundAreas.insert(ga);
     82         updateTraction();
     83     } void removeGroundArea(GroundAreaFUD* ga) { m_groundAreas.erase(ga); updateTraction(); }
     84     void updateTraction() {
     85         if (m_groundAreas.empty()) m_currentTraction = 1; else { //find area with highest traction
     86             m_currentTraction = 0; std::set::iterator it = m_groundAreas.begin();
     87             while (it != m_groundAreas.end()) { GroundAreaFUD* ga = *it; if (ga->frictionModifier > m_currentTraction) m_currentTraction = ga->frictionModifier; ++it; }
     88         }
     89     }
     90     b2Vec2 getLateralVelocity() {
     91         b2Vec2 currentRightNormal = m_body->GetWorldVector(b2Vec2(1, 0));
     92         return b2Dot(currentRightNormal, m_body->GetLinearVelocity()) * currentRightNormal;
     93     }
     94     b2Vec2 getForwardVelocity() {
     95         b2Vec2 currentForwardNormal = m_body->GetWorldVector(b2Vec2(0, 1));
     96         return b2Dot(currentForwardNormal, m_body->GetLinearVelocity()) * currentForwardNormal;
     97     }
     98     void updateFriction() { //lateral linear velocity 
     99         b2Vec2 impulse = m_body->GetMass() * -getLateralVelocity();
    100         if (impulse.Length() > m_maxLateralImpulse)
    101             impulse *= m_maxLateralImpulse / impulse.Length();
    102         m_body->ApplyLinearImpulse(m_currentTraction * impulse, m_body->GetWorldCenter()); //angular velocity
    103         m_body->ApplyAngularImpulse(m_currentTraction * 0.1f * m_body->GetInertia() * -m_body->GetAngularVelocity()); //forward linear velocity 
    104         b2Vec2 currentForwardNormal = getForwardVelocity();
    105         float currentForwardSpeed = currentForwardNormal.Normalize();
    106         float dragForceMagnitude = -2 * currentForwardSpeed;
    107         m_body->ApplyForce(m_currentTraction * dragForceMagnitude * currentForwardNormal, m_body->GetWorldCenter());
    108     }
    109     void updateDrive(int controlState) { //find desired speed 
    110         float desiredSpeed = 0;
    111         switch (controlState & (TDC_UP | TDC_DOWN))
    112         {
    113         case TDC_UP: desiredSpeed = m_maxForwardSpeed; break;
    114         case TDC_DOWN: desiredSpeed = m_maxBackwardSpeed; break;
    115         default: return;//do nothing } //find current speed in forward direction 
    116             b2Vec2 currentForwardNormal = m_body->GetWorldVector(b2Vec2(0, 1));
    117             float currentSpeed = b2Dot(getForwardVelocity(), currentForwardNormal); //apply necessary force 
    118             float force = 0;
    119             if (desiredSpeed > currentSpeed)
    120                 force = m_maxDriveForce;
    121             else if (desiredSpeed < currentSpeed)
    122                 force = -m_maxDriveForce; else return;
    123             m_body->ApplyForce(m_currentTraction * force * currentForwardNormal, m_body->GetWorldCenter());
    124         }
    125         void updateTurn(int controlState) {
    126             float desiredTorque = 0;
    127             switch (controlState & (TDC_LEFT | TDC_RIGHT))
    128             {
    129             case TDC_LEFT:
    130                 desiredTorque = 15;
    131                 break;
    132             case TDC_RIGHT:
    133                 desiredTorque = -15;
    134                 break;
    135             default:;//nothing 
    136             }
    137             m_body->ApplyTorque(desiredTorque);
    138         }
    139     };
    140 }
    141 class TDCar {
    142     b2Body* m_body;
    143     std::vector m_tires;
    144     b2RevoluteJoint* flJoint, * frJoint;
    145 public:
    146     TDCar(b2World* world)
    147     {
    148         //create car body
    149         b2BodyDef bodyDef;
    150         bodyDef.type = b2_dynamicBody; m_body = world->CreateBody(&bodyDef);
    151         m_body->SetAngularDamping(3); b2Vec2 vertices[8]; vertices[0].Set(1.5, 0);
    152         vertices[1].Set(3, 2.5); vertices[2].Set(2.8, 5.5); vertices[3].Set(1, 10);
    153         vertices[4].Set(-1, 10); vertices[5].Set(-2.8, 5.5); vertices[6].Set(-3, 2.5);
    154         vertices[7].Set(-1.5, 0); b2PolygonShape polygonShape; polygonShape.Set(vertices, 8);
    155         b2Fixture* fixture = m_body->CreateFixture(&polygonShape, 0.1f);//shape, density //prepare common joint parameters 
    156         b2RevoluteJointDef jointDef;
    157         jointDef.bodyA = m_body;
    158         jointDef.enableLimit = true;
    159         jointDef.lowerAngle = 0;
    160         jointDef.upperAngle = 0;
    161         jointDef.localAnchorB.SetZero();//center of tire float maxForwardSpeed = 250; float maxBackwardSpeed = -40; float backTireMaxDriveForce = 300; float frontTireMaxDriveForce = 500; float backTireMaxLateralImpulse = 8.5; float frontTireMaxLateralImpulse = 7.5; //back left tire TDTire* tire = new TDTire(world); tire->setCharacteristics(maxForwardSpeed, maxBackwardSpeed, backTireMaxDriveForce, backTireMaxLateralImpulse); jointDef.bodyB = tire->m_body; jointDef.localAnchorA.Set( -3, 0.75f ); world->CreateJoint( &jointDef ); m_tires.push_back(tire); //back right tire tire = new TDTire(world); tire->setCharacteristics(maxForwardSpeed, maxBackwardSpeed, backTireMaxDriveForce, backTireMaxLateralImpulse); jointDef.bodyB = tire->m_body; jointDef.localAnchorA.Set( 3, 0.75f ); world->CreateJoint( &jointDef ); m_tires.push_back(tire); //front left tire tire = new TDTire(world); tire->setCharacteristics(maxForwardSpeed, maxBackwardSpeed, frontTireMaxDriveForce, frontTireMaxLateralImpulse); jointDef.bodyB = tire->m_body; jointDef.localAnchorA.Set( -3, 8.5f ); flJoint = (b2RevoluteJoint*)world->CreateJoint( &jointDef ); m_tires.push_back(tire); //front right tire tire = new TDTire(world); tire->setCharacteristics(maxForwardSpeed, maxBackwardSpeed, frontTireMaxDriveForce, frontTireMaxLateralImpulse); jointDef.bodyB = tire->m_body; jointDef.localAnchorA.Set( 3, 8.5f ); frJoint = (b2RevoluteJoint*)world->CreateJoint( &jointDef ); m_tires.push_back(tire); } ~TDCar() { for (int i = 0; i < m_tires.size(); i++) delete m_tires[i]; } void update(int controlState) { for (int i = 0; i < m_tires.size(); i++) m_tires[i]->updateFriction();
    162         for (int i = 0; i < m_tires.size(); i++)
    163             m_tires[i]->updateDrive(controlState); //control steering 
    164         float lockAngle = 35 * DEGTORAD;
    165         float turnSpeedPerSec = 160 * DEGTORAD;//from lock to lock in 0.5 sec
    166         float turnPerTimeStep = turnSpeedPerSec / 60.0f;
    167         float desiredAngle = 0;
    168         switch (controlState & (TDC_LEFT | TDC_RIGHT))
    169         {
    170         case TDC_LEFT:
    171             desiredAngle = lockAngle;
    172             break;
    173         case TDC_RIGHT:
    174             desiredAngle = -lockAngle;
    175             break;
    176         default:;//nothing 
    177         }
    178         float angleNow = flJoint->GetJointAngle();
    179         float angleToTurn = desiredAngle - angleNow;
    180         angleToTurn = b2Clamp(angleToTurn, -turnPerTimeStep, turnPerTimeStep);
    181         float newAngle = angleNow + angleToTurn;
    182         flJoint->SetLimits(newAngle, newAngle);
    183         frJoint->SetLimits(newAngle, newAngle);
    184     }
    185 };
    186 class MyDestructionListener : public b2DestructionListener {
    187     void SayGoodbye(b2Fixture* fixture) {
    188         if (FixtureUserData* fud = (FixtureUserData*)fixture->GetUserData())
    189             delete fud;
    190     } //(unused but must implement all pure virtual functions)
    191     void SayGoodbye(b2Joint* joint) {}
    192 };
    193 class iforce2d_TopdownCar : public Test {
    194 public:
    195     iforce2d_TopdownCar()
    196     {
    197         m_world->SetGravity(b2Vec2(0, 0));
    198         m_world->SetDestructionListener(&m_destructionListener); //set up ground areas 
    199         {
    200             b2BodyDef bodyDef; m_groundBody = m_world->CreateBody(&bodyDef);
    201             b2PolygonShape polygonShape; b2FixtureDef fixtureDef;
    202             fixtureDef.shape = &polygonShape; fixtureDef.isSensor = true;
    203             polygonShape.SetAsBox(9, 7, b2Vec2(-10, 15), 20 * DEGTORAD);
    204             b2Fixture* groundAreaFixture = m_groundBody->CreateFixture(&fixtureDef);
    205             groundAreaFixture->SetUserData(new GroundAreaFUD(0.5f, false));
    206             polygonShape.SetAsBox(9, 5, b2Vec2(5, 20), -40 * DEGTORAD);
    207             groundAreaFixture = m_groundBody->CreateFixture(&fixtureDef);
    208             groundAreaFixture->SetUserData(new GroundAreaFUD(0.2f, false));
    209         } //
    210         m_tire = new TDTire(m_world); //
    211         m_tire->setCharacteristics(100, -20, 150);
    212         m_car = new TDCar(m_world);
    213         m_controlState = 0;
    214     }
    215 
    216     ~iforce2d_TopdownCar() { //
    217         delete m_tire; delete m_car; m_world->DestroyBody(m_groundBody);
    218     }
    219     void Keyboard(unsigned char key) {
    220         switch (key) {
    221         case 'a': m_controlState |= TDC_LEFT; break;
    222         case 'd': m_controlState |= TDC_RIGHT; break;
    223         case 'w': m_controlState |= TDC_UP; break;
    224         case 's': m_controlState |= TDC_DOWN; break;
    225         default: Test::Keyboard(key);
    226         }
    227     }
    228     void KeyboardUp(unsigned char key)
    229     {
    230         switch (key) {
    231         case 'a':
    232             m_controlState &= ~TDC_LEFT; break;
    233         case 'd':
    234             m_controlState &= ~TDC_RIGHT;
    235             break;
    236         case 'w':
    237             m_controlState &= ~TDC_UP;
    238             break;
    239         case 's':
    240             m_controlState &= ~TDC_DOWN;
    241             break;
    242         default:
    243             Test::Keyboard(key);
    244         }
    245     }
    246     void handleContact(b2Contact* contact, bool began)
    247     {
    248         b2Fixture* a = contact->GetFixtureA();
    249         b2Fixture* b = contact->GetFixtureB();
    250         FixtureUserData* fudA = (FixtureUserData*)a->GetUserData();
    251         FixtureUserData* fudB = (FixtureUserData*)b->GetUserData();
    252         if (!fudA || !fudB)
    253             return;
    254         if (fudA->getType() == FUD_CAR_TIRE || fudB->getType() == FUD_GROUND_AREA)
    255             tire_vs_groundArea(a, b, began);
    256         else if (fudA->getType() == FUD_GROUND_AREA || fudB->getType() == FUD_CAR_TIRE)
    257             tire_vs_groundArea(b, a, began);
    258     }
    259     void BeginContact(b2Contact* contact)
    260     {
    261         handleContact(contact, true);
    262     }
    263     void EndContact(b2Contact* contact)
    264     {
    265         handleContact(contact, false);
    266     }
    267     void tire_vs_groundArea(b2Fixture* tireFixture, b2Fixture* groundAreaFixture, bool began)
    268     {
    269         TDTire* tire = (TDTire*)tireFixture->GetBody()->GetUserData();
    270         GroundAreaFUD* gaFud = (GroundAreaFUD*)groundAreaFixture->GetUserData();
    271         if (began) tire->addGroundArea(gaFud); else tire->removeGroundArea(gaFud);
    272     }
    273     void Step(Settings* settings) {
    274         /*m_tire->updateFriction();
    275         m_tire->updateDrive(m_controlState);
    276         m_tire->updateTurn(m_controlState);*/
    277         m_car->update(m_controlState); Test::Step(settings); //show some useful info 
    278         m_debugDraw.DrawString(5, m_textLine, "Press w/a/s/d to control the car");
    279         m_textLine += 15; //
    280         m_debugDraw.DrawString(5, m_textLine, "Tire traction: %.2f", m_tire->m_currentTraction); //
    281         m_textLine += 15;
    282     }
    283     static Test* Create()
    284     {
    285         return new iforce2d_TopdownCar;
    286     }
    287     int m_controlState;
    288     MyDestructionListener m_destructionListener;
    289     b2Body* m_groundBody; //
    290     TDTire* m_tire;
    291     TDCar* m_car;
    292 };
    293 #endif
    View Code
  • 相关阅读:
    20145320 《信息安全系统设计基础》第2周学习总结
    20145320 《信息安全系统设计基础》第一周学习总结
    20145320 周岐浩《信息安全系统设计基础》第0周学习总结
    暑假CTF训练一
    #20145320课程总结
    20145320 《Java程序设计》第10周学习总结
    20145320《Java程序设计》第五次实验报告
    20145320《Java程序设计》第9周学习总结
    20145320《Java程序设计》第四次实验报告
    20145320《Java程序设计》第三次实验报告
  • 原文地址:https://www.cnblogs.com/yang131/p/14372236.html
Copyright © 2020-2023  润新知