当前位置 : 主页 > 手机开发 > 其它 >

用Cocos2d-x-3.0及Box2d预测物体弹道轨迹

来源:互联网 收集:自由互联 发布时间:2021-06-13
英文论坛原帖: http://discuss.cocos2d-x.org/t/cocos3-0-tutorial-predict-a-trajectory-with-cocos2d-x-and-box2d/13493 如何使用cocos2d-x和Box2d来预测物体弹道轨迹 本部分内容设定了隐藏,需要回复后才能看到 创

英文论坛原帖:
http://discuss.cocos2d-x.org/t/cocos3-0-tutorial-predict-a-trajectory-with-cocos2d-x-and-box2d/13493

如何使用cocos2d-x和Box2d来预测物体弹道轨迹

 

 


本部分内容设定了隐藏,需要回复后才能看到

创建一个新项目

用这些代码创建一个新cocos2d-x项目:
cocos new MyGame -p com.MyCompany.MyGame -l cpp -d ~/MyCompany

关于创建新项目的细节请查阅下面的网页:
http://cocos2d-x.org/wiki/How_to_Start_A_New_Cocos2D-X_Game

注意:当你使用cocos-console新创建一个项目时,文件夹cocos2d会在你的项目文件夹里生成。但因为它太大了,所以我并没有将它上传。

素材资源
下载ball.png 和 dot.png 并复制进Resources文件夹。



  

Linux版本

打开你的项目文件夹并且在文件夹CMakeLists.txt第161行添加box2d(在on target link libraries那一部分)

box2d
结果看起来就像是:
target_link_libraries(${APP_NAME}
      ui
      network
      storage
      spine
      cocostudio
      cocosbuilder
      extensions
      audio
      cocos2d
      box2d
  )
Windows版本

打开你的proj.win32 .SLN 文件并添加Box2D文件依赖

右键点击解决方案Solution而不是项目名称然后点击添加add—>现有项目add exist project,搜索外部资源“BOX2D“并添加

现在右键点击解决方案,点击属性,选择项目依赖项Project Dependencies并勾取libBox2D使其加入编译

现在右键点击你的项目名称(解决方案的里面),并选择引用reference,在底部点击添加新引用ADD NEW REFERENCE然后勾选libBox2D并点击确定OK。

点击确定OK关闭窗口。

是时候敲键盘写代码了:

在HelloWorldScene.h里,在第四行也就是#include "cocos2d.h"的下面添加:


? 1 USING_NS_CC;

在public的下面添加:

? 1 2 3 bool onTouchBegan(Touch* touch, Event* event); void onTouchMoved(Touch* touch, Event* event); void onTouchEnded(Touch* touch, Event* event);

在INIT主要函数中添加鼠标监听事件(提示:是在HelloWorldScene.cpp)

? 1 2 3 4 5 6 7 8 9 10 //SET MOUSE LISTENER auto listener = EventListenerTouchOneByOne::create(); listener->setSwallowTouches( true );   listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this ); listener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this ); listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this );   _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this ); //END MOUSE LISTENER

在CPP主文件里(HelloWorldScene.cpp)添加下列函数:

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 bool HelloWorld::onTouchBegan(Touch* touch, Event* event) {        return true ; }   void HelloWorld::onTouchMoved(Touch* touch, Event* event) {     }   void HelloWorld::onTouchEnded(Touch* touch, Event* event) {   }

在INIT函数中添加:

? 1 2 3 4 5 6 7 8 9 10 11 //CREATE A BALL dragOffsetStartX = 0;     dragOffsetEndX = 0;     dragOffsetStartY = 0;     dragOffsetEndY = 0;     existBall= false ;     ballX = 500; ballY = 200;     ball =Sprite::create( "ball.png" ); ball->setPosition(CCPoint(ballX,ballY)); this ->addChild(ball);

在头文件(HelloWorldScene.h)中添加:

? 1 2 3 4 5 6 7 8 9 10 11 12 Sprite *ball; bool existBall; float ballX; float ballY;     int dragOffsetStartX; int dragOffsetEndX; int dragOffsetStartY; int dragOffsetEndY;     b2Body *ballBody;     b2CircleShape ballShape; b2BodyDef ballBodyDef;   void defineBall();

添加物理引擎

在头文件中添加box2d程序库:

? 1 #include <Box2D/Box2D.h>

添加b2ContactListener
更改:

? 1 class HelloWorld : public cocos2d::Layer
成:
? 1 class HelloWorld : public cocos2d::Layer, public b2ContactListener
然后添加:
? 1 2 b2World *world; float deltaTime;
在INIT函数里添加下列代码:
? 1 2 b2Vec2 gravity = b2Vec2(0.0f, -10.0f); world = new b2World(gravity);    
参数-10.0f指出了在y轴上的重力加速度:
现在我们需要添加一个SCALE_RATIO。将其定义在文件顶端:
? 1 #define SCALE_RATIO 32.0

SCALE_RATIO指出了将单位:像素转换成单位:米的值,因为BOX2D使用的计量单位是米。

在主文件(HelloWorldScene.cpp)中添加:

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void HelloWorld::defineBall() {      ballShape.m_radius = 45 / SCALE_RATIO;      b2FixtureDef ballFixture;      ballFixture.density=10;      ballFixture.friction=0.8;      ballFixture.restitution=0.6;      ballFixture.shape=&ballShape;        ballBodyDef.type= b2_dynamicBody;      ballBodyDef.userData=ball;        ballBodyDef.position.Set(ball->getPosition().x/SCALE_RATIO,ball->getPosition().y/SCALE_RATIO);        ballBody = world->CreateBody(&ballBodyDef);      ballBody->CreateFixture(&ballFixture);      ballBody->SetGravityScale(10); }    

在添加球精灵this->addChild(ball)后面引用函数:

? 1 HelloWorld::defineBall();


添加一个时间来更新physics

在头文件里添加:
? 1 void update( float dt);

在主文件cpp中添加:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 //Simulate Physics void HelloWorld::update( float dt){     int positionIterations = 10;       int velocityIterations = 10;       deltaTime = dt;     world->Step(dt, velocityIterations, positionIterations);         for (b2Body *body = world->GetBodyList(); body != NULL; body = body->GetNext())         if (body->GetUserData())       {           CCSprite *sprite = (CCSprite *) body->GetUserData();           sprite->setPosition(ccp(body->GetPosition().x * SCALE_RATIO,body->GetPosition().y * SCALE_RATIO));           sprite->setRotation(-1 * CC_RADIANS_TO_DEGREES(body->GetAngle()));             }        world->ClearForces();      world->DrawDebugData();         }  

在init函数中引用scheduleUpdate:

? 1 scheduleUpdate();

如果这个时候你尝试着运行你的应用程序,你会看到掉了个球。

现在添加一堵墙,是我们的球能够反弹。

在头文件中添加:
? 1 void addWall( float w, float h, float px, float py);

在主文件夹cpp中添加:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void HelloWorld::addWall( float w, float h, float px, float py) {        b2PolygonShape floorShape;        floorShape.SetAsBox(w/ SCALE_RATIO,h/ SCALE_RATIO);      b2FixtureDef floorFixture;      floorFixture.density=0;      floorFixture.friction=10;      floorFixture.restitution=0.5;      floorFixture.shape=&floorShape;      b2BodyDef floorBodyDef;        floorBodyDef.position.Set(px/ SCALE_RATIO,py/ SCALE_RATIO);      b2Body *floorBody = world->CreateBody(&floorBodyDef);        floorBody->CreateFixture(&floorFixture);   }      

并且在INIT文件主函数里添加:

? 1 2 3 addWall(visibleSize.width ,10,(visibleSize.width / 2) ,0); //CEIL addWall(10 ,visibleSize.height ,0,(visibleSize.height / 2) ); //LEFT addWall(10 ,visibleSize.height ,visibleSize.width,(visibleSize.height / 2) ); //RIGHT

为弹道轨迹添加指示点

在头文件里添加:
? 1 Sprite *points[32];
并且在INI主函数里添加:
? 1 2 3 4 for ( int i = 1 ; i <= 31; i++){      points<i> =CCSprite::create( "dot.png" );      this ->addChild(points<i>); }</i></i>

添加控制

删除掉原先在INIT方法里的HelloWorld::defineBall();

现在在方法 onTouchBegan里面添加方法:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 dragOffsetStartX = touch->getLocation().x; dragOffsetStartY = touch->getLocation().y;   CCPoint touchLocation = touch->getLocation();   ballX = touchLocation.x; ballY = touchLocation.y;   if (existBall){         world->DestroyBody(ballBody); }   ball->setPosition(ccp(ballX ,ballY));

在onTouchMoved里面添加:

? 1 2 3 4 5 6 7 8 9 CCPoint touchLocation = touch->getLocation();   dragOffsetEndX = touchLocation.x; dragOffsetEndY = touchLocation.y;   float dragDistanceX = dragOffsetStartX - dragOffsetEndX; float dragDistanceY = dragOffsetStartY - dragOffsetEndY;   HelloWorld::simulateTrajectory(b2Vec2((dragDistanceX )/SCALE_RATIO,(dragDistanceY )/SCALE_RATIO));


现在我们需要创建函数simulateTrajectory。

在头文件中添加:
? 1 void simulateTrajectory(b2Vec2 coord);

在cpp文件中添加
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void HelloWorld::simulateTrajectory(b2Vec2 coord){        //define ball physicis      HelloWorld::defineBall();        ballBody->SetLinearVelocity(b2Vec2(coord.x,coord.y));      for ( int i = 1; i <= 31; i++){      world->Step(deltaTime,10,10);      points<i>->setPosition(CCPoint(ballBody->GetPosition().x*SCALE_RATIO,ballBody->GetPosition().y*SCALE_RATIO));      world->ClearForces();        }        world->DestroyBody(ballBody); }</i>

如果你试着运行代码,你会得到个球,在屏幕中心的球,如果你试着拖拽鼠标,你会看到从球里伸展出弹道轨迹。

投球
现在我们需要添加onTouchEnded
? 1      existBall = true ;

? 1 2 3 4 5 6 7 8 9 10 11 HelloWorld::defineBall();   CCPoint touchLocation = touch->getLocation();   dragOffsetEndX = touchLocation.x; dragOffsetEndY = touchLocation.y;   float dragDistanceX = dragOffsetStartX - dragOffsetEndX; float dragDistanceY = dragOffsetStartY - dragOffsetEndY;   ballBody->SetLinearVelocity(b2Vec2((dragDistanceX)/SCALE_RATIO,(dragDistanceY)/SCALE_RATIO));  

添加简单的投掷力量
为了添加投掷力量仅仅只需添加一个乘法系数,将其添加进头文件里:
? 1 float powerMultiplier;
设置创建球时的力量大小:

? 1 powerMultiplier = 10;

然后把下列行:
? 1 HelloWorld::simulateTrajectory(b2Vec2((dragDistanceX )/SCALE_RATIO,(dragDistanceY )/SCALE_RATIO));
改为:
? 1 HelloWorld::simulateTrajectory(b2Vec2((dragDistanceX * powerMultiplier)/SCALE_RATIO,(dragDistanceY * powerMultiplier)/SCALE_RATIO));
还有行:
? 1 ballBody->SetLinearVelocity(b2Vec2((dragDistanceX)/SCALE_RATIO,(dragDistanceY)/SCALE_RATIO));
改为:
? 1 ballBody->SetLinearVelocity(b2Vec2((dragDistanceX * powerMultiplier)/SCALE_RATIO,(dragDistanceY * powerMultiplier)/SCALE_RATIO));
网友评论