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.
Related
I am very new to Swift and currently coding a minigolf game.
However, the player can hit the ball n times.
How do I make a simple view which should show how many hits the player has left?
I think that you want something like this:
First of all, i recommend you to create a function to call when the game is restarted, there you can reset the scene, reset the player moves, etc...
You may do this like:
func restart(){
//Everything you need to restart the game
}
To call it later you just have to:
restart()
Ok, let's go to what you asked now:
declare a Int variable that contains the number of moves that the player has:
var playerMoves = 10 //Whatever number you want
Ok, you have a variable that contains the number of moves, now you have to show this on your scene, to do this, create an SKLabelNode:
let moveLabel = SKLabelNode()
Now, set the label text to be equal your playerMoves, set the position, the zPosition, the font, whatever you want:
moveLabel.text = "\(playerMoves)" //add this line to restart function that i mentioned and also set the variable playerMoves to "n" again.
moveLabel.position = ....
moveLabel.fontSize = ....
moveLabel.zPosition = ... //A number higher than any other zPosition
addChild(moveLabel) //Don't forget to add the label to scene!
Thats it! And now you have to update the playerMoves every time the player moves, to do this i'm assuming you are controlling somehow when the player moves (using update function, touches began, created a function, etc....)
so...when the player take one move:
playerMoves -= 1
moveLabel.text = "\(playerMoves)"
THATS IT!!! :) HOPE IT HELPS!
there are several ways to go about it. the most common way would be to overlay a spritekit scene over the scenekit scene. in the spritekit scene you can have a label element that you update
the code might look something like
let overlay = SKScene(fileNamed: "yourspritekitscene.sks")
yourScnView.overlaySKScene = menuOverlay
you can also assign a spritekit scene as a texture on a 3D object in your scene. or you can can make the numbers a texture you swap as you count down.
I need to create a road(one simple horizontal line) using SpriteKit, so i have four obstacles to put anywhere position on the road. These obstacles will be in a "shelf" and I have to drag them to the road.
How can i do that using SpriteKit and the new Swift2 ?
PS: I'm beginner on spriteKit.
So you meant to make some SKSpriteNode (road) as you say and put another SKSpriteNode onto that road. (Further I assume that you already have sprite nodes of the road and one obstacle)
define the property of your gameScene:
let roadAndObstaclesLayer: SKNode!
then in didMoveToView you have to add the road SKSpriteNode and obstacle SKSpriteNode to that layer. Your have to make either spawn obstacle method or you have to make position of your obstacles by yourself.
In general it would be like:
roadAndObstaclesLayer = SKNode()
roadAndObstaclesLayer.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetHeight(frame) / 4) // position of your layer
roadAndObstaclesLayer.addChild(road) //child road is added
roadAndObstaclesLayer.zPosition = 0 //zPosition of the layer in the scene
road.zPosition = 0 //zPosition of the child (road) in the layer
roadAndObstaclesLayer.addChild(obstacle) //child obstacle is added
obstacle.zPosition = 1 //zPosition of the child (obstacle) in the layer above child rode
addChild(roadAndObstaclesLayer) //child of the scene is added
As you understand this is an example of single obstacle that is on the road. Your obstacle and road would be placed at the same place but if you want to make some difference of the positions so you have to describe the position of obstacle separately.
As well you can place road and obstacle in different layers or in scene itself separately so their position would be independent according to each other. So in other words it depends on what do you want see at the end.
Hope it helps.
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.
In Swift, I have some code like this:
let wand = SKSpriteNode(imageNamed: "Wand")
let item = SKSpriteNode(imageNamed: "Item")
...
func didBeginContact(contact: SKPhysicsContact) {
contact.bodyB.node!.removeAllActions()
var imageToAdd = contact.bodyB.node?.name
wand.addChild(SKSpriteNode(imageNamed: imageToAdd!))
}
What I want is when a certain type of item touches the wand, I want to attach it to the wand. The bitmap masks are set and all of that works perfectly. But, when addChild adds the image, it's in the center of the wand and I want to control where it gets added.
Additional information. I'm using physicsBody to animate the wand and the items. The wand is controlled by the user touching the screen. I tried a few ways to connect the two objects, SKPhysicsJointFixed.jointWithBodyA and SKPhysicsJointSliding.jointWithBodyA but couldn't get it to work the way I wanted. I think joining the two physics bodies is overkill for what I'm doing, but I could be wrong. My real goal is:
1) to add (or join) one sprite (the wand) to another sprite (an item)
2) allow the wand to continue to be controlled (animated) by the user touch
3) have control over the relative position of the item in relation to some point on the wand.
It's the third item that is tough. Any help is appreciated, let me know if you need to see more code.
Your First Question:
The default position of the SKSpriteNode is (0,0) so if you add it to a parent node, the SKSpriteNode will thus be in the middle of the parent node's coordinate system. If you want to add the image a bit higher on the wand, lets say 100 points up, you just say imageToAdd.position = CGPointMake(0,100). The child node will remain attached at that location. Another option of course is to create a joint, which isn't overkill at all if you want the wand and the attachment to have physics properties.
Your Second Question:
As long as you don't remove the physics body from the wand, it will still be there and could be controlled by the user.
Your Third Question:
The attached item will have a certain position relative to the wand since you created it as a child node. If you need to move the item you would create an SKAction. For example, if you needed to move the item down the wand, you could say:
moveDownWand = SKAction.moveByX(0.0, y: pointsToMoveDownBy, duration: someDuration)
attachedItem.runAction(moveDownWand)
Hope this helps, let me know if you have questions.
Thanks #M321K, you put me on the right track! Here is what I did:
var nodeToAdd = SKSpriteNode(imageNamed: imageToAdd!)
nodeToAdd.position = CGPointMake(0, -40)
wand.addChild(nodeToAdd)
I had to create the sprite and set it's position before adding it to the wand. Huge help, thanks much.
so I have a sprite that is created every second and that is moving at a random position (sprite1) and another sprite that has a fixed position (sprite2). I would like that when sprite1 collide with sprite2, sprite1 is like sticked to it (it stops moving and is sticked to it) . How can I do this please ? sorry for my english I'm french :/
p.s : sprite2 is rotating with accelerometer, so if sprite1 collide with it I would like that it rotate too :)
I think, you can try to use box2d to do this. It will help to detect collisions and to manage rotations, movement, etc.
I think, you can do it simply in Cocos2d.
1) First set the rect for sprite1 and sprite2 using CGRectMake(x,y,width,height)
2) As you told sprite1 is moving at random position and sprite2 is fixed to particular position, you can check them collide by using CGRectIntersectsRect([sprite1 bounds],[sprite2 bounds]).
3) if it intersects, set sprite1.position = sprite2.position
Note: you said sprite1 is rotating, rect can be fit only to the regular bodies. if you want exact collision or physical properties for sprite better you can go for box2d.
If you don't want to use Box2d (which can handle circle collisions), you can try something like this:
1.) Detect collision, is the distance between the two circles center point (x,y), less than the sum of the two circles radius.
2.) Make the Sprite1 stick to Sprite2, Stop the movement of Sprite1, and save the relative delta (x,y) to Sprite2, then whenever Sprite2 moves or rotates apply the same delta movement and rotation to Sprite1.