Box2D-b2body GetUserData始终返回null [英] Box2D - b2body GetUserData always returns null

查看:88
本文介绍了Box2D-b2body GetUserData始终返回null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图根据box2d中b2body的位置调整精灵的位置和旋转。

I am trying to adjust the position and rotation of a sprite based on that of a b2body in box2d.

创建了body并设置userData属性后,到保存小精灵和位置等的身体对象的问题。问题是在tick方法中,b-> GetUserData永远不会检索放置在其中的对象。您看到以下内容有问题吗?

After I have created the body im setting the userData property to that of my body object that holds the sprite and position etc. The problem is that in the tick method b->GetUserData never retrieves the object I put in there. Can you see anything wrong with the following?

这是我的添加播放器方法:

Here is my add player method:

-(void) addPlayerShip
{
    CCSpriteSheet *sheet = [CCSpriteSheet spriteSheetWithFile:@"PlayerShip.png" capacity:1];

    //Get sprite sheet
    CCSprite *sprite = [CCSprite spriteWithSpriteSheet:sheet rect:CGRectMake(0,0,64,64)];
    [sheet addChild:sprite];

    CGSize screenSize = [CCDirector sharedDirector].winSize;

    sprite.position = ccp( screenSize.width/2, screenSize.height/2);

    [self addChild:sheet];

    // Define the dynamic body.
    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(sprite.position.x/PTM_RATIO, sprite.position.y /PTM_RATIO);
    bodyDef.angularVelocity=0;

    b2Body *body = world->CreateBody(&bodyDef);

    b2PolygonShape dynamicTriangle;

    dynamicTriangle.m_vertexCount=3;
    dynamicTriangle.m_vertices[0].Set(0,-1);
    dynamicTriangle.m_vertices[1].Set(1,1);
    dynamicTriangle.m_vertices[2].Set(-1,1);

    // Define the dynamic body fixture.
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &dynamicTriangle;
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.0f;
    fixtureDef.restitution=0.0f;

    b2Fixture *fixture = body->CreateFixture(&fixtureDef);

    b2Vec2 *vector = new b2Vec2;

    BodyObject *bodyObject = [[BodyObject alloc] initWithBody:body 
                                                   andFixture:fixture 
                                                  andVelocity:vector 
                                                    andSprite:sprite];


    bodyDef.userData = bodyObject;
}

和tick方法始终在b-> GetUserData上返回null

and the tick method that is always returning null on b->GetUserData

-(void) tick: (ccTime) dt
{
    int32 velocityIterations = 8;
    int32 positionIterations = 1;

    world->Step(dt, velocityIterations, positionIterations);

    //Iterate over the bodies in the physics world
    for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
    {
        if (b->GetUserData() != NULL) {
            //Synchronize the Sprites position and rotation with the corresponding body
            GameObject *myObject = (GameObject*)b->GetUserData();
            myObject.Sprite.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
            myObject.Sprite.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
        }   
    }
}

最后是bodyObject

and finally the bodyObject

#import "BodyObject.h"


@implementation BodyObject

@synthesize Body;
@synthesize Fixture;

-(id) initWithBody:(b2Body*) body 
        andFixture:(b2Fixture*) fixture 
       andVelocity:(b2Vec2*) velocity 
         andSprite:(CCSprite*) sprite
{
    self = [super initWithSprite:(CCSprite*)sprite 
                     andVelocity:(b2Vec2*)velocity];

    self.Body=body;
    self.Fixture=fixture;

    return self;
}

@end

目标c的新特性如果我做的任何重大错误请让我知道!

im new to objective c so if im doing anything majorly wrong please let me know!

编辑:
我在这里尝试了另一段代码,我似乎可以进一步。

I have tried another bit of code here and i seem to be able to get a bit further.

if I set bodyDef.UserData = sprite; 

在行之后

bodyDef.position.Set(sprite.position.x/PTM_RATIO, sprite.position.y /PTM_RATIO); 

然后GetUserData返回精灵。但是,如果我在addPlayerShip方法的末尾将用户数据设置为sprite,则它将再次返回null。精灵/主体对象是否放置在某个地方?

then GetUserData returns the sprite. if however I set the user data to the sprite at the end of the addPlayerShip method then it returnns null again. Is the sprite / body object being disposed of somewhere?

推荐答案

您正在将userdata分配给bodyDef 之后 您调用CreateBody(),因此它永远不会添加到实际主体中。

You are assigning the userdata to the bodyDef AFTER you call CreateBody(), so it is never being added to the actual body.

b2BodyDef是拥有用于创建实体的设置的结构。调用CreateBody()后,对此结构的更改将无效。

b2BodyDef is a struct that holds settings to create a body. Once you've called CreateBody(), changes to this struct have no effect.

您可以通过移动bodyDef.UserData = sprite自己找到解决方案;在调用CreateBody()之前的某行。这是放置它的正确位置。如果您出于某种原因(其他变量?)而在函数末尾需要它,则需要重构代码,以防止出现这种情况。

You found the solution yourself by moving the bodyDef.UserData = sprite; line somewhere before CreateBody() is called. This is the correct place to put it. If you think you need it at the end of the function for some reason (other variables?), then you need to refactor your code so that this is not the case.

我将更改此行(以及BodyObject类):

I would change this line (and the BodyObject class):

BodyObject *bodyObject = [[BodyObject alloc] initWithBody:body 
                                               andFixture:fixture 
                                              andVelocity:vector 
                                                andSprite:sprite];

,以便您无需实例化box2d元素即可对其进行实例化(即在定义它们之前),然后创建这些值后,使用属性来分配这些值。这样,您可以将此对象作为主体的用户数据传递,创建主体,然后使用 [bodyObject setBody:body];

so that you can instantiate it without needing the box2d elements (i.e. before they have been defined), then use the properties to assign these values after they have been created. This way you can pass this object as the body's userdata, create the body, then assign the b2Body* using [bodyObject setBody:body];

别忘了确保您的身体和灯具属性不是只读。

Don't forget to ensure your Body and Fixture properties are not readonly.

最终代码可能看起来像

-(void) addPlayerShip
{
    CCSpriteSheet *sheet = [CCSpriteSheet spriteSheetWithFile:@"PlayerShip.png" capacity:1];

    //Get sprite sheet
    CCSprite *sprite = [CCSprite spriteWithSpriteSheet:sheet rect:CGRectMake(0,0,64,64)];
    [sheet addChild:sprite];

    CGSize screenSize = [CCDirector sharedDirector].winSize;

    sprite.position = ccp( screenSize.width/2, screenSize.height/2);

    [self addChild:sheet];

    b2Vec2 *vector = new b2Vec2;

    BodyObject *bodyObject = [[BodyObject alloc] initWithSprite:sprite 
                                                   andVelocity:vector];

    //MOVES THE BODY DEFINITION AFTER THE BODYOBJECT DEFINITION
    // Define the dynamic body.
    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.position.Set(sprite.position.x/PTM_RATIO, sprite.position.y /PTM_RATIO);
    bodyDef.angularVelocity=0;
    bodyDef.userData = bodyObject;

    b2Body *body = world->CreateBody(&bodyDef);

    b2PolygonShape dynamicTriangle;

    dynamicTriangle.m_vertexCount=3;
    dynamicTriangle.m_vertices[0].Set(0,-1);
    dynamicTriangle.m_vertices[1].Set(1,1);
    dynamicTriangle.m_vertices[2].Set(-1,1);

    // Define the dynamic body fixture.
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &dynamicTriangle;
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.0f;
    fixtureDef.restitution=0.0f;

    b2Fixture *fixture = body->CreateFixture(&fixtureDef);

    [bodyObject setBody:body];
    [bodyObject setFixture:fixture];
}

bodyObject类将看起来像这样:

The bodyObject class would then simply look like this:

#import "BodyObject.h"


@implementation BodyObject

@synthesize Body;
@synthesize Fixture;

-(id) initWithSprite:(CCSprite*) sprite 
       andVelocity:(b2Vec2*) velocity 
{
    self = [super initWithSprite:(CCSprite*)sprite 
                     andVelocity:(b2Vec2*)velocity];

    return self;
}

@end

这篇关于Box2D-b2body GetUserData始终返回null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆