I have a physics body that is uneven but not dynamic (the terrain) and a physics body (character) that is dynamic and is on top of the terrain, and I want this character to move along the terrain simulating kind of a "walking" action where it will keep going up the terrain but it won't fall back (or move back) like a ball because of gravity, and to set a maximum tilt so that it does not tip over.
My attempt was to add a force in the direction I want the character to move but this is causing the character to fall back due to gravity, and I don't want to disable gravity because then character won't fall down when going down the terrain.
Thank you very much
this is why using a physics engine for a platforming game is very difficult and not always a great approach..
you can try sprite.physicsBody.allowsRotation = false
might help
Create SKAction to move your character to destination point or dx and dy. Run that SKAction from your character node with the runAction. Like
SKAction.moveByX(...
When the action is finished, gravity will bring the character down.
If the movement is slow, play with the character's physicsBody friction and/or mass.
You can also change the the character's physicsBody.velocity = CGVectorMake(
And your terrain will be better with edgeLoop physicsBody which won't be dynamic.
And with uneven you mean inclined but smooth? If not smooth and with edges, your character may get held up at an edge depending on center of gravity of character and if you are allowing rotation.
Related
I am making a top down game where I am having cannons fire and having their projectiles move to the clicked location via the SKAction moveTo:duration. I am supposed to have wind change the trajectory so I have the cannonball implemented as an SKPhysicsBody and I am setting gravity to be a the windspeed since it is the only thing I can find that applies a constant force like wind would. The problem I am having is moveTo is probably the wrong way to be implementing the cannonball. The ball moves according to the path it should but then lands at the tapped location which is not what I want. I can't find a good alternative to moveTo. Any ideas?
You have to solve the projectile equations to determine the force needed and angle to applyImpulse. Solving the equation is only considering the gravity force and impulse force applied to projectile using the applyImpulse with your distances known from your cannons to user's click projectile destination.
Your applyImpulse launches the projectile, you start your wind and other external forces which will have an impact on the projectile path, changing it's destination from that of user's clicked.
You need to know few physics and math to re-arrange the equations and solve them :)
Not sure if you need to do all the advanced math, just set the angle of your cannon and apply impulse to the cannonball, and use the scene.physicsWorld.gravity as your wind, just make sure you also give your cannonball a physicsbody that has dynamic and affectedByGravity set to true.
To calculate the angle, you would do:
let angle = atan2(Double(touch.y - cannon.y),Double(touch.x - cannon.x))
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:.
Is there any way to set an x,y coordinate that gravity pulls towards?
We want to suck a number of objects with physicsbodies towards a point as if it was a black hole.
Not for the regular world gravity.
To achieve this effect, you have to apply to each body an impulse every frame. The strength and direction of the impulse depends on the distance of the body (node) to the gravity source's position.
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));
I'm making a Breakout clone and having a little trouble with the ball-to-paddle collisions. I have a rectangle represent both the ball and the paddle and when they intersect, the Y vector representing the ball's velocity is negated (as shown below). That all works fine. The problem is when the paddle is moving to the right I want it to nudge the ball a little to the right (as opposed to it just reflecting off normally) and I want the same to happen in the opposite direction is the paddle is moving to the left. I'm not sure how to go about doing this and I've looked all over. Any help would be appreciated. Thanks.
if (paddleRectangle.Intersects(ballRectangle))
{
ballVelocity.Y *= -1;
collision.Play(); //a collision sound
}
EDIT: Basically I want to slightly change the angle at which the ball bounces off the paddle based on which direction the paddle is moving. If the paddle is not moving, then the ball will bounce normally (by inverting the Y component of the ball's velocity)
Add the paddle's velocity vector to the paddle's normal vector (this basically bends the normal in the direction the paddle is moving) and normalize the result. Use this as the collision normal for reflection.
Vector2 collisionNormal = Vector2.Normalize(paddleNormal + (paddleVelocity * desiredEffectAmount));
ballVelocity = Vector2.Reflect(ballVelocity, collisionNormal);
i did some grinding in my head... and here are results. to achieve that you will need, moving direction of paddle, speed of paddle, ball speed, ball direction. and then by some math function calucalte angle and speed of bounce.
i think this image (if bouncing is phisicaly correct) will give you idea how to create this. can't help you with function that will handle this but i would go and try that way as in image.
You want a little friction, but probably not real friction.
Try scaling the paddle speed down by some factor and adding it to the ball velocity.