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;
};

OtherCast.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° の角度を向いている可能性があります。角度をラジアンに、またはその逆に変換することを忘れたり、誤って変換したりすることがよくあります。これらの問題はどれも珍しいものではありません。

既知の位置に 2 つのオブジェクトを手動で配置するテスト ケースを設定し、光線が確実に交差するように光線を投射すると便利です。ペンと紙を取り出して位置と光線をトレースし、デバッグ実行中の変数の値が一致するかどうかを確認します。これは、不適切なベクトル、角度などによる問題を特定するのに役立ちます。

于 2012-12-15T14:35:40.817 に答える