I am currently moving a rocket using this code:
let location = touch.locationInNode(self)
rocket.position.y = location.y
I want to know if it would be easier to use the SKActionTimingMode.EaseOut and if so, how do I make the rocket move up and down along the Y-axis using an SKAction.
Is there a way to smoothly move a node with the code I am already using?
The app is set to landscape.
Here's how you can do it with SKAction. I think using SKAction would be much smoother. Alternatively, you could also attach a physics body to the node and call applyForce to it by calculating the force of the swipe or if its a touch then calling applyImpulse with a predefined value depending on where the touch occurred (i.e. above or below the object.)
let location = touch.locationInNode(self)
let action = SKAction.moveToY(location.y, duration: 3.0) // Or however much time you want to the action to run.
action.timingMode = .EaseInEaseOut
rocket.runAction(action)
Related
Im creating a game that where you tap to start the player to make him jump, and then as he goes up, more and more objects generate for you to collect to gain points (think of doodle jump). I have it set up so this will happen, but instead of being given a boost by the object, he just floats up out of the scene. Id also like to know how to remove the object from the scene when the player touches it. Thanks in advance(:
Here is my code for making him gain velocity when he touches the object:
func bounceOff() {
player.physicsBody?.affectedByGravity = false
player.physicsBody?.applyImpulse(CGVectorMake(0, 10))
let advance = SKAction.moveByX(0, y: 10, duration: 5)
runAction(advance)
}
Your object goes off the screen because you cancel gravity. The impulse you apply pushes up, but there is no force pulling down. As to removing node from the scene. You can use node's removeFromParent method.
If I'm making a game in SpriteKit that has a large "world", and I need the user to have the option of zooming in and out of the SKScene, how would I go about this? Or, to make things simpler, in the didMoveToView function, how can I present more of the world to the user's device's screen (without using world.runAction(SKAction.scaleTo(0.5)) or something)?
There's a SKCameraNode that's built specifically for this. The SKCameraNode defines the viewport into your scene. You create a camera node and assign it to the camera property of your scene.
let cameraNode = SKCameraNode()
cameraNode.position = CGPoint(x: scene.size.width / 2, scene.size.height / 2)
scene.addChild(cameraNode)
scene.camera = cameraNode
You can then create actions and run those actions on the camera. So to zoom in on the scene, you'd do this.
let zoomInAction = SKAction.scale(to: 0.5, duration: 1)
cameraNode.run(zoomInAction)
The cameraNode basically is a square node in the scene, that I think takes the proportions of the view by default? Cuz there's no size initializer. So when you make it smaller, the scene looks like it gets zoomed. To zoom out you'd make an action that increases the scale. Basically imagine a rectangle on your entire scene, and whatever is in the cameraNode's rectangle directly shows on your iPhone screen. You can also add moveTo actions and sequence actions and set timingModes on the actions same as if it were your normal spriteNode.
Here's the WWDC where the apple guy shows what I've just said. CameraNode bit is around 3 mins before the end.
https://developer.apple.com/videos/play/wwdc2015-604/
So, the best solution I could could find goes something like this. In the didMoveToView function, create an SKSpriteNode called World and make it whatever size you want your world to be. Then, write world.setScale(0.5) if you want a 50% zoom-out. However, if you have a player node that needs to always be centered in the screen, you'll need to add the following to your update function.
override func update(currentTime: CFTimeInterval) {
world.position.x = -player.position.x * (0.5)
world.position.y = -player.position.y * (0.5)
}
I'm trying to create a shooting mechanism in a simple shooter type game. To put it simply, there's a "line" at the bottom of the screen where the "bullet" lies (think like a bow and arrow), and the player needs to be able to tap and drag the bullet back like a slingshot. The movements I'm needing along the line are left and right along the line, and obviously to be able to drag the bullet down with the line to create the slingshot effect.
My only theory on how to do this is to create a rope like I've seen other people do with many different segments that are all connected with joints, and then connect the ball to the line with joints as well..but how do I allow the ball to move along the line and interact with each other like a slingshot. Surely the ball would just get tacked onto one of the little segments and not be able to slide around?
Is this something huge and bad or is there a somewhat manageable way to tackle this for someone not super versed in Swift?
I would create a rope with the bullet attached to the end (have the bullet's location be the end of the rope):
let rope = SKSpriteNode(imageNamed: "rope")
rope.position = //location at bottom of screen
rope.size = //size that looks good resting
rope.name = "restingRope"
rope.anchorPoint = CGPointZero
self.addChild(restingRope)
Then, when the user presses and drags the bullet, remove that rope, create a new rope whose length is from the origin of "rope" (the original rope) to wherever the user has their finger according to the touchesMoved function. Then move the bullet to the end of the new rope and change its position by using the SKAction.moveBy(x: , y: , duration: ) function. Don't forget to remove the old rope.
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
childNodeWithName("restingRope")?.removeFromParent()//remove origional rope
var nodeTouched = SKNode()
var currentNodeTouched = SKNode()
let rope = childNodeWithName("rope") //reference old rope
for touch: AnyObject in touches {
childNodeWithName("strechedRope")?.removeFromParent() //remove strechedRope (will do nothing if it has not been initialized)
let location = touch.locationInNode(self)
var strechedRope = SKSpriteNode(imageNamed: "rope")
strechedRope.position = rope!.position
strechedRope.anchorPoint = CGPointZero
strechedRope.size = CGSizeMake(location.x - rope!.position.x, 5)
strechedRope.name = "strechedRope"
self.addChild(strechedRope)
}
}
When the user lets go (touchesEnded), apply an impulse to the bullet and move the rope with it. I did not include any of the bullet code because it seems self explanatory. If not, let me know.
Hope this helped and good luck.
Here is how I would do this, hopefully this fits your expectations. This is mostly for 2d but could work in 3d. Your slingshot should be made out of three things.
One line
Another line
Slingshot sprite
Bullet
Then what you do from their is sorta simple. I would write out the code, but I don't exactly know how to draw a line between two moving points. But basically what you would do is draw line 1 from the slingshot to the bullet, and line2 from the slingshot to the bullet. Then make the bullet draggable, and then when it is released get the vector from the dragged position, to the original bullet position, and apply it as a physics impulse. This should work.
I am creating an Iphone game in Xcode using swift , and there is a ball i want it to keep constantly rotating , i think i need to do it with the update method , but how could i do it , and if there another way with out using the update method please let me know
You could use an SKAction (take a look at the documentation; you'll see SKActions have a variety of uses). For a rotation you could do:
// The angle is measured in radians and the duration is measured in seconds.
let rotateAction = SKAction.rotateByAngle(1, duration: 1)
To make the action run forever you can use another SKAction:
let repeatAction = SKAction.repeatActionForever(rotateAction)
Finally, you need to make your node (ball) run the action:
ball.runAction(repeatAction)
Take a look at the SKNode documentation for other methods you can use to run an SKAction.
Also, I'm assuming you're new to Sprite Kit, so I'd recommend you take a look at The Sprite Kit Programming Guide.
I am using SpriteKit, and my sprite is slowing as it approaches the touched point.
I would like the sprite to remain at a fixed speed as it moved from initial point to the touched point on the screen.
Currently, i have the duration set to 3.0
In the touchesEnded event, i gather the new point of the touch and save the value to a property.
In the scene update event, i perform a
float realMoveDuration = 3.0;
SKAction *actionMove = [SKAction moveTo:self.newPoint duration:realMoveDuration];
[self.player runAction:[SKAction sequence:#[actionMove]]];
So when the player sprite starts getting closer to the touch point, the movement slows down, and gradually reaches the touch point.
This is not the action I am looking for, i would like the player sprite to continue at a constant rate of travel to the touched point.
You should just run your SKAction in the touchesEnded event.
If you have that code in the update event, it's starting a new SKAction 60 times per second. You only ever need to run a new SKAction when there is a change in destination.
If there is a change in destination before you reach the original destination, you should remove the action from that node and then add a new one.
Also, not certain about the specifics of what you are doing, but how quickly an object moves is based on the distance and the time you have specified for it to get there. So if you want a node to move at a consistent speed, regardless of distance, you need to make a calculation to determine the right duration to set for your SKAction.
For example if speed represents pixels/units per second you might do this to calculate your duration :
duration = distance / speed;
If you are using an SKAction to move the sprite, use the timingMode property. The default is SKActionTimingLinear. So if you haven't changed it, the node should move at a constant speed.
Here's a link to the available Action Timing Modes.