首页 > 代码库 > coco2d-x3.2使用物理引擎Physicals制作Breakout游戏

coco2d-x3.2使用物理引擎Physicals制作Breakout游戏

HelloWorldScene.h

 1 #ifndef __HELLOWORLD_SCENE_H__ 2 #define __HELLOWORLD_SCENE_H__ 3  4 #include "cocos2d.h" 5 #include "GameOverScene.h" 6  7 USING_NS_CC; 8  9 class HelloWorld : public cocos2d::Layer10 {11 public:12     static cocos2d::Scene* createScene();13     virtual void onEnter() override;14     virtual bool init();  15     16     CREATE_FUNC(HelloWorld);17     18     Sprite* ball;//弹射的球19     Sprite* paddle;//玩家控制的可移动碰撞块20     Sprite* edgeSp;//碰撞盒子21     22     PhysicsWorld* m_world;23     24     void setPhyWorld(PhysicsWorld* world){ m_world = world; };25     void tick(float dt);26     27     bool onTouchBegan(Touch* touch, Event* event);28     void onTouchMoved(Touch* touch, Event* event);29     void onTouchEnded(Touch* touch, Event* event);30     31     bool onContactBegin(const PhysicsContact& contact);32     33 };34 35 #endif

HelloWorldScene.cpp

  1 #include "HelloWorldScene.h"  2   3 USING_NS_CC;  4   5 Scene* HelloWorld::createScene()  6 {  7     auto scene = Scene::createWithPhysics();  8     //设置Debug模式,你会看到物体的表面被线条包围,主要为了在调试中更容易地观察  9     scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL); 10      11     Vect gravity(0.0f, 0.0f); 12     //设置重力 13     scene->getPhysicsWorld()->setGravity(gravity); 14      15     auto layer = HelloWorld::create(); 16      17     layer->setPhyWorld(scene->getPhysicsWorld()); 18      19     scene->addChild(layer); 20      21     return scene; 22      23 } 24  25 /** 26 PHYSICSBODY_MATERIAL_DEFAULT常量是默认材质,材质是由结构体PhysicsMaterial定义的,结构体PhysicsMaterial成员有:density(密度)、friction(磨擦系数)和restitution(弹性系数)。 27 密度可以用来计算物体的质量,密度可以为零或者为正数。 28 摩擦系数经常会设置在0.0~1.0之间,0.0表示没有摩擦力,1.0会产生强摩擦。 29 弹性系数的值通常设置到0.0~1.0之间,0.0表示物体不会弹起,1.0表示物体会完全反弹,即称为弹性碰撞。 30  **/ 31 bool HelloWorld::init() 32 { 33     if ( !Layer::init() ) 34     { 35         return false; 36     } 37      38     auto visibleSize = Director::getInstance()->getVisibleSize(); 39     auto origin = Director::getInstance()->getVisibleOrigin(); 40      41     edgeSp = Sprite::create(); 42     //创建一个盒子,用来碰撞 43     //矩形的大小、设置材质、设置边的宽度 44     auto boundBody = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3); 45     //设置物体的弹性 0表示完全不反弹。1完全反弹 46     boundBody->getShape(0)->setRestitution(1.0f); 47     //设置摩擦力 48     boundBody->getShape(0)->setFriction(0.0f); 49     //设置密度 50     boundBody->getShape(0)->setDensity(1.0f); 51     edgeSp->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2)); 52     edgeSp->setPhysicsBody(boundBody); 53     this->addChild(edgeSp); 54     edgeSp->setTag(0); 55      56     //CategoryBitmask, 默认值为 0xFFFFFFFF 57     //ContactTestBitmask, 默认值为 0x00000000 58     //CollisionBitmask, 默认值为 0xFFFFFFFF 59     //如果采用默认的数值,碰撞是可以检测的,但是碰撞事件是不会发出的,so我们的onContactBegin就被屏蔽了 60     //果想我们的两个物体即发生碰撞又可以检测到,不让它们&的值不等于0就ok了 61     edgeSp->getPhysicsBody()->setCategoryBitmask(0x01); 62     edgeSp->getPhysicsBody()->setContactTestBitmask(0x01); 63     edgeSp->getPhysicsBody()->setCollisionBitmask(0x01); 64      65     ball = Sprite::create("Ball.png", Rect(0, 0, 52, 52)); 66     ball->setPosition(100, 100); 67     //创建物体,并且物体的形状为圆形,第一参数为半径,第二个参数为物体材质 68     //第三个参数为边的厚度,就是在Debug模式下看到的物体外面线条的厚度,默认为0 69     auto ballBody = PhysicsBody::createCircle(ball->getContentSize().width / 2.); 70     ballBody->getShape(0)->setRestitution(1.0f); 71     ballBody->getShape(0)->setFriction(0.0f); 72     ballBody->getShape(0)->setDensity(1.0f); 73     ballBody->setGravityEnable(false); 74     Vect force = Vect(1000000.0f, 1000000.0f); 75     //是对物体施加一个冲量 76     ballBody->applyImpulse(force); 77     ball->setPhysicsBody(ballBody); 78     ball->setTag(1); 79     this->addChild(ball); 80      81     ball->getPhysicsBody()->setCategoryBitmask(0x01); 82     ball->getPhysicsBody()->setContactTestBitmask(0x01); 83     ball->getPhysicsBody()->setCollisionBitmask(0x01); 84      85     paddle = Sprite::create("Paddle.png"); 86     //创建物体,并且物体的形状为矩形 87     auto paddleBody = PhysicsBody::createBox(paddle->getContentSize(), PHYSICSBODY_MATERIAL_DEFAULT); 88     paddleBody->getShape(0)->setRestitution(1.0f); 89     paddleBody->getShape(0)->setFriction(0.0f); 90     paddleBody->getShape(0)->setDensity(10.0f); 91     paddleBody->setGravityEnable(false); 92     paddleBody->setDynamic(false); 93     paddle->setPosition(visibleSize.width / 2, 50); 94     paddle->setPhysicsBody(paddleBody); 95     paddle->setTag(2); 96     this->addChild(paddle); 97      98     for (int i = 0; i < 4; i++) { 99         100         static int padding = 100;101         102         // 创建方块并添加到层中103         auto block = Sprite::create("blocks.png");104         auto blockBody = PhysicsBody::createBox(block->getContentSize(), PHYSICSBODY_MATERIAL_DEFAULT);105         blockBody->getShape(0)->setDensity(10.0f);106         blockBody->getShape(0)->setFriction(0.0f);107         blockBody->getShape(0)->setRestitution(1.f);108         blockBody->setDynamic(false);109         int xOffset = padding + block->getContentSize().width / 2 +110         ((block->getContentSize().width + padding)*i);111         block->setPosition(xOffset, 450);112         block->setPhysicsBody(blockBody);113         block->setTag(3);114         this->addChild(block);115         116         block->getPhysicsBody()->setCategoryBitmask(0x01);117         block->getPhysicsBody()->setContactTestBitmask(0x01);118         block->getPhysicsBody()->setCollisionBitmask(0x01);119     }120     121     this->schedule(schedule_selector(HelloWorld::tick),0);122     123     return true;124 }125 126 void HelloWorld::onTouchMoved(Touch* touch, Event* event)127 {128     Point touchLocation = this->convertToWorldSpace(this->convertTouchToNodeSpace(touch));129     paddle->setPositionX(touchLocation.x);130 }131 132 bool HelloWorld::onTouchBegan(Touch* touch, Event* event)133 {134     return true;135 }136 137 void HelloWorld::onTouchEnded(Touch* touch, Event* event)138 {139     140 }141 142 bool HelloWorld::onContactBegin(const PhysicsContact& contact)143 {144     if (ball->getPositionY() <= 50)145     {146         auto gameOverScene = GameOverScene::create();147         gameOverScene->getLayer()->getLabel()->setString("You Lose!");148         Director::getInstance()->replaceScene(gameOverScene);149     }150     151     auto spriteA = (Sprite*)contact.getShapeA()->getBody()->getNode();152     auto spriteB = (Sprite*)contact.getShapeB()->getBody()->getNode();153     int tagA = spriteA->getTag();154     int tagB = spriteB->getTag();155     156     if (tagA == 3)157     {158         spriteA->removeFromParentAndCleanup(true);159     }160     161     if (tagB == 3)162     {163         spriteB->removeFromParentAndCleanup(true);164     }165     166     return true;167 }168 169 void HelloWorld::tick(float dt)170 {171     bool isWin = true;172     Vector<PhysicsBody*> bodies = m_world->getAllBodies();173     Vector<PhysicsBody*>::iterator iter;174     for (iter=bodies.begin();iter!=bodies.end();iter++) {175         if ((*iter)->getNode()->getTag() == 3)176         {177             isWin = false;178         }179     }180     181     if (isWin == true)182     {183         auto gameOverScene = GameOverScene::create();184         gameOverScene->getLayer()->getLabel()->setString("You Win!");185         Director::getInstance()->replaceScene(gameOverScene);186     }187 }188 189 void HelloWorld::onEnter()190 {191     Layer::onEnter();192     193     auto touchListener = EventListenerTouchOneByOne::create();194     touchListener->setSwallowTouches(true);195     196     touchListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);197     touchListener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);198     touchListener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);199     _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);200     201     //添加监听器202     auto contactListener = EventListenerPhysicsContact::create();203     //设置监听器的碰撞开始函数204     contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegin, this);205     206     //添加到事件分发器中207     _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);208     209 }

GameOverScene.h

 1 #ifndef __SampleGame1__GameOverScene__ 2 #define __SampleGame1__GameOverScene__ 3  4 #include "cocos2d.h" 5  6 class GameOverLayer : public cocos2d::LayerColor 7 { 8 public: 9     GameOverLayer():_label(NULL) {};10     virtual ~GameOverLayer();11     bool init();12     CREATE_FUNC(GameOverLayer);13     14     void gameOverDone();15     16     CC_SYNTHESIZE_READONLY(cocos2d::LabelTTF*, _label, Label);17 };18 19 class GameOverScene : public cocos2d::Scene20 {21 public:22     GameOverScene():_layer(NULL) {};23     ~GameOverScene();24     bool init();25     CREATE_FUNC(GameOverScene);26     27     CC_SYNTHESIZE_READONLY(GameOverLayer*, _layer, Layer);28 };29 30 #endif

GameOverScene.cpp

 1 #include "GameOverScene.h" 2 #include "HelloWorldScene.h" 3 USING_NS_CC; 4  5  6 bool GameOverScene::init() 7 { 8     if( Scene::init() ) 9     {10         this->_layer = GameOverLayer::create();11         this->_layer->retain();12         this->addChild(_layer);13         14         return true;15     }16     else17     {18         return false;19     }20 }21 22 GameOverScene::~GameOverScene()23 {24     if (_layer)25     {26         _layer->release();27         _layer = NULL;28     }29 }30 31 bool GameOverLayer::init()32 {33     if ( LayerColor::initWithColor( Color4B(255,255,255,255) ) )34     {35         auto winSize = Director::getInstance()->getWinSize();36         this->_label = LabelTTF::create("","Artial", 32);37         _label->retain();38         _label->setColor( Color3B(0, 0, 0) );39         _label->setPosition( Point(winSize.width/2, winSize.height/2) );40         this->addChild(_label);41         42         this->runAction( Sequence::create(43                                           DelayTime::create(3),44                                           CallFunc::create(CC_CALLBACK_0(GameOverLayer::gameOverDone, this)),45                                           NULL));46         47         return true;48     }49     else50     {51         return false;52     }53 }54 55 void GameOverLayer::gameOverDone()56 {57     Director::getInstance()->replaceScene( HelloWorld::createScene() );58 }59 60 GameOverLayer::~GameOverLayer()61 {62     if (_label)63     {64         _label->release();65         _label = NULL;66     }67 }

游戏中图片:

技术分享技术分享技术分享

游戏运行效果:

技术分享

coco2d-x3.2使用物理引擎Physicals制作Breakout游戏