Monday, April 21, 2014

Bài 6 - Ball - Physics cơ bản trong Cocos2dx -v3 (Part2)




Hi cả nhà!

Thời gian qua nhanh quá mà chả làm được cái gì, chán ghê. Cũng tại mình vừa vấp phải mấy vấn đề khó giải quyết trong cocos2dx - V3 nên tìm hiểu mãi mới ra. Trong bài này mình cũng trình bày luôn vấn đề đó là gì. Bây giờ chúng ta cùng tiếp tục bài trước về Physics nhé

Ở bài trước chúng ta đã tạo mới 1 Project Ball rồi đúng không, bây giờ là phần code thể hiện physics trong đó.

Let's go!


Các bạn theo đường dẫn sau: Q/android/project/ball/class, mở file HelloWorldScene.h lên. Code của file đó sẽ như vầy:

#ifndef __HELLOWORLD_SCENE_H__

#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

USING_NS_CC;

class HelloWorld : public cocos2d::Layer

{

public:

Sprite* _ball;

PhysicsWorld* m_world;

void setPhyWorld(PhysicsWorld* world){ m_world = world; };

static cocos2d::Scene* createScene();

virtual bool init();

virtual void onAcceleration(Acceleration* acc, Event* unused_event);

bool onContactBegin(const PhysicsContact &contact);

CREATE_FUNC(HelloWorld);

};


#endif // __HELLOWORLD_SCENE_H__

Các bạn không phải sửa đổi gì nhé, mình sẽ giải thích 1 chút về mấy thứ "là lạ trong đó"cho mọi người"

Sprite* _ball; // là 1 con trỏ kiểu Sprite tên là _ball, con trỏ này để quản lý cái gọi là quả bóng trong chương trình chúng ta.

PhysicsWorld* m_world; // Con trỏ kiểu PhysicsWorld tên m_world, gán cho nó các thuộc tính vật lý

void setPhyWorld(PhysicsWorld* world){ m_world = world; }; //hàm gán thuộc tính vật lý cho m_world,


virtual void onAcceleration(Acceleration* acc, Event* unused_event); // hàm này liên quan tới gia tốc kế thì phải
bool onContactBegin(const PhysicsContact &contact); // Hàm này để phát hiện va chạm giữa 2 quả bóng

Tiếp đến các bạn mở file HelloWorldScene.cpp lên nào (file nguồn các bạn down ở bên dưới nhé, vì mình dán vào đây thì bài dài dòng quá), trong đó bạn chú ý một số đoạn sau,

Trong hàm tạo Scene : Scene* HelloWorld::createScene(){}

auto scene = Scene::createWithPhysics(); // Câu lệnh này tạo 1 Scene gắn thuộc tính Physics
---

auto layer = HelloWorld::create(); // Tạo 1 layer của lớp HelloWorld

layer->setPhyWorld(scene->getPhysicsWorld()); // đặt thuộc tính Physics cho biết m_world của đối tượng layer,

scene->getPhysicsWorld() //nghĩa là lấy Physics của scene rồi gán cho m_world của layer

tiếp theo, hàm init()

_ball = Sprite::create("Ball.jpg", Rect(0, 0, 52, 52)); // Tạo 1 quả bóng nằm trong hình vuông 52 pixel

_ball->setPosition(Point(400,600)); // đặt ở vị trí 400, 600

auto ballBody = PhysicsBody::createCircle(_ball->getContentSize().width / 2); // Tạo 1 khung body có đặc tính vật lý để phát hiện va chạm, khung này dạng tròn có đường kính = nội dung của _ball chia 2.

ballBody->setContactTestBitmask(0x1); // Cái này rất quan trọng, nếu ko có thì hàm onContactBegin ko có tác dụng, tìm trên mạng mãi mới sửa được lỗi này

_ball->setPhysicsBody(ballBody); // Gán body cho _ball

this->addChild(_ball); // thêm vào layer HelloWorld đã tạo ở trên

ball2 được tạo ra tương tự

tiếp theo, đoạn này sẽ tạo ra 1 khung bao quanh màn hình, khi quả bóng chạm vào sẽ dừng lại. nó giống một bức tường ( 1 cái hộp ) vậy thôi, không cần giải thích nhiều nhé, cứ code mà đập thôi

auto edgeSp = Sprite::create();

auto boundBody = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);

edgeSp->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));

edgeSp->setPhysicsBody(boundBody);

this->addChild(edgeSp);

edgeSp->setTag(0);

Tiếp theo, quan trọng nè

auto Listener = EventListenerPhysicsContact::create(); // Biến này để "lắng nghe" các tương tác vật lý xảy ra

Listener->onContactBegin=CC_CALLBACK_1(HelloWorld::onContactBegin,this); // gọi hàm onContactBegin, hàm này sẽ xử lý khi va chạm xảy ra, hàm này là hàm chồng lên( gọi là hàm overide của 1 hàm mẫu đã có của thư viện - bạn nào học C++ sẽ hiểu rõ).

_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

// dòng này để xử lý ông Listener bên trên kia,

Túm lại đoạn trên đây để phát hiện ra tương tác giữa 2 quả bóng bạn tạo ra, rồi gọi hàm onContactBegin để xử lý.

Bạn mới học thì cứ dập khuôn từng đoạn code, tạm thời đừng hỏi sao phải viết thế, viết khác được không ( Haizzz, ko biết giải đáp thế nào nhỉ). Viết khác được, nhưng hãy nắm chắc cái ban đầu đi đã rồi phát triển sau.

Bây giờ tới hàm onContactBegin{}, format của nó chắc chắn phải viết như sau, sau đó thêm gì thì thêm vào trong 2 dấu ngoặc

bool HelloWorld::onContactBegin(const PhysicsContact &contact)

{

return true;

}

thêm đoạn này vào để xóa 2 quả bóng khi chạm nhau

auto ObjA = (Sprite*)contact.getShapeA()->getBody()->getNode();

auto ObjB = (Sprite*)contact.getShapeB()->getBody()->getNode();

this->removeChild(ObjB,true);

this->removeChild(ObjA,true);

tiếp theo, hàm này this->setAccelerometerEnabled(true); // Gia tốc kế của máy điện thoại

Chạy thử nhé, các bạn đừng quên lệnh này nhé

cocos run -s q:android/project/ball -p win32 

Nếu bạn thấy 2 quả bóng đập vào nhau và biến mất là đã thành công

Bạn thử bỏ dòng lệnh ballBody->setContactTestBitmask(0x1); đi xem, 2 quả bóng có va vào nhau nhưng ko có gì xảy ra phải không. Hehe, mỗi dòng lệnh này mà mình tìm kiếm mất gần tuần. HIX

Vấn đề Physic đã giải quyết xong

Nâng cao lên 1 chút nào

Xóa dòng this->setAccelerometerEnabled(true); và layer->setPhyWorld(scene->getPhysicsWorld());, Xóa tiếp hàm onAcceleration, kết quả ko đổi đúng ko, tốc độ rơi vẫn thế (trên win), 2 quả bóng chạm nhau vẫn biến mất. Lệnh này hình như thiết lập gia tốc kế. Các bạn thử thiết lập và xoay màn hình điện thoại xem nhé. Quả bóng sẽ lăn theo hướng rơi xuống cạnh đáy màn hình

Nhưng thử xóa dòng _ball->setPhysicsBody(ballBody); ball2->setPhysicsBody(ball2Body); Bạn sẽ thấy 2 quả bóng đứng im luôn. Có thể thấy hàm này giống như việc đặt vào quả bóng 1 khối lượng nào đó vậy ( chắc tương đương với bán kính). Quên mất vật nặng nhẹ đều rơi như nhau với gia tốc G mà

Bây giờ thêm lại 2 lệnh setPhysicsBody bên trên, rồi thêm dòng lệnh sau: scene->getPhysicsWorld()->setGravity(Vect(0.0f,-5000.0f)); Bạn sẽ thấy quả bóng rơi rất nhanh, đó, chỗ này chính là thiết lập gia tốc trọng lực, sét càng cao thì rơi càng nhanh.

Như vậy qua bài này, bạn đã biết làm thế nào để thiết lập 1 Physics cơ bản cho chương trình rồi nhé. Sang phiên bản mới ( mình đang xài V3 RC2) bạn chỉ cần nắm mấy lệnh cơ bản sau

auto scene = Scene::createWithPhysics(); // Tạo 1 Scene có thuộc tính Physics ( đã bao gồm gia tốc )

scene->getPhysicsWorld()->setGravity(Vect(0.0f,-3000.0f)); // Thay đổi gia tốc, nhớ là phải có dấu "-"

auto ballBody = PhysicsBody::createCircle(_ball->getContentSize().width);

_ball->setPhysicsBody(ballBody);  // thiết lập thuộc tính vật lý ( cụ thể là khối lượng và ranh giới của vật thể )

ballBody->setContactTestBitmask(0x1);  // Thiết lập sự phát hiện va chạm giữa 2 vật

// và đoạn này để lắng nghe sự va chạm nếu có

auto contactListener = EventListenerPhysicsContact::create();

contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegin, this);

_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

DOWN Mã nguồn và file Resource

Bài 7: Menu - Từ cơ bản tới phức tạp (Part 1)

51 comments:

  1. Replies
    1. Bài 6 - Ball - Physics Cơ Bản Trong Cocos2Dx -V3 (Part2) ~ Cùng Tôi Học Lập Trình Game Với Cocos2Dx >>>>> Download Now

      >>>>> Download Full

      Bài 6 - Ball - Physics Cơ Bản Trong Cocos2Dx -V3 (Part2) ~ Cùng Tôi Học Lập Trình Game Với Cocos2Dx >>>>> Download LINK

      >>>>> Download Now

      Bài 6 - Ball - Physics Cơ Bản Trong Cocos2Dx -V3 (Part2) ~ Cùng Tôi Học Lập Trình Game Với Cocos2Dx >>>>> Download Full

      >>>>> Download LINK jC

      Delete
  2. OK men, cũng đang nhiều việc, hix

    ReplyDelete
    Replies
    1. #ifndef __HELLOWORLD_SCENE_H__
      #define __HELLOWORLD_SCENE_H__

      #include "cocos2d.h"

      class HelloWorld : public cocos2d::Layer
      {
      public:
      static cocos2d::Scene* createScene();

      virtual bool init();

      // a selector callback
      void menuCloseCallback(cocos2d::Ref* pSender);

      // implement the "static create()" method manually
      CREATE_FUNC(HelloWorld);
      };

      #endif // __HELLOWORLD_SCENE_H__
      code mình mở lên chỉ có nhiêu đây

      Delete
    2. This comment has been removed by the author.

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Bạn ơi với ball trong ví dụ của bạn mình xét applyImpulse với một Vect khá lớn thì ball vượt ra khỏi khung bao màn hình.Làm thế nào để biết độ lớn giới hạn tác động vào khung bao màn hình ko nhỉ ?

    ReplyDelete
  5. Ủa, trong bài 5 - 6 Physics cơ bản này, mình đâu có đề cập tới ApplyImpulse nhỉ, bạn lấy nó ở ví dụ khác rồi.

    Để xác định khung màn hình thì tạo 1 cái body bằng kích thước của màn hình
    auto size = Director::getInstance()->getVisibleSize();
    auto boundBody = PhysicsBody::createEdgeBox(size, PHYSICSBODY_MATERIAL_DEFAULT, 3);

    vậy thôi, khi đó quả bóng ko thể ra khỏi khung màn hình được

    ReplyDelete
  6. Cái này sử dụng chipmunk hả bạn?

    ReplyDelete
    Replies
    1. Chính hắn, Chipmunk mặc định được Engine sử dụng nhé. Ngoài ra còn có Box2D nữa. Những bài sau mình sẽ giới thiệu sau.

      Delete
  7. khi nào ra lò bài 7 thế bạn :)

    ReplyDelete
    Replies
    1. Tìm kiếm nhé bạn ơi, hoặc vào link "Trang chủ" có bài mới nhất

      Sắp ra tới bài 17 rồi, link cuối từng bài là do mình quên cập nhật thôi, Hiz

      Delete
  8. Mình đã down file và làm như bạn hướng dẫn như không hiểu tại sao lúc chạy lại thì bị lỗi không chạy được Lúc Build thì cũng báo thành công (0 warning, 0 Error) có một câu lệnh trong cmd sau cùng sau khi build xong: Error running command, return code: -1073741819. Bạn sửa giùm mình với.

    ReplyDelete
    Replies
    1. Mình đã Down lại code, tạo lại 1 project khác với Cocos2d-x V3.1.1 mới nhất, copy Class, Resource vào, build lại và chạy vẫn OK nhé bạn ơi ( Win7 -32).

      Hay bạn quên Resource?

      Delete
    2. ok mình đã sửa được rồi. Thanks bạn nhiều

      Delete
    3. Tiện thể cho mình hỏi bạn dùng IDE gì để lập trình cocos2dx có IDE gì để nó hỗ trợ cocos2dx qua đó cho phép hỗ trợ sinh ra các gợi ý của thư viện cocos2dx này. Chẳng hạn mình #include "cocos2d.h" thì có IDE nào nó sẽ hỗ trợ khi mình sư dụng các class trong cocos2d.h nó sẽ sinh ra gợi ý ấy giúp cho mình dễ viết code hơn cơ chế nó tương tự vs studio ấy

      Delete
    4. OK, cái này dễ nhé bạn.

      Bạn dùng Mac OS thì IDE là Xcode ( mình ko rõ có phải cài thêm Plugin gì ko - vì ko xài ) nhưng nó tính năng auto code, + giải thích các Function luôn

      Bạn dùng Win, thì ngon nhất là VS 2012 ( hoặc 13) + Visual Assix 10.8.2001 ( có Crack) là ngon luôn. Thằng Visual Assix này rất hay, nó "chọc" thẳng vào Engine Cocos, vào thư viện rồi các Extention để hỗ trợ sinh ra AutoCode. Trong bài 3 mình có giới thiệu dùng thằng này mà. Code sướng, nhàn lắm.

      Tuy nhiên với Beginer thì nên code tay = Notepad++ 1 thời gian cho quen tay phím rồi hãy dùng các IDE trên

      Delete
    5. Bạn Trần Xuân ơi mình cài Visual Assist vào rồi nhưng mình gõ ctrl + space nát luôn mà nó vẫn ko autocode hay show suggestions gì hết. Mình cũng ko thể xem được định nghĩa hàm và các đối số khi để chuột vào tên hàm. Mình down bản 10-8-2043 tại đây http://sinhvienit.net/forum/visual-assist-x-10-8-2043-full-c-r-a-c-k-e-d.331415.html. Nó có cần set up gì thêm ko bạn?

      Delete
  9. Bạn giải thích giùm mình cái từ khóa auto với mình thấy bạn sử dụng cái từ này khá nhiều
    từ auto Scene, rồi auto Layer mình không hiểu lắm

    ReplyDelete
    Replies
    1. auto là 1 biến từ nhé, nó là từ khóa của C, C++ bình thường thôi.

      Có 5 loại biến từ: auto, register, static, extern, và volatile. Biến từ dùng để xác định phạm vi hoạt động của biến trong chương trình, và đối với các hàm khi được khai báo

      - auto : kiểu mặc định của các biến được khai báo, biến khai báo kiểu auto trong hàm sẽ bị hủy giá trị khi thoát khỏi hàm.sử dụng loại này là dễ hiểu nhất. Trong các hàm của Cocos hay dùng mà chẳng cần quan tâm lắm tới Kiểu của biến nhỉ => đôi khi gây khó hiểu vì không nhớ biến mình tạo ra thuộc lớp nào. Nhiều lúc tiện tay cứ auto hết luôn ( mình toàn thấy dùng với các lớp, chứ ít thấy dùng với các kiểu dữ liệu cơ bản như int, float, double,...)


      - static : biến được khai báo trong loại này thì chỉ có thể truy xuất từ hàm mà nó khai báo, giá trị của biến sẽ được lưu giữ lại khi thoát khỏi hàm. Thường dùng để lưu trữ, hoặc dùng làm biến chung cho cả 1 LỚP

      Các loại dưới mình cũng ít gặp trong Cocos
      - register : các biến được khai báo loại này sẽ được lưu trữ ở vùng thanh ghi mà có tốc độ truy xuất cao nhất biến sẽ bị hủy khi ra khỏi hàm.
      - extern : dùng để khai báo các biến nằm ở các source file khác.
      - volatile : ngược lại với kiểu register, biến được khai báo loại này sẽ được lưu trữ ở những vùng nhớ bình thường (Ram).

      Vậy đó, hãy tìm trong sách hoặc search "Phạm vi hoạt động của biến trong C++" để biết thêm chi tiết

      Delete
    2. Vậy thì có auto hay bỏ đi có được không ạ?

      Delete
  10. *Có đoạn lệnh mình không hiểu lắm bạn giải thích giùm mình với (lâu rồi mới ôn lại C++)
    câu lệnh tạo ballbody(file hellowordscene.cpp)
    PhysicsBody* ball2Body = PhysicsBody::createCircle(ball2->getContentSize().width/2);
    Ở đây tham số trong hàm createCircle ở trên chỉ có 1 tham số. Trong khi đó mình tìm đến file include của nó thì tham số truyền vào có đến 3 tham số (câu lệnh dưới) radius, material, offset
    PhysicsBody* PhysicsBody::createCircle(float radius, const PhysicsMaterial& material, const Point& offset)
    Tại sao câu lệnh tạo ballbody phía trên vẫn chạy được dù không đủ số lượng các tham số mà ở đây là 3 tham số?
    *Và thêm một đoạn nữa ở file hellowordscene.h có đoạn:
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
    Trong file helloworldscene.cpp cách gọi lại là
    HelloWorld* layer = HelloWorld::create();
    Thì ở đây rõ ràng đoạn HelloWorld::create(); nó sẽ gọi đến hàm CREATE_FUNC(HelloWorld); Tại sao lại như vậy gọi create nhưng lại chỉ qua CREATE_FUNC
    ở đây mình chưa thấy bạn khai báo hàm create() không biết hàm này ở đâu ra ?

    ReplyDelete
  11. + PhysicsBody* ball2Body = PhysicsBody::createCircle(ball2->getContentSize().width/2);

    Ở lệnh này mình cũng chưa coi lại thư viện hàm của nó, nhưng mình chắc chắn là, 2 tham số còn lại là mặc định. Bạn hãy nghiên cứu "Tham số mặc định của hàm" trong C ++. Như này

    Function(int a, int b=0, int c = 1) =>khi gọi Function(a) thì b, c mặc định là 0,1.
    bạn có thể gọi Function(a,b) hoặc Function(a,b,c) nhưng ko thể gọi Function() vì tham số a không có giá trị mặc định nào. OK chưa

    + HelloWorld::create(); không phải gọi create() của lớp HelloWorld mà gọi create() của lớp Layer. HelloWorld là lớp dẫn xuất của Layer nên nó kế thừa các hàm cơ bản của lớp Layer này nhé, vì thế ko cần khai báo create() là 1 hàm mới của HelloWorld, được "cha mẹ cho" thì xài thôi.

    + CREATE_FUNC(HelloWorld);

    bạn có thể không cần lệnh này

    Tìm hiểu ở đây về CREATE_FUNC http://discuss.cocos2d-x.org/t/using-create-func/11781/2

    ReplyDelete
  12. Nếu mình muốn quả bóng rơi mà ko bị nhảy lên thì làm thế nào vậy bạn... Mh muốn quả bóng rơi thì nó nằm đo luôn ấy...

    ReplyDelete
  13. bạn cho mình hỏi, vì sao khi 2 quả bóng va chạm thì nó ko tự xóa như theo code nhỉ?
    http://i.imgur.com/vSYHNih.png

    ReplyDelete
    Replies
    1. Ảnh bạn up như vậy thì sao biết lỗi ở đâu, code bạn như nào mới được?

      Delete
    2. code của mình giống của bạn cho mà :) . nếu trùng tọa độ của ball ngay ban đầu thì nó xóa 2 ball. còn nếu ko trùng thì lúc sau 2 ball va chạm sẽ ko bị xóa, thanks bạn :)

      Delete
    3. bạn có thể cho mình địa chỉ facebook hay email để mình liên lạc nhờ bạn giúp đỡ được không?
      https://www.facebook.com/ducthien2811 đây là facebook của mình, hi vọng nhận được sự giúp đở của bạn :)

      Delete
    4. #include "HelloWorldScene.h"
      #include "AppMacros.h"

      Scene* HelloWorld::createScene()
      {

      auto sceneball = Scene::createWithPhysics();// tạo 1 cảnh có thêm các thuộc tính vật lý

      sceneball->getPhysicsWorld()->setGravity(Vect(0.0f, -3000.0f)); // trong cảnh đó các thuộc tính vật lý có giá trị như bên
      auto layer = HelloWorld::create();
      layer->setPhyWorld(sceneball->getPhysicsWorld()); // trong cảnh đó có layer và layer này dc thiết lập thuộc tính vật lý đó?

      //->>>>cho mình hỏi tại sao xóa dòng trên thì bóng vẫn di chuyển????


      sceneball->addChild(layer);

      return sceneball;
      }

      // on "init" you need to initialize your instance
      bool HelloWorld::init()
      {
      //////////////////////////////
      // 1. super init first
      if (!Layer::init())
      {

      return false;
      }

      auto visibleSize = Director::getInstance()->getVisibleSize();

      auto origin = Director::getInstance()->getVisibleOrigin();

      _ball = Sprite::create("Ball.jpg", Rect(0, 0, 52, 52));
      _ball->setPosition(Point(20, 40));
      auto ballBody = PhysicsBody::createCircle(_ball->getContentSize().width / 2);
      ballBody->setContactTestBitmask(0x1);
      _ball->setPhysicsBody(ballBody);// gắn các thuộc tính của ballBody cho _ball
      this->addChild(_ball);

      auto _ball1 = Sprite::create("Ball.jpg", Rect(0, 0, 52, 52));
      _ball1->setPosition(Point(110,110));
      auto ballBody1 = PhysicsBody::createCircle(_ball1->getContentSize().width/2);
      ballBody->setContactTestBitmask(0x1);
      _ball1->setPhysicsBody(ballBody1);
      this->addChild(_ball1);

      auto edgeSp = Sprite::create();
      auto boundBody = PhysicsBody::createEdgeBox(visibleSize, PHYSICSBODY_MATERIAL_DEFAULT, 3);
      edgeSp->setPosition(Point(visibleSize.width/2, visibleSize.height/2));// có phải biên được vẽ từ tọa độ tâm của hình???
      edgeSp->setPhysicsBody(boundBody);
      this->addChild(edgeSp);
      edgeSp->setTag(0); //---------------------------> bạn cho mình hỏi đây là gì??????

      /*auto Listener=EventListenerPhysicsContactWithGroup::create(100);

      auto Listener=EventListenerPhysicsContactWithBodies::create(ball2->getPhysicsBody(), _ball->getPhysicsBody());*/

      auto contactListener = EventListenerPhysicsContact::create();
      contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegin, this);
      _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

      // gốc tọa độ là xét theo node cha
      // vị trí của 1 hình là dc xét theo tâm của hình đó

      return true;
      }


      void HelloWorld::onAcceleration(Acceleration* acc, Event* unused_event)
      {
      //this->setAccelerometerEnabled(true);
      }
      bool HelloWorld::onContactBegin( PhysicsContact &contact)
      {
      auto ObjA = (Sprite*)contact.getShapeA()->getBody()->getNode();
      auto ObjB = (Sprite*)contact.getShapeB()->getBody()->getNode();
      this->removeChild(ObjA, true);
      this->removeChild(ObjB, true);
      return true;
      }

      Delete
    5. edgeSp->setTag(0); // 1 cách để phân biệt các đối tượng với nhau = getTag()
      edgeSp->setTag(kSAN); chẳng hàn, kSAN được định nghĩa qua enum


      Ko đặt trùng tọa độ, rơi xuống sàn rồi lăn chạm vào nhau, ko xử lý va chạm à?

      Delete
    6. ballBody->setContactTestBitmask(0x1); mình có xem ở trên, thấy bạn bảo cái này là để phát hiện va chạm mà?

      Delete
    7. Chính xác là như này nhé

      + setContactTestBitmask là để set khả năng va chạm cho 2 vật thể ( ví dụ vật thể A có bitmask giống vật B = x chẳng hạn, thì mới xử lý va chạm, rồi mới xét đến Tag). Tag có thể hiểu là: vật thể đó tên là gì? loại nào, tùy mình quy định.

      + Nếu 2 vật không cùng bitmask thì ko thể bắt contact trong va chạm được, ko xử lý event được nhé, và Tag cũng chẳng để làm gì

      + BitMask được tính theo phép AND từng bit nhé, bạn dùng VS + VAX thì chỉ chuột vào hàm nó sẽ hiện ra chú thích

      + Bạn ko đặt bitmask xem có gì xảy ra ko là biết ngay

      Delete
    8. bạn cho mình hỏi với, khi create xong cái khung để giới hạn di chuyển của 2 quả bóng, thì câu lệnh nào để kiểm tra sự va chạm giữa khung và bóng. Câu lệnh nào để ngăn cho 2 quả bóng ko vượt qua được khung vậy?
      - mình có thay đổi:
      +ballBody->setContactTestBitmask(0x1);
      +ballBody1->setContactTestBitmask(2);
      +xóa dòng edgeSp->setTag(0);
      ->nó vẫn hoạt động bình thường. vì sao vậy bạn?

      -còn nếu thay đổi:
      xóa 2 dòng:
      + ballBody->setContactTestBitmask(0x1);
      + ballBody1->setContactTestBitmask(0x1);
      thì nó ko hoạt động. cái này giống với bạn nói

      Delete
  14. mình fix dc lỗi rồi, thanks bạn. thì ra là do thằng này
    ballBody->setContactTestBitmask(0x1);
    sửa lại thành
    ballBody1->setContactTestBitmask(0x1);

    ReplyDelete
  15. Sao ad ko làm 1 cái mục lục link đến từng bài phía bên phải web, cho ae để mở bài nhỉ!

    ReplyDelete
    Replies
    1. Có nút "Bài mới" kìa bạn ơi. chỗ ba cái Tab, ngay dưới search

      Delete
  16. _ball = Sprite::create("Ball.jpg", Rect(0, 0, 52, 52));

    cho mình hỏi cái Ball.jpg add vào chương trình như thế nào vậy, hay là chép vào thư mục nào

    thanks bạn

    ReplyDelete
  17. Cho mình hỏi, mình build code qua android thì ok nhưng mình bỏ file apk zô máy ảo chạy thì nó lỗi là sao bạn

    ReplyDelete
    Replies
    1. Máy ảo ko chạy được nhé, hình như do OpenGL, test máy thật đi, giờ hầu như ai chả có máy android

      Delete
  18. sao cái source trên lại không dùng được cho cocos v2.2.3 bạn nhỉ?

    ReplyDelete
  19. cho em hỏi với em viết đoạn code tới
    _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);
    thì máy báo lỗi
    "use of undeclared identifier oncontactListener" trong đó em làm y hệt của anh ah??

    ReplyDelete
    Replies
    1. Bạn copy thêm 1 đoạn code nữa đi :) Mình cũng đang học nà

      Delete
  20. This comment has been removed by the author.

    ReplyDelete
  21. Bạn ơi, mình đã làm theo bài 5 nhưng khi build ra thì 2 file .cpp và .h không giống như của bạn mà y chang file hello world. Nếu vậy thì mình phải tự code tay để thay đổi hay như thế nào.
    Thanks bạn!

    ReplyDelete
  22. Bạn ơi cho mình hỏi là mấy cái hàm có sẵn đó là có sẵn trong source gả bạn?
    Vậy mình làm sao biết được hàm nào có sẵn trong source và sao biết tính chất hàm đó dùng để làm gì mà truy xuất tới?

    ReplyDelete
  23. This comment has been removed by the author.

    ReplyDelete
  24. This comment has been removed by the author.

    ReplyDelete
  25. http://prntscr.com/8veuzi Em bị cái lỗi này. ai giúp em với, em cám ơn

    ReplyDelete
  26. This comment has been removed by the author.

    ReplyDelete
  27. Bài 6 - Ball - Physics Cơ Bản Trong Cocos2Dx -V3 (Part2) ~ Cùng Tôi Học Lập Trình Game Với Cocos2Dx >>>>> Download Now

    >>>>> Download Full

    Bài 6 - Ball - Physics Cơ Bản Trong Cocos2Dx -V3 (Part2) ~ Cùng Tôi Học Lập Trình Game Với Cocos2Dx >>>>> Download LINK

    >>>>> Download Now

    Bài 6 - Ball - Physics Cơ Bản Trong Cocos2Dx -V3 (Part2) ~ Cùng Tôi Học Lập Trình Game Với Cocos2Dx >>>>> Download Full

    >>>>> Download LINK

    ReplyDelete