I am making a basic app that pushes shapes across the screen and detects collision with Sprite Kit. My first attempt was using moveTo on the nodes. The issue I had was with collision, the objects would rotate around each other instead of bounce.
Therefore I found I need to use applyForce OR applyImpulse.
In this situation I have a circle for example that is position off screen at its start of life. We then determine a target exit point, and want to 'flick'/'push' the node in that direction.
I cannot figure out how to applyImpulse towards the target end position I have as a CGPoint. I need to get this to a CGVector but I am not sure what needs to be done. I had a look around and found some Ray tuts but they just show applyForce or moveTo. I am not sure how to calculate this.
I found a site that explains 2D physics well.
http://www.rodedev.com/tutorials/gamephysics/
With this I worked out what the angle needed to be and have a speed that I can control and it works well.
You can move an object by changing manually the x and y position so you can reach your end point. In the update function you change yourObject.position.x and yourObject.position.y if I have understood correctly your question. If not please be more explicit. Hope that helps.
Related
I am newbie in IOS Gaming, and i need to create a game using Sprite Kit framework for functionality similar to angry bird pulley system, and also wants to find the distance the object is travelled from the pulley to its landing.
Can anyone help me out with this, i would be thankfull for it.
Thanks in advance.
One way you could code a slingshot effect would to use a starting point on the screen at let's say (x=100,y=100). You would display a SpriteNode of a slingshot with the Y centered at the (100,100).
The next step would be to use touchesBegan:withEvent: in the area of the slingshot to let your code know the player is looking to shoot the slingshot.
You would use touchesMoved:withEvent: to track how far back (how much tension) the player is pulling back from the slingshot.
The release would be triggtouchesEnded:withEvent. Based on how far the touch began (x=100) and how far back is was released (for example x=30), you can apply force like this:
float forceUsed = startTouchX - endTouchX;
[_projectile.physicsBody applyForce:CGVectorMake(forceUsed, 0)];
If you are looking to angle the shot you would also have to track Y and use that variable instead of the 0 above.
As for calculating distance between 2 points on the screen, it boils down to x and y coordinates. Subtract objectA.position.x from objectB.position.x
Things can get a lot more complex of course but that all depends on what you want to do in your code. Hope this helps.
P.S. The touches above are all part of the UIResponder Class.
I'm working on a game in which the user should be able to trigger 'rods' that come out from the edge of the screen to displace elements on screen (balls). These projectiles roughly resemble pool-cues. Or perhaps pinball plungers, except that they start from the 'loaded' position (mostly offscreen), and when triggered, they eject out, then quickly retreat.
I'm unclear how I should build these with Sprite Kit.
The game uses the PhysicsEngine, and the onscreen balls should be effected both by gravity AND they should be displaced when they collide with the rods. However the rods should neither be effected by gravity, not displaced when they collide with the balls -- they should simply retreat regardless of whether they've made contact with the balls.
I realize I can set the affectedByGravity property for the rods. However because they will still displace slightly when they collide with the balls. How can I 'fix' or 'peg' them in place? Do I need to use an SKPhysicsSlidingJoint? If so, has anyone encountered any examples online? Is there a simpler way to do this?
A related physics engine, Box2D distinguishes static, kinematic, and dynamic bodies.
Kinematic bodies can move and will collide with other objects, but they are themselves not affected by dynamic bodies or forces like gravity. Thus, consider setting rod.dynamic = NO; but animate it with actions. See also here in the reference for SKPhysicsBody.
I'm pretty new to Box2D and cocos2d. I'm trying to do something which I thought would be pretty simple, but it is turning out to be more difficult than I had expected and I cannot find a working answer anywhere.
Basically, I want to move a b2body and rotate it to a certain point with animation.
I can get it to the correct position and rotation with:
targetBody->SetTransform(b2Vec2(10.0f,1.0f),10);
But I have no idea how to animate it there over time. I tried using cocos2d animation on the sprite used for the body, but that doesn't do anything. Any ideas?
There are a couple of ways you could do this.
You could use SetTransform every time step to update the position of the body gradually over time, in effect performing the animation yourself. The drawback with this method is that the body is 'teleporting' to the new position rather than moving, so it has no momentum, which means you can get odd results if it hits anything along the way. Still, if you know it will not hit anything or does not need to react to a collision this would be ok.
The other way is to SetLinearVelocity and SetAngularVelocity to give the body proper movement. This will keep the results of a collision realistic, and you don't need to keep updating anything every timestep. On the other hand, you will need to detect when the body has arrived at the desired position and then set the velocities back to zero, otherwise it will just keep moving. For dynamic bodies you will also need to counter gravity somehow, either by setting the gravity scale of the body to zero, or by applying an upwards force to balance gravity, or by changing the body type to kinematic during the move.
In general, you use Box2D to simulate the physical behavior of objects in relation to each other. The rules of mechanics implemented by Box2D dictate how your cocos2d CCSprites move if you continuously update the translation and rotation of your sprites according to their corresponding Box2d b2Body. You will have some kind of repeatedly invoked tick: method in which you step your Box2d world along in time, and in which you update your sprite positions according to simulation results of Box2d.
This pattern corresponds to b2Bodys of type b2_dynamicBody. Physical laws dictate the motion of the body in this case, and your sprites will follow these simulation results. This is why setting a conflicting position of a sprite by means of a CCAction or even directly will be undone almost instantaneously with the next tick:.
Solution 1: kinematic body type
However, there do exist other modes for a b2Body, and one of these is b2_kinematicBody in which the translation is no longer governed by the world but by the velocities or angular speeds you dictate through setters. So it would be one solution to work with body type b2_kinematicBody as in:
b2BodyDef bdef;
bdef.type = b2_kinematicBody;
With this you would manipulate the velocity and angular speed of a b2Body explicitly. In this case, Box2d is still responsible for moving bodies around, but according the velocities you dictate, and without any force effects of collision or gravity applied to this particular body. Also with this strategy, your CCSprites will follow b2Bodys. Setting conflicting positions for your sprites directly or by applying a CCAction would not make sense for the same reason as described above.
Solution 2: decouple sprites from Box2d
An alternative way to animating sprites would be to fully decouple those sprites from Box2d. In this case, you would simply not have any b2Body that governs the position of the sprite you are going to animate. Now, in this case, only you will dictate the position and rotation of your CCSprite, i.e. directly either through its position property or by applying a CCAction.
Recently I have a new project that uses Box2D as physics engine. And I am having some trouble with the body's position.
I want to draw images on the sprite, so I just use body.GetPosition as image's position. But I found that body.GetPosition returns the same value as body.GetWorldCenter, and I just wondering that I did something wrong.
I use box2d flash 2.1a in my project. And I currently subtract this position with half-width and half-height to walk around. Also, can you tell me if there is some way to solve my problem or draw the image in the correct positon in Box2D.
Thank you.
update
so sorry to post before read manual.
after RTM I got that body has two points,first is origin point and the second is center of mass ,so a regular shape's world center is always the same as it's origin point. sorry to post is.
Have you set the image in the userdata for the body? Your getting the body's position but you need to have a function that runs each world tick that can set the images position to the new location. Box2d is just numbers defining a simulation. Those numbers are constantly updating so the image needs to have position set each time there is a game tick. Hope this helps
In my app before, I was using box2D methods to move my bodies around but now I changed it so that I am controlling my CCSprites directly. Anyway I have this code:
myBody->ApplyForce(b2Vec2(AccelPoint.x, -40.0f), myBody->GetPosition());
myBody was a b2Body. And AccelPoint.x was the x value so my body could moves around controlled by the UIAccelerometer only on the X axis.
Also, the -40 was a constant for gravity.
So, what would be the equivalent in Cocos2D code?
Thanks!
You will need to store a velocity for the sprite, and every time step add a little bit to that velocity in the direction of the force. Then just move the sprite by the velocity each time step.