STDIO
Tìm kiếm gần đây

    Nội dung

    Box2D - Phần 6: Ray Casting

    23/01/2015
    07/04/2017
    Box2D - Phần 6: Ray Casting
    Tiếp tục loạt bài viết giới thiệu về thư viện vật lý trò chơi Box2D. Bài viết này giới thiệu một thành phần của Box2D là Ray Casting. Ray Casting là gì? Nhiệm vụ của nó trong mô phỏng thế giới vật lý? Cách tạo? Ví dụ về Ray Casting được sự hỗ trợ của Cocos2d-x.

    Giới thiệu

    Trong các loạt bài viết trước tìm hiểu về thư viện vật lý trò chơi Box2D, tôi đã giới thiệu về các thuật ngữ và các khái niệm cơ bản. Tiếp tục loạt bài viết tìm hiểu về Box2D, trong bài viết này tôi tiếp tục giới thiệu một thành phần đó là Ray Casting. Khái niệm, thành phần và ví dụ về Ray Casting, đó là nội dung mà tôi sẽ giới thiệu trong bài viết này.

    Tiền đề bài viết

    Bài viết nằm trong loạt bài viết tìm hiểu về thư viện vật lý trò chơi Box2D.

    Bài viết nằm trong những loạt bài viết của chương trình Tự Học Cocos2d-x 3.x.x:: www.stdio.vn/programs/content/2/lap-trinh-game-voi-cocos2dx của Stdio.vn :: www.stdio.vn.

    Đối tượng hướng đến

    Bài viết này tôi hướng đến các lập trình viên đã có kiến thức cơ bản về lập trình games 2D, có kinh nghiệm làm việc với Box2D trong các bài viết trước và chưa có kiến thức tương đương.

    Ray Casting là gì?

    Là một đoạn thẳng, được xác định trong Physics World. Có tác dụng tìm ra các đối tượng đang ở trong một phần nhất định của Physics World. Bạn có thể tưởng tượng rằng Ray Casting khá giống với rada.

    Thành phần

    Input

    Là thành phần mà bạn xác định khởi tạo.

    • position1
    • position2
    • maxFraction
    Phân tích
    • Với position1 và position2 bạn có thể xác định được hướng của Ray Casting. Có điểm đầu là position1 và điểm cuối là position2.
    • Bạn có khoảng cách của position1 và position2 là một giá trị lenght. Lúc này, độ dài của Ray Casting bằng giá trị của length*maxFraction.

    Output

    Là thành phần mà bạn nhận được khi Ray Casting bị một đối tượng cắt qua.

    • normal
    • fraction

    ss_1

    Ví dụ

    Khởi tạo dự án của bạn. Ở trong dự án đó sẽ có các file như sau:

    ss_2

    Với các file GLES-Render.h và GLES-Render.cpp có tác dụng vẽ những gì liên quan tới Physics World. Bạn có thể download ở phần Download của bài viết.

    Header

    Trong file HelloWorldScene.h tôi có như sau:

    #ifndef __HelloWorld_Scene_h__
    #define __HelloWorld_Scene_h__
    
    #define PTM_RATIO 32
    
    #include "cocos2d.h"
    #include "Box2D\Box2D.h"
    #include "GLES-Render.h"
    
    USING_NS_CC;
    
    using namespace cocos2d::ui;
    
    class RayCastMultipleCallback : public b2RayCastCallback {
    public:
    	enum {
    		e_maxCount = 3
    	};
    
    	RayCastMultipleCallback() {
    		m_count = 0;
    	}
    
    	float32 ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float32 fraction) {
    		b2Body* body = fixture->GetBody();
    		void* userData = body->GetUserData();
    		if (userData) {
    			int32 index = *(int32*)userData;
    			if (index == 0)
    				return -1.0f;
    		}
    
    		b2Assert(m_count < e_maxCount);
    
    		m_points[m_count] = point;
    		m_normals[m_count] = normal;
    		++m_count;
    
    		if (m_count == e_maxCount)
    			return 0.0f;
    		return 1.0f;
    	}
    
    	b2Vec2 m_points[e_maxCount];
    	b2Vec2 m_normals[e_maxCount];
    	int32 m_count;
    };
    
    class RayCastClosestCallback : public b2RayCastCallback {
    public:
    	RayCastClosestCallback() {
    		m_hit = false;
    	}
    
    	float32 ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float32 fraction) {
    		b2Body* body = fixture->GetBody();
    		void* userData = body->GetUserData();
    		if (userData) {
    			int32 index = *(int32*)userData;
    			if (index == 0)
    				return -1.0f;
    		}
    
    		m_hit = true;
    		m_point = point;
    		m_normal = normal;
    		return fraction;
    	}
    
    	bool m_hit;
    	b2Vec2 m_point;
    	b2Vec2 m_normal;
    };
    
    class HelloWorld : public cocos2d::Layer, public b2ContactListener {
    public:
        static cocos2d::Scene* createScene();
        virtual bool init();
    	void update(float dt);
    
    	void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags);
    	void onDraw(const Mat4 &transform, uint32_t flags);
    
    	void addbox(float, float);
    	
        CREATE_FUNC(HelloWorld);
    
    private:
    	b2World* m_world;
    	float32 m_angle;
    	GLESDebugDraw* debugDraw;
    	CustomCommand _customCmd;
    };
    
    #endif // __HelloWorld_Scene_h__
    
    Phân tích
    • Dòng 14-72: Tôi hiện thực 2 loại Ray Casting. Mỗi loại có một tác dụng, tác dụng của từng loại tôi sẽ nói đến ở phần sau.

    Source

    Trong file HelloWorldScene.cpp, bạn chỉ cần thật sự chú ý tới hàm update().

    void HelloWorld::update(float dt) {
    
        int positionIterations = 10;  // Vị trí
        int velocityIterations = 10; // Vận tốc
    
        float deltaTime = dt; // Bước thời gian
    
        std::vector<b2Body *>toDestroy;
       	m_world->Step(dt, velocityIterations, positionIterations);
    
        for (b2Body *body = m_world->GetBodyList(); body != NULL; body = body->GetNext()) {
    	if (body->GetUserData()) {
    		Sprite *sprite = (Sprite *)body->GetUserData();
    		sprite->setPosition(Point(body->GetPosition().x * PTM_RATIO, body->GetPosition().y * PTM_RATIO));
    		sprite->setRotation(-1 * CC_RADIANS_TO_DEGREES(body->GetAngle()));
        }
    		
    	m_world->ClearForces();
    	m_world->DrawDebugData();
        }
    
    
    	float32 L = 11.0f;
        b2Vec2 point1(10.0f, 10.0f);
        b2Vec2 d(L * cosf(m_angle), L * sinf(m_angle));
        b2Vec2 point2 = point1 + d;
    
        // Loại 1
        /*RayCastAClosestCallback callback; 
        m_world->RayCast(&callback, point1, point2);
    
        if (callback.m_hit) {
            debugDraw->DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f));
    		debugDraw->DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f));
    		b2Vec2 head = callback.m_point + 0.5f * callback.m_normal;
    		debugDraw->DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f)); 
    	} else {
    		debugDraw->DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f));
    	}*/
    
        //Loại 2
        /*RayCastMultipleCallback callback;
    	m_world->RayCast(&callback, point1, point2);
    	debugDraw->DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f));
    
    	for (int32 i = 0; i < callback.m_count; ++i) {
    		b2Vec2 p = callback.m_points[i];
    		b2Vec2 n = callback.m_normals[i];
    		debugDraw->DrawPoint(p, 5.0f, b2Color(0.4f, 0.9f, 0.4f));
    		debugDraw->DrawSegment(point1, p, b2Color(0.8f, 0.8f, 0.8f));
    		b2Vec2 head = p + 0.5f * n;
    		debugDraw->DrawSegment(p, head, b2Color(0.9f, 0.9f, 0.4f));
    	}*/
    	m_angle += 0.25f * b2_pi / 180.0f;
    }
    Phân tích
    • Dòng 3-21: Những đoạn code này có lẽ rất quen với các bạn. Nó chỉ đơn giản là sự cập nhật của Physics World.
    • Dòng 23-26: Ở đây tôi đang xác định điểm đầu, điểm cuối. Điểm đầu là một điểm cho trước, điểm cuối được xác định bởi độ dài Ray Casting với điểm đầu.
    • Dòng 29-53: Đây là lần lượt các Ray Casting mà tôi sử dụng. Tôi sẽ sử dụng dần từ trên xuống dưới để bạn có thể thấy được tác dụng của 2 loại Ray Casting này.

    Tổng kết

    Sau khi lần lượt sử dụng các loại Ray Casting ở phần Ví dụ tôi có các kết quả sau:

    Loại 1

    ss_4

    Loại 2

    ss_3

    Mọi thắc mắc bạn có thể bình luận tại bài viết hoặc liên hệ với Trương Đạt :: www.stdio.vn/users/index/11/truong-dat.

    Download

    RayCasting_Example

    Tham khảo

    http://www.cocos2d-x.org

    Thảo luận

    Đăng nhập

    Bài viết liên quan

    Chipmunk - Phần 5: Ray Casting

    Chipmunk - Phần 5: Ray Casting

    Tiếp tục loạt bài viết giới thiệu về thư viện vật lý trò chơi Chipmunk. Trong bài viết này tôi sẽ giới thiệu về một thành phần mới là Ray Casting ...

    Trương Xuân Đạt

    23/01/2015

    Làm Sao Để Chia Tách, Cắt Một Đối Tượng Với Box2D?

    Làm Sao Để Chia Tách, Cắt Một Đối Tượng Với Box2D?

    Bạn cần một sự chia tách, cắt một đối tượng trong thế giới games có vật lý của bạn, hoặc có thể hơn bạn cần một một vụ nổ thật sự. Trong bài ...

    Trương Xuân Đạt

    23/01/2015

    Box2D - Phần 1: Giới Thiệu Và Một Số Thuật Ngữ Và Khái Niệm

    Box2D - Phần 1: Giới Thiệu Và Một Số Thuật Ngữ Và Khái Niệm

    Giới thiệu về engine vật lý sử dụng trong games là Box2D. Giới thiệu Box2D, các khái niệm, cách thành phần liên quan, cách khởi tạo và thao tác với một số thành phần ...

    Trương Xuân Đạt

    23/01/2015

    Box2D - Phần 2: Thuật Ngữ Và Khái Niệm

    Box2D - Phần 2: Thuật Ngữ Và Khái Niệm

    Tiếp tục loạt bài viết tìm hiểu về thư viện vật lý trò chơi Box2D. Trong bài viết này giới thiệu về collision, bắt sự kiện collision, collision filtering và hiện thực, ...

    Trương Xuân Đạt

    23/01/2015

    Box2D - Phần 3: Joint

    Box2D - Phần 3: Joint

    Tiếp tục chuỗi bài viết giới thiệu về Box2D. Bài viết giới thiệu về joint, tác dụng, cách khởi tạo, thiết lập cài đặt, cách kiểm soát và nhận ...

    Trương Xuân Đạt

    23/01/2015

    Box2D - Phần 5: Joint (Tiếp Theo)

    Box2D - Phần 5: Joint (Tiếp Theo)

    Tiếp tục chuỗi bài viết giới thiệu về thư viện vật lý trò chơi Box2D. Bài viết này giới thiệu về các loại joint có sẵn trong Box2D về khái niệm, ...

    Trương Xuân Đạt

    23/01/2015

    Box2D - Phần 4: Joint (Tiếp Theo)

    Box2D - Phần 4: Joint (Tiếp Theo)

    Bài viết nằm trong loạt bài viết tìm hiểu về thư viện vật lý trò chơi Box2D. Bài viết này sẽ giới thiệu các loại joint có sẵn trong Box2D. Các ...

    Trương Xuân Đạt

    23/01/2015

    CBP-7: Cài Đặt Phản Ứng Cho Entity

    CBP-7: Cài Đặt Phản Ứng Cho Entity

    Thiết lập phản ứng của Entity nhằm điều khiển các Component. Mỗi Entity đều có một phản ứng riêng biệt, tùy thuộc vào người định nghĩa nó, hệ thống phản ứng này sẽ giúp ...

    Tuấn Trần

    20/08/2015

    Chipmunk - Phần 1: Giới Thiệu

    Chipmunk - Phần 1: Giới Thiệu

    Bài viết này trong loạt bài viết của tôi giới thiệu về thư viện vật lý trò chơi Chipmunk. Trong bài viết này sẽ giới thiệu các khái niệm và thuật ...

    Trương Xuân Đạt

    23/01/2015

    STDIO Starter Kit - Các Thành Phần Cần Thiết Để Học Điện Tử Cơ Bản

    STDIO Starter Kit - Các Thành Phần Cần Thiết Để Học Điện Tử Cơ Bản

    Bộ STDIO Starter Kit là bộ kit điện tử thống kê các thành phần cần thiết nhất cho người mới bắt đầu học điện tử bao gồm các bài hướng dẫn lập trình, sử dụng từng thành ...

    Điện Tử Ứng DụngSản phẩm

    19/10/2014

    STDIO
    Trang chính
    Công ty TNHH STDIO

    30, Trịnh Đình Thảo, Hòa Thạnh, Tân Phú, Hồ Chí Minh
    +84 28.36205514 - +84 942.111912
    [email protected]

    383/1 Quang Trung, Phường 10, Quận Gò Vấp, Hồ Chí Minh
    Số giấy phép ĐKKD: 0311563559 do sở Kế hoạch và Đầu Tư TPHCM cấp ngày 23/02/2012

    ©STDIO, 2013 - 2020