Chào các bạn!
Cũng nhanh ghê nhỉ, 17 bài rồi đấy, hehe. Chúng ta đã cùng nhau làm xong 1 Project đầu tiên bằng Cocos2d-x v3 cơ đấy. Trong bài này mình sẽ giới thiệu với mọi người 1 Project game khác cũng hay ho không kém, đó là dạng game phá gạch nổi tiếng của điện tử 4 nút ngày xưa.
Hãy cùng tìm hiểu nhé!
Trong game này mình sẽ phải làm các công việc sau:
+ Thêm các đối tượng vào game
+ Thiết lập các thuộc tính vật lý ( dùng Chipmunk cho dễ )
+ Tạo chuyển động của bóng
+ Di chuyển thanh chắn
B1 - Thêm các đối tượng vào game - Thiết lập thuộc tính vật lý
Tạo 1 Project mới với lệnh quen thuộc
>cocos new breakout -p com.vn.breakout -l cpp -d f:android/project
Và nhớ thêm dòng lệnh USING_NS_CC; vào file HelloWorldScene.h nhé
Mở file HelloWorldScene.h thêm vào các dòng lệnh sau ở phần public
Sprite* ball; // Bóng
Sprite* paddle; // Thanh chắn
Sprite* edgeSp; // Khung màn hình
PhysicsWorld* m_world; // World
void setPhyWorld(PhysicsWorld* world){ m_world = world; };
// Sự kiện Touch
void onTouchMoved(Touch *touch, Event *event);
void onTouchEnded(Touch *touch, Event *event);
bool onTouchBegan(Touch *touch, Event *event);
OK
Mở file HelloWorldScene.cpp, ta phải sửa hàm createScene() 1 chút như sau
// Các lệnh này chắc mình ko cần giải thích nhiều nhỉ
auto scene = Scene::createWithPhysics();
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
Vect gravity(0.0f, 0.0f); // Vector gia tốc =0
scene->getPhysicsWorld()->setGravity(gravity);
auto layer = HelloWorld::create();
layer->setPhyWorld(scene->getPhysicsWorld());
Hàm init() xóa hết chỉ để lại các dòng này
if ( !Layer::init() )
{
return false;
}
auto visibleSize = Director::getInstance()->getVisibleSize();
auto origin = Director::getInstance()->getVisibleOrigin();
//---Xóa hết
return true;
Thêm vào giữa phần "Xóa hết" đoạn code dài sau
// Cũng rất quen thuộc nếu bạn đã đọc các bài trước về phần vật lý sử dụng Chipmunk, mình giải thích một số cái thôi nhé
edgeSp = Sprite::create();
auto boundBody = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3); // Tạo khung vật lý
boundBody->getShape(0)->setRestitution(1.0f); // Đàn hồi
boundBody->getShape(0)->setFriction(0.0f); // Ma sát
boundBody->getShape(0)->setDensity(1.0f); // Tỷ trọng, mật độ
edgeSp->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2)); // Đặt vị trí, tâm của Box trung giữa màn hình
edgeSp->setPhysicsBody(boundBody); // Đặt physicsBody
boundBody->setContactTestBitmask(0x000001); // Đây là lệnh quan trọng, nếu ko có nó, thì ko có điều gì xảy ra khi có va chạm hết
this->addChild(edgeSp); // Add vào Layer
edgeSp->setTag(0); // Tag==0, để kiểm tra đối tượng khi va chạm thuộc loại nào
ball = Sprite::create("Ball.png", Rect(0, 0, 52, 52));
ball->setPosition(100, 100);
auto ballBody = PhysicsBody::createCircle(ball->getContentSize().width / 2.); // Khung vật lý hình tròn
ballBody->getShape(0)->setRestitution(1.0f);
ballBody->getShape(0)->setFriction(0.0f);
ballBody->getShape(0)->setDensity(1.0f);
ballBody->setGravityEnable(false); // Không set Gia tốc
Vect force = Vect(1010000.0f, 1010000.0f); // Tạo 1 Vector lực tác động theo hướng 45 độ, vì x = y kìa
ballBody->applyImpulse(force); // Đẩy 1 lực vào khung quả bóng
ball->setPhysicsBody(ballBody); // Sét Physic body
ballBody->setContactTestBitmask(0x000001); //
ball->setTag(1);
this->addChild(ball);
// Giải thích tương tự phần ball
paddle = Sprite::create("Paddle.png");
auto paddleBody = PhysicsBody::createBox(paddle->getContentSize(), PHYSICSBODY_MATERIAL_DEFAULT);
paddleBody->getShape(0)->setRestitution(1.0f);
paddleBody->getShape(0)->setFriction(0.0f);
paddleBody->getShape(0)->setDensity(10.0f);
paddleBody->setGravityEnable(false);
paddleBody->setDynamic(false); // Vật tĩnh khi tương tác, ko đàn hồi, ko đổi vị trí
paddle->setPosition(visibleSize.width / 2, 50);
paddle->setPhysicsBody(paddleBody);
paddleBody->setContactTestBitmask(0x000001); // Có tương tác
ball->setTag(2);
this->addChild(paddle);
Thêm 1 đoạn code tạo 1 em Listener để bắt sự kiện Touch ( dùng cho điều khiển thanh chắn ) trước lệnh Return true;
// Quá quen thuộc rồi
auto touchListener = EventListenerTouchOneByOne::create();
touchListener->setSwallowTouches(true);
touchListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
touchListener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);
touchListener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
B2 - Tạo chuyển động của bóng
Tạo 1 chuyển động đầu cho quả bóng bằng lệnh sau ( ở hàm init() phía trên đã tạo rồi đó)
Vect force = Vect(1010000.0f, 1010000.0f); // Tạo 1 Vector lực tác động theo hướng 45 độ, vì x = y kìa
ballBody->applyImpulse(force); // Đẩy 1 lực vào khung quả bóng
B3 - Di chuyển thanh chắn
bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
{
return true; // Không dùng nhưng vẫn phải trả lại giá trị True
}
void HelloWorld::onTouchEnded(Touch* touch, Event* event)
{
// Không dùng
}
OK các men!
Chúng ta build và chạy thử luôn nhé,
Vậy là xong bài 17, rất đơn giản phải không, vì toàn kiến thức cơ bản chúng ta đã học phần trước. Tóm lại ở bài này chúng ta làm được một số việc sau:
+ Ôn lại kiến thức về Chipmunk Physics
+ Tạo quả bóng di chuyển = Vector lực, dễ vãi
+ Di chuyển đối tượng = onTouchMoved - Cái này hay và thiết thực nè
Download Resource và Class ở đây
Ở bài sau chúng ta sẽ tìm hiểu cách "đóng gạch" à, tạo gạch, và phá gạch, rồi game Over nữa
Chào các bạn và hẹn gặp lại ở bài sau!
Bài 18: Game thứ 2 - Breakout - Tạo và phá gạch ( Part 2)
Cảm ơn bạn rất,
ReplyDeleteNhờ vào các tut của bạn mình đã có được căn bản, giờ nghiên cứu lên thấy dễ......
Chưa tới phần khó đó thôi.
DeleteThanks mọi người đã theo dõi!
Mình không nói nó dễ... Ý mình là những phần bạn đã up, đã giải thích.. dễ hiểu..Nhờ đó mà lấy được căn bản :3
ReplyDeleteohhh, Thanks Thanh
DeleteBạn ơi cho mình hỏi sử dụng các thuộc tính vật lý là phải cài đặt gì đúng không bạn.
ReplyDeleteCó 2 thư viện vật lý để dùng trong cocos2dx
Delete+ Chipmunk: đơn giản, dễ cài đặt. Chỉ cần sử dụng các câu lệnh theo đúng cú pháp( trong các bài trước) là OK
+ Box 2D: Phức tạp trong việc khai báo sử dụng hơn 1 chút. Câu lệnh theo đúng cú pháp trong bài 15-16.
Tùy theo yêu cầu và ý đồ game mà ta thêm bớt 1 vài thuộc tính vật lý phụ ( đàn hồi, ma sát, gia tốc,v..v..)..
1 Một tutorial khá hay
ReplyDeletehttp://www.cocos2d-x.org/forums/6/topics/53301
Mai mốt sẽ thử cái tut đó, mọi người có thời gian hãy nghiên cứu trước
DeleteCho mình hỏi có điều kiện gì với cái hàm vector lực này không?
ReplyDeleteVect force = Vect(1010000.0f, 1010000.0f)
- Mình cho giá trị nó to lên thì ball biến mất luôn. Không bị ngăn bởi khung chắn bao quanh nữa
Thanks
ad cho minh hoi tao moi truong vat ly trong ban v2.2 ntn a.?
ReplyDeleteLời khuyên của mình nên chuyển sang V3 đi có nhiều cái mới hơn
DeleteCòn về câu hỏi của bạn. V2.2 mình chưa từng xài bao giờ. Nhưng mình search api của nó thì ko có hàm setphysicsBody (Hàm này là hàm Physic built-in của Engine. Hệ physic riêng của Engine). Xem qua engine thì hình như chưa phát triển hệ PHysic riêng. Tuy nhiên bạn có thể dùng Box2D, chipmunk ( đã hỗ trợ ).
V2. hay dùng boundingBox cho bài đơn giản
Thêm nữa các plugin, soft giờ hỗ trợ V3 nhiều, V2 sắp bỏ đi tới nơi rồi. V4 chuẩn bị ra nữa kìa
DeleteChè giải thích hộ tớ cái lệnh này có nghĩa j ?PHYSICSBODY_MATERIAL_DEFAULT
DeleteCảm ơn bài viết của bạn,
ReplyDeleteCho mình hỏi, mình gặp trường hợp như thế này, khi bóng bay thì nó bay vài vòng ok, sau đó nó tăng tốc và bay ra ngoài khung màn hình luôn, bay mất luôn.
Không biết làm sao để tránh lỗi này vậy bạn
Mình cảm ơn