For a puzzle game project on iOS, I try to subclass the SKSpriteNode class from SpriteKit with the following code:
class SKPuzzle: SKSpriteNode {
var name2:String = "";
}
I need to add other variables in SKSpriteNode like another name (name2) in this case. Here is the use I made of the class in a class type SKScene:
class GameScene: SKScene {
let background = SKSpriteNode(imageNamed: "BW")
var selectedNode = SKPuzzle()
override init(size: CGSize) {
super.init(size: size)
let imageNames = [sheet.Puzzle13() , sheet.Puzzle19(),sheet.Puzzle30(),
sheet.Puzzle11(), sheet.Puzzle29(), sheet.Puzzle35() ]
for i in 0..<imageNames.count {
let imageName = imageNames[i]
let sprite = SKPuzzle(texture: imageName)
sprite.name = kAnimalNodeName
sprite.name2 = "\(i)"
let offsetFraction = (CGFloat(i) + 1.0)/(CGFloat(imageNames.count) + 1.0)
sprite.position = CGPoint(x: size.width * offsetFraction, y: size.height / 2)
sprite.zPosition = 1
background.addChild(sprite)
}
}
I have the sprite object from the subclass SKPuzzle wich contains the new variable name2.
sprite.name2 = "\(i)"
The problem I have is the variable selectedNode (created with)
var selectedNode = SKPuzzle()
used later in the program contain always a nil value for the data name and name2. When I click on the jigsaw parts of the game, I get the following error:
fatal error: unexpectly found nil while unwrapping an optional value in the following function:
func panForTranslation(translation : CGPoint) {
let position = selectedNode.position
if selectedNode.name! == kAnimalNodeName {
selectedNode.position = CGPoint(x: position.x + translation.x * 2, y: position.y + translation.y * 2)
}
}
selectedNode seems containing only nil values. The code is working fine when I just use the SKSpriteNode but failed with my SKPuzzle class.
Here is the whole code of the program:
import SpriteKit
import UIKit
private let kAnimalNodeName = "puzzle"
private let kdancing = "dancing"
class SKPuzzle: SKSpriteNode {
var name2:String = "";
}
class GameScene: SKScene {
let background = SKSpriteNode(imageNamed: "BW")
var selectedNode = SKPuzzle()
var selectedVideo = SKVideoNode()
override init(size: CGSize) {
super.init(size: size)
// 1
self.background.name = kdancing
self.background.anchorPoint = CGPointZero
background.zPosition = 0
self.addChild(background)
//background.play()
// 2
let sheet = Statiques()
let sprite_dancing1 = SKSpriteNode(texture: sheet.Dancing1())
let sprite_dancing2 = SKSpriteNode(texture: sheet.Dancing2())
sprite_dancing1.name = kdancing
sprite_dancing2.name = kdancing
sprite_dancing1.position = CGPoint(x: 837, y: 752)
sprite_dancing1.zPosition = 1
sprite_dancing2.position = CGPoint(x: 1241, y: 752)
sprite_dancing2.zPosition = 1
background.addChild(sprite_dancing1)
background.addChild(sprite_dancing2)
let imageNames = [sheet.Puzzle13() , sheet.Puzzle19(), sheet.Puzzle30(), sheet.Puzzle11(), sheet.Puzzle29(), sheet.Puzzle35() ]
for i in 0..<imageNames.count {
let imageName = imageNames[i]
let sprite = SKPuzzle(texture: imageName)
sprite.name = kAnimalNodeName
sprite.name2 = "\(i)"
let offsetFraction = (CGFloat(i) + 1.0)/(CGFloat(imageNames.count) + 1.0)
sprite.position = CGPoint(x: size.width * offsetFraction, y: size.height / 2)
sprite.zPosition = 1
background.addChild(sprite)
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let positionInScene = touch.locationInNode(self)
selectNodeForTouch(positionInScene)
}
}
override func didMoveToView(view: SKView) {
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: Selector("handlePanFrom:"))
self.view!.addGestureRecognizer(gestureRecognizer)
}
func handlePanFrom(recognizer : UIPanGestureRecognizer) {
if recognizer.state == .Began {
var touchLocation = recognizer.locationInView(recognizer.view)
touchLocation = self.convertPointFromView(touchLocation)
self.selectNodeForTouch(touchLocation)
} else if recognizer.state == .Changed {
var translation = recognizer.translationInView(recognizer.view!)
translation = CGPoint(x: translation.x, y: -translation.y)
self.panForTranslation(translation)
recognizer.setTranslation(CGPointZero, inView: recognizer.view)
} else if recognizer.state == .Ended {
}
}
func degToRad(degree: Double) -> CGFloat {
return CGFloat(degree / 180.0 * M_PI)
}
func selectNodeForTouch(touchLocation : CGPoint) {
// 1
let touchedNode = self.nodeAtPoint(touchLocation)
if touchedNode is SKPuzzle {
// 2
if !selectedNode.isEqual(touchedNode) {
selectedNode.removeAllActions()
selectedNode.runAction(SKAction.rotateToAngle(0.0, duration: 0.1))
//selectedNode = touchedNode as! SKSpriteNode
// 3
if touchedNode.name! == kAnimalNodeName {
let sequence = SKAction.sequence([SKAction.rotateByAngle(degToRad(-4.0), duration: 0.1),
SKAction.rotateByAngle(0.0, duration: 0.1),
SKAction.rotateByAngle(degToRad(4.0), duration: 0.1)])
selectedNode.runAction(SKAction.repeatActionForever(sequence))
}
}
}
}
func panForTranslation(translation : CGPoint) {
let position = selectedNode.position
if selectedNode.name! == kAnimalNodeName {
selectedNode.position = CGPoint(x: position.x + translation.x * 2, y: position.y + translation.y * 2)
}
}
}
Thanks by advance for your help, I'm beginning to code with Swift on iOS.
When selectedNode is created by SKPuzzle(), name is nil.
You have to set selectedNode.name to some value in init method.
Related
I'm doing a game where you have to capture candies using a spider hung by a thread, as I show in this link: Game screenshot (I'm new here so I can't post images yet). I already have the movement of the spider from left to right and also I'm able to catch the candies using SKAction moving through 'Y', my only issue is I didn't figure it out yet how to know if the spider don't capture any candy, during his movement, I was trying use the allContactedBodies function when the action finish but the count of the array returned is always zero. Any suggestions?
Here is the code :
class GameScene: SKScene, SKPhysicsContactDelegate {
private var rope = SKSpriteNode(imageNamed: "rope")
private var anchor = SKSpriteNode(imageNamed: "anchor")
private var currentCharacter: SKSpriteNode!
private var candy: SKSpriteNode!
var direction : String = "backward"
var lastCandyAdded: TimeInterval = 0
let candyVelocity: CGFloat = 4.0
let characterBitMask : UInt32 = 0x1 << 1
let candyBitMask: UInt32 = 0x1 << 2
let characterVelocity: CGFloat = 18.0
var direction : String = "backward"
override func didMove(to view: SKView) {
self.physicsWorld.contactDelegate = self
self.addAnchor()
self.addRope()
self.addCharacter()
let jointOneFixed = SKPhysicsJointFixed.joint(withBodyA: anchor.physicsBody!, bodyB: rope.physicsBody!, anchor: anchor.position)
self.physicsWorld.add(jointOneFixed);
let jointTwoFixed = SKPhysicsJointFixed.joint(withBodyA: rope.physicsBody!, bodyB: currentCharacter.physicsBody!, anchor: currentCharacter.position)
self.physicsWorld.add(jointTwoFixed);
}
func addAnchor(){
anchor.position = CGPoint(x: self.size.width / 2, y: self.size.height + 1)
anchor.anchorPoint = CGPoint(x: 0.5, y: 0.5)
anchor.setScale(1)
anchor.zPosition = 2
anchor.name = "anchor"
anchor.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: anchor.size.width, height: anchor.size.height))
anchor.physicsBody?.affectedByGravity = false
anchor.physicsBody?.friction = 0;
anchor.physicsBody?.linearDamping = 0;
anchor.physicsBody?.mass = 10;
self.addChild(anchor)
}
func addCharacter() {
let characterName: String = UserDefaults.standard.string(forKey: "current_character")!
currentCharacter = SKSpriteNode(imageNamed: characterName);
currentCharacter.position = CGPoint(x: self.size.width / 2, y: self.size.height - 400)
currentCharacter.anchorPoint = CGPoint(x: 0.5, y: 0.5)
currentCharacter.setScale(0.43)
currentCharacter.zPosition = 2
currentCharacter.name = "character"
currentCharacter.physicsBody = SKPhysicsBody(rectangleOf: currentCharacter.size)
currentCharacter.physicsBody?.categoryBitMask = characterBitMask
currentCharacter.physicsBody?.contactTestBitMask = candyBitMask
currentCharacter.physicsBody?.collisionBitMask = candyBitMask;
currentCharacter.physicsBody?.affectedByGravity = false;
currentCharacter.physicsBody?.friction = 0;
currentCharacter.physicsBody?.linearDamping = 0;
currentCharacter.physicsBody?.mass = 20;
self.addChild(currentCharacter)
}
func addRope() {
rope.position = CGPoint(x: anchor.position.x, y: anchor.position.y - 70)
rope.setScale(0.65)
rope.zPosition = 1
rope.name = "rope"
rope.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: rope.size.width, height: rope.size.height))
rope.physicsBody?.affectedByGravity = false;
rope.physicsBody?.friction = 0;
rope.physicsBody?.linearDamping = 0;
rope.physicsBody?.mass = 5;
rope.physicsBody?.allowsRotation = false
self.addChild(rope)
}
func addCandy() {
let number = Int.random(min: 1, max: 24)
let candyWord = "candie"
let candyTexture = SKTexture(imageNamed: "\(candyWord)\(number)")
candy = SKSpriteNode(texture: candyTexture)
candy.zPosition = 3
candy.setScale(0.40)
candy.physicsBody = SKPhysicsBody(circleOfRadius: max(candy.size.width / 2, candy.size.height / 2))
candy.physicsBody?.isDynamic = true
candy.name = "candy"
candy.physicsBody?.categoryBitMask = candyBitMask
candy.physicsBody?.contactTestBitMask = characterBitMask
candy.physicsBody?.collisionBitMask = characterBitMask
candy.physicsBody?.affectedByGravity = false
candy.position = CGPoint(x: self.frame.size.width + 20, y: self.frame.size.height / 2 + 150)
self.addChild(candy)
}
func moveCandy() {
self.enumerateChildNodes(withName: "candy", using: {(node, stop) -> Void in
if let candy = node as? SKSpriteNode {
candy.position = CGPoint(x: candy.position.x - self.candyVelocity, y: candy.position.y)
if candy.position.x < 0 {
candy.removeFromParent()
}
}
})
}
override func update(_ currentTime: TimeInterval) {
self.moveCandy()
self.moveCharacter()
if currentTime - self.lastCandyAdded > 0.75 {
self.lastCandyAdded = currentTime + Double.random(min: 0.00, max: 0.60)
self.addCandy()
}
}
func collisionBetween(candy: SKNode, object: SKNode) {
let moveUp = SKAction.moveBy(x: 0, y: 100, duration:0.0)
let shrinkRope = SKAction.animate(with: [SKTexture(imageNamed: "rope")], timePerFrame: 0)
let moveUpBlock = SKAction.run({
self.anchor.run(moveUp)
})
let shrinkRopeBlock = SKAction.run({
self.rope.run(shrinkRope)
})
let sequence = SKAction.sequence([SKAction.wait(forDuration: 0.07), shrinkRopeBlock, moveUpBlock])
self.run(sequence)
candy.removeFromParent()
}
func didBegin(_ contact: SKPhysicsContact) {
guard let nodeA = contact.bodyA.node else { return }
guard let nodeB = contact.bodyB.node else { return }
if nodeA.name == "candy" && nodeB.name == "character" {
collisionBetween(candy: nodeA, object: nodeB)
} else if nodeA.name == "character" && nodeB.name == "candy" {
collisionBetween(candy: nodeB, object: nodeA)
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){
let moveDown = SKAction.moveBy(x: 0, y: -100, duration:0.0)
let stretchRope = SKAction.animate(with: [SKTexture(imageNamed: "rope_stretch")], timePerFrame: 0)
let moveDownBlock = SKAction.run({
self.anchor.run(moveDown, completion: {
var physicBodies = self.currentCharacter.physicsBody?.allContactedBodies();
// This count is always zero
print(physicBodies?.count)
})
})
let stretchRopeBlock = SKAction.run({
self.rope.run(stretchRope)
})
let sequence = SKAction.sequence([moveDownBlock, stretchRopeBlock])
self.run(sequence)
}
func moveCharacter(){
self.enumerateChildNodes(withName: "anchor", using: {(node, stop) -> Void in
if let anchorNode = node as? SKSpriteNode {
if anchorNode.position.x < 120 {
anchorNode.position = CGPoint(x: anchorNode.position.x + self.characterVelocity, y: anchorNode.position.y)
self.direction = "forward"
} else if anchorNode.position.x > self.size.width - 120 {
anchorNode.position = CGPoint(x: anchorNode.position.x - self.characterVelocity, y: anchorNode.position.y)
self.direction = "backward"
} else if self.direction == "forward" {
anchorNode.position = CGPoint(x: anchorNode.position.x + self.characterVelocity, y: anchorNode.position.y)
self.direction = "forward"
} else {
anchorNode.position = CGPoint(x: anchorNode.position.x - self.characterVelocity, y: anchorNode.position.y)
self.direction = "backward"
}
}
})
}
}
First of all you have a lot of code in this question...too much, it makes it hard to focus on what is really happening. You are also missing a block of code for moveCharacter().
You should strongly look at creating subclasses for your player, rope and (mostly)candies. I would also look into creating an array of candies initially so that you are not dynamically creating physics objects during run time.
As for your question wouldn't it be as simple as creating a couple of variables in your class
private var isMoving = false
private var didGetCandy = false
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//prevent the user from firing the move while in the middle of a move
guard !isMoving else { return }
isMoving = true
let moveDownBlock = SKAction.run({
self.anchor.run(moveDown) {
//this is an appreviated form of a 'completion' block
self.isMoving = false
print("did I get a candy \(didGetCandy)")
}
})
}
func collisionBetween(candy: SKNode, object: SKNode) {
didGetCandy = true
}
I calculated the speed of UIGestureRecognizer and I want to use it as velocity of Physicsbody in SpriteKit.
How can I do that since Speed is calculated in touches began and touches ended method, while my Physicsbody is wrapped in swipeUp & swipeDown etc functions, which does not have access to the Speed variable?
Here is my code:
class GameScene: SKScene, SKPhysicsContactDelegate, SKViewDelegate, UIGestureRecognizerDelegate, UIViewControllerTransitioningDelegate {
var Kite = SKSpriteNode(imageNamed: "ASC_8025_large.jpg")
#objc let minusButton = SKSpriteNode(imageNamed: "minus.jpg")
#objc let plusButton = SKSpriteNode(imageNamed: "plus.png")
//override init(Kite: SKSpriteNode) {
//For long Long press gesture to work
let longPressGestureRecPlus = UILongPressGestureRecognizer()
let longPressGestureRecMinus = UILongPressGestureRecognizer(target: self, action: #selector(longPressed(press:)))
//First we declare all of our Gestures...
//swipes
let swipeRightRec = UISwipeGestureRecognizer()
let swipeLeftRec = UISwipeGestureRecognizer()
let swipeUpRec = UISwipeGestureRecognizer()
let swipeDownRec = UISwipeGestureRecognizer()
//rotate
let rotateRec = UIRotationGestureRecognizer()
//taps
let tapRec = UITapGestureRecognizer()
let tapRec2 = UITapGestureRecognizer()
override func didMove(to view: SKView) {
// Get label node from scene and store it for use later
Kite.size = CGSize(width: 40.0, height: 40.0)
Kite.position = CGPoint(x: frame.midX, y: frame.midY)
plusButton.size = CGSize(width: 30.0, height: 30.0)
plusButton.position = CGPoint(x: frame.midX, y: frame.minY + 20.0)
plusButton.name = "plusButton"
//plusButton.isUserInteractionEnabled = true
addChild(Kite)
addChild(plusButton)
swipeRightRec.addTarget(self, action: #selector(GameScene.swipedRight) )
swipeRightRec.direction = .right
self.view!.addGestureRecognizer(swipeRightRec)
swipeLeftRec.addTarget(self, action: #selector(GameScene.swipedLeft) )
swipeLeftRec.direction = .left
self.view!.addGestureRecognizer(swipeLeftRec)
swipeUpRec.addTarget(self, action: #selector(GameScene.swipedUp) )
swipeUpRec.direction = .up
self.view!.addGestureRecognizer(swipeUpRec)
swipeDownRec.addTarget(self, action: #selector(GameScene.swipedDown) )
swipeDownRec.direction = .down
self.view!.addGestureRecognizer(swipeDownRec)
//notice the function this calls has (_:) after it because we are passing in info about the gesture itself (the sender)
rotateRec.addTarget(self, action: #selector (GameScene.rotatedView (_:) ))
self.view!.addGestureRecognizer(rotateRec)
// again notice (_:), we'll need this to find out where the tap occurred.
tapRec.addTarget(self, action:#selector(GameScene.tappedView(_:) ))
tapRec.numberOfTouchesRequired = 1
tapRec.numberOfTapsRequired = 1
self.view!.addGestureRecognizer(tapRec)
tapRec2.addTarget(self, action:#selector(GameScene.tappedView2(_:) ))
tapRec2.numberOfTouchesRequired = 1
tapRec2.numberOfTapsRequired = 2 //2 taps instead of 1 this time
self.view!.addGestureRecognizer(tapRec2)
longPressGestureRecPlus.addTarget(self, action: #selector(longPressed(press:)))
longPressGestureRecPlus.minimumPressDuration = 2.0
self.view?.addGestureRecognizer(longPressGestureRecPlus)
}
//the functions that get called when swiping...
#objc func swipedRight() {
print("Right")
Kite.physicsBody?.velocity = CGVector(dx: 60, dy: 60)
//Tilts the Kite towards Right
let tiltRight = SKAction.rotate(toAngle: -1.00, duration: 0.1)
Kite.run(tiltRight)
}
#objc func swipedLeft() {
Kite.physicsBody?.velocity = CGVector(dx: -60, dy: 60)
//Tilts the Kite towards Right
let tiltLeft = SKAction.rotate(toAngle: 1.00, duration: 0.1)
Kite.run(tiltLeft)
print("Left")
}
#objc func swipedUp() {
Kite.physicsBody?.velocity = CGVector(dx: 60, dy: 60)
//Straightens the Kite
let straightens = SKAction.rotate(toAngle: 0.00, duration: 0.1)
Kite.run(straightens)
print("Up")
}
#objc func swipedDown() {
Kite.physicsBody?.velocity = CGVector(dx: 0, dy: -60)
print("Down")
}
// what gets called when there's a single tap...
//notice the sender is a parameter. This is why we added (_:) that part to the selector earlier
#objc func tappedView(_ sender:UITapGestureRecognizer) {
let point:CGPoint = sender.location(in: self.view)
print("Single tap")
print(point)
}
// what gets called when there's a double tap...
//notice the sender is a parameter. This is why we added (_:) that part to the selector earlier
#objc func tappedView2(_ sender:UITapGestureRecognizer) {
let point:CGPoint = sender.location(in: self.view)
print("Double tap")
print(point)
}
//what gets called when there's a rotation gesture
//notice the sender is a parameter. This is why we added (_:) that part to the selector earlier
#objc func rotatedView(_ sender:UIRotationGestureRecognizer) {
if (sender.state == .began) {
print("rotation began")
}
if (sender.state == .changed) {
print("rotation changed")
//you could easily make any sprite's rotation equal this amount like so...
//thePlayer.zRotation = -sender.rotation
//convert rotation to degrees...
let rotateAmount = Measurement(value: Double(sender.rotation), unit: UnitAngle.radians).converted(to: .degrees).value
print("\(rotateAmount) degreess" )
}
if (sender.state == .ended) {
print("rotation ended")
}
}
func removeAllGestures(){
//if you need to remove all gesture recognizers with Swift you can do this....
for gesture in (self.view?.gestureRecognizers)! {
self.view?.removeGestureRecognizer(gesture)
}
//this is good to do before a SKScene transitions to another SKScene.
}
func removeAGesture()
{
//To remove a single gesture you can use...
self.view?.removeGestureRecognizer(swipeUpRec)
}
//Fix the gesture recognizing the plusButton
#objc func longPressed(press: UILongPressGestureRecognizer) {
if press.state == .began {
isUserInteractionEnabled = true
let positionInScene = press.location(in: self.view)
let touchedNode = self.atPoint(positionInScene)
plusButton.name = "plusButton"
Kite.physicsBody?.velocity = CGVector(dx: 0, dy: 60.0*3)
print("Pressed on the screen")
if let name = touchedNode.name {
if name == "plusButton" {
print("LONG TAPPED")
}
}
}
}
var start: CGPoint?
var startTime: TimeInterval?
var taps = 0
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Began")
Kite.physicsBody = SKPhysicsBody(rectangleOf: Kite.size)
Kite.physicsBody?.affectedByGravity = false
//Kite.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
Kite.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 5))
plusButton.name = "plusButton"
plusButton.isUserInteractionEnabled = false
//We figure how to interact with BUTTON in Spritekit
let touch = touches.first
let positionInScene = touch!.location(in: self)
let touchedNode = self.atPoint(positionInScene)
if let name = touchedNode.name {
if name == "plusButton" {
taps += 1
Kite.size = CGSize(width: 200, height: 200)
print("tapped")
print("Taps", taps)
}
}
for touch in touches {
let location:CGPoint = touch.location(in: self.view!)
start = location
startTime = touch.timestamp
}
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Ended")
//Calculating Speed of the Gestures
for touch in touches {
let location:CGPoint = touch.location(in: self.view!)
var dx:CGFloat = location.x - start!.x;
var dy:CGFloat = location.y - start!.y;
var magnitude:CGFloat = sqrt(dx*dx+dy*dy)
//Calculate Time
var dt:CGFloat = CGFloat(touch.timestamp - startTime!)
//Speed = Distance / Time
var speed:CGFloat = magnitude / dt
var speedX:CGFloat = dx/dt
var speedY:CGFloat = dy/dt
print("SpeedY", speedX)
print("SpeedY", speedY)
}
}
so calculating the speed from a vector like dx and dy is
let speed = sqrtf(Float(pow(dx!, 2) + pow(dy!, 2)))
So if you want apply the speed as velocity to an object you need at least one of the directions.
let newDx = 0 // means in no x direction
// next you can change the formula to your new dy to match the given speed
let newDy = sqrtf(pow(speed, 2) - Float(pow(newDx, 2)))
yourNode.physicsBody?.velocity = CGVector(dx: newDx, dy: CGFloat(newDy))
I'm trying to make a small mini game where you drag a ball around the screen and every 10 seconds a ball gets added in that follows you. so far the you can drag a ball around the screen and a ball follows you, but when another ball gets added in the balls group together. I think this is because the ball is following me depending on how fast I'm going. so is there a certain way in which I can have the balls follow me at a certain speed constantly, like 10 pixels a second or something, and that should prevent the balls from grouping together.
I am currently working on the score so it should soon go up every second you survive. and you die if you touch one of the balls.
below is the code and a short gif of my current code
!(https://gyazo.com/1d6a56527bfd0884e8a26cff730f4e03)
import SpriteKit
import GameplayKit
struct physicsCatagory{
static let me : UInt32 = 0x1 << 1
static let enemy : UInt32 = 0x1 << 2
}
class GameScene: SKScene, SKPhysicsContactDelegate {
private func makeEnemyName() -> String {
enemyCounter += 1
return "enemy\(enemyCounter)"
}
private func addEnemyToDict(enemy: SKSpriteNode, target: SKSpriteNode) {
if let name = enemy.name { spriteDictionary[name] = (enemy, target) }
else { print("enemy not found") }
}
private func removeEnemyFromDict(enemy: SKSpriteNode) {
if let name = enemy.name { spriteDictionary[name] = nil }
else { print("enemy not removed from dictionary!") }
}
private func moveFollowerToTarget(_ sprites: FollowerAndTarget) {
let action = SKAction.move(to: sprites.target.position, duration: 1)
sprites.follower.run(action)
}
private func allEnemiesMoveToTarget() {
for sprites in spriteDictionary.values {
moveFollowerToTarget(sprites)
}
}
let enemySpeed: CGFloat = 300
var me = SKSpriteNode()
// Tuple to keep track of enemy objects:
typealias FollowerAndTarget = (follower: SKSpriteNode, target: SKSpriteNode)
// [followerName: (followerSprite, targetSprite):
var spriteDictionary: [String: FollowerAndTarget] = [:]
// Give each enemy a unique name for the dictionary:
var enemyCounter = 0
var died = Bool()
override func didMove(to view: SKView) {
createScene()
}
func createEnemy () {
if died == true{
}
else {
let enemy = SKSpriteNode(imageNamed: "enemy1")
enemy.name = makeEnemyName()
addEnemyToDict(enemy: enemy, target: me)
moveFollowerToTarget((follower: enemy, target: me))
enemy.size = CGSize(width: 60, height: 60)
enemy.position = CGPoint(x:667, y: 200)
enemy.physicsBody?.restitution = 0.5
enemy.physicsBody = SKPhysicsBody(circleOfRadius: 60)
enemy.physicsBody?.affectedByGravity = false
enemy.zPosition = 2
enemy.physicsBody?.linearDamping = 0
enemy.physicsBody?.isDynamic = true
enemy.physicsBody?.categoryBitMask = physicsCatagory.enemy
enemy.physicsBody?.collisionBitMask = physicsCatagory.me
enemy.physicsBody?.contactTestBitMask = physicsCatagory.me
addChild(enemy)
}
}
func didBegin(_ contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == physicsCatagory.me && secondBody.categoryBitMask == physicsCatagory.enemy || firstBody.categoryBitMask == physicsCatagory.enemy && secondBody.categoryBitMask == physicsCatagory.me {
died = true
restartScene()
}
}
var lose: SKLabelNode!
func restartScene(){
self.removeAllChildren()
self.removeAllActions()
died = false
if let nextScene = GameScene(fileNamed: "menuScene"){
nextScene.scaleMode = self.scaleMode
let transition = SKTransition.fade(withDuration: 1)
view?.presentScene(nextScene, transition: transition)
}
}
func createScene(){
me = self.childNode(withName: "me") as! SKSpriteNode
me.physicsBody = SKPhysicsBody(circleOfRadius: 20)
me.physicsBody?.affectedByGravity = false
me.physicsBody?.categoryBitMask = physicsCatagory.me
me.physicsBody?.collisionBitMask = physicsCatagory.enemy
me.zPosition = 2
self.physicsWorld.contactDelegate = self
let border = SKPhysicsBody (edgeLoopFrom: self.frame)
border.friction = 0
self.physicsBody = border
run(SKAction.repeatForever(SKAction.sequence([SKAction.run(createEnemy), SKAction.wait(forDuration: 4.0)])))
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
allEnemiesMoveToTarget()
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
allEnemiesMoveToTarget()
}
}
override func update(_ currentTime: TimeInterval) {
// Will iterate through dictonary and then call moveFollowerToTarget()
// thus giving each enemy a new movement action to follow.
allEnemiesMoveToTarget()
}
}
Here you go:
import SpriteKit
import GameplayKit
struct physicsCatagory{
static let me : UInt32 = 0x1 << 1
static let enemy : UInt32 = 0x1 << 2
static let coin : UInt32 = 0x1 << 3
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var lose: SKLabelNode!
var me = SKSpriteNode()
// Tuple to keep track of enemy objects:
typealias FollowerAndTarget = (follower: SKSpriteNode, target: SKSpriteNode)
// [followerName: (followerSprite, targetSprite):
var spriteDictionary: [String: FollowerAndTarget] = [:]
// Give each enemy a unique name for the dictionary:
var enemyCounter = 0
let enemySpeed: CGFloat = 3
var died = Bool()
var timer = SKLabelNode()
var timerValue: Int = 0 {
didSet {
timer.text = "\(timerValue)"
}
}
private func makeEnemyName() -> String {
enemyCounter += 1
return "enemy\(enemyCounter)"
}
private func addEnemyToDict(enemy: SKSpriteNode, target: SKSpriteNode) {
if let name = enemy.name { spriteDictionary[name] = (enemy, target) }
else { print("enemy not found") }
}
private func removeEnemyFromDict(enemy: SKSpriteNode) {
if let name = enemy.name { spriteDictionary[name] = nil }
else { print("enemy not removed from dictionary!") }
}
// dont change anything outside of this, this is what makes the enemy follow you, so i have to have the enemy follow me at a constant speed
private func moveFollowerToTarget(_ sprites: FollowerAndTarget) {
let location = me.position
// Aim
let dx = location.x - sprites.follower.position.x
let dy = location.y - sprites.follower.position.y
let angle = atan2(dy, dx)
sprites.follower.zRotation = angle
// Seek
let vx = cos(angle) * enemySpeed
let vy = sin(angle) * enemySpeed
sprites.follower.position.x += vx
sprites.follower.position.y += vy
}
private func allEnemiesMoveToTarget() {
for sprites in spriteDictionary.values {
moveFollowerToTarget(sprites)
}
}
private func keepEnemiesSeparated() {
for sprites in spriteDictionary.values {
let iterator = sprites.follower
iterator.constraints = []
// get every other follower:
var otherFollowers: [SKSpriteNode] = []
for sprites in spriteDictionary.values {
if sprites.follower == iterator { continue }
else { otherFollowers.append(sprites.follower) }
}
// Assign constrain
for follower in otherFollowers {
let distanceBetween = CGFloat(60)
let constraint = SKConstraint.distance(SKRange(lowerLimit: distanceBetween), to: follower)
iterator.constraints!.append(constraint)
}
}
}
func createEnemy () {
if died { return }
let enemy = SKSpriteNode(color: .green, size: CGSize(width: 60, height: 60))
enemy.size = CGSize(width: 60, height: 60)
enemy.zPosition = 2
enemy.position.y -= size.height / 2
enemy.physicsBody = {
let pb = SKPhysicsBody(circleOfRadius: 30)
pb.restitution = 0.5
pb.affectedByGravity = false
pb.linearDamping = 0
pb.isDynamic = true
pb.categoryBitMask = physicsCatagory.enemy
pb.collisionBitMask = physicsCatagory.me
pb.contactTestBitMask = physicsCatagory.me
return pb
}()
enemy.name = makeEnemyName()
addEnemyToDict(enemy: enemy, target: me)
moveFollowerToTarget((follower: enemy, target: me))
keepEnemiesSeparated()
addChild(enemy)
}
func createCoin () {
let coin = SKSpriteNode(color: .yellow, size: CGSize(width: 20, height: 20))
let height = self.view!.frame.height
let width = self.view!.frame.width
let randomPosition = CGPoint( x:CGFloat( arc4random_uniform( UInt32( floor( width ) ) ) ),
y:CGFloat( arc4random_uniform( UInt32( floor( height ) ) ) )
)
coin.position = randomPosition
addChild(coin)
}
func restartScene(){
self.removeAllChildren()
self.removeAllActions()
died = false
let nextScene = GameScene(size: self.size)
nextScene.scaleMode = self.scaleMode
let transition = SKTransition.fade(withDuration: 1)
view?.presentScene(nextScene, transition: transition)
}
func createScene(){
me = SKSpriteNode(color: .blue, size: CGSize(width: 60, height: 60))
me.physicsBody = SKPhysicsBody(circleOfRadius: 30)
me.physicsBody?.affectedByGravity = false
me.physicsBody?.categoryBitMask = physicsCatagory.me
me.physicsBody?.collisionBitMask = physicsCatagory.enemy
me.zPosition = 2
timer = SKLabelNode(fontNamed: "Chalkduster")
timer.text = "\(timerValue)"
addChild(me)
addChild(timer)
let wait = SKAction.wait(forDuration: 1)
let block = SKAction.run({
[unowned self] in
if self.timerValue >= 0{
self.timerValue += 1
}else{
self.removeAction(forKey: "countdown")
}
})
let sequence = SKAction.sequence([wait,block])
run(SKAction.repeatForever(sequence), withKey: "countdown")
self.physicsWorld.contactDelegate = self
let border = SKPhysicsBody (edgeLoopFrom: self.frame)
border.friction = 0
self.physicsBody = border
run(SKAction.repeatForever(SKAction.sequence([SKAction.run(createEnemy), SKAction.wait(forDuration: 2.0)])))
run(SKAction.repeatForever(SKAction.sequence([SKAction.run(createCoin), SKAction.wait(forDuration: TimeInterval(arc4random_uniform(11) + 5))])))
}
override func didMove(to view: SKView) {
scene?.anchorPoint = CGPoint(x: 0.5, y: 0.5)
createScene()
}
func didBegin(_ contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == physicsCatagory.me && secondBody.categoryBitMask == physicsCatagory.enemy
|| firstBody.categoryBitMask == physicsCatagory.enemy && secondBody.categoryBitMask == physicsCatagory.me {
died = true
restartScene()
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
allEnemiesMoveToTarget()
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
allEnemiesMoveToTarget()
}
}
override func update(_ currentTime: TimeInterval) {
// Will iterate through dictonary and then call moveFollowerToTarget()
// thus giving each enemy a new movement action to follow.
allEnemiesMoveToTarget()
}
}
I am making a spritekit game where you need to move the player back and forth to catch objects falling down the screen. (You gain a point when the player collides with the falling object.)Recently I added restart button function. Before the restart button comes up everything works fine but when I restart the scene and the objects fall to hit the player the player falls off the screen once they make contact. This is odd because I have already set it to make the player (or person) not affected by gravity and not to be dynamic. Again before I press the button it works fine. Why are the characteristics of the person not there once I restart the scene. If you could take a look at my code and tell me why this is happening I would greatly appreciate it.
import SpriteKit
struct physicsCatagory {
static let person : UInt32 = 0x1 << 1
static let Ice : UInt32 = 0x1 << 2
static let IceTwo : UInt32 = 0x1 << 3
static let IceThree : UInt32 = 0x1 << 4
static let Score : UInt32 = 0x1 << 5
}
class GameScene: SKScene, SKPhysicsContactDelegate {
func restartScene(){
self.removeAllChildren()
self.removeAllActions()
scorenumber = 0
lifenumber = 0
createScene()
random()
//spawnThirdIce()
Died = false
}
func createScene(){
physicsWorld.contactDelegate = self
lifenumber = 0
SpeedNumber = 1
BackGround.size = CGSize(width: self.frame.width, height: self.frame.height)
BackGround.position = CGPointMake(self.size.width / 2, self.size.height / 2)
BackGround.zPosition = -5
self.addChild(BackGround)
Score.size = CGSize(width: 2563, height: 1)
Score.position = CGPoint(x: 320, y: -20)
Score.physicsBody = SKPhysicsBody(rectangleOfSize: Score.size)
Score.physicsBody?.affectedByGravity = false
Score.physicsBody?.dynamic = false
Score.physicsBody?.categoryBitMask = physicsCatagory.Score
Score.physicsBody?.collisionBitMask = 0
Score.physicsBody?.contactTestBitMask = physicsCatagory.IceThree
Score.color = SKColor.blueColor()
Score.zPosition = -5
self.addChild(Score)
person.zPosition = 1
person.position = CGPointMake(self.size.width/2, self.size.height/10)
person.setScale(0.6)
person.physicsBody = SKPhysicsBody (rectangleOfSize: CGSize(width: 40, height: 50))
person.physicsBody?.affectedByGravity = false
person.physicsBody?.categoryBitMask = physicsCatagory.person
person.physicsBody?.contactTestBitMask = physicsCatagory.Ice
person.physicsBody?.collisionBitMask = physicsCatagory.Ice
person.physicsBody?.dynamic = false
person.physicsBody?.affectedByGravity = false
ScoreLable = SKLabelNode(fontNamed: "Zapfino")
ScoreLable.position = CGPoint(x: self.frame.width / 2, y: 1700)
ScoreLable.text = "\(scorenumber)"
ScoreLable.fontColor = UIColor.yellowColor()
ScoreLable.fontSize = 150
ScoreLable.fontName = "Zapfino "
self.addChild(ScoreLable)
self.addChild(person)
}
func random() -> CGFloat{
return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}
func random(min min: CGFloat, max: CGFloat) -> CGFloat{
return random() * (max - min) + min
}
var gameArea: CGRect
override init(size: CGSize) {
let maxAspectRatio: CGFloat = 16.0/9.0
let playableWidth = size.height / maxAspectRatio
let margin = (size.width - playableWidth) / 2
gameArea = CGRect(x: margin, y: 0, width: playableWidth, height: size.height)
super.init(size: size)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var timeOfLastSpawn: CFTimeInterval = 0.0
var timePerSpawn: CFTimeInterval = 1.2
var scorenumber = Int()
var lifenumber = Int()
var SpeedNumber : Double = 0.5
var person = SKSpriteNode(imageNamed: "Person1")
let Score = SKSpriteNode()
var ScoreLable = SKLabelNode()
let BackGround = SKSpriteNode (imageNamed: "BackGround")
var restartButton = SKSpriteNode()
var Died = Bool()
override func didMoveToView(view: SKView) {
createScene()
}
func createButton(){
restartButton = SKSpriteNode(color: SKColor.blueColor(), size: CGSize(width: 200, height: 100))
restartButton.position = CGPoint(x: self.gameArea.width/2, y: self.gameArea.height/2)
restartButton.zPosition = 6
self.addChild(restartButton)
}
func didBeginContact(contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == physicsCatagory.person && secondBody.categoryBitMask == physicsCatagory.IceThree || firstBody.categoryBitMask == physicsCatagory.IceThree && secondBody.categoryBitMask == physicsCatagory.person{
scorenumber++
if scorenumber == 20 {
timePerSpawn = 1.0
}
if scorenumber == 40{
timePerSpawn = 0.89
}
if scorenumber == 60{
timePerSpawn = 0.6
}
if scorenumber == 80{
timePerSpawn = 0.5
}
if scorenumber == 100{
timePerSpawn = 0.4
}
if scorenumber == 120{
timePerSpawn = 0.3
}
ScoreLable.text = "\(scorenumber)"
CollisionWithPerson(firstBody.node as! SKSpriteNode, Person: secondBody.node as! SKSpriteNode)
}
if firstBody.categoryBitMask == physicsCatagory.Score && secondBody.categoryBitMask == physicsCatagory.IceThree ||
firstBody.categoryBitMask == physicsCatagory.IceThree && secondBody.categoryBitMask == physicsCatagory.Score{
lifenumber++
if lifenumber == 1{
//person.texture
person.texture = SKTexture (imageNamed: "Flower#2")
}
if lifenumber == 2{
person.texture = SKTexture (imageNamed: "Flower #3")
}
if lifenumber == 3{
createButton()
// self.view?.presentScene(EndScene())
Died = true
}
}
}
func CollisionWithPerson (Ice: SKSpriteNode, Person: SKSpriteNode){
Person.removeFromParent()
}
func spawnThirdIce(){
var Ice = SKSpriteNode(imageNamed: "Ice")
Ice.zPosition = 2
Ice.setScale(1.5)
Ice.physicsBody = SKPhysicsBody(rectangleOfSize: Ice.size)
Ice.physicsBody?.categoryBitMask = physicsCatagory.IceThree
Ice.physicsBody?.contactTestBitMask = physicsCatagory.person | physicsCatagory.Score
Ice.physicsBody?.affectedByGravity = false
Ice.physicsBody?.dynamic = true
let randomXStart = random(min:CGRectGetMinX(gameArea), max: CGRectGetMaxX(gameArea))
let randomXend = random(min:CGRectGetMinX(gameArea),max: CGRectGetMaxX(gameArea))
let startPoint = CGPoint(x: randomXStart, y: self.size.height * 1.2)
let endpoint = CGPoint(x: randomXend, y: -self.size.height * 0.2)
Ice.position = startPoint
let moveEnemy = SKAction.moveTo(endpoint, duration: 2.0)
let deleteEnemy = SKAction.removeFromParent()
let enemySequence = SKAction.sequence([moveEnemy , deleteEnemy])
Ice.runAction(enemySequence)
self.addChild(Ice)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches{
let location = touch.locationInNode(self)
if Died == true{
if restartButton.containsPoint(location){
restartScene()
}
}
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
if Died == true {
}
else{
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
let previousTouch = touch.previousLocationInNode(self)
let ammountDragged = location.x - previousTouch.x
person.position.x += ammountDragged
if person.position.x > CGRectGetMaxX(gameArea) - person.size.width/2{
person.position.x = CGRectGetMaxX(gameArea) - person.size.width/2
}
if person.position.x < CGRectGetMinX(gameArea) + person.size.width/2{
person.position.x = CGRectGetMinX(gameArea) + person.size.width/2
}
}
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
if (currentTime - timeOfLastSpawn > timePerSpawn) {
spawnThirdIce()
self.timeOfLastSpawn = currentTime
}
}
}
Hey I have a 3D game thats not really a game yet. But it has a SceneKit 3D scene and a overlayskscene for the HUD/Controls. the "base" is the base of the joystick and the ball is the handle the problem is that the joystick does not move at all unless the scnView.allowsCameraControl = true. I find that weird. and this is my entire view controller code so nothings left out and if you want you can literally copy and paste it into Xcode to see what I'm talking about. Any help?
Code:
import iAd
import UIKit
import GameKit
import SceneKit
import StoreKit
import SpriteKit
import QuartzCore
import Foundation
import AVFoundation
import AudioToolbox
class GameViewController: UIViewController, ADBannerViewDelegate, SKPhysicsContactDelegate, SKSceneDelegate, SCNSceneRendererDelegate, SCNPhysicsContactDelegate{
var stickActive:Bool = false
let base = SKSpriteNode(imageNamed:"VirtualJoystickBase")
let ball = SKSpriteNode(imageNamed:"VirtualJoyStickHandle")
let ship = SKSpriteNode(imageNamed:"Ship")
var ButtonA = SKSpriteNode(imageNamed:"GreenAButton")
var ButtonO = SKSpriteNode(imageNamed:"CircleButton")
var ButtonY = SKSpriteNode(imageNamed:"YellowYButton")
var ButtonSquare = SKSpriteNode(imageNamed:"BlueSquareButton")
let FieldScene = SCNScene(named: "art.scnassets/TesingCampusField.dae")!
let GuyScene = SCNScene(named: "art.scnassets/Guy.dae")!
let overlayScene = SKScene(size: CGSizeMake(100, 100))
override func viewDidLoad() {
super.viewDidLoad()
let scnView = self.view as! SCNView
scnView.overlaySKScene = overlayScene
scnView.backgroundColor = UIColor.whiteColor()
scnView.scene = FieldScene
scnView.delegate = self
scnView.overlaySKScene!.delegate = self
scnView.overlaySKScene!.anchorPoint = CGPointMake(0, 0)
scnView.overlaySKScene!.physicsWorld.contactDelegate = self
scnView.overlaySKScene!.physicsWorld.gravity = CGVectorMake(0.0, 0.0)
scnView.allowsCameraControl = true
scnView.showsStatistics = false
let Guy1: SCNNode = GuyScene.rootNode.childNodeWithName("Bob_014", recursively: true)!
FieldScene.rootNode.addChildNode(Guy1)
//----Positioning-the-Base-of-the-Joystick-----------
base.size = CGSize(width: 14, height: 24)
base.position = CGPointMake(15, 19)
base.zPosition = 0
overlayScene.addChild(base)
//----Positing-the-Ball/Joystick-----------
ball.size = CGSize(width: 10, height: 17)
ball.position = base.position
ball.zPosition = 1
overlayScene.addChild(ball)
//----A-Button--Creation -------------------
ButtonA.size = CGSize(width: 6, height: 9)
ButtonA.anchorPoint = CGPointMake(-13.3, -0.5)
ButtonA.zPosition = 0
overlayScene.addChild(ButtonA)
//----B-Button--Creation -------------------
ButtonO.size = CGSize(width: 6, height: 9)
ButtonO.anchorPoint = CGPointMake(-14.4, -1.7)
ButtonO.zPosition = 0
overlayScene.addChild(ButtonO)
//----C-Button--Creation -------------------
ButtonSquare.size = CGSize(width: 6, height: 9)
ButtonSquare.anchorPoint = CGPointMake(-12.2, -1.7)
ButtonSquare.zPosition = 0
overlayScene.addChild(ButtonSquare)
//----C-Button--Creation -------------------
ButtonY.size = CGSize(width: 6, height: 9)
ButtonY.anchorPoint = CGPointMake(-13.3, -2.7)
ButtonY.zPosition = 0
overlayScene.addChild(ButtonY)
//---Setting-Up-Ships-Position/PhysicsBody---------------------
ship.position = CGPointMake(0, 100)
ship.size = CGSize(width: 80, height: 80)
ship.physicsBody?.dynamic = true
ship.physicsBody?.allowsRotation = true
ship.physicsBody?.affectedByGravity = true
ship.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "Ship"), size: ship.size)
ship.physicsBody!.friction = 0
ship.physicsBody!.restitution = 0
ship.physicsBody!.linearDamping = 0
ship.physicsBody!.angularDamping = 0
//--------------------------
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
GuyScene.rootNode.addChildNode(cameraNode)
cameraNode.position = SCNVector3(x: 0, y: 5, z: 15)
//-----------------------------------------------
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = SCNLightTypeOmni
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
FieldScene.rootNode.addChildNode(lightNode)
//-----------------------------------------------
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = SCNLightTypeAmbient
ambientLightNode.light!.color = UIColor.darkGrayColor()
FieldScene.rootNode.addChildNode(ambientLightNode)
//----------------------------------------------
}
func YButtonPressed() {
let YButtonPressed = SKTexture(imageNamed: "YellowYButtonPressed")
let OrignalButtonY = SKTexture(imageNamed:"YellowYButton")
let YButtonPressedAnimation = SKAction.animateWithTextures([YButtonPressed, OrignalButtonY], timePerFrame: 0.2)
let RunYButtonPressedAnimation = SKAction.repeatAction(YButtonPressedAnimation, count: 1)
ButtonY.runAction(RunYButtonPressedAnimation)
}
func OButtonPressed() {
let OButtonPressed = SKTexture(imageNamed: "CircleButtonPressed")
let OrignalButtonO = SKTexture(imageNamed:"CircleButton")
let OButtonPressedAnimation = SKAction.animateWithTextures([OButtonPressed, OrignalButtonO], timePerFrame: 0.2)
let RunOButtonPressedAnimation = SKAction.repeatAction(OButtonPressedAnimation, count: 1)
ButtonO.runAction(RunOButtonPressedAnimation)
}
func SquareButtonPressed() {
let SquareButtonPressed = SKTexture(imageNamed: "BlueSquareButtonPressed")
let OrignalButtonSquare = SKTexture(imageNamed:"BlueSquareButton")
let SquareButtonPressedAnimation = SKAction.animateWithTextures([SquareButtonPressed, OrignalButtonSquare], timePerFrame: 0.2)
let RunSquareButtonPressedAnimation = SKAction.repeatAction(SquareButtonPressedAnimation, count: 1)
ButtonSquare.runAction(RunSquareButtonPressedAnimation)
}
func AButtonPressed() {
let AButtonPressed = SKTexture(imageNamed: "GreenAButtonPressed")
let OrignalButtonA = SKTexture(imageNamed:"GreenAButton")
let AButtonPressedAnimation = SKAction.animateWithTextures([AButtonPressed, OrignalButtonA], timePerFrame: 0.2)
let RunAButtonPressedAnimation = SKAction.repeatAction(AButtonPressedAnimation, count: 1)
ButtonA.runAction(RunAButtonPressedAnimation)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch: AnyObject in touches {
let location = touch.locationInNode(self.overlayScene)
if (CGRectContainsPoint(base.frame, location)) {
print("stickActive = true")
stickActive = true
} else {
print("stickActive = false")
stickActive = false
}
}
for touch: AnyObject in touches {
let location1 = touch.locationInNode(self.overlayScene)
if self.overlayScene.nodeAtPoint(location1) == self.ButtonA {
AButtonPressed()
print("AButtonPressed")
}
}
for touch: AnyObject in touches {
let location2 = touch.locationInNode(self.overlayScene)
if self.overlayScene.nodeAtPoint(location2) == self.ButtonO {
OButtonPressed()
print("OButtonPressed")
}
}
for touch: AnyObject in touches {
let location3 = touch.locationInNode(self.overlayScene)
if self.overlayScene.nodeAtPoint(location3) == self.ButtonY {
YButtonPressed()
print("YButtonPressed")
}
}
for touch: AnyObject in touches {
let location4 = touch.locationInNode(self.overlayScene)
if self.overlayScene.nodeAtPoint(location4) == self.ButtonSquare {
SquareButtonPressed()
print("SquarButtonPressed")
}
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self.overlayScene)
if self.overlayScene.nodeAtPoint(location) == self.ball {
if (stickActive == true) {
let v = CGVector(dx: location.x - base.position.x, dy: location.y - base.position.y)
let angle = atan2(v.dy, v.dx)
//println( deg + 180)
let length:CGFloat = base.frame.size.height / 2
let xDist:CGFloat = sin(angle - 1.57879633) * length
let yDist:CGFloat = cos(angle - 1.57879633) * length
if (CGRectContainsPoint(base.frame, location)) {
ball.position = location
} else {
ball.position = CGPointMake( base.position.x - xDist, base.position.y + yDist)
}
ship.zRotation = angle - 1.57879633
let calcRotation : Float = Float(angle - 1.57879633) + Float(M_PI_2);
let intensity : CGFloat = 200.0 // put your value
let xVelocity = intensity * CGFloat(cosf(calcRotation))
let yVelocity = intensity * CGFloat(sinf(calcRotation))
let vector : CGVector = CGVectorMake(xVelocity, yVelocity)
//Apply force to spaceship
ship.physicsBody?.applyForce(vector)
// ends stackActive
}
}
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self.overlayScene)
if self.overlayScene.nodeAtPoint(location) == self.ball {
if (stickActive == true) {
let move:SKAction = SKAction.moveTo(base.position, duration: 0.05)
move.timingMode = .EaseOut
ball.runAction(move)
}
}
}
}
//====================================================================
override func shouldAutorotate() -> Bool {
return true
}
//====================================================================
override func prefersStatusBarHidden() -> Bool {
return true
}
//====================================================================
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return .AllButUpsideDown
} else {
return .All
}
}
//====================================================================
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
}
there's an issue in SceneKit where the SpriteKit overlay isn't automatically redrawn when changes are made in the 2D scene but the 3D scene is left untouched. In other words, the 2D overlay is only redrawn when the 3D view needs to be redrawn.
You can set the playing property of the SCNView to YES to fix this. Alternatively you can call -setNeedsDisplay whenever you make a change to the overlay scene.