chapter8 實驗手冊
《chapter8 實驗手冊》由會員分享,可在線閱讀,更多相關(guān)《chapter8 實驗手冊(14頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、第八章 碰撞檢測與運動模擬 基于Box2D的游戲?qū)嵗? (一)基礎知識 物理模擬、精靈的繪制與移動、觸摸事件的應用 (1) 繪制游戲界面 (2) 通過單點觸摸屏幕,球桿瞄準目標 (3) 設置能量條(觸屏檢測) (4) 球桿擊球 (5) 碰撞檢測(物理模擬) (二)游戲配置文件 游戲需要新建一個Config.h的頭文件,此文件用來定義游戲中需要的參數(shù)。 #include "cocos2d.h" USING_NS_CC; using namespace cocos2d; #define PTM_RATIO 32 // 定義32像素代表1米 static c
2、onst int SLIDER_BG_TAG = 1000; static const int SLIDER_TAG = 1001; static const int DASH_LINE_TAG = 1002; static const int MAIN_BILLIARDS_TAG = 1003; static const int AIM_ICON_TAG = 1004; static const int AIM_GAN_TAG = 1005; static const int MAX_SPEED = 2600; static const std::string ball
3、[5] = { "Chapter07/Ball/3.png", "Chapter07/Ball/4.png", "Chapter07/Ball/5.png", "Chapter07/Ball/6.png", "Chapter07/Ball/10.png" }; static const Vec2 ballPos[] = { Vec2(300,500), Vec2(500,300), Vec2(100,600), Vec2(600,100), Vec2(800,500) }; (三)物理場景的繪制 由PhysicsScene.h類實現(xiàn)
4、,這里具體給出其實現(xiàn),定義均在實現(xiàn)文件中實現(xiàn)了。 PhysicsScene.cpp #include "PhysicsScene.h" PhysicsScene::PhysicsScene(){} PhysicsScene::~PhysicsScene(){} bool PhysicsScene::init() { if (!Layer::init()) { return false; } // physics scene Size visibleSize = Director::getInstance()->getVisibleSize();
5、 Vec2 origin = Director::getInstance()->getVisibleOrigin(); // 定義世界的邊界 auto body = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT,5.0f); auto edgeNode = Node::create(); edgeNode->setPosition(Vec2(visib
6、leSize.width/2,visibleSize.height/2)); edgeNode->setPhysicsBody(body); this->addChild(edgeNode); // 屏幕觸摸 auto listener = EventListenerTouchOneByOne::create(); listener->onTouchBegan = CC_CALLBA
7、CK_2(PhysicsScene::onTouchBegan, this); Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this); return true; } Scene* PhysicsScene::createScene() { // 創(chuàng)建物理世界 auto scene = Scene::createWithPhysics(); // 繪制調(diào)試遮罩 // scene->getPhysicsWor
8、ld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL); auto layer = PhysicsScene::create(); scene->addChild(layer); return scene; } bool PhysicsScene::onTouchBegan(Touch *touch, Event *unused_event) { Vec2 location = touch->getLocation(); addNewSpriteAtPosition(location); return fal
9、se; } void PhysicsScene::addNewSpriteAtPosition(Vec2 p) { int picpath = rand() % 11; auto sp = Sprite::create(StringUtils::format("Chapter07/Ball/%d.png",picpath)); sp->setTag(1); auto body = PhysicsBody::createCircle(sp->getContentSize().width / 2); // auto body = PhysicsBody::cre
10、ateBox(sp->getContentSize()); sp->setPhysicsBody(body); sp->setPosition(p); this->addChild(sp); } (四)物理物體的封裝,桌球的實現(xiàn) 由BilliardSprite.h類實現(xiàn),這里具體給出其實現(xiàn),定義均在實現(xiàn)文件中實現(xiàn)了。 BilliardSprite.cpp #include "BilliardSprite.h" BilliardSprite::BilliardSprite(){} void BilliardSpri
11、te::update(float t) { _sprite->setPosition(Vec2( _body->GetPosition().x * PTM_RATIO, _body->GetPosition().y * PTM_RATIO)); _sprite->setRotation(-1 * CC_RADIANS_TO_DEGREES(_body->GetAngle())); } BilliardSprite::~BilliardSprite() { if (_name != NULL) { _name = NULL; } } Bi
12、lliardSprite* BilliardSprite::create(char* name, bool isStatic, bool isBullet, b2World* world, std::string picPath, Vec2 position, float density /*= 1.0*/, float friction /*= 0.1*/, float restitution /*= 0.78 */) { BilliardSprite *pRet = new(std::nothrow) B
13、illiardSprite(); if (pRet && pRet->init(name, isStatic, isBullet, world, picPath, position, density, friction, restitution)) { pRet->autorelease(); return pRet; } else { delete pRet; pRet = NULL; return NULL; } } bool BilliardSprite::init(char* name, bool isStatic,
14、 bool isBullet, b2World* world, std::string picPath, Vec2 position, float density /*= 1.0*/, float friction /*= 0.1*/, float restitution /*= 0.78*/) { if (!Sprite::init()) { return false; } _name = name; // 創(chuàng)建精靈 _sprite = Sprite::create(picPath); th
15、is->addChild(_sprite); // bodyDef b2BodyDef bodyDef; if (!isStatic) { bodyDef.type = b2_dynamicBody; } if (isBullet) { bodyDef.bullet = true; } bodyDef.position.Set(position.x / PTM_RATIO,position.y / PTM_RATIO); // 創(chuàng)建body _body = world->CreateBody(&bodyDef); _bo
16、dy->SetUserData(this); b2CircleShape circle; circle.m_radius = (_sprite->getContentSize().width / 2 ) / PTM_RATIO; if (isStatic) { // 靜態(tài) _body->CreateFixture(&circle,0.0f); } else { // 動態(tài) b2FixtureDef fixtureDef; fixtureDef.shape = &circle; fixtureDef.density = densit
17、y; fixtureDef.friction = friction; fixtureDef.restitution = restitution; _body->CreateFixture(&fixtureDef); } this->scheduleUpdate(); return true; } (五)碰撞監(jiān)聽 由GameContactListener.h類實現(xiàn),這里具體給出其實現(xiàn),定義均在實現(xiàn)文件中實現(xiàn)了。 GameContactListener.cpp #include "GameContactListener.h" #include "B
18、illiardSprite.h"
GameContactListener::GameContactListener(){}
GameContactListener::~GameContactListener(){}
void GameContactListener::BeginContact(b2Contact*contact)
{
CCLOG("%s",static_cast
19、ic_cast
20、 void GameContactListener::PostSolve(b2Contact* contact,const b2ContactImpulse* impulse) { // handle post-solve event } void GameContactListener::deleteBody(){} (六)初始化物理世界 PhysicsBox2dScene.cpp文件中 void PhysicsBox2dScene::initPhysics() { Size s = Director::getInstance()->getVisibleS
21、ize(); _ContactListener = new GameContactListener(); // gravity b2Vec2 gravity; gravity.Set(0.0f, 0.0f); // create world _world = new b2World(gravity); _world->SetContactListener(_ContactListener); // 碰撞 // allow sleep _world->SetAllowSleeping(true); // physics test 避
22、免碰撞檢測不連續(xù)產(chǎn)生碰撞穿透 _world->SetContinuousPhysics(true); // ground b2BodyDef groundBodyDef; // left down groundBodyDef.position.Set(0, 0); // create ground b2Body* groundBody = _world->CreateBody(&groundBodyDef); groundBody->SetUserData("boundary"); // shape b2EdgeShape groundB
23、ox; // down groundBox.Set(b2Vec2(0,0),b2Vec2(s.width/PTM_RATIO,0)); groundBody->CreateFixture(&groundBox,0); // up groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO)); groundBody->CreateFixture(&groundBox,0); // left groundBox.Set(b2Vec2
24、(0,s.height/PTM_RATIO),b2Vec2(0,0)); groundBody->CreateFixture(&groundBox,0); // right groundBox.Set(b2Vec2((s.width - 60)/PTM_RATIO,s.height/PTM_RATIO),b2Vec2((s.width - 60)/PTM_RATIO,0)); groundBody->CreateFixture(&groundBox,0); } (七)初始化場景 初始化: PhysicsBox2dScene::PhysicsBox2dScene(
25、) { _world = NULL; _aim = false; _angle = 0.0f; _curPower = 0.0f; _powerEnd = false; _sliderSpeed = 0.0f; _aimPos = Vec2(-1,-1); _canAim = true; } 在PhysicsBox2dScene.cpp文件中init函數(shù)中初始化場景: 1、繪制能量條 // slider bg auto slider_bg = Sprite::create("Chapter07/slider/bg-f.png"); sli
26、der_bg->setPosition(Vec2(visibleSize.width - 30, visibleSize.height/2)); this->addChild(slider_bg, 2, SLIDER_BG_TAG); // init power slider rect _powerRect = Rect(visibleSize.width - 58, 0, 58,visibleSize.height); // slider auto slider = Sprite::create("Chapter07/slider/fg-f.png")
27、; this->addChild(slider, 3, SLIDER_TAG); slider->setVisible(false); // slider left auto slider_left = Sprite::create("Chapter07/slider/bg-left.png"); slider_left->setPosition(Vec2(visibleSize.width - 60, visibleSize.height/2)); this->addChild(slider_left, 2); 2、繪制非物理世界邊界 // slider
28、 left auto slider_left = Sprite::create("Chapter07/slider/bg-left.png"); slider_left->setPosition(Vec2(visibleSize.width - 60, visibleSize.height/2)); this->addChild(slider_left, 2); // boundary left auto boundary_left = Sprite::create("Chapter07/slider/bg-left.png"); boundary_left->se
29、tPosition(Vec2(3, visibleSize.height/2)); this->addChild(boundary_left); // boundary right auto boundary_right = Sprite::create("Chapter07/slider/bg-left.png"); boundary_right->setPosition(Vec2(visibleSize.width - 2, visibleSize.height/2)); this->addChild(boundary_right, 2); 3、初始化瞄準區(qū)域
30、(物理世界大?。? // init aim rect _aimRect = Rect(0, 0, visibleSize.width - 60, visibleSize.height); 4、初始化物理世界 // init physics world this->initPhysics(); 5、初始化桌球 // 白球 _mainBilliards = BilliardSprite::create("main", false, true, _world, "Chapter07/Ball/8.png", Vec2(200,visibleSize.height/2));
31、 this->addChild(_mainBilliards, 10, MAIN_BILLIARDS_TAG); for (int i=0;i<5;i++) { auto ballSprite = BilliardSprite::create("ball",false, false, _world, ball[i], ballPos[i]); this->addChild(ballSprite); } 6、初始化添加瞄準線、瞄準圖片和球桿 // dash line auto dashLine = Sprite::create("Chapter07/aim/do
32、t_line.png"); this->addChild(dashLine, 2, DASH_LINE_TAG); dashLine->setAnchorPoint(Vec2(0.5, 0)); dashLine->setVisible(false); // aim icon auto aim_icon = Sprite::create("Chapter07/aim/aim.png"); this->addChild(aim_icon, 10, AIM_ICON_TAG); aim_icon->setScale(0.4f); aim_icon->setVis
33、ible(false); // 球桿 auto aim_gan = Sprite::create("Chapter07/aim/gan-f.png"); this->addChild(aim_gan, 10, AIM_GAN_TAG); aim_gan->setAnchorPoint(Vec2(0.5, 0)); aim_gan->setScale(0.6f); aim_gan->setVisible(false); (八)能量條的控制 1、能量條區(qū)域觸摸響應事件的設置 設置觸摸開始時響應的事件: bool PhysicsBox2dScene::on
34、TouchBegan(Touch *touch, Event *unused_event) { if (_aimRect.containsPoint(touch->getLocation()) && _canAim) { _aim = true; auto start_p = changePos(_mainBilliards->getPosition()); auto end_p = touch->getLocation(); updateLine(start_p, end_p); } _powerEnd = false; r
35、eturn true; } 設置觸摸移動時響應的事件,分為兩種情況,一種是當觸摸移動的區(qū)域的是非物理世界時,改變的是能量條的狀態(tài);另一種情況是當觸摸移動的區(qū)域的是物理世界區(qū)域時,改變的是球桿瞄準的方向: void PhysicsBox2dScene::onTouchMoved(Touch *touch, Event *unused_event) { auto slider_bg = (Sprite*)getChildByTag(SLIDER_BG_TAG); if (_powerRect.containsPoint(touch->getStartLocation()) &&
36、 _aim) { _curPower = touch->getStartLocation().y - touch->getLocation().y; if (_curPower<0) { _curPower = 0; } else if( _curPower > slider_bg->getContentSize().height ) { _curPower = slider_bg->getContentSize().height; } updatePowerSlider(_curPower); } else if (_
37、aimRect.containsPoint(touch->getStartLocation()) && _canAim) { if (_aimRect.containsPoint(touch->getLocation())) { auto start_p = changePos(_mainBilliards->getPosition()); auto end_p = touch->getLocation(); updateLine(start_p, end_p); } } } 設置觸摸結(jié)束時響應的事件: void PhysicsBox
38、2dScene::onTouchEnded(Touch *touch, Event *unused_event) { if (_powerRect.containsPoint(touch->getLocation()) && _aim) { auto slider_bg = (Sprite*)getChildByTag(SLIDER_BG_TAG); _sliderSpeed = _curPower / slider_bg->getContentSize().height * 50.0f; // 擊球 auto start_p = changePos(_m
39、ainBilliards->getPosition()); auto end_p = _aimPos; auto v = changePos((end_p - start_p).getNormalized()); float q = _curPower / slider_bg->getContentSize().height; // 設置白球速度 _mainBilliards->SetLinearVelocity(b2Vec2(v.x * q * MAX_SPEED, v.y * q * MAX_SPEED)); auto dash_line = (
40、Sprite*)getChildByTag(DASH_LINE_TAG); dash_line->setVisible(false); auto aim_icon = (Sprite*)getChildByTag(AIM_ICON_TAG); aim_icon->setVisible(false); auto aim_gan = (Sprite*)getChildByTag(AIM_GAN_TAG); aim_gan->setVisible(false); // 擊球運動后,在所有物體都靜止之前無法再進行瞄準和擊球 _canAim = false;
41、 _aim = false; _powerEnd = true; // 進度條可以消除 } } 2、為控制條添加監(jiān)聽 在PhysicsBox2dScene.cpp文件中init函數(shù)中 // add touch listener auto listener = EventListenerTouchOneByOne::create(); listener->onTouchBegan = CC_CALLBACK_2(PhysicsBox2dScene::onTouchBegan, this); listener->onTouchMoved = CC_CA
42、LLBACK_2(PhysicsBox2dScene::onTouchMoved, this); listener->onTouchEnded = CC_CALLBACK_2(PhysicsBox2dScene::onTouchEnded, this); Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener,this); (九)改變球桿方向 b2Vec2 PhysicsBox2dScene::changePos(Vec2 pos) { r
43、eturn b2Vec2(pos.x/PTM_RATIO, pos.y/PTM_RATIO); } cocos2d::Vec2 PhysicsBox2dScene::changePos(b2Vec2 pos) { return Vec2(pos.x*PTM_RATIO, pos.y*PTM_RATIO); } (十)更新瞄準線的位置和球桿位置 void PhysicsBox2dScene::updateLine(Vec2 start_p, Vec2 end_p) { _aimPos = end_p; // update line _angle = (_
44、aimPos - start_p).getNormalized().getAngle() ; auto dashLine = (Sprite*)getChildByTag(DASH_LINE_TAG); dashLine->setPosition(start_p); dashLine->setTextureRect(Rect(0,0,2,abs((end_p - start_p).getLength()))); dashLine->setRotation(CC_RADIANS_TO_DEGREES(-_angle) + 90.0f); dashLine->setVisibl
45、e(true); // update aim icon auto aim_icon = (Sprite*)getChildByTag(AIM_ICON_TAG); aim_icon->setPosition(_aimPos); aim_icon->setVisible(true); // 計算球桿位置 auto aim_gan_pos = Vec2( (((end_p - start_p).getLength() + 45) * start_p.x - 45 * end_p.x) / (end_p - start_p).getLength(), ((
46、(end_p - start_p).getLength() + 45) * start_p.y - 45 * end_p.y) / (end_p - start_p).getLength()); auto aim_gan = (Sprite*)getChildByTag(AIM_GAN_TAG); aim_gan->setPosition(aim_gan_pos); aim_gan->setRotation(CC_RADIANS_TO_DEGREES(-_angle) - 90.0f); aim_gan->setVisible(true); } (十一)實現(xiàn)碰撞檢測
47、(物理模擬) 1、碰撞檢測(物理模擬)的實現(xiàn)函數(shù) void PhysicsBox2dScene::update(float delta) { float timeStep = 1.0f / 60.0f; // 時間同步 int32 velocityIterations = 8; // 速度迭代次數(shù) int32 positionIterations = 1; // 位置迭代次數(shù) _world->Step(timeStep,velocityIterations,positionIterations); _ContactListener->deleteBo
48、dy(); // 循環(huán)判定游戲輸贏 for (b2Body* Cur = _world->GetBodyList(); Cur; Cur = Cur->GetNext() ) { if ( Cur->GetType() == b2_dynamicBody && Cur->IsAwake() == true ) { // 模擬阻力 Cur->SetLinearVelocity(b2Vec2(Cur->GetLinearVelocity().x * 0.989, Cur->GetLinearVelocity().y * 0.989)); if( ab
49、s(Cur->GetLinearVelocity().x) < 0.5f && abs(Cur->GetLinearVelocity().y) < 0.5f ) { Cur->SetAwake(false); } } } if (_powerEnd) { // 滑塊消失 if (_curPower !=0) { _curPower -= _sliderSpeed; } else if (_curPower <= 0) { _curPower = 0.0f; } updatePowerSli
50、der(_curPower); } // 所有球靜止才可以進行瞄準 int awak = 0; for (b2Body* Cur = _world->GetBodyList(); Cur; Cur = Cur->GetNext() ) { if ( Cur->GetType() == b2_dynamicBody && Cur->IsAwake() == true ) { awak ++; } } if (awak == 0) { _canAim = true; } } 2、在PhysicsBox2dScene.cpp文件中init函數(shù)中添加定時刷新函數(shù),實現(xiàn)物理模擬,碰撞檢測 // main loop this->scheduleUpdate(); (十二)游戲運行效果如圖。
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年防凍教育安全教育班會全文PPT
- 2025年寒假安全教育班會全文PPT
- 初中2025年冬季防溺水安全教育全文PPT
- 初中臘八節(jié)2024年專題PPT
- 主播直播培訓提升人氣的方法正確的直播方式如何留住游客
- XX地區(qū)機關(guān)工委2024年度年終黨建工作總結(jié)述職匯報
- 心肺復蘇培訓(心臟驟停的臨床表現(xiàn)與診斷)
- 我的大學生活介紹
- XX單位2024年終專題組織生活會理論學習理論學習強黨性凝心聚力建新功
- 2024年XX單位個人述職述廉報告
- 一文解讀2025中央經(jīng)濟工作會議精神(使社會信心有效提振經(jīng)濟明顯回升)
- 2025職業(yè)生涯規(guī)劃報告自我評估職業(yè)探索目標設定發(fā)展策略
- 2024年度XX縣縣委書記個人述職報告及2025年工作計劃
- 寒假計劃中學生寒假計劃安排表(規(guī)劃好寒假的每個階段)
- 中央經(jīng)濟工作會議九大看點學思想強黨性重實踐建新功