I am making a Tetris kind of game, where I want my blocks to fall at a constant velocity. I want to achieve it using SpriteKit Physics Words Gravity.
Problem is that gravity is necessarily acceleration and hence block start to move faster as they fall. I know I can turn gravity off and use actions to move the block but I wish to do it with gravity.
Is there a way to make the gravitational force in SpriteKit world a linear constant velocity?
Using the default physics you will not achieve what you are looking for.
In the definition of Gravity in Spite Kit is clear that is a acceleration, so is no possible to achieve linear speed with it.
A vector that specifies the gravitational acceleration applied to
physics bodies in the physics world.
But, you can have some workarounds to achieve the behavior you want.
Gravity Acceleration 0, and add speed to the falling object.
Limit the maximum Speed of an Object.
Do you own physics
I Think the best way to do it, with gravity working as default, is by limiting the maximum speed.
2 - Limit the maximum Speed
Consulting this post.
In didSimulatePhysics(), you can verify the speed of the object, and limit it.
Like this (Credits to #Andrew, in the original post)
- (void)didSimulatePhysics {
if (node.physicsBody.velocity.x < MAX_SPEED_X) {
node.physicsBody.velocity = CGVectorMake(MAX_SPEED_X, MAX_SPEED_Y);
}
}
Related
I'm working on a project where I have a node affected by gravity. I would like to be able to apply a vertical acceleration to this node without touching gravity. Pretty much like a hot air balloon that I would make go up or down while other objects are still normally affected by gravity.
balloon = Vehicle()
balloon.physicsBody = SKPhysicsBody(polygonFrom: path)
balloon.physicsBody?.affectedByGravity = true
I tried playing around with applyForce(_:) and impulse but what I'd like is a proper acceleration and not a punctual impulse to defy gravity over time! Any suggestion?
What you're looking for are physics fields (SKFieldNode), in Sprite Kit.
These provide the ability to influence objects with general forces, like wind, lift, black hole style attraction etc.
You can read about them here.
The really important consideration of how they can work is in this quote:
Physics bodies with affectedByGravity set to false are still affected
by the gravity fields created by linearGravityField(withVector:) and
radialGravityField().
But what they forgot to also make clear(er) is that objects influenced by gravity are ALSO influenced by these fields.
I'm working for a small bouncing ball game using the SpriteKit physics engine. My problem is:
When I apply a huge impulse on the bouncing ball to have it fall on ground fast, sometimes it may pass through the ground (very thin, height=2).
I find this in the Apple document, but it doesn't work.
Specify High Precision Collisions for Small or Fast-Moving Objects
When Sprite Kit performs collision detection, it first determines the locations of all of the physics bodies in the scene. Then it determines whether collisions or contacts occurred. This computational method is fast, but can sometimes result in missed collisions. A small body might move so fast that it completely passes through another physics body without ever having a frame of animation where the two touch each other.
If you have physics bodies that must collide, you can hint to Sprite Kit to use a more precise collision model to check for interactions. This model is more expensive, so it should be used sparingly. When either body uses precise collisions, multiple movement positions are contacted and tested to ensure that all contacts are detected.
ship.physicsBody.usesPreciseCollisionDetection = YES;
You can set your sprite's node.physicsBody.usesPreciseCollisionDetection = YES; but this will not guarantee a collision flag all the time as your sprite's velocity could simply be just too high.
You should apply a speed limit to your nodes as to prevent them from going too fast. Something like this:
if(node.physicsBody.velocity.dx > 200)
node.physicsBody.velocity = CGVectorMake(200, node.physicsBody.velocity.dy);
The above code example will limit the right movement, dx, of your node to 200 while keeping the dy (up/down) velocity as is.
Hi guys i want to apply slow motion in upward direction,
what i am confused, when i applyimpulse
[self.physicsBody applyImpulse:CGVectorMake(0, 60)];
it does applyimpulse with required speed as it measure from its velocity mass and other physics things
what i need to applyImpulse but with controlling speed of impluse that is applied on object on which impulse is being applied.
i tried to set even self.speed but got no success,
how one can achieve desired impluse or Force on an sprite with controlling over speed.
are there some properties that should i set for the SKSpriteNode before applying Impulse,
or some thing else?
Any suggestion or thoughts will be appreciated
Thanks
The speed property of SKNode is to do with SKActions, however the speed property of SKPhysicsWorld is what you probably want to tweak to achieve physics in slow motion.
It says the following in the documentation about the speed property of SKPhysicsWorld
The default value is 1.0, which means the simulation runs at normal speed. A value other than the default changes the rate at which time passes in the physics simulation. For example, a speed value of 2.0 indicates that time in the physics simulation passes twice as fast as the scene’s simulation time. A value of 0.0 pauses the physics simulation.
Access it from within your SKScene subclass like this-
self.physicsWorld.speed = 0.5; // half speed (slow motion)
All forces are applied as actual physics forces on physics bodies.
The resulting movement of the body that had the force applied to it depends on not just the magnitude and direction of the force but also the size and density (i.e. mass) of the body the force is being applied to and where on the body the force is applied.
I'm not entirely sure what you mean when you say you need "controlling speed of impulse" though.
Maybe what you need is not to use forces at all but to move the node manually.
You could use an action [SKAction moveByX:y:] or update the position in the update method. This way you can control the speed of the movement exactly.
Is it possible to accelerate an SKSpriteNode?
I know the velocity can be set easily with node.physicsBody.velocity but how hard would it be to set it's acceleration?
Working backwards from newtons second law a motion : F = m.a
You can achieve a desired acceleration by using applyForce where the force is the acceleration multiplied by the mass.
[node.physicsBody applyForce:CGVectorMake(node.mass*acceleration.dx,
node.mass*acceleration.dy)];
applyImpulse instantly imparts a quantity of energy (in Newton.seconds). Your object doesn't accelerate so much as instantly reach the desired speed. This is unlikely to look very natural as it implies near-infinite power (energy divided by time) therefore is only really suitable for explosions (shooting bullets for example).
applyForce applies a force (in Newtons) for the time-interval the simulation runs in (i.e.: 1/60th of a second). This allows you to correctly accelerate an object and simulate many different forces being applied simultaneously (gravity, wind, rocket boost etc.) in different directions.
Also worthy of note is applyForce:atPoint: this allows you to specify at which point of the object the force is applied. For example if you were simulating a balloon with a string, the string would apply its weight to the bottom of the balloon, whereas the lift of the base in balloon would be applied to the centre of the ballon. Applying a force elsewhere than at the centre of gravity will cause the object to rotate.
Lastly, you have the corresponding applyAngularImpulse: and applyTorque: which allow you to influence an object's rotation speed. This is useful for example if you want to keep an object upright despite various bounces: you could apply a torque proportional to the angle (or square it if you want to avoid oscillations).
All this is very well documented here: SKPhysicsBody
But if you need more information about the physics themselves then have a look at Wikipedia:
Newtonian Physics and associated pages (angular momentum for example).
If you want it to accelerate, then you should change the direction of gravity for the object
self.physicsWorld.gravity = CGVectorMake(dx,dy)
but this would make everything accelerate, if that is okay
I have developed game something like coin dozer. And for the smooth movement of coin i have add one Physics Material to each coin but my game is very slow after doing that . Is there any alternative of that or how can i make coin movement smooth without use of Physics material . So can anybody help me to come out from this situation.
So the problem is physics calculation.
DO NOT use the mesh of the graphic as the collider to calculate coin's moving, especially when there are lots of triangles and verts on the mesh. You should choose a simpler collider, maybe something like prism would behavior similar as a coin and reduce a lot of calculation. You can use another simple prism mesh exported from 3d software and make a new game object with that mesh. Stripe off everything related to physics(rigid body, collider and physics material) from the origin coin. Then organize the visible coin without physics and the new added object(which handle all physics) to the same parent. Less triangles in a mesh collider means less calculation. Control the collider mesh triangles as few as possible. I suggest to use a box collider as a start point to check if the performance improves.
Another thing might help is changing the Solver Iteration Count in the Physics Setting. You can try to change it to a lower value (maybe 3 or 4 is enough for a coin game) from the default.
Limit the frame rate to a lower value alse can help, but it is the last way you should go.
You can add physics to the coins with delay. I mean add physics when coin is near to fall. Also you need to destroy every coin body when you are removing the coin out of the scene. If you are removing only sprite the there will be too many bodies on the scene.