Move Box2d Bodies around a Point - ios

i have created two b2body and i want to move one body around a specific point. For this purpose, i have created two bodies and created a b2revoluteJoint between those bodies. But it doesn't produce the desired effect.
Below is my code:
-(id) init
{
if( (self=[super init])) {
self.touchEnabled = YES;
CGSize winSize = [[CCDirector sharedDirector] winSize];
b2Vec2 gravity = b2Vec2(0.0f, 0.0f);
bool allowBodiesToSleep = true;
world = new b2World(gravity);
world->SetAllowSleeping(allowBodiesToSleep);
world->SetContinuousPhysics(true);
_debugDraw = new GLESDebugDraw( PTM_RATIO );
world->SetDebugDraw(_debugDraw);
uint32 flags = 0;
flags += b2Draw::e_shapeBit;
flags += b2Draw::e_jointBit;
flags += b2Draw::e_aabbBit;
flags += b2Draw::e_pairBit;
flags += b2Draw::e_centerOfMassBit;
_debugDraw->SetFlags(flags);
// Arm
arm = [CCSprite spriteWithFile:#"arm.png"];
[self addChild:arm];
[arm setPosition:ccp(winSize.width/2, winSize.height/2)];
b2BodyDef spriteBodyDef;
spriteBodyDef.linearDamping = 1;
spriteBodyDef.angularDamping = 1;
spriteBodyDef.type = b2_dynamicBody;
spriteBodyDef.position.Set(arm.position.x/PTM_RATIO, arm.position.y+1/PTM_RATIO);
spriteBodyDef.userData = (__bridge void *)arm;
spriteBody = world->CreateBody(&spriteBodyDef);
b2PolygonShape spriteShape;
spriteShape.SetAsBox(arm.contentSize.width/PTM_RATIO/2, arm.contentSize.height/PTM_RATIO/2);
b2FixtureDef spriteShapeDef;
spriteShapeDef.shape = &spriteShape;
spriteBody->CreateFixture(&spriteShapeDef);
monster = [CCSprite spriteWithFile:#"body.png"];
[monster setPosition:ccp(winSize.width*0.37, winSize.height/2)];
[self addChild:monster];
b2BodyDef monsterBodyDef;
monsterBodyDef.position.Set(monster.position.x/PTM_RATIO, monster.position.y/PTM_RATIO);
monsterBodyDef.userData = (__bridge void *)monster;
monsterBody = world->CreateBody(&monsterBodyDef);
b2PolygonShape monsterShape;
monsterShape.SetAsBox(monster.contentSize.width/PTM_RATIO/2, monster.contentSize.height/PTM_RATIO/2);
b2FixtureDef monsterShapeDef;
monsterShapeDef.shape = &monsterShape;
monsterBody->CreateFixture(&monsterShapeDef);
b2RevoluteJointDef armJointDef;
armJointDef.Initialize(monsterBody, spriteBody, b2Vec2(monster.position.x/PTM_RATIO,monster.position.y/PTM_RATIO));
armJointDef.enableMotor = false;
armJointDef.enableLimit = true;
armJointDef.localAnchorA = b2Vec2(0, 0);
armJointDef.localAnchorB = b2Vec2(1, 0);
armJointDef.motorSpeed = -10;
armJointDef.lowerAngle = CC_DEGREES_TO_RADIANS(9);
armJointDef.upperAngle = CC_DEGREES_TO_RADIANS(75);
armJointDef.maxMotorTorque = 100;
armJoint = (b2RevoluteJoint*)world->CreateJoint(&armJointDef);
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(monster.position.x/PTM_RATIO, monster.position.y/PTM_RATIO);
//or make it static bodyDef.type = b2_staticBody;
b2Body * body = world->CreateBody(&bodyDef);
//create circle shape
b2CircleShape circle;
circle.m_radius = 20.0/PTM_RATIO;
//define fixture
b2FixtureDef fixtureDef;
fixtureDef.shape = &circle;
fixtureDef.density = 1;
fixtureDef.restitution = 0.7;
fixtureDef.friction = 0.4;
body->CreateFixture(&fixtureDef);
}
return self;
}
And touch functions to move body:
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (mouseJoint != nil) return;
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
monster.visible = NO;
if (locationWorld.x < spriteBody->GetWorldCenter().x + 50.0/PTM_RATIO)
{
b2MouseJointDef md;
md.bodyA = monsterBody;
md.bodyB = spriteBody;
md.target = locationWorld;
md.maxForce = 2;
mouseJoint = (b2MouseJoint *)world->CreateJoint(&md);
}
}
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
spriteBody->SetTransform(locationWorld, angle);
}
I am completely new in Box2d, so if anyone have done such thing. Kindly explain me.
Thanks :)

Not sure what you're trying here, but it seems a work for box2d joints. You could try adding a DistanceJoint to attach your dynamic bodies to a static body that will be the center.

Related

Objective C - SpriteKit - Unable to detect contact between ball and paddle node

I am trying to detect the collision between the ball node and either one of the paddle nodes but the message to confirm the collision is not being fired.
Could somebody help me understand where I am going wrong?
//categories for detecting contacts between nodes
static const uint32_t ballCategory = 0x1 << 0;
static const uint32_t paddleCategory = 0x1 << 1;
#interface GameScene ()
#property BOOL contentCreated;
#property(nonatomic) UITouch *playerOnePaddleControlTouch;
#property(nonatomic, weak) UITouch *paddleTouch;
#property(nonatomic) SKSpriteNode *paddleOneNode;
#property(nonatomic) SKSpriteNode *paddleTwoNode;
#property(nonatomic) SKSpriteNode *ballNode;
#property(nonatomic) SKLabelNode *playerOneScoreNode;
#property(nonatomic) SKLabelNode *playerTwoScoreNode;
#property(nonatomic) NSInteger playerOneScore;
#property(nonatomic) NSInteger playerTwoScore;
#end
#implementation GameScene
- (void)didMoveToView:(SKView *)view
{
if (!self.contentCreated)
{
[self createSceneContents];
self.contentCreated = YES;
}
}
- (void) createSceneContents
{
self.backgroundColor = [SKColor blackColor];
self.scaleMode = SKSceneScaleModeAspectFit;
[self addChild: [self newGameNode]];
self.physicsWorld.gravity = CGVectorMake(0, 0);
self.physicsWorld.contactDelegate = self;
// Create border around screen
SKPhysicsBody* borderBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
self.physicsBody = borderBody;
self.physicsBody.friction = 0;
// Create Paddle One
SKSpriteNode *paddleOne = [self newPaddle];
paddleOne.position = CGPointMake(CGRectGetMidX(self.frame)/8, CGRectGetMidY(self.frame));
paddleOne.name = #"paddleOne";
paddleOne.physicsBody.categoryBitMask = paddleCategory;
paddleOne.physicsBody.contactTestBitMask = ballCategory;
[self addChild:paddleOne];
// Create Paddle Two
SKSpriteNode *paddleTwo = [self newPaddle];
paddleTwo.position = CGPointMake((CGRectGetMaxX(self.frame) - CGRectGetMidX(self.frame) / 8), CGRectGetMidY(self.frame));
paddleTwo.name = #"paddleTwo";
paddleTwo.physicsBody.categoryBitMask = paddleCategory;
paddleTwo.physicsBody.contactTestBitMask = ballCategory;
[self addChild:paddleTwo];
// Create ball
SKSpriteNode *ball = [self newBall];
ball.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[self addChild:ball];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.frame.size.width/2];
ball.physicsBody.friction = 1.0f; //normally 1.0f
ball.physicsBody.restitution = 1.0f; //normally 1.0f
ball.physicsBody.linearDamping = 0.0f; //normally 0.0f
ball.physicsBody.allowsRotation = NO;
ball.physicsBody.categoryBitMask = ballCategory;
ball.physicsBody.contactTestBitMask = paddleCategory;
[ball.physicsBody applyImpulse:CGVectorMake(1.0f, -1.0f)];
// Create score labels
self.playerOneScoreNode = [SKLabelNode labelNodeWithFontNamed:#"Helvetica"];
self.playerTwoScoreNode = [SKLabelNode labelNodeWithFontNamed:#"Helvetica"];
self.playerOneScoreNode.fontColor = self.playerOneScoreNode.fontColor = [SKColor whiteColor];
self.playerOneScoreNode.fontSize = self.playerTwoScoreNode.fontSize = 90;
self.playerOneScoreNode.position = CGPointMake((CGRectGetWidth(self.frame))* 0.25, (CGRectGetHeight(self.frame)) - 80);
self.playerTwoScoreNode.position = CGPointMake((CGRectGetWidth(self.frame)) * 0.75, (CGRectGetHeight(self.frame)) - 80);
[self addChild:self.playerOneScoreNode];
[self addChild:self.playerTwoScoreNode];
// Set Scores to 0
self.playerOneScore = 7;
self.playerTwoScore = 0;
self.playerOneScoreNode.text = [NSString stringWithFormat:#"%ld",self.playerOneScore];
self.playerTwoScoreNode.text = [NSString stringWithFormat:#"%ld",self.playerTwoScore];
}
- (SKSpriteNode *)newPaddle
{
SKSpriteNode *paddle = [[SKSpriteNode alloc]initWithColor:[SKColor whiteColor] size:CGSizeMake(16,64)];
return paddle;
}
- (SKSpriteNode *)newBall
{
SKSpriteNode *ball = [[SKSpriteNode alloc]initWithColor:[SKColor redColor] size:CGSizeMake(16, 16)];
return ball;
}
- (SKLabelNode *) newGameNode
{
SKLabelNode *gameNode = [SKLabelNode labelNodeWithFontNamed:#"Chalkduster"];
gameNode.text = #" Pong";
gameNode.fontSize = 50;
gameNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
gameNode.fontColor = [SKColor blueColor];
return gameNode;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
self.paddleTouch = [touches anyObject];
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInNode:self];
SKNode *paddleOne = [self childNodeWithName:#"paddleOne"];
SKNode *paddleTwo = [self childNodeWithName:#"paddleTwo"];
if (touchPoint.x < CGRectGetMidX(self.frame)) {
paddleOne.position = CGPointMake(paddleOne.position.x, touchPoint.y);
}
else
{
paddleTwo.position = CGPointMake(paddleTwo.position.x, touchPoint.y);
}
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
if (self.paddleTouch) {
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInNode:self];
CGPoint previousPoint = [touch previousLocationInNode:self];
SKSpriteNode *paddleOne = (SKSpriteNode*)[self childNodeWithName:#"paddleOne"];
SKSpriteNode *paddleTwo = (SKSpriteNode*)[self childNodeWithName:#"paddleTwo"];
int paddleOneY = paddleOne.position.y + (touchPoint.y - previousPoint.y);
int paddleTwoY = paddleTwo.position.y + (touchPoint.y - previousPoint.y);
if (touchPoint.x < CGRectGetMidX(self.frame)) {
paddleOne.position = CGPointMake(paddleOne.position.x, paddleOneY);
}
else
{
paddleTwo.position = CGPointMake(paddleTwo.position.x, paddleTwoY);
}
}
}
// React to collision's between nodes/bodies
// Currently not working....need to understand this set of code.
-(void)didBeginContact:(SKPhysicsContact *)contact
{
SKPhysicsBody *firstBody;
SKPhysicsBody *secondBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
firstBody = contact.bodyA;
secondBody = contact.bodyB;
}
else
{
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if (firstBody.categoryBitMask == ballCategory && secondBody.categoryBitMask == paddleCategory)
{
NSLog(#"Ball has touched Paddle");
}
}
#end
Your paddleOne and paddleTwo does not have SKPhysicsBody.
Add these (change size of physics body if needed)
paddleOne.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: paddleOne.size];
paddleTwo.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: paddleTwo.size];

Having issues with touchesBegan method

I have my sound on logo showing up on the screen and the sound off logo appears when i test it. what I want it to do is change from sound on to sound off when I tap on it. The buttons do acknowledge the tap but nothing happens. I don't have much experience in change node images when they're tapped so I don't really know if I used the most efficient code. Can someone look over my code and see what's wrong? Thanks in advance!
#implementation MyScene
{
SKSpriteNode *soundLogo;
SKSpriteNode *soundOff;
}
-(void) addSoundOff:(CGSize)size {
soundOff = [SKSpriteNode spriteNodeWithImageNamed:#"soundOff"];
//resize sprite
soundOff.size = CGSizeMake(soundOff.size.width/2.25, soundOff.size.height/2.25);
//position it
soundOff.position = CGPointMake(65, 25);
//name sound off
soundOff.name = #"soundOff";
soundOff.zPosition = 0;
soundOff.alpha = 0;
//[self addChild:soundOff];
}
-(void) addSoundOn:(CGSize)size {
soundLogo = [SKSpriteNode spriteNodeWithImageNamed:#"soundLogo"];
//resize sprite
soundLogo.size = CGSizeMake(soundLogo.size.width/2.25, soundLogo.size.height/2.25);
//position sprite
CGPoint myPoint = CGPointMake(65, 25);
soundLogo.position = myPoint;
//name sound logo
soundLogo.name = #"soundOn";
//add action
//soundLogo.alpha = 1;
soundLogo.zPosition = 100;
[self addChild:soundLogo];
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
if ([node.name isEqualToString:#"soundOn"]) {
soundOff.zPosition = 100;
soundOff.alpha = 1;
soundLogo.alpha = 0;
soundLogo.zPosition = 0;
// [node removeFromParent];
// [node addChild:soundOff];
NSLog(#"sound on is pressed");
}
if ([node.name isEqualToString:#"soundOff"]) {
soundLogo.zPosition = 100;
soundLogo.alpha = 1;
soundOff.alpha = 0;
soundOff.zPosition = 0;
// [node removeFromParent];
// [node addChild:soundLogo];
NSLog(#"sound off is pressed");
}
}
It seems nothing wrong in your addSoundOff and addSoundOn functions. What you can do as one of the solutions to change alpha and zPosition properties of SKSpriteNode . And also createsoundOff and soundLogo as instance variables under the implementation. So here is the all code:
#import "MyScene.h"
#implementation MyScene
{
SKSpriteNode *soundLogo;
SKSpriteNode *soundOff;
}
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
[self addSoundOn:self.size];
[self addSoundOff:self.size];
}
return self;
}
-(void) addSoundOff:(CGSize)size {
soundOff = [SKSpriteNode spriteNodeWithImageNamed:#"soundOff"];
//resize sprite
soundOff.size = CGSizeMake(soundOff.size.width/2.25, soundOff.size.height/2.25);
//position it
soundOff.position = CGPointMake(65, 25);
//name sound off
soundOff.name = #"soundOff";
soundOff.alpha = 0;
soundOff.zPosition = 0;
[self addChild:soundOff];
}
-(void) addSoundOn:(CGSize)size {
SKTexture *soundOn = [SKTexture textureWithImageNamed:#"soundLogo"];
soundLogo = [SKSpriteNode spriteNodeWithTexture:soundOn];
//resize sprite
soundLogo.size = CGSizeMake(soundLogo.size.width/2.25, soundLogo.size.height/2.25);
//position sprite
CGPoint myPoint = CGPointMake(65, 25);
soundLogo.position = myPoint;
//name sound logo
soundLogo.name = #"soundOn";
//add action
soundLogo.zPosition = 100;
[self addChild:soundLogo];
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:location];
//sound logo pressed to turn sound on/off
if ([node.name isEqualToString:#"soundOn"]) {
soundOff.alpha = 1;
soundOff.zPosition = 100;
soundLogo.alpha = 0;
soundLogo.zPosition = 0;
NSLog(#"sound on is pressed");
}
if ([node.name isEqualToString:#"soundOff"]) {
soundOff.alpha = 0;
soundOff.zPosition = 0;
soundLogo.alpha = 1;
soundLogo.zPosition = 100;
NSLog(#"sound off is pressed");
}
}
#end

how to move one object over another object without bounce in box2d in iphone?

I want to move one object over another object without bounce when they collide.
In Simple i have one ball(body) and i have one Rectangular line image(body), the image is slope 45 degree.
The ball fall from the top speed is 20 when the ball touch on the slope image(Static Body) it will bounce always and continue running.
When the ball come over the line image it will not bounce and slow down the speed according to the collision and ball stop in the end. Same as it happens in real world when ball collide with something , the ball speed will slow down and it turn according to the collision and then stop due to decreasing speed of collision.
I am doing this, but cant achieve the result what i want.
-(id) init
{
if( (self=[super init])) {
CGSize winSize = [CCDirector sharedDirector].winSize;
// Create a world
b2Vec2 gravity = b2Vec2(0.0f, 0.0f);
_world = new b2World(gravity);
///////////////////////// Ball ///////////////////////////////
// Create sprite and add it to the layer
CCSprite *ball = [CCSprite spriteWithFile:#"ball.png"];
ball.position = ccp(100, 200);
ball.tag = 1;
[self addChild:ball];
// Create ball body
b2BodyDef ballBodyDef;
ballBodyDef.type = b2_dynamicBody;
ballBodyDef.position.Set(127/PTM_RATIO, 210/PTM_RATIO);
ballBodyDef.userData = ball;
ballBody = _world->CreateBody(&ballBodyDef); // b2Body * ballBody
// Create circle shape
b2CircleShape circle;
circle.m_radius = 26.0/PTM_RATIO;
// Create shape definition and add to body
b2FixtureDef ballShapeDef;
ballShapeDef.shape = &circle;
ballShapeDef.density = 15.0f;
ballShapeDef.friction = 2.f;
ballShapeDef.restitution = 0.0f;
_ballFixture = ballBody->CreateFixture(&ballShapeDef);
b2Vec2 force = b2Vec2(73, -52);
ballBody->ApplyLinearImpulse(force, ballBodyDef.position);
//ballBody->SetLinearVelocity(b2Vec2(10,0)); // try
// ballBody->SetAngularVelocity(0); // try
///////////////////////// Ball ///////////////////////////////
// Create paddle and add it to the layer
CCSprite *paddle = [CCSprite spriteWithFile:#"paddle.png"];
paddle.position = ccp(winSize.width/2, 50);
[self addChild:paddle];
// Create paddle body
b2BodyDef paddleBodyDef;
paddleBodyDef.type = b2_staticBody; //b2_staticBody, b2_dynamicBody
paddleBodyDef.position.Set(winSize.width/2/PTM_RATIO, 50/PTM_RATIO);
paddleBodyDef.userData = paddle;
paddleBodyDef.angle = 75;
_paddleBody = _world->CreateBody(&paddleBodyDef);
// Create paddle shape
b2PolygonShape paddleShape;
paddleShape.SetAsBox(paddle.contentSize.width/PTM_RATIO/2, paddle.contentSize.height/PTM_RATIO/2);
// Create shape definition and add to body
b2FixtureDef paddleShapeDef;
paddleShapeDef.shape = &paddleShape;
paddleShapeDef.density = 25.0f;
paddleShapeDef.friction = 1.1f;
paddleShapeDef.restitution = 0.1f;
_paddleFixture = _paddleBody->CreateFixture(&paddleShapeDef);
// Restrict paddle along the x axis
b2PrismaticJointDef jointDef;
b2Vec2 worldAxis(0.0f, 0.0f);
jointDef.collideConnected = true;
jointDef.Initialize(_paddleBody, _groundBody, _paddleBody->GetWorldCenter(), worldAxis);
_world->CreateJoint(&jointDef);
[self schedule:#selector(tick:)];
self.touchEnabled = YES;
}
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (_mouseJoint != NULL) return;
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
if (_paddleFixture->TestPoint(locationWorld)) {
b2MouseJointDef md;
md.bodyA = _groundBody;
md.bodyB = _paddleBody;
md.target = locationWorld;
md.collideConnected = true;
md.maxForce = 1000.0f * _paddleBody->GetMass();
_mouseJoint = (b2MouseJoint *)_world->CreateJoint(&md);
_paddleBody->SetAwake(true);
}
// [self kick];
}
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (_mouseJoint == NULL) return;
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
_mouseJoint->SetTarget(locationWorld);
}
Ok so You have mad very small mistak, problem is with gravity.
change it to
b2Vec2 gravity = b2Vec2(0.0f, -10.0f);

Box2D getPosotion error Thread 1: EXC_BAD_ACCESS iPhone

I am working on a game . I am facing problem in box2d.
I have created a World and a Web (sprite,body) and then i am throwing web on touchend, and a tick selector which gets position of sprite and its giving error.
Here is tick selector
onTouchEnd
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
if (freeBody) {
[self schedule: #selector(tick:)];
[self schedule:#selector(WebHitsFood:) interval:0.01f];
freeBody->SetType(b2_dynamicBody);
//this is the maximum force that can be applied
const CGFloat maxForce = 600;
//get the location of the end point of the swipe
UITouch *myTouch = [touches anyObject];
CGPoint location = [myTouch locationInView:[myTouch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
//get the rotation b/w the start point and the end point
CGFloat rotAngle = atan2f(location.y - startPoint.y,location.x - startPoint.x);
//the distance of the swipe if the force
CGFloat distance = ccpDistance(startPoint, location) * 0.5;
//put a cap on the force, too much of it will break the rope
if (distance>maxForce) distance = maxForce;
//apply force
freeBody->ApplyForce(b2Vec2(cosf(rotAngle) * distance, sinf(rotAngle) * distance), freeBody->GetPosition());
//lose the weak reference to the body for next time usage.
freeBody = nil;
}
self.isTouchEnabled = NO;
}
and Create Web Method
-(void) createWeb
{
freeBodySprite = [CCSprite spriteWithFile:#"web1.png"];//web_ani_6_1
//freeBodySprite.position = ccp(100, 300);
[self addChild:freeBodySprite z:2 tag:6];
CGPoint startPos = CGPointMake(100, 320/1.25);
bodyDef.type = b2_staticBody;
bodyDef.position = [self toMeters:startPos];
bodyDef.userData = freeBodySprite;
float radiusInMeters = ((freeBodySprite.contentSize.width * freeBodySprite.scale/PTM_RATIO) * 0.5f);
shape.m_radius = radiusInMeters;
fixtureDef.shape = &shape;
fixtureDef.density = 0.5f;
fixtureDef.friction = 1.0f;
fixtureDef.restitution = 0.0f;
circularObstacleBody = world->CreateBody(&bodyDef);
stoneFixture = circularObstacleBody->CreateFixture(&fixtureDef);
freeBody = circularObstacleBody;
}
Are you sure the GetPosition() is the problem? Try adding the line
float test = b->GetPosition().x;
just before the one giving you the issue to determine whether the issue is actually with GetPosition() or whether it is the myActor.position that is the source of the exc_bad_access.
Easy way to fix that crash:
for(b2Body* b= world->GetBodyList(); b; B->GetNext())
{
id sprite = b->GetUserData();
if( sprite && [sprite isKindOfClass:[CCSprite class])
{
CCSprite *myActor = (CCSprite*) sprite;
myActor.position = CGPointMake(b->getPosition().x*PTM_RATIO, b->getPosition().y*PTM_RATIO);
myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
}
}

sprite not updating to the correct position

I have written a code to display using CCLog the exact position of a sprite when a mousejoint moving it is released. Below is the Sprite.mm class and the ccTouchesEnded method (which is in the HelloWorldLayer.mm class). The sprite position is not updating, the output is constantly x: 0.00 and y: 0.00.
Sprite.mm:
-(id)addSprite:(CCLayer *)parentLayer
inWorld:(b2World *)world
{
PhysicsSprite *aSprite = [PhysicsSprite spriteWithFile:#"spriteIm.png"];
aSprite.tag = 1;
[parentLayer addChild:aSprite];
b2BodyDef spriteBodyDef;
spriteBodyDef.userData = aSprite;
spriteBodyDef.type = b2_dynamicBody;
CGSize s = [CCDirector sharedDirector].winSize;
spriteBodyDef.position = [Convert toMeters:ccp(s.width * 0.25,s.height-400)];
b2FixtureDef fixtureDef;
fixtureDef.density = 0.01;
b2CircleShape circleShape;
circleShape.m_radius = aSprite.contentSize.width/2 / PTM_RATIO;
fixtureDef.shape = &circleShape;
spriteBody = world->CreateBody( &spriteBodyDef );
spriteFixture = spriteBody->CreateFixture( &fixtureDef );
[aSprite setPhysicsBody:spriteBody];
return aSprite;
}
ccTouchesEnded:
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if (mouseJoint)
{
for(b2Body *b = world->GetBodyList(); b; b=b->GetNext()) {
if (b->GetUserData() != NULL) {
CCSprite *mySprite = (CCSprite *)b->GetUserData();
if (mySprite.tag == 1) {
CGPoint spritePosition = mySprite.position;
CCLOG(#"the sprite position is x:%0.2f, y:%0.2f", spritePosition.x, spritePosition.y);
}
}
}
world->DestroyJoint(mouseJoint);
mouseJoint = NULL;
}
}
Please help. I've been at it for a few days.
I finally managed to get it working. I guess the x:0.00 and y:0.00 were because I was taking the position of the sprite not the body. The sprite is parented to the body so it was giving its position inside it's parent, which is 0,0. This is how I understand it. Here are the changes I made to the ccTouchesEnded code.
ccTouchesEnded:
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if (mouseJoint)
{
for(b2Body *b = mouseJoint->GetBodyB(); b; b=b->GetNext()) {
if (b->GetUserData() != NULL)
{
CCSprite *mySprite = (CCSprite*)b->GetUserData();
if (mySprite.tag == 1) {
mySprite.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
CCLOG(#"the sprite postion is x:%0.2f , y:%0.2f", mySprite.position.x, mySprite.position.y);
}
}
}
world->DestroyJoint(mouseJoint);
mouseJoint = NULL;
}
}

Resources