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
Ví dụ
Khởi tạo dự án của bạn. Ở trong dự án đó sẽ có các file như sau:
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
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: