Hey guys i have a question here, How do i create a body that will not have physic function until i press it? i have this code in my init
CCSprite *tail = [CCSprite spriteWithFile:#"Ball.jpg"];
[self addChild:tail z:1];
b2BodyDef tailBodyDef;
tailBodyDef.type = b2_dynamicBody;
tailBodyDef.position.Set(100/PTM_RATIO, 100/PTM_RATIO);
tailBodyDef.userData = tail;
tailBody = world->CreateBody(&tailBodyDef);
b2CircleShape circle;
circle.m_radius = 26.0/PTM_RATIO;
b2FixtureDef tailShapeDef;
tailShapeDef.shape = &circle;
tailShapeDef.density = 1.0f;
tailShapeDef.friction = 0.2f;
tailShapeDef.restitution = 0.8f;
tailBody->CreateFixture(&tailShapeDef);
[self schedule: #selector(tick:)];
The ball will drop off the the edge of screen at the start of game, but thats not what i want. i want it to stay at the same position until i press it. is there anyway i could hold the object back until i give some input?
Haven't tried it but toggling the setActive property seems perfect.
tailBody->setActive(NO);
Check out the 'activation' section here: http://www.box2d.org/manual.html#_Toc258082973
Related
I am trying to move an SKSpriteNode with physics by setting it's velocity. I am doing this on top of another SKNode (the map) that is part of the SKScene. Positions of "cities" are stored in custom Location objects.
I know the location of the initial SKSpriteNode (the ship) and I know the desired location. From what I've read, I can move the sprite by setting it's velocity. I do so like this:
float dy = _player.desiredLocation.yCoordinate - _mapNode.pin.position.y;
float dx = _player.desiredLocation.xCoordinate - _mapNode.pin.position.x;
_mapNode.pin.physicsBody.velocity = CGVectorMake(dx, dy);
This is all inside the didSimulatePhysics function inside the SKScene. Once the user taps a Location, I find the position and set the velocity. This seems to work well the FIRST time, but the sprite moves all over the place in subsequent times. Any idea what could be going wrong here?
PS: Setting skView.showsPhysics = YES; puts the circle of the physics body way off the position of the sprite.
In the map node:
self.pin = [SKSpriteNode spriteNodeWithImageNamed:[IPGameManager sharedGameData].world.player.ship.type];
self.pin.userInteractionEnabled = NO;
self.pin.position = CGPointMake([IPGameManager sharedGameData].world.player.location.xCoordinate, [IPGameManager sharedGameData].world.player.location.yCoordinate);
self.pin.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:10.0];
self.pin.physicsBody.dynamic = YES;
self.pin.physicsBody.allowsRotation = NO;
self.pin.physicsBody.friction = 0.0;
self.pin.physicsBody.linearDamping = 0.0;
[self addChild:self.pin];
I am having a physicsSprite of kinematics body type and I want to move the body and sprite bit down and back to its position. I tried it like this Inside update method:
for (NSValue *bodyValue in [self getGoalPostBodiesList])
{
b2Body *gPBody = (b2Body *)[bodyValue pointerValue];
PhysicsSprite *pSprite =(PhysicsSprite *) gPBody->GetUserData();
NSLog(#"\n tag value of Sprite = %d",pSprite.tag);
if(pSprite == goal1)
{
pSprite.position = CGPointMake((gPBody->GetPosition().x)*32.0,(gPBody->GetPosition().y)*32.0);
float angle = gPBody->GetAngle();
pSprite.rotation = -(CC_RADIANS_TO_DEGREES(angle));
id moveDownAction = [CCMoveTo actionWithDuration:0.5 position:CGPointMake(pSprite.position.x,(pSprite.position.y )- 40)];
id moveUpAction = [CCMoveTo actionWithDuration:0.5 position:CGPointMake(pSprite.position.x,(pSprite.position.y )+ 40)];
CCSequence *seqAction = [CCSequence actions:moveDownAction,moveUpAction, nil];
[pSprite runAction:seqAction];
b2Vec2 pos = b2Vec2(pSprite.position.x/32.0, pSprite.position.y/32.0);
gPBody->SetTransform(pos, CC_DEGREES_TO_RADIANS(pSprite.rotation));
gPBody->SetLinearVelocity(b2Vec2(0.0f, 0.0f));
gPBody->SetAngularVelocity(0.0f);
}
}
Still the sprite is not changing its position.
Anyone's help will be deeply appreciated.
Thanks all,
MONISH
To summarize your code, you update the position of your sprite to reflect that of the body, start an animation, and then update the position of the body to correspond to the position of the sprite. So naturally, nothing should move here, since your CCMoveTo actions have not exerted any effect on your sprite yet.
Second, your update method may be called very often, like dozens of times per second, so the animation gets reset continously and will not make any visible progress.
To follow a consistent pattern, how about you set the velocity of your kinematic bodies. Also, update the position of your sprites to correspond to these bodies as you would do for dynamic bodies, but don't set the transformation of your bodies to correspond to their sprites.
I have a Box2d body which I'm attempting to break into multiple pieces. To do this, I iterate over its fixtures and generate new bodies for each. Using debug draw, I can see that this seems to be working.
As you can see in the above image, the primary body is being broken and a secondary body (labelled: 2) is being generated. Based on the shape rendering from the debug layer, they're being represented correctly. The issue I'm having is that the CCSprite I'm associating with my primary b2body isn't being correctly positioned in reference to the new body. It seems as though the associated CCSprite is being positioned (given an anchor point of 0, 0) as if it were still part of a larger shape.
For reference, here's the code I'm using:
for (b2Fixture *f = body->GetFixtureList(); f; f = f->GetNext())
{
NSString *newSpriteFrameName = (NSString *)f->GetUserData();
// Steal some of our parent bodies properties
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.position = [self physicsPosition];
bd.angle = [self angle];
b2Body *newBody = _world->CreateBody(&bd);
b2FixtureDef fixtureDef;
fixtureDef.shape = f->GetShape();
fixtureDef.density = f->GetDensity();
fixtureDef.restitution = f->GetRestitution();
fixtureDef.friction = f->GetFriction();
fixtureDef.userData = f->GetUserData();
newBody->CreateFixture(&fixtureDef);
// Try to transfer any angular and linear velocity
b2Vec2 center1 = [self worldCenter];
b2Vec2 center2 = newBody->GetWorldCenter();
CGFloat angularVelocity = parentBody->GetAngularVelocity();
b2Vec2 velocity1 = [self linearVelocity] + b2Cross(angularVelocity, center1 - center1);
b2Vec2 velocity2 = [self linearVelocity] + b2Cross(angularVelocity, center2 - center1);
newBody->SetAngularVelocity(angularVelocity);
newBody->SetLinearVelocity(velocity2);
// Create a new destructable entity
CCSprite *newSprite = [CCSprite spriteWithSpriteFrameName:newSpriteFrameName];
SIDestructableEntity *newEntity = [[SIDestructableEntity alloc] initWithBody:newBody node:newSprite];
[[newEntity ccNode] setAnchorPoint:CGPointMake(0, 0)];
[game.entities addObject:newEntity];
[game.entityLayer addChild:[newEntity ccNode]];
}
Here's how I'm setting my CCSprites location each logic tick:
b2Vec2 position = body->GetPosition();
ccNode.position = CGPointMake(PTM_RATIO*position.x, PTM_RATIO*position.y);
ccNode.rotation = -1 * CC_RADIANS_TO_DEGREES(body->GetAngle());
This line looks suspicious.
[[newEntity ccNode] setAnchorPoint:CGPointMake(0, 0)];
The sprite usually has an anchor point of (0.5,0.5). If your body's anchor point is in the middle (can't tell from code above), then an anchor of (0.5,0.5) for the sprite would put it in the middle as well. Putting it at (0,0) puts the sprite's top left corner at the position of the sprite.
My guess is that your body anchor is at the bottom left of body and the sprite anchor is at the top right, giving the effect you are seeing.
I have a sprite which will move right,left and jump.
I need to add the action to a animated sprite ie an animated sprite should jump, turn right and left.
Can anyone please tell me how to do it with sample code.
This is quite simple with cocos2d code here:
Sprite *mySprite = [Sprite spriteWithFile#"mySprite.png"];
[mySprite setPosition:ccp(x,y)];
[self addChild:mySprite]; //This displays the Sprite in your layer
Now for the sequence you intend to do...
id moveRight = [MoveBy actionWithDuration:2 position ccp(x+k,y) //Where k is how much to the right you want it to go.
id moveLeft = [MoveBy actionWithDuration:2 position ccp(x-k,y)];
id jump = [JumpBy actionWithDuration:1 position:ccp (x,y) height:1 jumps:1];
id sequence = [Sequence actions:moveRight,moveLeft,jump,nil];
[mySprite runAction:sequence];
Hope that's clear.
-Oscar
Basically I have 2 polygons for my body. When I add a sprite for userData, the position of the texture isn't where I want it to be. What I want to do is adjust the position of the texture within the body. Here's the code sample of where I am setting this:
CCSpriteSheet *sheet = (CCSpriteSheet*) [self getChildByTag:kTagSpriteSheet];
CCSprite *pigeonSprite = [CCSprite spriteWithSpriteSheet:sheet rect:CGRectMake(0,0,40,32)];
[sheet addChild:pigeonSprite z:0 tag:kPigeonSprite];
pigeonSprite.position = ccp( p.x, p.y);
bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
bodyDef.userData = sprite;
b2Body *body = world->CreateBody(&bodyDef);
b2CircleShape dynamicCircle;
dynamicCircle.m_radius = .25f;
dynamicCircle.m_p.Set(0.0f, 1.0f);
// Define the dynamic body fixture.
b2FixtureDef circleDef;
circleDef.shape = &dynamicCircle;
circleDef.density = 1.0f;
circleDef.friction = 0.3f;
body->CreateFixture(&circleDef);
b2Vec2 vertices[3];
vertices[0].Set(-0.5f, 0.0f);
vertices[1].Set(0.5f, 0.0f);
vertices[2].Set(0.0f, 1.0f);
b2PolygonShape triangle;
triangle.Set(vertices, 3);
b2FixtureDef triangleDef1;
triangleDef1.shape = ▵
triangleDef1.density = 1.0f;
triangleDef1.friction = 0.3f;
body->CreateFixture(&triangleDef1);
I'm not that familiar with objective-c but I'll give it a try.
All I can see is that you are storing a pointer to the sprite object in the body's user data and then leaving it there. If you want the body's position to be transferred to the sprite you need to update it every frame.
In C++ this would look something like this.
// To be called each time physics should be updated.
void physicsStep(float32 timeStep, int32 velocityIterations, int32 positionIterations) {
// This is the usual update routine.
world.Step(timeStep, velocityIterations, positionIterations);
world.ClearForces();
// SpriteClass can be replaced with any class you favor.
// Assume there is a known pointer to the b2Body. Otherwise you'll have to get that,
// or iterate over all bodies in the world.
SpriteClass *sprite = (SpriteClass*)body->GetUserData();
// Once you have the pointer you can transfer all the data.
sprite.position = body->GetPosition();
sprite.angle = body->GetAngle();
// ... and so on
}
User data is just an arbitrary storage space in the b2Body and Box2D has no idea about what you decide to store there.
To move sprite with body then You have to set the sprite position accotring to body
in your update method
like this in COCOS2D-X
Here
sprite = static_cast<CCSprite*>body->GetUserData();
sprite->setPosition(vec2(body->GetPosition().x*PTM_RATIO, body->GetPosition().y*PTM_RATIO));
sprite->setRotation(-CC_Radian_to_Degree(body->GetAngle));
PTM_RATIO = 32;