STDIO
Tìm kiếm gần đây
    Nội dung
    0
    0
    Chia sẻ
    Nội dung
    0
    0
    Chia sẻ

    Box2D - Phần 6: Ray Casting

    Giới thiệu Ray Casting và nhiệm vụ của nó trong mô phỏng thế giới vật lý?
    23/01/2015 30/09/2020 4 phút đọc
    Box2D - Phần 6: Ray Casting

    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, 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.hGLES-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 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: 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 sẽ nói đến ở phần sau.

    Source

    Trong file HelloWorldScene.cpp, 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: sự cập nhật của Physics World.
    • Dòng 23-26: 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 được sử dụng.

    Tổng kết

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

    Loại 1

    ss_4

    Loại 2

    ss_3
    0 Bình luận
    Lập Trình Game

    Lập Trình Game

    Kiến thức, kỹ thuật, kinh nghiệm lập trình game.

    Khi bạn nhấn vào sản phẩm do chúng tôi đề xuất và mua hàng, chúng tôi sẽ nhận được hoa hồng. Điều này hỗ trợ chúng tôi có thêm kinh phí tạo nhiều nội dung hữu ích. Tìm hiểu thêm.
    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
      developer@stdio.vn
    • 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 - 2021