我试图根据box2d中b2body的精灵来调整精灵的位置和旋转。
在我创建了body后,我将userData属性设置为保存精灵和位置等的body对象的属性。问题是在tick方法中b-> GetUserData永远不会检索我放在那里的对象。你能看到以下任何问题吗?
这是我的添加播放器方法:
-(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;
}
和在b-> GetUserData
上始终返回null的tick方法-(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
#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不熟悉所以如果我做了什么重大错误请告诉我!
编辑: 我在这里尝试了另外一些代码,我似乎能够进一步了解。
if I set bodyDef.UserData = sprite;
在行
之后bodyDef.position.Set(sprite.position.x/PTM_RATIO, sprite.position.y /PTM_RATIO);
然后GetUserData返回精灵。但是,如果我在addPlayerShip方法结束时将用户数据设置为精灵,则它再次返回null。精灵/身体对象是否被处置?
答案 0 :(得分:4)
您正在将用户数据分配给bodyDef AFTER 您调用CreateBody(),因此永远不会将其添加到实际正文中。
b2BodyDef是一个结构,用于保存创建主体的设置。一旦调用CreateBody(),对此结构的更改就不起作用。
您通过移动bodyDef.UserData = sprite自己找到了解决方案;调用CreateBody()之前的某处。这是放置它的正确位置。如果您认为在函数结束时由于某种原因需要它(其他变量?),那么您需要重构代码,以便不是这种情况。
我会改变这一行(和BodyObject类):
BodyObject *bodyObject = [[BodyObject alloc] initWithBody:body
andFixture:fixture
andVelocity:vector
andSprite:sprite];
这样您就可以在不需要box2d元素的情况下实例化它(即在它们被定义之前),然后使用属性在创建它们之后分配这些值。这样您就可以将此对象作为正文的用户数据传递,创建正文,然后使用[bodyObject setBody:body];
不要忘记确保您的身体和夹具属性不只读。
最终代码可能如下所示:
-(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类看起来像这样:
#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
答案 1 :(得分:1)
如果有人遇到与GetUserData()返回null相同的问题,即使你是SetUserData。 然后不要犯错,假设比b2World.QueryShape()给出回调中的主体。不,它给你Fixtures。你必须 fixture.GetBody()。GetUserData()(我的情况是:javascript中的box2dweb;这是我搜索答案的问题,我假设其他人会这样来)