How to create a semi-circle Physics Body by using sprite kit - ios

I'm creating a semi-circle node when i try to develop a simple sprite kit game, but i wish the physics body of the node just cover the circle object's edge, and the physics body rotates with the circle(to change the physics body programatically), what should i do?

You can do complex shapes using SKPhysicsBody -bodyWithPolygonFromPath:
There are even tools that let you draw your shape and generate the code for you. See this question for examples: SpriteKit's SKPhysicsBody with polygon helper tool

Related

Implementing bodyWithBodies in Sprite Kit

I am using Apple's Sprite Kit to create a game, and currently I have drawn an SKShapeNode object that looks similar to the following:
My actual sprite has rounded edges, but for simplicity, I am trying to get everything working with this shape first. I am able to draw the sprite perfectly fine. However, I am having trouble creating a physics body to cover the sprite. I want the sprite to recognize collisions anywhere along its surface, so I want a physics body that covers only the dark gray area. Also, I want the sprite to respond to forces and impulses, so I need a volume-based physics body.
My first idea was to simply use the same CGPathRef that I used to create the image for the sprite, and pass it to the bodyWithPolygonFromPath method to create a corresponding physics body. I have come to find this will not work, as my shape is not convex.
So, now I am thinking I should be able to use bodyWithBodies to create a physics body shaped appropriately. I want to create three rectangular physics bodies (one to cover the left of the gray area, one to cover the top, and one to cover the right), and use those to create one physics body whose area covers the gray area of my sprite by using this:
mySprite.physicsbody = [SKPhysicsBody bodyWithBodies:#[body1, body2, body3]];
However, the main problem I am having is correctly positioning the individual bodies that go into the array, which is passed to the bodyWithBodies method. By using the above method, I obviously have no way of controlling where these physics bodies are being placed in relation to each other. The result is all three physics bodies stacking on top of each other in the center of mySprite.
How exactly are you supposed to position the physics bodies in the array relative to each other before passing them to the bodyWithBodies method?

SpriteKit - drawing circles containing other circles with physics body

I am new to Objective-C and I am trying to make a simple spriteKit game which contains a circle and a ball inside it. I want to move the ball around in this circle as well on the iPhone movement. So far I have created the circle and am able to put the ball on the screen.
My problem is that I am not sure the ball is actually inside the circle or on top of it. When I attach a physics body on the ball, it drops out of the screen and does not stop on the circle's bottom edge. I am using SKShapeNode for both the circle and ball.
Please help me to provide the right documentation to go through or a little piece of code that can resolve this.
You need to assign appropriate physics bodies to your nodes. See Simulating Physics in the Sprite Kit Programming Guide.
From your description, it sounds like you need to create the outter circle's physics body with the bodyWithEdgeLoopFromPath: method (and provide a path representing the circle). Note that an edge loop physics body is not dynamic and can only collide with volume-based bodies.
The inner balls physics body can be created with bodyWithCircleOfRadius:.

How to convert coordinates of one SKNode to another SKNode?

I figured out that if you want to use physics in Sprite Kit you have to specify anchor points in world coordinates. Say you have a big node tree and there is a car here and a wheel there. You know their coordinates in their parent nodes only. You want to define a spring joint between car and wheel but you have to tell Sprite Kit the anchors in coordinate space of your scene.
How would you then convert the spring anchor point on the car and the spring anchor point on the wheel center into world coordinates?
In UIKit there are conversion methods like convertPoint:toWindow: etc.
How do you do this in Sprite Kit?
You should be able to use SKNode convertPoint:toNode:.
[wheelNode convertPoint:CGPointMake(0,0) toNode:carNode];
[carNode convertPoint:CGPointMake(0,0) toNode:treeNode];
Something like that...

Two Box2D Sprite Geometries Travel Different Distances With Same Impulse

I've created a box2d body that is attached to a second box2d body with a weld joint. The first box2d sprite associated with the body is in the shape of a stick. The second box2d body is a person that throws the first box2d body. The first box2d body is initialized as a polygon shape with a specified density, friction, and restitution. Depending on the game state, the first box2d body may get changed to a different sprite (but the box2d body remains the same). The new sprite is in the shape of a box. When the change to a new sprite is made, the original weld joint is destroyed and the new sprite is substituted. A new weld joint is created to reattach the box2d body to the second box2d body (i.e. reattached to the person). In addition, the box2d fixture of the first body is changed to have more friction and less restitution because I don't want the second type of sprite to bounce and slide as much as the first type of sprite.
In each case, I have an impulse that I apply to the first box2d body when I programmatically break the weld joint. With the second sprite (the box), the distance traveled after applying the impulse is much farther than the first sprite (the stick). I don't understand why there is such a difference since I've only changed the "look" of what is being thrown. The density and mass is the same. When I step through the code, the linear velocity appears to be the same in the box2d structure. There is apparently something in the physics that I don't understand.
My goal is to have both sprite types travel to the same location if given the same impulse. Is it possible to enable each sprite type behave the same? Please provide some guidance to achieve my goal.
Below is the code where I remove the old sprite and reattach the new sprite (note that "attachedBody" is the box2D body that was previously defined with the old sprite):
b2WeldJoint *myJoint;
// break the existing joint
// Destroy joint so the attachedBody will be free from the player
world->DestroyJoint(myJoint);
// Substitute the existing sprite with a new sprite. Also transform the position of the new sprite so that it is still touching the players hand
Box2DSprite *sprite = (Box2DSprite *) attachedBody->GetUserData();
[sprite setDisplayFrame: [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName: #"newSprite.png"] ];
attachedBody->SetTransform(teamA.foreArmBody->GetWorldPoint(b2Vec2(65.0/100.0, -25.0/100.0)), -40.0f); // move new sprite to the players hand. Rotate the angle by 40.
// Make this new sprite stick when it lands
attachedBody->GetFixtureList()->SetFriction(8.0);
attachedBody->GetFixtureList()->SetRestitution(0.0);
// Create a new weld joint with the players hand and the new sprite
b2WeldJointDef weldJointDef;
weldJointDef.Initialize(attachedBody, teamA.foreArmBody, teamA.foreArmBody->GetWorldPoint(b2Vec2(6.0/100.0, -10.0/100.0)));
weldJointDef.collideConnected = false;
myJoint = (b2WeldJoint*)world->CreateJoint(&weldJointDef);
After digging deeper to answer the above comments, I found that I was not comparing apples and oranges. My problem is that in one case, the first body (the stick) had zero velocity when I applied the impulse. When I substituted the sprite of the first body with a new sprite and then gave it the same impulse, the body had a non-zero initial velocity. Therefore it travelled much farther. My solution is simple. I just need to set the velocity to zero before applying the impulse to cause the two different sprites to travel the same distance. For example:
attachedBody->SetLinearVelocity(b2Vec2(0,0));

Cocos2D 'fake' 3D projection on sprites. How to update Box2D bodies AND the debug draw to match.

I am using Cocos2D with the following settings:
[director_ setProjection:kCCDirectorProjection3D]; in the appDelegate class
kmGLRotatef(-47, 1.0, 0, 0); in my layer's draw method
This ensures that my objects are presented in a simulated 3D environment.
I've added Box2D for collision detection. I've setup the bodies. When I enable the debug drawing, then the bodies are arranged on the whole screen and the sprites are arranged in a perspective.
How can I add the same perspective for the bodies too?
The advice given is to find a bounding box from the fake 3d transformation in cocos2d of the sprite. Then use this bounding box for both the body's debug drawing and also to determine the new (or transformed) body for box2d.

Resources