How to flick a SKSpriteNode like a soccer ball - ios

If I had a SKSpriteNode on the screen, how would I be able to flick it so that it would simulate the physics of a soccer ball being kicked. how to throw SKSpriteNode? I am guessing that it would be sort of like this question, but instead of the node following your finger first before it is flicked shouldn't happen. It should look like when you flick you are swiping towards the node and then once your finger hits the node it moves it like the physics of a soccer ball. Can anyone give me a place to start in order to achieve this??

I would recommend using the touchesBegan method and touchesMoved method. Basically, keep track of the last position of the touch, along with the timestamp (using NSTimeInterval), and on each touchesMoved check if the soccer ball has the touch location inside it (using [soccerBall containsPoint:location]. Then, calculate the force that you should impart on the ball (compare timestamps, and compare positions), and then run:
[soccerBall.physicsBody applyImpulse:CGVectorMake(dx, dy)];
Replace dx and dy with the results of your calculations. You may wish to add a scale value to make sure that you get the results you are looking for.

Related

Swift/Xcode "Snake Game"

I am a student learning how to code in Xcode using swift. I am currently trying to make an app similar to the snake game that hopefully everyone knows.
I am currently on a windows computer so I can't show my code at the moment. I doubt you will need it for what I'm asking.
I am trying to make my Sprite Node (Just a while square) move with a swipe of the screen in the up, down, left, right fashion just like the original snake game. I have the Gesture Recognizer set up so it prints out what direction your swiping.
How can I make the sprite node move with a swipe? I want it to move infinitely in that direction until you either 1.) hit a will and you respawn/game over or 2.) swipe in a different direction.
I assume you add velocity to the node when you swipe so you just add the code into that swipe snippet but how do I make it apply ONLY to the "snake"?
You can use an SKAction to move the snakeHead toward the wall that corresponds to the direction you want to move. This can be done in the action parameter when you declare your gestures.
I suggest using .move(to: duration:) and to maintain a constant speed toward each wall you can use the distance, speed, time formula to calculate the duration for the .move(to: duration:) action.
Check out https://developer.apple.com/documentation/spritekit/skaction
https://developer.apple.com/documentation/spritekit/skaction/1417768-move

physicsBody.applyImpulse & collision happening twice instead of once

Heres the deal. My ball drops, hits the floor, and bounces back up with the help of the following code
ball.physicsBody?.applyImpulse(CGVectorMake(0, 25))
However, sometimes the ball recognises two collisions instead of one (on impact) and the ball gets applyImpulse x2. (Due to lag or something?) Causing the ball to fly way to fast. How do i make sure the ball doesn't collide with the floor twice? The ball is 16x16 an the floor is 16x160. I didn't have this problem earlier when the ball and floor were larger. But i really want to solve the problem and it must be possible!
What is happening is the ball is not moving fast enough between updates to be off the paddle before the next update check.
Remember what we did for the boss? Same thing gets applied to the paddle. When the ball hits the paddle, remove the contact check for it. Now you are going to have to add another node in, so that when you pass this node, you reenable the paddle check

Drag and launch type thing in Swift Sprite Kit?

If I have a sprite node, just a white circle somewhere on the screen, how am I able to make it so when I drag, let's say downwards and slightly to the left, the circle sprite would launch upwards and to the right and then gradually come down, like a golf shot.
Another way of explaining the mechanic is the Angry Birds game, where you launch the birds of the slingshot, the birds move in the opposite direction of your drag and gradually come down.
For another live example of the mechanics of the circle, look at the app, Desert Golfing.
Thanks, and if you don't know what I mean just comment and I'll try to explain it better.
OPTIONAL: If you do know how to do the slingshot type mechanic for the circle, do you also know how to add an arrow to the screen so users know which way the circle will launch?
Ill try to break your problem down into small steps that you could then solve yourself:
Detect the swipe:
use a UIPanGestureRecognizer. You will be able to implement a method that is called whenever a user drags their finger in a certain direction.
Here are some good references:
- Pan Gesture Official Documentation
- A very useful question that can serve you as a guide
Detect the magnitude of the swipe in order to impart an impulse
Check out the second link above. What you have to do is in the method for the gesture recognizer you will detect certain flags such as when the user starts the pan or ends the pan. Then, you can check for the location at those moments. With the Pythagorean theorem you should be able to get the distance and use that as the magnitude.
Apply impulse:
Create a physics body for your sprite and then make sure that you have gravity set inside your physics world. This allows the sprite to move in a parabolic motion. Then, use applyImpulse: on your physics body with your magnitude.
Regarding the arrow, you can easily do some delegation from within your pan gesture handler that gets the magnitude of the swipe and projects a reflection that your arrow will then show. Your question is pretty loaded so going into more detail is impossible, but best of luck. Hope this helps!

calculating angle based on user touch

I have a game with a character that can cast fire balls. Right now in my game, when I tap anywhere on the screen, I shoot a fireball at my touch point. For this fireball I'm using an SKEmitterNode where I've created a fireball particle emitter.
The problem I'm running into is, my fireball has an angle set already, but I want that angle to change based on where I tap, so that the trailing flames are behind the fireball, not going up or down or whatever I've set it to in the sks file.
I've never done something like this, is there something built into swift already for calculating angles? I can't find much on google
There are two options:
1) first one is that you can use :
fireBall.moveTo(touchLocation.x, touchLocation.y)
function so you can avoid use angles (if I understand you correctly). touchLocation is CGPoint of location of the touch event.
2) second one use as it was said before you will get an angle:
atan2(deltaY,deltaX)

How to implement mouse joint in Sprite Kit?

I have working implementation of drag and drop feature written in Cocos2d + Box2d for iOS. I need to port it to Sprite Kit. The logic is pretty basic:
when user touching the screen, find sprite under the finger
create mouse joint between found sprite and the scene's physics body, set joint's target to position of touch
when touches moved, update joint's target to new position
when touches ended, remove the joint
Everything is working quite well. I like the way physics is simulated when touches ends - the dragged shape has velocity dependent on dragging speed and direction, so when I left my finger from the screen while moving the sprite, it will continue moving in the same direction, but now affected by gravity and damping.
Unfortunately, I'm not able to reproduce the same effect using Sprite Kit. There is no such joint like mouse joint, but I have tried using other joint types. I almost succeeded with SKPhysicsJointFixed - I'm creating new sprite and joint between it and dragged sprite, when touches moving I'm moving the newly created sprite. Unfortunately it doesn't work like mouse joint in Cocos2d + Box2d - while dragging the sprite, its velocity always equals zero. So, every time I left my finger from the screen, the dragged sprite stops immediately and start falling affected by gravity. No matter how fast I move the finger when dragging, after releasing dragged shape, it behaves exactly the same way.
My question is how to implement mouse joint in Sprite Kit, or how to implement drag and drop feature that works like described above?
Update:
This is a box2d mouse joint example that could give you more clear view on what I am trying to implement using Sprite Kit:
http://blog.allanbishop.com/wp-content/uploads/2010/09/Box2DJointTutorial1.swf
I'm pretty new to iOS development so I guess this might not be the best way, but this is how I solved it and it seems to work pretty smooth actually.
I'm using a UIPanGestureRecognizer to handle the touch event. I set this one up in my didMoveToView: with this code:
UIPanGestureRecognizer *gestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
An UIPanGestureRecognizer is passed to handlePan: and I check with recognizer.state == UIGestureRecognizerStateEnded if the touched stopped. This is where I want to "release" the object and "let it fly away". For doing so I needed to calculate a few things, first of all I get the velocity of the finger/touch with this code:
CGPoint velocity = [recognizer velocityInView:recognizer.view];
(I use the same method (handlePan:) with other statements for getting the right object when touch starts, and letting the object be under the finger all the time by setting the position of the object to the location of the touch when moving)
Now I know the velocity, but I still don't know how much force I need to apply to the object. You should be able to calculate the force by this formula: Force = mass * acceleration. We know the mass (object.physicsBody.mass) and we know the velocity. To get the acceleration we need the time as well because acceleration = velocity / time.
In my update: method that is called every time a new frame is to be rendered I calculate the difference between the last time a frame was about to be rendered by doing something like this:
self.delta = currentTime - self.lastTime;
self.lastTime = currentTime;
I now can calculate which force that is needed to get the object moving in the velocity I'm "dragging it in". To do this I do the following:
[self.currentNode.physicsBody applyForce:CGVectorMake(velocity.x/self.delta * self.currentNode.physicsBody.mass, -velocity.y/self.delta * self.currentNode.physicsBody.mass)];
I take velocity divided with the difference in time since last frame (self.delta) to get the acceleration, and then multiply it with the mass of the object to get the force needed to keep (or actually getting) the object moving in the same direction and in the same velocity as it was moved by my finger.
This is working for me at the moment and I hope it helps other people too, and please tell me if I got something wrong or if there is a better solution. So far I have not found any "native solution".
If the only issue is velocity, then that is simple to fix.
Subtract the current touch position from the previous touch position to get the velocity between the last and current touch. Use applyForce: to apply this velocity to the body.
In order to prevent the body from moving on its own while dragging, read out the new velocity from the body after calling applyForce: and keep it in an ivar and set the body's velocity to zero.
When the touch ends, set the body's velocity to the one you keep as an ivar.
If this doesn't work, try using applyImpulse: and/or setting the velocity before calling any of the two methods, ie:
sprite.physicsBody.velocity = bodyVelocity;
[sprite.physicsBody applyForce:touchVelocity];
bodyVelocity = sprite.physicsBody.velocity;
sprite.physicsBody.velocity = CGVectorMake(0, 0);
That way you can keep the body's velocity without losing control over it while dragging.

Resources