Bài 18: Game thứ 2 - Breakout - Tạo và phá gạch (Part 2)

Người đăng: chisenhungsuutam on Thứ Sáu, 23 tháng 5, 2014

Chào mọi người!

Vậy là chúng ta đã đi được 1 chặng đường kha khá của Cocos2d-x V3 rồi. Cũng chuẩn bị xong Project thứ 2 đấy chứ. Trong phần này mình sẽ hướng dẫn các bạn nốt công việc đơn giản là "xếp gạch và phá gạch" nhé. Sẽ rất đơn giản thôi.

Những công việc trong bài này:
+ Tạo gạch
+ Xử lý va chạm vật lý
+ Kiểm tra việc phá gạch, hết thì WINGAME
+ Kiểm tra GameOver khi bóng rơi không trúng thanh chắn

- Nhìn có vẻ nhiều việc vậy thôi, nhưng mà đơn giản lắm, vì cũng khá giống Game đầu tiên

Bắt đầu luôn nhé! À, file Resource và Class các bạn down hết ở bài 17 rồi đó

B1 - Tạo gạch

Vì Class mình up ở bài 17 dùng cho cả bài 18 ( Mình comment những đoạn code chưa dùng, bạn chỉ việc phá comment ra thôi)

Mở file HelloWorldScene.cpp thêm vào đoạn code sau

for (int i = 0; i < 5; i++) {
static int padding = 100;
auto block = Sprite::create("blocks.png");
auto blockBody = PhysicsBody::createBox(block->getContentSize(), PHYSICSBODY_MATERIAL_DEFAULT);
blockBody->getShape(0)->setDensity(10.0f);
blockBody->getShape(0)->setFriction(0.0f);
blockBody->getShape(0)->setRestitution(1.f);
blockBody->setDynamic(false);
// Tạo khoảng cách đều nhau giữa cách khối gạch
int xOffset = padding + block->getContentSize().width / 2 +
((block->getContentSize().width + padding)*i);
block->setPosition(xOffset, 450);
blockBody->setContactTestBitmask(0x000001);
block->setPhysicsBody(blockBody);
block->setTag(3);
this->addChild(block);
}

B2 - Xử lý va chạm - Phá gạch, Game Over

* Thêm ContactListener

auto dispatcher = Director::getInstance()->getEventDispatcher();
auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegin, this);  
dispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

* Dựng 1 hàm onContactBegin

bool HelloWorld::onContactBegin(PhysicsContact& contact)
{
// Lấy 2 đối tượng va chạm
auto spriteA = (Sprite*)contact.getShapeA()->getBody()->getNode();
auto spriteB = (Sprite*)contact.getShapeB()->getBody()->getNode();

// Kiểm tra loại đối tượng
int tagA = spriteA->getTag();
int tagB = spriteB->getTag();

if (tagA == 3) // Là gạch
{

this->removeChild(spriteA,true); // Xóa gạch

//spriteA->removeFromParentAndCleanup(true);
}

if (tagB == 3)  // Là gạch
{
this->removeChild(spriteB,true); // Xóa gạch

//spriteB->removeFromParentAndCleanup(true);
}

// Nếu bóng va chạm với sạn mà tọa độ Y của bóng nhỏ hơn thanh chắn thì Game Over
if ((tagA == 0 || tagB  == 0 )& (ball->getPositionY() <= paddle->getPositionY()))
{
auto gameOverScene = GameOverScene::create();
gameOverScene->getLayer()->getLabel()->setString("You Lose!");
Director::getInstance()->replaceScene(gameOverScene);
}

return true;
}

Lớp GameOverScene này giống với Project đầu tiên nhé

B2 - Kiểm tra Win game

Xây dựng hàm Tick() như sau, nhớ khai báo nguyên mẫu hàm

void HelloWorld::tick(float dt)
{
// 1 biến bool xác nhận Win game ban đầu gán = true;
bool isWin = true;
// Vector bodies lấy tất cả các bodies của world ( ball, edge, paddle body), về vector bạn nghiên cứu thêm C++ nâng cao nhé, cũng gần giống mảng, và cũng khá giống Stack. Khai báo vector thì như này Vector<Kiểu biến> tên_biến
Vector<PhysicsBody*> bodies = m_world->getAllBodies();

// Duyệt từng phần tử của vector trên, kiếm tra loại đối tượng = Tag, Bạn nên tìm hiểu lại lệnh for nhé, nó có nhiều biến thể cho từng loại lớp đặc biệt, đọc phần C++ nâng cao phần list, vector, queue,v..
// Đừng dập khuôn for chỉ có dạng for( int i=0; i<N; i++) nhé

for each(PhysicsBody* body in bodies) // Câu lệnh này lỗi Khi build android, bạn hãy sửa lại thành  for (auto body : bodies) nhé, đây là chuẩn mới C++ 11
{
if (body->getNode()->getTag() == 3) // Nếu còn body của "gạch", tức là chưa phá hết
{
isWin = false; // Chưa Win
}
}
// Duyệt hết mà  isWin vẫn ko đổi thì xử lý Win game
if (isWin == true)
{
auto gameOverScene = GameOverScene::create();
gameOverScene->getLayer()->getLabel()->setString("You Win!");
Director::getInstance()->replaceScene(gameOverScene);
}
}

Để gọi hàm Tich() này bạn thêm 1 dòng lệnh này 
this->schedule(schedule_selector(HelloWorld::tick),0); vào cuối hàm init() là xong,

Nếu bạn dùng scheduleUpdate() thì build hàm update(float dt) nhé

Build and Run nào

















Chúng ta kết thúc bài 18 ở đây nhé. Tóm lại trong cả bài 17 và 18 chúng ta học được gì?

+ Tạo world vật lý với Chipmunk
+ Move đối tượng = kéo, drag trên màn hình
+ Xử lý va chạm, 
+ Win game, Over Game
+ Biết thêm 1 chút về Vector, để dành các bài sau nhé

Những hạn chế của game này
+ Thiếu phần tính điểm, để những bài sau
+ Thiếu âm thanh ( bạn có thể thêm vào như Game trước nhé )
+ Thiếu phần Level chơi
+ Thiếu phần menu 
+ Đồ họa hơi cùi mía.

* Lưu ý khi build Android, bạn phải khai báo các file cpp mới tạo vào file Android.MK trong thư mục prj.android, như sau, chú ý dấu \








Dòng cuối ko có dấu \

Các dòng trên đều có

GameOverScene.cpp là Class mới tạo, phải khai báo vào đây, file .h thì ko cần

OK, và chú ý sửa lỗi code theo đúng chuẩn C++11 là build APK thành công thôi. Đã test và rút ra EXP nhé


Các bạn thấy đấy, 1 bài quá dễ đúng không. Nhưng nếu không đọc qua những bài phía trước thì chắc hẳn bài này ko dễ nuốt đâu nhỉ. Mong mọi người đừng ỷ vào những gì đã biết mà coi thường những thứ dễ dàng. Hãy học từ dễ đến khó, từ chưa biết đến biết, từ biết thành PRO. từ pro tới SÁNG TẠO nha, đó mới là đích tới của chúng ta. Thực ra đâu có đích nào là cuối.
Các bạn có thể phát triển thêm game này nếu có thời gian nhé.
Nếu không chúng ta cùng đi tiếp nào.

More about

BÀ MERKEL MẮNG TẬP CẬN BÌNH

Người đăng: chisenhungsuutam


BÀ MERKEL MẮNG TẬP CẬN BÌNH

Tập này! Cái mặt chú dày
Chắc là bị đấm bấy nay chứ gì ?
Vai phải mụn nhọt li bì
Dao đâm, kiếm chém mấy kỳ chưa thôi (1)
Vai trái rớm máu hỡi ôi
Phù Tang họ nện ba hồi bảy chương. (2)
Hông phải chú có còn xương
More about

1 Tin vui - 1 Tin buồn

Người đăng: chisenhungsuutam on Thứ Năm, 22 tháng 5, 2014

Hix, Chào mọi người!

Không biết còn ai theo mình đọc tới bài này không nhỉ? Món lập trình vốn đã khô khan, lập trình game lại càng khó nuốt. Lúc mới đầu hẳn nhiều bạn cũng háo hức vào tìm hiểu, nhưng rồi theo thời gian đam mê giảm dần, sự hóc búa và lượng kiến thức tăng dần, đã có một vài người ra đi không trở lại. Đã thế món này cũng khá kén độc giả, không phải ai cũng hào hứng ghé vào đọc, có khi chỉ ghé qua +1 rồi lại đi ra, haizzz!

Sau 17 bài viết cơ bản này chắc các bạn cũng đã nắm được những điều căn bản trong Cocos2dx-V3 đủ để làm vài game đơn giản rồi nhỉ. Nhưng để làm được những game hay và hấp dẫn chúng ta còn phải học thêm nhiều thứ nữa ví như: thuật toán, animation, hiệu ứng, nâng cao hơn..v.v...

Thật đáng tiếc là từ trước tới nay, tài liệu làm game, viết game, chia sẻ trên mạng vốn đã ít, tài liệu bằng tiếng Việt lại càng khan hiếm hơn. Thật ra cũng có nhiều lý do:

+ Chỉ có tài liệu căn bản + nâng cao cho những bài, những game đơn giản, hoặc đã qua thời kiếm được tiền cho tác giả, nên mới được Share Code.
+ Không ai Share Project đang phát triển của họ cả. Làm vậy chẳng khác đem nồi cơm nhà mình đi cho hàng xóm.
+ Việt Nam mình cũng khan hiếm người làm game thực thụ để sống, đa phần là tay trái. Kiến thức thật sự không thể bằng các bạn nước ngoài nên hầu như ít có Tut chất lượng.
+ Tut tiếng Anh cũng kha khá nhưng hầu như là Tút cũ, vì họ cũng phải rành thời gian mà học phiên bản mới chứ.

Và đây là 1 Tin buồn cho các bạn
- Ở bài trước mình có giới thiệu với mọi người trang chia sẻ Video hướng dẫn Cocos2dx - V3 khá hay và bổ ích, nhưng đến thời điểm này đã TẠM DỪNG được 2-3 tuần nay rồi, chán ghê. Mất đi 1 nguồn bổ sung kiến thức. Không biết tác giả có bị sao không? Hi vọng là trong thời gian tới lại được tái khởi động.

Để tránh cho các bạn khỏi sự nản lòng, sau đây là Tin vui từ trang chủ Cocos2d-x.org
- Đã có phiên bản nâng cấp của V3 là Cocos2d-x V3.1 RC0: với những nâng cấp đáng giá sau
+ Sprite3D:
+ VideoPlayer
+ Nhiều thứ khác hấp dẫn lắm
ChangeLog đầy đủ ở đây 

=> Vậy là Engine vẫn tiếp tục được hỗ trợ và phát triển từ Team, hi vọng trong thời gian tới, nó sẽ hoàn thiện hơn, giúp chúng ta phát triển game 2D, và 3D ( chắc sẽ tiến tới thôi ) dễ dàng hơn.

Nói thêm chút Cocos2D-x V2 dừng lại ở 2.2.3 rồi nhé, và ko có cập nhật mới nữa. Anh em nên chuyển lên 3.x để tiếp cận với xu hướng mới nhé.

Thanks tất cả đã đọc bài.

Hãy tham khảo Các bài học của mình

More about

Bài 17: Game thứ 2 - Breakout ( Part 1)

Người đăng: chisenhungsuutam on Thứ Tư, 21 tháng 5, 2014

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

Xây dựng 3 hàm Touch, vì ta chỉ sử dụng hàm onTouchMoved để di chuyển nên các hàm Touch khác ta để rỗng nhé:

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 ResourceClass ở đâ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)

More about

Bài 16: Box2D - Một thư viện vật lý khác của Cocos2d-x (Part 2)

Người đăng: chisenhungsuutam

Hi all!

Bài 15 Chúng ta đang tìm hiểu về Box2D, và xây dựng 1 ứng dụng nhỏ sử dụng physic Box2D. Ở bài này chúng ta nâng cao lên 1 chút, là điều khiển quả bóng, làm cho nó va đập với màn hình. Nội dung chính như sau:


+ Làm chuyển động quả bóng bằng vector + lực
+ Đoán trước hướng di chuyển của quả bóng

Mời bạn cùng theo dõi!

B1 - Làm chuyển động quả bóng bằng vector + lực

Các bạn mở Class đã làm ở bài 15 ra

* Mở file HelloWorldScene.h, phần Public thêm vào đoạn code sau:

// Các biến này, bạn xem các đoạn code dưới sẽ hiểu ý nghĩa
bool existBall;
float ballX;
float ballY;  
int dragOffsetStartX;
int dragOffsetEndX;
int dragOffsetStartY;
int dragOffsetEndY;  
float powerMultiplier; // :Lực
Sprite *points[32];
void defineBall(); // Tạo quả bóng theo Box2D

//Mô phỏng đường đivoid simulateTrajectory(b2Vec2 coord);

//Bắt các sự kiện Touch bool onTouchBegan(Touch* touch, Event* event);
void onTouchMoved(Touch* touch, Event* event);
void onTouchEnded(Touch* touch, Event* event);

* Mở file HelloWorldScene.cpp, Xóa hết code của bài cũ ( để đỡ nhầm lẫn chỉ trừ lại đoạn sau)

if ( !Layer::init() )
{
return false;
}

Size visibleSize = Director::getInstance()->getVisibleSize();
Point origin = Director::getInstance()->getVisibleOrigin();

// ĐÃ XÓA HẾT
return true;


+ Thêm vào chỗ xóa kia Các đoạn code sau:

b2Vec2 gravity = b2Vec2(0.0f, -10.0f); // Vector gia tốc
world = new b2World(gravity);  // Tạo world

//Tạo 1 quả bóng, Lưu tọa độ các điểm đầu và cuối dragOffsetStartX = 0;  
dragOffsetEndX = 0;  
dragOffsetStartY = 0;  
dragOffsetEndY = 0;  
existBall= false;

ballX = 500;
ballY = 200;
powerMultiplier = 10; // Giá trị lực 10
ball =Sprite::create("ball.png");
ball->setPosition(Point(ballX,ballY));
this->addChild(ball);

// Dựng khung bao quanh 3 phía màn hình addWall(visibleSize.width ,10,(visibleSize.width / 2) ,0); // Sàn
addWall(10 ,visibleSize.height ,0,(visibleSize.height / 2) ); //Trái
addWall(10 ,visibleSize.height ,visibleSize.width,(visibleSize.height / 2) ); // Phải


//Bắt sự kiện Touch 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);

scheduleUpdate(); // Update Scene theo Time


+ Xây dựng hàm addWall như sau, rất giống bài 15, thì vẫn là dựng khung physic body = Box2D mà

void HelloWorld::addWall(float w,float h,float px,float py) {

b2PolygonShape floorShape; // Hình dạng Sàn

floorShape.SetAsBox(w/ SCALE_RATIO,h/ SCALE_RATIO); // Hình vuông, hoặc chữ nhật
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);

}

+ Hàm defineBall(), thật ra là khai báo lại việc tạo body physic cho quả bóng ở bài 15, chuyển nó thành 1 hàm riêng thôi

void HelloWorld::defineBall(){
bodyShape.m_radius = 45 / SCALE_RATIO;

fixtureDef.density=10;
fixtureDef.friction=0.8;
fixtureDef.restitution=0.6;
fixtureDef.shape=&bodyShape;

bodyDef.type= b2_dynamicBody;
bodyDef.userData=ball;

bodyDef.position.Set(ball->getPosition().x/SCALE_RATIO,ball->getPosition().y/SCALE_RATIO);

ballBody = world->CreateBody(&bodyDef);
ballBody->CreateFixture(&fixtureDef);
ballBody->SetGravityScale(10);
}

+ Dựng hàm onTouchBegan

bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
{
// Lưu tọa độ điểm Touch đầu tiên dragOffsetStartX = touch->getLocation().x;
dragOffsetStartY = touch->getLocation().y;

Point touchLocation = touch->getLocation(); // Lấy tọa độ điểm Touch

// Lưu lại
ballX = touchLocation.x;
ballY = touchLocation.y;

// Kiểm tra nếu điểm Touch chưa có quả bóng, thì xóa body bóng đã tạo ở hàm defineBall()
if (existBall){      
world->DestroyBody(ballBody);
}

ball->setPosition(Point(ballX ,ballY)); // Đặt vị trị mới ở ballX ,ballY
return true;
}

+ Hàm onTouchEnded

void HelloWorld::onTouchEnded(Touch* touch, Event* event)
{

existBall = true;

HelloWorld::defineBall(); // Tạo body quả bóng tại điểm Touch cuối

Point touchLocation = touch->getLocation(); // Lấy điểm Touch

// Lưu điểm Touch cuốidragOffsetEndX = touchLocation.x;
dragOffsetEndY = touchLocation.y;

// Khoảng di chuyển của bóngfloat dragDistanceX = dragOffsetStartX - dragOffsetEndX;
float dragDistanceY = dragOffsetStartY - dragOffsetEndY;

// Tạo chuyển động cho body với 1 vận tốc không đổi có phương và độ lớn = vector có điểm cuối, điểm đầu đã lưu, nhân thêm 1 lực = 10 = powerMultiplierballBody->SetLinearVelocity(b2Vec2((dragDistanceX*powerMultiplier)/SCALE_RATIO,(dragDistanceY*powerMultiplier)/SCALE_RATIO));
}

+ Hàm onTouchMoved

void HelloWorld::onTouchMoved(Touch* touch, Event* event)
{

}

Bạn build & run thử xem, có thành công ko?, thử kéo quả bóng và thả ra, sẽ thấy quả bóng bắn đi và va đập với thành màn hình, OK nha, sang ngay bước 2

B2 - Đoán hướng di chuyển của bóng

Bạn cần xây dựng 2 hàm sau đây

onTouchMoved

void HelloWorld::onTouchMoved(Touch* touch, Event* event)
{
Point touchLocation = touch->getLocation();

// Lưu lại điểm cuối dragOffsetEndX = touchLocation.x;
dragOffsetEndY = touchLocation.y;

// Khoảng di chuyển của bóng float dragDistanceX = dragOffsetStartX - dragOffsetEndX;
float dragDistanceY = dragOffsetStartY - dragOffsetEndY;

//Gọi hàm mô phỏng đường đi của bóng, vector nhân thêm 1 lực = 10 = powerMultiplier HelloWorld::simulateTrajectory(b2Vec2((dragDistanceX * powerMultiplier)/SCALE_RATIO,(dragDistanceY * powerMultiplier)/SCALE_RATIO));
}

+ simulateTrajectory

void HelloWorld::simulateTrajectory(b2Vec2 coord){
//Định nghĩa physics body bóng HelloWorld::defineBall();

// Tạo chuyển động cho body với 1 vận tốc không đổi có phương và độ lớn = vector truyền vào
ballBody->SetLinearVelocity(b2Vec2(coord.x,coord.y));


// Duyệt mảng point for (int i = 1; i <= 31; i++){

//Trong hàm Step, Giá trị đối số phải bằng gia tốc 10 và powerMultiplier (=10) world->Step(deltaTime,10,10);
points[i]->setPosition(Point(ballBody->GetPosition().x*SCALE_RATIO,ballBody->GetPosition().y*SCALE_RATIO));
world->ClearForces();
}
world->DestroyBody(ballBody);
}

+ Trong hàm init(), thêm vào đoạn code

// Khởi tạo mảng Sprite gồm 31 chấm nhỏ, để biểu diễn đường đi của bóng for (int i = 1 ; i <= 31; i++){
points[i] =Sprite::create("dot.png");
this->addChild(points[i]);
}

Build rồi chạy thử nào, Khi bạn kéo quả bóng sẽ thấy có 1 đường chấm chấm biểu diễn hướng đi của nó. Thả tay ra, quả bóng bay đúng theo hướng đó là thành công.



Vậy là đã xong bài 16, tổng kết lại trong bài này chúng ta học được cách:
+ Tạo lực chuyển động cho 1 đối tượng
+ Biểu diễn đường đi của nó trong world

Mở rộng bài này ra, ta có thể làm được trò chơi Bi-a đấy, các bạn ạ.

Thôi để dành các bài sau nghiên cứu tiếp

P/S: Qua bài 15, 16 các bạn thấy là trong Box2D, sprite bị phụ thuộc vào Body, thiết lập và di chuyển body trước, sau đó mới hiện sprite theo vị trí body. Còn trong Chipmunk thì ngược lại, cài đặt vị trí của Sprite trước, đặt body theo sau. Xem lại các bài trước về Physics.

Chào và hẹn gặp lại.

Bài 17: Game thứ 2 - Breakout ( Part 1)

More about

Phần mềm tạo ảnh động cực hay

Người đăng: chisenhungsuutam

Easy GIF Animator là phần mềm hỗ trợ bạn tạo được banner động, text động và button động một cách dễ dàng. Điều này có nghĩa là bạn không phải thuê các công ty quảng cáo tạo cho bạn nữa, bạn hoàn toàn có thể tự tạo và quảng cáo trên các diễn đàn hay trên chính website của mình. 
Đây là link phần mềm  Easy GIF Animator: http://tinyurl.com/p8z3fbz. Hoàn toàn không có virus nha nên các bạn cứ tự nhiên dùng.
Còn đây chính là giao diện chính của Easy GIF Animator:
phần mềm Easy GIF Animator
Phần mềm Easy GIF Animator
Cách sử dụng Easy GIF Animator cơ bản chỉ gồm 3 bước. 
Bước 1: Chọn ảnh, video
Sử dụng những ảnh mà bạn muốn tạo ảnh động hoặc sử dụng luôn những đoạn video có sẵn. Sự khác nhau giữa 2 đối tượng này là: Nếu bạn chọn ảnh thì có thể là tạo ảnh động cho riêng biệt ảnh đó hoặc ảnh động chuyển đổi giữa 2 ảnh khác nhau bằng các hiệu ứng có trong phần mềm.
Còn nếu bạn chọn video thì không cần tạo hiệu ứng nữa, hiệu ứng sẽ được lấy từ video luôn. 
Bước 2: Chỉnh sửa ảnh, video và thêm hiệu ứng
Phần mềm Easy GIF Animator hỗ trợ bạn chỉnh sửa ảnh trực tiếp trên đó hoặc giúp bạn kết nối ảnh của bạn tới phần mềm paint. Khi này bạn có thể chỉnh sửa thêm một số chi tiết đơn giản như: thêm chữ, khung, thu nhỏ, phóng to ảnh. 
phần mềm Easy GIF Animator
Chỉnh ảnh trên Easy GIF Animator
Sau đó bạn tiến hành thêm hiệu ứng cho từng ảnh hoặc giữa các ảnh với nhau. Bạn có thêm bao nhiêu ảnh cũng được nhưng thông tường ta chỉ sử dụng từ 2-5 ảnh để tránh tình trạng rối mắt cho người xem. Trong phần mềm Easy GIF Animator đã có sẵn các hiệu ứng để bạn chọn nhé. 
Để thêm hiệu ứng bạn vào phần transition effect. Trong quá trình thêm hiệu ứng cho ảnh thì bạn có thể thêm chữ và hiệu ứng chữ cho ảnh đó luôn. 
Hiệu ứng sẽ chuyển đổi theo từng ảnh và bạn hoàn toàn có thể sắp xếp được ảnh nào sẽ xuất hiện trước, ảnh nào sẽ xuất hiện sau bằng cách di chuyển vị trí  của các ảnh theo thứ tự trên dưới nhé. 
Bước 3: Export ảnh, video 
Thực hiện xong 2 bước trên là bạn có thể xuất ảnh, video ra để dùng được rồi. Bạn có thể sử dụng chức năng save as để có được ảnh động dưới dạng .gif hoặc video dưới dạng .avi
Hoặc bạn có thể sử dụng chức năng export  để lấy file dưới dạng Flash để up lên website. 
Vậy là bạn đã có được một ảnh động từ phần mềm Easy GIF Animator rồi !
>>>Một chia sẻ nhỏ rằng: Bạn có thể tự tạo ra những ảnh động dưới dạng .gif và chia sẻ lên google + (hay còn gọi là google plus) để seo rất hiệu quả đó. 

Hãy bắt đầu tạo cho mình những ảnh động thú vị nhé !
More about

Google cập nhật Panda 4.0

Người đăng: chisenhungsuutam on Thứ Ba, 20 tháng 5, 2014

Google cập nhật Panda 4.0 - Ngày hôm nay 25/5/2014 Matt Cutts đã công bố điều này trên trang cá nhân Twitter.

Bản cập nhật Panda 4.0 ảnh hưởn đến các ngôn ngữ, với tiếng Anh, thuật toán sẽ có tác động lên khoảng 7,5% các truy vấn.

Google cập nhật Panda 4.0


Panda 4.0
 

Thuật toán Panda của Google ra đời tháng 2 năm 2011, được viết bởi Navneet Panda. Ngày 25 tháng ba năm 2014, Google Panda được cấp bằng sáng chế bởi Cơ quan Sáng chế Hoa Kỳ. 



Panda cập nhật lần 01 ngày 24/2/2011

Panda Cập nhật lần 2 ngày 11/4/ 2011
Panda Cập nhật lần 3 ngày 10/5/2011
Panda Cập nhật lần 4 ngày 16/6/2011
Panda Cập nhật lần 5 ngày 23/7/2011
Panda Cập nhật lần 6 ngày 12/8/2011
Panda Cập nhật lần 7 ngày 28/9/2011
Panda Cập nhật lần 8 ngày 19/10/2011
Panda Cập nhật lần 9 ngày 18/11/2011
Panda Cập nhật lần 10 ngày 18/1/2012
Panda Cập nhật lần 11 ngày 27/2/2012
Panda Cập nhật lần 12 ngày 23/3/2012
Panda Cập nhật lần 13 ngày 19/4/2012
Panda Cập nhật lần 14 ngày 27/4/2012
Panda Cập nhật lần 15 ngày 09/6/2012
Panda Cập nhật lần 16 ngày  25/62012
Panda Cập nhậtlần 17 ngày 24/7/2012
Panda Cập nhật lần 18 ngày 20/8 2012
Panda Cập nhậtlần 19 ngày 18/9 2012
Panda Cập nhật lần 20 ngày 27/9/2012
Panda Cập nhật lần 21 ngày 5/11/2012
Panda Cập nhật lần 22 ngày 21/11 2012
Panda Cập nhật lần 23 ngày 21/12/2012
Panda Cập nhật lần 24 ngày 22/1/2013
Panda Cập nhật lần 25 ngày 15/3/2013
More about