If anyone knows how to do this, I have a sprite node that I want to position all around the screen "Like stars" and I want to create a field node that pulls the "stars" to the center of the screen as more stars spawn basically creating a vortex like action.
This is how I created the node in this "addObjects" function, How is it that I can have this "stars" effect? and have them come towards the center of the screen unlimitedly? thanks a bunch
func addObjects() {
for (var i=0 ; i<5 ; i++) {
let PositiveNode = SKSpriteNode(imageNamed: "Enemy1")
PositiveNode.physicsBody = SKPhysicsBody(circleOfRadius: PositiveNode.frame.size.width/2)
PositiveNode.physicsBody?.dynamic = true
self.addChild(PositiveNode)
}
I had a thought that maybe making a for loop could help me achieve my goal , but I'm probably wrong.
To simulate a black hole effect you can use a radialGravityField SKFieldNode. As for an unlimited number of stars, you can create SKSpriteNodes and remove them from the scene once they reach a predefined position. That being the center of radial gravity field.
The important thing here is to removeFromParent as to avoid a memory leak caused by constantly creating new nodes without removing the ones in the center.
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'm making my first shooter game using Swift and SpriteKit and I've recently been running into problems with setScale(). I have a Laser class whose instances are added as children to a Ship class. I now realize that any down scaling of the parent node will scale its child as well. In my update method in GameScene I check the position of each child named 'Laser' to determine if it should be removed from its parent when offscreen. I recently updated some of my sprites- including their relative sizes, and I noticed that the position of each laser is way off, as they are removed far before they reach the end of the screen and upon debugging their x positions are in fact far larger than where they are displayed onscreen. I also noticed that the starting x of each Laser instance is relative to its original position within the Ship instance. So the ship may be halfway across the screen but the laser x position still starts at 0 and if the ship is able to pass the laser, the laser's position becomes negative--is there a way to grab its position on the screen rather than relative to its start within its parent?
This is the code I'm doing the check with:
self.aShip.gun.enumerateChildNodesWithName("laser",
usingBlock: { node, _ in
if let aLaser = node as? Laser { i
if(aLaser.position.x > self.size.width){
aLaser.removeFromParent()
}
}
}
)
It seems like scaling has a ton more baggage than I would normally assume, so any insight into this problem or how to manage the relation between code and sprites would be awesome!!
EDIT:
I found that adding let positionInScene = self.convertPoint(aLaser.position, fromNode: self.aShip.gun) under if let aLaser = node as? Laser {and consequently using positionInScene rather than the aLaser position works.. however, I still don't fully understand the scaling effect going on with aLaser and it's position and don't know if its efficient to have to convert positions like this at the rate of update (60 times a second).
What I'm trying to do is moving a sprite in a random direction or a random point and have it continue moving - with the affects of physics. I tried moving a sprite to a random point and although it worked, it just stopped if the random point was in the middle of the screen. I'm just hoping for the basics so any code/help from someone would be helpful. Also if you think theres a post already on this, can you list the hyperlink? I spent some time researching and I couldn't figure it out. Thanks in advance!
See SKPhysicsBody and methods like applyImpulse.
In short, you create and configure an SKPhysicsBody; assign it to the sprite; and then apply force vectors to the body. Procedural example:
let sprite = SKShapeNode(circleOfRadius: 10)
sprite.physicsBody = SKPhysicsBody(circleOfRadius: 10)
sprite.physicsBody.friction = 0.2
sprite.physicsBody.restitution = 0.75
sprite.physicsBody.mass = 0.5
sprite.physicsBody.applyImpulse(CGVector(1, 1))
Much of this you can configure declaratively, rather than procedurally, with the SpriteKit scene editor in Xcode.
I have several sprite physics bodies lined up next to one another, each physics body should be just slightly touching the next physics body. When I leave the app in idle for a few minutes, some of the physics bodies start to over lap each other, and when I leave the app in idle for hours, the physics body are significantly overlapping each other (about 5-10 pixels). It could be that the sprites are moving, not the physics bodies, I can really tell which one.
I don't think that collisions between the physics bodies is pushing the position around, as I setup each physics body's collisionBitMask so that they do not collide with one another. Also, there is currently no SKActions in place to move anything in the app.
Below is the code I use to setup each physics body:
spriteSegment = SKSpriteNode(texture: arrayTextureSegments[segmentType])
spriteSegment.position.x = CGFloat(countSegment) * 30 // the spriteSegment size is 30 by the way
spriteSegment.physicsBody = SKPhysicsBody(rectangleOfSize: spriteSegment.size)
spriteSegment.physicsBody?.restitution = 0
spriteSegment.physicsBody?.dynamic = false
spriteSegment.physicsBody?.affectedByGravity = false
spriteSegment.physicsBody?.categoryBitMask = bitType1
spriteSegment.physicsBody?.collisionBitMask = bitType2
spriteSegment.physicsBody?.contactTestBitMask = bitType2
addChild(spriteSegment)
Does anybody know what would be creating this behaviour?
EDIT:
Done up a sample and I still get the same strange behaviour where the images change position. I notice a small change at 20 mins, but if the app is left in idle for a hour, you should be able to clearly see what I'm talking about.
GameScene.swift code:
http://hostcode.sourceforge.net/view/3496
GameViewController.swift code:
http://hostcode.sourceforge.net/view/3497
Segment Image (0#2x~iphone.png):
Edit:
Here is an image of the difference before and after an hour. The blueish color is the physics body outline.
EDIT:
Don't know if I've done this right, but link for entire project: click here
Last Edit:
I recorded where each sprite was every 20 mins, here are the results.
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.