topdownCar 例子

Easter79
• 阅读 563

//这个是老外教程附带的文件,直接复制下来放到Testbed例子的目录。你懂得 /* * Author: Chris Campbell - www.iforce2d.net * * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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. * 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: * 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. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ #ifndef IFORCE2D_TOPDOWN_CAR_H #define IFORCE2D_TOPDOWN_CAR_H #include #include #ifndef DEGTORAD #define DEGTORAD 0.0174532925199432957f #define RADTODEG 57.295779513082320876f #endif enum { TDC_LEFT = 0x1, TDC_RIGHT = 0x2, TDC_UP = 0x4, TDC_DOWN = 0x8 }; //types of fixture user data enum fixtureUserDataType { FUD_CAR_TIRE, FUD_GROUND_AREA }; //a class to allow subclassing of different fixture user data class FixtureUserData { fixtureUserDataType m_type; protected: FixtureUserData(fixtureUserDataType type) : m_type(type) {} public: virtual fixtureUserDataType getType() { return m_type; } virtual ~FixtureUserData() {} }; //class to allow marking a fixture as a car tire class CarTireFUD : public FixtureUserData { public: CarTireFUD() : FixtureUserData(FUD_CAR_TIRE) {} }; //class to allow marking a fixture as a ground area class GroundAreaFUD : public FixtureUserData { public: float frictionModifier; bool outOfCourse; GroundAreaFUD(float fm, bool ooc) : FixtureUserData(FUD_GROUND_AREA) { frictionModifier = fm; outOfCourse = ooc; } }; class TDTire { public: b2Body* m_body; float m_maxForwardSpeed; float m_maxBackwardSpeed; float m_maxDriveForce; float m_maxLateralImpulse; std::set m_groundAreas; float m_currentTraction; TDTire(b2World* world) { b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; m_body = world->CreateBody(&bodyDef); b2PolygonShape polygonShape; polygonShape.SetAsBox( 0.5f, 1.25f ); b2Fixture* fixture = m_body->CreateFixture(&polygonShape, 1);//shape, density fixture->SetUserData( new CarTireFUD() ); m_body->SetUserData( this ); m_currentTraction = 1; } ~TDTire() { m_body->GetWorld()->DestroyBody(m_body); } void setCharacteristics(float maxForwardSpeed, float maxBackwardSpeed, float maxDriveForce, float maxLateralImpulse) { m_maxForwardSpeed = maxForwardSpeed; m_maxBackwardSpeed = maxBackwardSpeed; m_maxDriveForce = maxDriveForce; m_maxLateralImpulse = maxLateralImpulse; } void addGroundArea(GroundAreaFUD* ga) { m_groundAreas.insert(ga); updateTraction(); } void removeGroundArea(GroundAreaFUD* ga) { m_groundAreas.erase(ga); updateTraction(); } void updateTraction() { if ( m_groundAreas.empty() ) m_currentTraction = 1; else { //find area with highest traction m_currentTraction = 0; std::set::iterator it = m_groundAreas.begin(); while (it != m_groundAreas.end()) { GroundAreaFUD* ga = *it; if ( ga->frictionModifier > m_currentTraction ) m_currentTraction = ga->frictionModifier; ++it; } } } b2Vec2 getLateralVelocity() { b2Vec2 currentRightNormal = m_body->GetWorldVector( b2Vec2(1,0) ); return b2Dot( currentRightNormal, m_body->GetLinearVelocity() ) * currentRightNormal; } b2Vec2 getForwardVelocity() { b2Vec2 currentForwardNormal = m_body->GetWorldVector( b2Vec2(0,1) ); return b2Dot( currentForwardNormal, m_body->GetLinearVelocity() ) * currentForwardNormal; } void updateFriction() { //lateral linear velocity b2Vec2 impulse = m_body->GetMass() * -getLateralVelocity(); if ( impulse.Length() > m_maxLateralImpulse ) impulse *= m_maxLateralImpulse / impulse.Length(); m_body->ApplyLinearImpulse( m_currentTraction * impulse, m_body->GetWorldCenter() ); //angular velocity m_body->ApplyAngularImpulse( m_currentTraction * 0.1f * m_body->GetInertia() * -m_body->GetAngularVelocity() ); //forward linear velocity b2Vec2 currentForwardNormal = getForwardVelocity(); float currentForwardSpeed = currentForwardNormal.Normalize(); float dragForceMagnitude = -2 * currentForwardSpeed; m_body->ApplyForce( m_currentTraction * dragForceMagnitude * currentForwardNormal, m_body->GetWorldCenter() ); } void updateDrive(int controlState) { //find desired speed float desiredSpeed = 0; switch ( controlState & (TDC_UP|TDC_DOWN) ) { case TDC_UP: desiredSpeed = m_maxForwardSpeed; break; case TDC_DOWN: desiredSpeed = m_maxBackwardSpeed; break; default: return;//do nothing } //find current speed in forward direction b2Vec2 currentForwardNormal = m_body->GetWorldVector( b2Vec2(0,1) ); float currentSpeed = b2Dot( getForwardVelocity(), currentForwardNormal ); //apply necessary force float force = 0; if ( desiredSpeed > currentSpeed ) force = m_maxDriveForce; else if ( desiredSpeed < currentSpeed ) force = -m_maxDriveForce; else return; m_body->ApplyForce( m_currentTraction * force * currentForwardNormal, m_body->GetWorldCenter() ); } void updateTurn(int controlState) { float desiredTorque = 0; switch ( controlState & (TDC_LEFT|TDC_RIGHT) ) { case TDC_LEFT: desiredTorque = 15; break; case TDC_RIGHT: desiredTorque = -15; break; default: ;//nothing } m_body->ApplyTorque( desiredTorque ); } }; class TDCar { b2Body* m_body; std::vector m_tires; b2RevoluteJoint *flJoint, *frJoint; public: TDCar(b2World* world) { //create car body b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; m_body = world->CreateBody(&bodyDef); m_body->SetAngularDamping(3); b2Vec2 vertices[8]; vertices[0].Set( 1.5, 0); vertices[1].Set( 3, 2.5); vertices[2].Set( 2.8, 5.5); vertices[3].Set( 1, 10); vertices[4].Set( -1, 10); vertices[5].Set(-2.8, 5.5); vertices[6].Set( -3, 2.5); vertices[7].Set(-1.5, 0); b2PolygonShape polygonShape; polygonShape.Set( vertices, 8 ); b2Fixture* fixture = m_body->CreateFixture(&polygonShape, 0.1f);//shape, density //prepare common joint parameters b2RevoluteJointDef jointDef; jointDef.bodyA = m_body; jointDef.enableLimit = true; jointDef.lowerAngle = 0; jointDef.upperAngle = 0; 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(); for (int i = 0; i < m_tires.size(); i++) m_tires[i]->updateDrive(controlState); //control steering float lockAngle = 35 * DEGTORAD; float turnSpeedPerSec = 160 * DEGTORAD;//from lock to lock in 0.5 sec float turnPerTimeStep = turnSpeedPerSec / 60.0f; float desiredAngle = 0; switch ( controlState & (TDC_LEFT|TDC_RIGHT) ) { case TDC_LEFT: desiredAngle = lockAngle; break; case TDC_RIGHT: desiredAngle = -lockAngle; break; default: ;//nothing } float angleNow = flJoint->GetJointAngle(); float angleToTurn = desiredAngle - angleNow; angleToTurn = b2Clamp( angleToTurn, -turnPerTimeStep, turnPerTimeStep ); float newAngle = angleNow + angleToTurn; flJoint->SetLimits( newAngle, newAngle ); frJoint->SetLimits( newAngle, newAngle ); } }; class MyDestructionListener : public b2DestructionListener { void SayGoodbye(b2Fixture* fixture) { if ( FixtureUserData* fud = (FixtureUserData*)fixture->GetUserData() ) delete fud; } //(unused but must implement all pure virtual functions) void SayGoodbye(b2Joint* joint) {} }; class iforce2d_TopdownCar : public Test { public: iforce2d_TopdownCar() { m_world->SetGravity( b2Vec2(0,0) ); m_world->SetDestructionListener(&m_destructionListener); //set up ground areas { b2BodyDef bodyDef; m_groundBody = m_world->CreateBody( &bodyDef ); b2PolygonShape polygonShape; b2FixtureDef fixtureDef; fixtureDef.shape = &polygonShape; fixtureDef.isSensor = true; polygonShape.SetAsBox( 9, 7, b2Vec2(-10,15), 20*DEGTORAD ); b2Fixture* groundAreaFixture = m_groundBody->CreateFixture(&fixtureDef); groundAreaFixture->SetUserData( new GroundAreaFUD( 0.5f, false ) ); polygonShape.SetAsBox( 9, 5, b2Vec2(5,20), -40*DEGTORAD ); groundAreaFixture = m_groundBody->CreateFixture(&fixtureDef); groundAreaFixture->SetUserData( new GroundAreaFUD( 0.2f, false ) ); } //m_tire = new TDTire(m_world); //m_tire->setCharacteristics(100, -20, 150); m_car = new TDCar(m_world); m_controlState = 0; } ~iforce2d_TopdownCar() { //delete m_tire; delete m_car; m_world->DestroyBody( m_groundBody ); } void Keyboard(unsigned char key) { switch (key) { case 'a' : m_controlState |= TDC_LEFT; break; case 'd' : m_controlState |= TDC_RIGHT; break; case 'w' : m_controlState |= TDC_UP; break; case 's' : m_controlState |= TDC_DOWN; break; default: Test::Keyboard(key); } } void KeyboardUp(unsigned char key) { switch (key) { case 'a' : m_controlState &= ~TDC_LEFT; break; case 'd' : m_controlState &= ~TDC_RIGHT; break; case 'w' : m_controlState &= ~TDC_UP; break; case 's' : m_controlState &= ~TDC_DOWN; break; default: Test::Keyboard(key); } } void handleContact(b2Contact* contact, bool began) { b2Fixture* a = contact->GetFixtureA(); b2Fixture* b = contact->GetFixtureB(); FixtureUserData* fudA = (FixtureUserData*)a->GetUserData(); FixtureUserData* fudB = (FixtureUserData*)b->GetUserData(); if ( !fudA || !fudB ) return; if ( fudA->getType() == FUD_CAR_TIRE || fudB->getType() == FUD_GROUND_AREA ) tire_vs_groundArea(a, b, began); else if ( fudA->getType() == FUD_GROUND_AREA || fudB->getType() == FUD_CAR_TIRE ) tire_vs_groundArea(b, a, began); } void BeginContact(b2Contact* contact) { handleContact(contact, true); } void EndContact(b2Contact* contact) { handleContact(contact, false); } void tire_vs_groundArea(b2Fixture* tireFixture, b2Fixture* groundAreaFixture, bool began) { TDTire* tire = (TDTire*)tireFixture->GetBody()->GetUserData(); GroundAreaFUD* gaFud = (GroundAreaFUD*)groundAreaFixture->GetUserData(); if ( began ) tire->addGroundArea( gaFud ); else tire->removeGroundArea( gaFud ); } void Step(Settings* settings) { /*m_tire->updateFriction(); m_tire->updateDrive(m_controlState); m_tire->updateTurn(m_controlState);*/ m_car->update(m_controlState); Test::Step(settings); //show some useful info m_debugDraw.DrawString(5, m_textLine, "Press w/a/s/d to control the car"); m_textLine += 15; //m_debugDraw.DrawString(5, m_textLine, "Tire traction: %.2f", m_tire->m_currentTraction); //m_textLine += 15; } static Test* Create() { return new iforce2d_TopdownCar; } int m_controlState; MyDestructionListener m_destructionListener; b2Body* m_groundBody; //TDTire* m_tire; TDCar* m_car; }; #endif

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java 复制Map对象(深拷贝与浅拷贝)
java复制Map对象(深拷贝与浅拷贝)CreationTime2018年6月4日10点00分Author:Marydon1.深拷贝与浅拷贝  浅拷贝:只复制对象的引用,两个引用仍然指向同一个对象
小尉迟 小尉迟
1年前
Mac上拷贝和复制有什么区别?
在Mac上,使用复制和拷贝时,都会创建一个新的条目,并且该条目与原始数据相同。但是这两者有什么区别?你知道吗?1、内容不同复制是直接生成一个一样的文件拷贝是复制内容,把它放到剪贴板上,但是还没有进行粘贴的内容2、位置不同复制的内容位置就在当下的目录里拷贝的
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
RAC环境单实例启动数据库收到ORA
     在RAC环境中,如果你在没有启动节点的集群服务的情况下单实例启动数据库,将收到类似如下的报错:\oracle@rhel1u01\$sqlSQL\Plus:Release10.2.0.5.0ProductiononTueApr215:00:272013Copyright(
Stella981 Stella981
3年前
Python+Selenium自动化篇
本篇文字主要学习selenium定位页面元素的集中方法,以百度首页为例子。0.元素定位方法主要有:id定位:find\_element\_by\_id('')name定位:find\_element\_by\_name('')class定位:find\_element\_by\_class\_name(''
Wesley13 Wesley13
3年前
Java爬虫之JSoup使用教程
title:Java爬虫之JSoup使用教程date:201812248:00:000800update:201812248:00:000800author:mecover:https://imgblog.csdnimg.cn/20181224144920712(https://www.oschin
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
Java多线程导致的的一个事物性问题
业务场景我们现在有一个类似于文件上传的功能,各个子站点接受业务,业务上传文件,各个子站点的文件需要提交到总站点保存,文件是按批次提交到总站点的,也就是说,一个批次下面约有几百个文件。      考虑到白天提交这么多文件会影响到子站点其他系统带宽,我们将分站点的文件提交到总站点这个操作过程独立出来,放到晚上来做,具体时间是晚上7:00到早上7:00。
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k