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
}
// Dùng để di chuyển thanh chắn sang ngang, 1 cách đơn giản nhất
void HelloWorld::onTouchMoved(Touch* touch, Event* event){
Point touchLocation = this->convertToWorldSpace(this->convertTouchToNodeSpace(touch));
// Để đơn giản thì dùng lệnh này cho dễ hiểu Point touchLocation = touch->getLocation();
paddle->setPositionX(touchLocation.x); // Đặt vị trí ngang của thanh chắn theo vị trí Touch
}
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)
{ 0 nhận xét... read them below or add one }
Đăng nhận xét