1

我尝试了一些从互联网上收集到的关于如何设置光线投射的不同方法,但无论我做什么,我都无法注册任何类型的连接。这里发生了什么?世界设置正确(例如,事物出现并碰撞等等),但光线投射似乎从未检测到任何东西,我尝试了三种不同的方法(两种略有不同)。为了完整起见,我将包括我的测试用例和附属类(你们中的一些人可能会认出 Ray Wenderlich 的设置):

ccLayer 标头

//B2dtest.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "Box2D.h"
#import "GLES-Render.h"
#import "MyContactListener.h"
#define PTM_RATIO 16
@interface B2dTest : CCLayer {
b2World* world;                 // strong ref
GLESDebugDraw *m_debugDraw;
MyContactListener *_contactListener;
b2Body* groundBody;
b2Body* wallBody;
DataModel *m;
float rayAngle;
b2Vec2 p1;
b2Vec2 p2;
b2Vec2 intersectionPoint;
}
+(CCScene *) scene;
-(void)initPhysics;
@end

ccLayer 类(最有可能在更新中出现问题的代码)

//B2dtest.mm
#import "B2dTest.h"
#import "RaysCastCallback.h"
#import "OtherCast.h"
enum {kTagParentNode = 1,};

@implementation B2dTest
+(CCScene *) scene
{
CCScene *scene = [CCScene node];
B2dTest *layer = [B2dTest node];
[scene addChild: layer];
return scene;
}
-(id) init
{
if( (self=[super init])) {
    [self initPhysics];
    [self addBarrier];
    [self scheduleUpdate];
}
return self;
}

-(void) initPhysics
{
CGSize s = [[CCDirector sharedDirector] winSize];
b2Vec2 gravity;
gravity.Set(0.0f, -21.0f);  //was ten
world = new b2World(gravity);
_contactListener = new MyContactListener();
world->SetContactListener(_contactListener);
world->SetAllowSleeping(true);
world->SetContinuousPhysics(true);  
m_debugDraw = new GLESDebugDraw( PTM_RATIO );
world->SetDebugDraw(m_debugDraw);
uint32 flags = 0;
flags += b2Draw::e_shapeBit;
m_debugDraw->SetFlags(flags);       
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0); // bottom-left corner
groundBody = world->CreateBody(&groundBodyDef);
b2EdgeShape groundBox;  
groundBox.Set(b2Vec2(0,s.height/PTM_RATIO/3), b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO/3));
b2FixtureDef fixtureDef;
fixtureDef.filter.categoryBits = 0x0004;
fixtureDef.filter.maskBits = 0x0002;
fixtureDef.shape = &groundBox;
fixtureDef.density = 0;
fixtureDef.restitution = 0.0f;
groundBody->CreateFixture(&fixtureDef);
}

-(void)addBarrier{
b2BodyDef bodyDef;
bodyDef.type = b2_staticBody;
wallBody = world->CreateBody(&bodyDef);
for (int i = 0; i < 2;i++){
    b2PolygonShape platform;
    platform.SetAsBox(2, .25, b2Vec2(12+ (i * 5), 9 + i),0);
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &platform;
    wallBody->CreateFixture(&fixtureDef);
}
}

-(void) draw{
ccDrawLine(ccp(p1.x,p1.y), 
           ccp(p2.x,p2.y));
[super draw];
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
kmGLPushMatrix();
world->DrawDebugData(); 
kmGLPopMatrix();
}


-(void) update: (ccTime) dt{
int32 velocityIterations = 4;
int32 positionIterations = 1;
world->Step(dt, velocityIterations, positionIterations);    
rayAngle = rayAngle + (2 * (M_PI / 180));
float rayLength = 200;
p1 = b2Vec2( 240, 240 ); //center of scene
p2 = p1 + rayLength * b2Vec2( sinf(rayAngle), cosf(rayAngle) );

RaysCastCallback callback;  //FIRST RAYCAST METHOD
world->RayCast(&callback, p1, p2);
if (callback.m_fixture){
    CCLOG(@"OH YESAAH!");
    p2 = b2Vec2(callback.m_point.x * PTM_RATIO, callback.m_point.y * PTM_RATIO);   
}

OtherCast allback; //SECONDRAYCASTMETHOD
world->RayCast(&allback, p1, p2);
if (allback.m_hit){
    CCLOG(@"OH YESAAH! AD");
    //   p2 = b2Vec2(callback.m_point.x * PTM_RATIO, callback.m_point.y * PTM_RATIO);   
}

b2RayCastInput input; //THIRDRAYCASTMETHOD
input.p1 = p1;
input.p2 = p2;
input.maxFraction = 1;
float closestFraction = 1; 
b2Vec2 intersectionNormal(0,0);
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext()) {
    for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext()) {
        b2RayCastOutput output;
        if ( ! f->RayCast( &output, input, 0 ) )
            continue;
        if ( output.fraction < closestFraction ) {
            CCLOG(@"woo");
            closestFraction = output.fraction;
            intersectionNormal = output.normal;
        }            
    }
}
}
@end

RaysCastCallback.h

#ifndef Shoot_N_Run_RaysCastCallback_h
#define Shoot_N_Run_RaysCastCallback_h
#endif
#import "Box2D.h"

class RaysCastCallback : public b2RayCastCallback{
public:
RaysCastCallback() : m_fixture(NULL) {
}

float32 ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float32 fraction) {        
    m_fixture = fixture;        
    m_point = point;        
    m_normal = normal;        
    m_fraction = fraction;        
    return fraction;     
}    

b2Fixture* m_fixture;    
b2Vec2 m_point;    
b2Vec2 m_normal;    
float32 m_fraction;
};

其他广播.h

#import "Box2D.h"
class OtherCast : public b2RayCastCallback{
public:
OtherCast()
{
    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)
        {
            // filter
            return -1.0f;
        }
    }

    m_hit = true;
    m_point = point;
    m_normal = normal;
    return fraction;
}

bool m_hit;
b2Vec2 m_point;
b2Vec2 m_normal;
};
4

1 回答 1

0

检查是否调用了 ReportFixture 方法。如果是,那么射线根本没有击中任何东西。这可能是由于值的比例,可能是光线太短或者对象距离太远(未应用 PTM_RATIO?)。但身体的形状也可能太小,或者它们甚至没有形状。也许光线指向相反的方向或 90° 角,很容易忘记或错误地将度数转换为弧度,反之亦然。这些问题都不是罕见的。

它有助于设置一个测试用例,在该测试用例中手动将两个对象放在已知位置,然后投射光线以保证光线相交。拿出笔和纸,跟踪位置和光线,查看调试运行期间的变量值是否匹配。这应该有助于定位由于不正确的矢量、角度和其他原因导致的任何问题。

于 2012-12-15T14:35:40.817 回答