Instruments Allocations of the charts using sprite kit template - swift

I'm trying to understand how Instruments works and to make my apps better. Below is an image of the result for default SpriteKit Template. I don't understand why are so many Allocations, because the code is small
override func didMoveToView(view: SKView) {
/* Setup your scene here */
let myLabel = SKLabelNode(fontNamed:"Chalkduster")
myLabel.text = "Hello, World!";
myLabel.fontSize = 65;
myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame));
self.addChild(myLabel)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
let sprite = SKSpriteNode(imageNamed:"Spaceship")
sprite.xScale = 0.5
sprite.yScale = 0.5
sprite.position = location
let action = SKAction.rotateByAngle(CGFloat(M_PI), duration:1)
sprite.runAction(SKAction.repeatActionForever(action))
self.addChild(sprite)
}
}
I try to find tutorials but many of them are very old

Well we aren't apple programmers, we don't really know what's going on inside SpriteKit.
I'm guessing it's just because of the complexity of the physics engine.
I suggest just watching out for leaks.

Related

Why my node is invisible

I'm currently trying to make a node that can change it's texture, but it's not visible on the simulator. I know it's there, cause I set showNodesCount to true and it displays that 2 nodes are on scene. It's displaying a cannon node, but not rgyBox node, that should change it's texture if I tap on cannon node. Here is my code:
class GameScene: SKScene {
var gameOver = false
let cannon = SKSpriteNode(imageNamed: "cannon")
let rgyArray = ["redBox", "greenBox", "yellowBox"]
var rgyBlock = SKSpriteNode()
func changeRgyColor() {
var randomRGY = Int(arc4random_uniform(3))
rgyBlock.texture = SKTexture(imageNamed: rgyArray[randomRGY])
}
override func didMoveToView(view: SKView) {
/* Setup your scene here */
cannon.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
self.addChild(cannon)
rgyBlock.texture = SKTexture(imageNamed: rgyArray[1])
rgyBlock.position = CGPointMake(self.cannon.position.x, self.cannon.position.y + 20)
self.addChild(rgyBlock)
rgyBlock.zPosition = 10
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if self.nodeAtPoint(location) == self.cannon {
changeRgyColor()
}
}
}
What am I doing wrong?
You need to recreate the rgyBlock by calling rgyBlock = SKSpriteNode(imageNamed: rgyArray[1]). Where it is defined at the top, it is defined as nothing. You then need to recreate it in didMoveToView. You can remove the texture set in didMoveToView for the rgyBlock.
You could do it a different way, and put imageNamed: "aTextureNameHere" into the define of rgyBlock. This will give rgyBlock a value. Then you can set the texture (as you already do) in didMoveToView. This way may be quicker and easier.

SpriteKit Gravity

Im just messing around in sprite-kit working on my game design skills and I came across something that I dont know how to do. That is make the physicsworld gravity more like moon gravity. I have a SKSpriteNode which is a red ball and I can drag that ball and click wherever I want it to go. What I wanted to create is somewhat of a throwing mechanism. Is this possible with one line of physics world gravity code? Or is it way more in depth this is code that I have.
import SpriteKit
class GameScene: SKScene {
let redBall = SKSpriteNode(imageNamed: "redball")
override func didMoveToView(view: SKView) {
let worldBorder = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = worldBorder
self.physicsBody?.friction = 1
self.physicsWorld.gravity = CGVectorMake(0, -1)
redBall.position = CGPoint(x:250,y:50)
addChild(redBall)
redBall.physicsBody = SKPhysicsBody(circleOfRadius: redBall.size.width/2)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch = touches.first as! UITouch
let location = touch.locationInNode(self)
redBall.position = location
}
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch = touches.first as! UITouch
let location = touch.locationInNode(self)
redBall.position = location
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
My game state right now is when I drag a ball to where I want and release it just drops. What I want to accomplish is for example if I grab the ball and drag up and to the right I want the ball to follow my the direction it was going when I released it. How would I create that in my code thanks!
In my code all I do is self.physicsworld.gravity = CGVectorMake(0, 0) (this would turn off gravity completely). Then just mess around with that vector and find something that feels like moon gravity.
You might have to make your game-scene be a SKPhysicsContactDelegate

How do I make an endless horizontal background in Swift?

import SpriteKit
class GameScene: SKScene {
let bgline1 = SKSpriteNode(imageNamed: "Line.png")
let bgline2 = SKSpriteNode(imageNamed: "Line.png")
override func didMoveToView(view: SKView) {
/* Setup your scene here */
backgroundColor = SKColor.whiteColor()
bgline1.anchorPoint = CGPointZero
bgline1.position = CGPointZero
bgline1.zPosition = 1
bgline1.size = CGSizeMake(self.frame.size.width, self.frame.size.height)
self.addChild(bgline1)
bgline2.anchorPoint = CGPointZero
bgline2.position = CGPointMake(bgline1.position.x-1, 0)
bgline2.zPosition = 1
bgline2.size = CGSizeMake(self.frame.size.width, self.frame.size.height)
self.addChild(bgline2)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered*/
bgline1.position = CGPoint(x: bgline1.position.x-4, y: bgline1.position.y)
bgline2.position = CGPoint(x: bgline2.position.x-4, y: bgline2.position.y)
if bgline1.position.x < -bgline1.size.width{
bgline1.position = CGPointMake(bgline2.position.x + bgline2.size.width, bgline1.position.y)
}
if bgline2.position.x < -bgline2.size.width{
bgline2.position = CGPointMake(bgline1.position.x + bgline1.size.width, bgline2.position.y)
}
}
}
This is my code for creating a scrolling horizontal endless background. It is supposed to make an endless background but it isn't. The code is not looping the first try but after that it does. I would like to know why it does not work and how should I fix it.
EDIT- Starts out with 2 nodes and a line and the fps is <20. Then the line ends and when it "runs out" the node count becomes 0 and fps becomes 60. Than after a few seconds the line pops back up and it runs perfectly like a endless scrolling background.
bgline2.position = CGPointMake(bgline1.size.width-1, 0)
This line of code somehow fixed the problem for me. I don't know how it fixed it but it did. If someone wants to explain this for me please do. I have not seen any tutorials out there that use this but it worked for me.
Rohit

Sprite Kit how to update an image on a button?

I am new to Swift and Sprite Kit.
I want in MyScene.swift to create a button that has a specific image. Every time I click on the button I want to change the button image with a new image.
How can I do that?
GameScene.swift
class GameScene: SKScene {
var rollButton:SKSpriteNode = SKSpriteNode(imageNamed: "dice1.png")
override func didMoveToView(view: SKView) {
rollButton.position = CGPoint(x: 79, y: 290) //this position is based to what? Is there an easier way to put a button using storyborard
rollButton.setScale(0.5) //what does setScale mean?
self.addChild(rollButton)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
for touch: AnyObject in touches {
if CGRectContainsPoint(rollButton.frame, touch.locationInNode(self)) {
changeButtonImage()
}
}
}
func changeButtonImage() {
//radom get value beteween 1 - 6
change the rollButton image with a new value??? //how to do that
}
Is there a way i an add a UIButton on Storyboard and than connect
GameScene,swift with that storyboard? (adding child nodes
programatically can be really hard)
The CGPoint of a node is based to what? the current UIView?
How to programatically change the image of a button (in swift using
SpriteKit Node) with other images if for example I have the images:
dice1, dice2, dice3...
This is the objective C code:
NSString *fileName = [NSString stringWithFormat:#"dice%d.png", num];
// Setting the uiimageview to the appropriate image
self.rollButton.image = [UIImage imageNamed:fileName];
I didn't find any good example with how to set buttons from storyborard and than using uiviewcontrollers to each new GameScene created,
First, create an array of the images you want the button to have:
let arrayOfImages = [
"image1.png",
"image2.png",
"image3.png",
"image4.png",
"image5.png",
"image6.png"
]
Then initialize the button sprite and give it a texture to start:
var rollButton = SKSpriteNode()
rollButton.texture = SKTexture(imageNamed: arrayOfImages[0])
Then, each time changeButtonImage() is called, generate a random number and change the button's texture:
var randomNumberBetween0And5 = Int(arc4random_uniform(6))
rollButton.texture = SKTexture(imageNamed: arrayOfImages[randomNumberBetween0And5])
If you want to build a button or a switch for generic use, you should try this control I made, the use its pretty straight forward:
You just initialize the type of Button/Switch you want (ColoredSprite, Textured or TextOnly)
let control = TWButton(normalColor: SKColor.blueColor(), highlightedColor: SKColor.redColor(), size: CGSize(width: 160, height: 80))
And after initialize you add a closure to it (like addTargetForSelector on UIButton)
control.addClosureFor(.TouchUpInside, target: self, closure: { (scene, sender) -> () in
scene.testProperty = "Changed Property"
})
}
That’s it! There’s more info on the readme section on the GitHub page: https://github.com/txaidw/TWControls
But if you want to implement in a specific node here’s how I did:
internal override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch = touches.first as! UITouch
let touchPoint = touch.locationInNode(self.parent)
if self.containsPoint(touchPoint) {
self.touchLocationLast = touchPoint
touchDown()
}
}
internal override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch = touches.first as! UITouch
let touchPoint = touch.locationInNode(self.parent)
self.touchLocationLast = touchPoint
}
internal override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch = touches.first as! UITouch
let touchPoint = touch.locationInNode(self.parent)
if let lastPoint = self.touchLocationLast where self.containsPoint(lastPoint) {
// Ended inside
touchUpInside()
}
else {
// Ended outside
touchUpOutside()
}
}

swift moving and releasing object with touch

I'm new to coding. I have created a scene in swift sprite kit with a ball and floor. When executed, the ball drops and bounces on the floor. I am looking for a bit advise on how to move and drop the ball with touches.
To detect drag ball you have to create UIPanGestureRecognizer and add it to the ball's view
let dragBall = UIPanGestureRecognizer(target: self, action:"dragBall:")
ball.addGestureRecognizer(dragBall)
Next step is implementing "dragBall" function which will handle drag event, example:
#IBAction func dragBall(recognizer: UIPanGestureRecognizer) {
let point = recognizer.locationInView(self.view);
ball.center.x=point.x
ball.center.y=point.y
}
You should also disable gravity for this object for time of dragging, you can check if Pan gesture ended by checking state of gesture recognizer, if state is UIGestureRecognizerStateEnded you should add gravity again
import SpriteKit
class GameScene: SKScene {
let ball = SKSpriteNode(imageNamed: "ball")
override func didMoveToView(view: SKView) {
/* Setup your scene here */
ball.position = CGPoint(x:500,y:500)
ball.anchorPoint = CGPoint(x:0.0,y:0.0)
ball.size = CGSize(width: 60, height: 60)
// physics
ball.physicsBody = SKPhysicsBody(circleOfRadius: 1)
// this defines the mass, roughness and bounciness
ball.physicsBody.friction = 0.2
ball.physicsBody.restitution = 0.8
ball.physicsBody.mass = 0.1
// this will allow the balls to rotate when bouncing off each other
ball.physicsBody.allowsRotation = true
self.addChild(ball)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
}
override func touchesMoved(touches: NSSet, withEvent event: UIEvent)
{ ball.position = touches.anyObject().locationInNode(self); }
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
by the end of the day i worked out this bit of code but it seems very hard to keep hold of ball