我正在读这本书:来自Rod Strougo和Ray Wenderlich的'学习Cocos2D',我决定用Cocos2d-Box2d制作我自己的iOS游戏。
现在我遇到了一个无法解决的问题。
我创建了一个名为Box2dLayer的类,它继承自CCLayer,我有Level1Layer
继承自Box2dLayer的类。
一切正常,直到我有两种不同类型的box2d体在屏幕上呈现。
现在每次我开始游戏时都会失败 - [Box2DLayer update:]方法给出以下内容:
线程1:EXC_BAD_ACCESS(代码= 1,地址= 0xsomething);
1 - {Box2DLayer update:]在第sp.position...
行
2 - [CCScheduler update:]第entry->impMethod( entry->target, updateSelector, dt );
行
这是我的代码:
//Box2DSprite.h
@interface Box2DSprite : CCSprite
{
b2Body *body;
}
@property (assign) b2Body *body;
@end
//Box2DSprite.mm
@implementation Box2DSprite
@synthesize body;
-(void)dealloc
{
body = NULL;
[super dealloc];
}
@end
//Box2DLayer.h
@interface Box2DLayer : CCLayer
{
b2World *world;
GLESDebugDraw *debugDraw;
b2MouseJoint *mouseJoint;
b2Body *groundBody;
}
-(void)setupGround;
@end
//Box2DLayer.mm
@implementation Box2DLayer
-(id)init
{
if (self = [super init]) {
[self scheduleUpdate];
[self setupWorld];
[self setupDebugDraw];
[self setupGround];
self.isTouchEnabled = YES;
}
return self;
}
- (void)setupWorld {
b2Vec2 gravity = b2Vec2(0.0f, -10.0f);
world = new b2World(gravity);
//world->SetContinuousPhysics(true);
}
-(void) draw {
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
kmGLPushMatrix();
world->DrawDebugData();
kmGLPopMatrix();
}
- (void)setupDebugDraw {
debugDraw = new GLESDebugDraw(PTM_RATIO *[[CCDirector sharedDirector] contentScaleFactor]);
world->SetDebugDraw(debugDraw);
debugDraw->SetFlags(b2Draw::e_shapeBit);
}
- (void)registerWithTouchDispatcher {
[[[CCDirectorIOS sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0
swallowsTouches:YES];
}
-(void)update:(ccTime)dt {
int32 velocityIterations = 3;
int32 positionIterations = 2;
world->Step(dt, velocityIterations, positionIterations);
for(b2Body *b = world->GetBodyList(); b != NULL; b = b->GetNext())
{
if (b->GetUserData() != NULL) {
Box2DSprite *sp = (Box2DSprite *) b->GetUserData();
sp.position = ccp(b->GetPosition().x * PTM_RATIO*RETSIZE,b->GetPosition().y * PTM_RATIO*RETSIZE);
sp.rotation = CC_RADIANS_TO_DEGREES(b->GetAngle() * -1);
}
}
}
-(void)setupGround{
CGSize winSize = [[CCDirector sharedDirector] winSize];
b2BodyDef groundBodyDef;
groundBodyDef.type = b2_staticBody;
groundBodyDef.position.Set(0, 10/RETSIZE/PTM_RATIO);
groundBody = world->CreateBody(&groundBodyDef);
CCSprite *gsprite = [CCSprite spriteWithFile:@"ground.png"];
groundBody->SetUserData(gsprite);
b2EdgeShape groundBox;
groundBox.Set(b2Vec2(0,0), b2Vec2(winSize.width/PTM_RATIO/RETSIZE-150/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
}
-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
CGPoint touchLocation = [touch locationInView:[touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
b2Vec2 locationWorld = b2Vec2(touchLocation.x/PTM_RATIO/RETSIZE, touchLocation.y/PTM_RATIO/RETSIZE);
b2AABB aabb;
b2Vec2 delta = b2Vec2(1.0/PTM_RATIO/RETSIZE, 1.0/PTM_RATIO/RETSIZE);
aabb.lowerBound = locationWorld - delta;
aabb.upperBound = locationWorld + delta;
SimpleQueryCallback callback(locationWorld);
world->QueryAABB(&callback, aabb);
if (callback.fixtureFound) {
b2Body *body = callback.fixtureFound->GetBody();
b2MouseJointDef joint;
joint.bodyA = groundBody;
joint.bodyB = body;
joint.target = locationWorld;
joint.maxForce = 100*body->GetMass();
joint.collideConnected = true;
mouseJoint = (b2MouseJoint *)world->CreateJoint(&joint);
// body->SetAwake(false);
return YES;
}
}
-(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event{
CGPoint touchLocation = [touch locationInView:[touch view]];
touchLocation = [[CCDirector sharedDirector]
convertToGL:touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
b2Vec2 locationWorld = b2Vec2(touchLocation.x/PTM_RATIO/RETSIZE, touchLocation.y/PTM_RATIO/RETSIZE);
if (mouseJoint) {
mouseJoint->SetTarget(locationWorld);
}
}
-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event{
if (mouseJoint) {
world->DestroyJoint(mouseJoint);
mouseJoint = NULL;
}
}
-(void) dealloc
{
if (world) {
delete world;
world = NULL;
}
if (debugDraw) {
delete debugDraw;
debugDraw = NULL;
}
[super dealloc];
}
@end
程序在update方法内部的for循环崩溃。注意如果我注释掉for循环,一切正常,但精灵没有附加到box2D主体。
如果你不能给出答案,有什么不对,请告诉我一系列可能存在的问题。 谢谢!
答案 0 :(得分:0)
你好错误说它是一个内存问题;你试图访问一些不存在的东西。 2件事;在你的代码中,我没有看到精灵体附着在世界的任何地方。 第二,为什么Box2dSprite类中的body属性赋值,不应该保留。
答案 1 :(得分:0)
最后我解决了这个问题!我只需要检查我想要更新的主体是不是静态的。现在一切正常。修正后的更新方法如下:
-(void)update:(ccTime)dt {
int32 velocityIterations = 3;
int32 positionIterations = 2;
world->Step(dt, velocityIterations, positionIterations);
for(b2Body *bdy = (world->GetBodyList()); bdy != NULL; bdy = bdy->GetNext())
{
if (bdy->GetType()!=b2_staticBody && bdy->GetUserData() != NULL) {
Box2DSprite *sp = (Box2DSprite *) bdy->GetUserData();
sp.position = ccp(bdy->GetPosition().x * PTM_RATIO*RETSIZE,bdy->GetPosition().y * PTM_RATIO*RETSIZE);
sp.rotation = CC_RADIANS_TO_DEGREES(bdy->GetAngle() * -1);
}
}
}