Swift MultiTouch objects - swift

This is my first game in Swift. I want to make a more advanced Breakout Game with SpriteKit like in this tutorial
I want to create 4 paddles and move them individually with 4 fingers, I tried to do that but when I move one paddle the second one moves too... What can I do ?
import SpriteKit
import AVFoundation
class GameScene: SKScene {
var fingerIsOnPaddle1 = false
var fingerIsOnPaddle2 = false
var fingerISOnPaddle3 = false
var fingerIsOnPaddle4 = false
let shurikenCategoryName = "shuriken"
let paddleCategoryName = "paddle"
let paddle2CategoryName = "paddle2"
let paddle3CategoryName = "paddle3"
let paddle4CategoryName = "paddle4"
let brickCategoryName = "brick"
let backgroundMusicPlayer = AVAudioPlayer()
override init(size: CGSize){
super.init(size: size)
let bgMusicURL = NSBundle.mainBundle().URLForResource("bgMusicMP3", withExtension: "mp3")
backgroundMusicPlayer = AVAudioPlayer(contentsOfURL: bgMusicURL, error: nil)
backgroundMusicPlayer.numberOfLoops = -1
backgroundMusicPlayer.prepareToPlay()
backgroundMusicPlayer.play()
let backgroundImage = SKSpriteNode(imageNamed: "bg")
backgroundImage.position = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 3)
self.addChild(backgroundImage)
self.physicsWorld.gravity = CGVectorMake(0, 0)
let worldBorder = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = worldBorder
self.physicsBody?.friction = 0
let shuriken = SKSpriteNode(imageNamed: "shuriken")
shuriken.name = shurikenCategoryName
shuriken.position = CGPointMake(self.frame.size.width/2, self.frame.size.height / 2)
self.addChild(shuriken)
shuriken.physicsBody = SKPhysicsBody(circleOfRadius: shuriken.frame.width / 2)
shuriken.physicsBody?.friction = 0
shuriken.physicsBody?.restitution = 1
shuriken.physicsBody?.linearDamping = 0
shuriken.physicsBody?.applyImpulse(CGVectorMake(2, 2))
shuriken.physicsBody?.allowsRotation = true
let paddle = SKSpriteNode(imageNamed: "paddle")
paddle.name = paddleCategoryName
paddle.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)/4)
self.addChild(paddle)
paddle.physicsBody = SKPhysicsBody(rectangleOfSize: paddle.frame.size)
paddle.physicsBody?.friction = 0.4
paddle.physicsBody?.restitution = 0.1
paddle.physicsBody?.dynamic = false
//paddle.position = CGPointMake(CGRectGetMidX(self.frame)/2, CGRectGetMidY(self.frame)/4)
//self.addChild(paddle)
let paddle2 = SKSpriteNode(imageNamed: "paddle")
paddle2.name = paddle2CategoryName
paddle2.position = CGPointMake(CGRectGetMidX(self.frame)/5, CGRectGetMidY(self.frame))
paddle2.zRotation = CGFloat(M_PI_2)
self.addChild(paddle2)
paddle2.physicsBody = SKPhysicsBody(rectangleOfSize: paddle.frame.size)
paddle2.physicsBody?.friction = 0.4
paddle2.physicsBody?.restitution = 0.1
paddle2.physicsBody?.dynamic = false
let paddle3 = SKSpriteNode(imageNamed: "paddle")
paddle3.name = paddle2CategoryName
paddle3.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)/4*7)
self.addChild(paddle3)
let paddle4 = SKSpriteNode(imageNamed: "paddle")
paddle4.name = paddle2CategoryName
paddle4.position = CGPointMake(CGRectGetMidX(self.frame)/5*9, CGRectGetMidY(self.frame))
paddle4.zRotation = CGFloat(M_PI_2)
self.addChild(paddle4)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let touch = touches.anyObject() as UITouch
let touchLocation = touch.locationInNode(self)
let body:SKPhysicsBody? = self.physicsWorld.bodyAtPoint(touchLocation)
if body?.node?.name == paddleCategoryName {
println("Paddle 1 touched")
fingerIsOnPaddle1 = true
}
if body?.node?.name == paddle2CategoryName{
println("Paddle 2 touched")
fingerIsOnPaddle2 = true
}
}
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
if fingerIsOnPaddle1{
let touch = touches.anyObject() as UITouch
let touchLoc = touch.locationInNode(self)
let prevTouchLoc = touch.previousLocationInNode(self)
let paddle = self.childNodeWithName(paddleCategoryName) as SKSpriteNode
var newXPos = paddle.position.x + (touchLoc.x - prevTouchLoc.x)
paddle.position = CGPointMake(newXPos, paddle.position.y)
}
if fingerIsOnPaddle2{
let touch2 = touches.anyObject() as UITouch
let touchLoc2 = touch2.locationInNode(self)
let prevTouchLoc2 = touch2.previousLocationInNode(self)
let paddle2 = self.childNodeWithName(paddle2CategoryName) as SKSpriteNode
var newYPos = paddle2.position.y + (touchLoc2.y - prevTouchLoc2.y)
paddle2.position = CGPointMake(paddle2.position.y, newYPos)
}
}
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
}
required init?(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
}
}

The crux of the issue here is in the touchesBegan function, which takes a Set of touches. It's a very common pattern to just take the first one, using anyObject(), but instead of doing that, you can loop over them, like this:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
for touch in touches as? UITouch {
let touchLocation = touch.locationInNode(self)
let body:SKPhysicsBody? = self.physicsWorld.bodyAtPoint(touchLocation)
if body?.node?.name == paddleCategoryName {
println("Paddle 1 touched")
fingerIsOnPaddle1 = true
}
if body?.node?.name == paddle2CategoryName{
println("Paddle 2 touched")
fingerIsOnPaddle2 = true
}
}
}

Related

Contact Delegate missing

I am trying to make a new level for my app. I am honestly just copy and pasting my code from the view controllers and gamescenes to other files that I changed the name of. Yes, I did change the names INSIDE the files too so It'll match the new level. However, my contact delegate won't work on my new level now. How can I fix this?
Cannot assign value of type 'Level1' to type 'SKPhysicsContactDelegate?'
What am I doing wrong? I just checked my main file that I had before creating a new level and it now has errors. I have't changed any of the coding.
import SpriteKit
import GameplayKit
class Level1: SKScene {
var ball = SKSpriteNode()
var danger1 = SKSpriteNode()
var danger2 = SKSpriteNode()
var goal = SKSpriteNode()
over
ride func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
ball = self.childNode(withName: "ball") as! SKSpriteNode
danger1 = self.childNode(withName: "danger1") as! SKSpriteNode
danger2 = self.childNode(withName: "danger2") as! SKSpriteNode
goal = self.childNode(withName: "goal") as! SKSpriteNode
let border = SKPhysicsBody(edgeLoopFrom: self.frame)
border.friction = 0
border.restitution = 0
danger1.physicsBody = SKPhysicsBody(rectangleOf: danger1.size)
danger1.physicsBody?.categoryBitMask = PhysicsCategories.dangerCategory
danger1.physicsBody?.isDynamic = false
danger2.physicsBody = SKPhysicsBody(rectangleOf: danger2.size)
danger2.physicsBody?.categoryBitMask = PhysicsCategories.dangerCategory
danger2.physicsBody?.isDynamic = false
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width/2)
ball.physicsBody?.categoryBitMask = PhysicsCategories.ballCategory
ball.physicsBody?.contactTestBitMask = PhysicsCategories.dangerCategory | PhysicsCategories.goalCategory
ball.physicsBody?.collisionBitMask = PhysicsCategories.none
ball.physicsBody?.isDynamic = true
ball.physicsBody!.affectedByGravity = false
goal.physicsBody = SKPhysicsBody(rectangleOf: goal.size)
goal.physicsBody?.categoryBitMask = PhysicsCategories.goalCategory
goal.physicsBody?.isDynamic = false
setupPhysics()
startGame()
}
func setupPhysics() {
physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
physicsWorld.contactDelegate = self
}
func startGame() {
ball.position = CGPoint(x: 0, y: 550)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
ball.position.x = location.x
ball.position.y = location.y
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
if contactMask == PhysicsCategories.ballCategory | PhysicsCategories.dangerCategory {
print("Contact")
} else if contactMask == PhysicsCategories.ballCategory | PhysicsCategories.goalCategory {
print("goal contact")
}
}
}
Instead of creating extension of GameScene, create extension of Level1
extension Level1: SKPhysicsContactDelegate

SKSpriteNode and SKAction with animating sprite

Im trying to get the player sprite in my game to animate according to what it is doing, ie.. walking, attacking, resting.
I have the following files AgentNode and GameScene.
The sprite spawns and moves around as I want, just with the initial action that was in place when the sprite was added to the scene.
for example if I add the sprite with the "restingFrames" animation, it spawns correctly but when the sprite is moved, the animation is still using "restingFrames" and not "walkingFrames" as I want. Can't figure it out, please help.
AgentNode.swift
import SpriteKit
import GameplayKit
class AgentNode: SKNode, GKAgentDelegate {
var agent = GKAgent2D()
var triangleShape = SKShapeNode()
var player = SKSpriteNode()
var walkingFrames: [SKTexture] = []
var restingFrames: [SKTexture] = []
var attackingFrames: [SKTexture] = []
var firstFrameTexture: SKTexture = SKTexture()
var playerSpawned = false
override init() {
super.init()
}
init(scene:SKScene, radius: Float, position: CGPoint) {
super.init()
self.position = position
self.zPosition = 10
scene.addChild(self)
agent.radius = radius
agent.position = simd_float2(Float(position.x), Float(position.y))
agent.delegate = self
agent.maxSpeed = 100 * 2
agent.maxAcceleration = 500 * 4
}
func setupPlayer() {
setupRestingPlayerAnimation()
setupWalkingPlayerAnimation()
setupAttackingPlayerAnimation()
}
func setupWalkingPlayerAnimation() {
let walkingPlayerAtlas = SKTextureAtlas(named: "WalkingPlayer")
let numImages = walkingPlayerAtlas.textureNames.count
for i in 1...numImages {
let walkingPlayerTextureName = "walk_front\(i)"
walkingFrames.append(walkingPlayerAtlas.textureNamed(walkingPlayerTextureName))
}
}
func setupRestingPlayerAnimation() {
let restingPlayerAtlas = SKTextureAtlas(named: "RestingPlayer")
let numImages = restingPlayerAtlas.textureNames.count
for i in 1...numImages {
let restingPlayerTextureName = "still_frame\(i)"
restingFrames.append(restingPlayerAtlas.textureNamed(restingPlayerTextureName))
}
}
func setupAttackingPlayerAnimation() {
let attackingPlayerAtlas = SKTextureAtlas(named: "AttackingPlayer")
let numImages = attackingPlayerAtlas.textureNames.count
for i in 1...numImages {
let attackingPlayerTextureName = "attack_frame\(i)"
attackingFrames.append(attackingPlayerAtlas.textureNamed(attackingPlayerTextureName))
}
}
func animatePlayer() {
var restingSequence = SKAction()
var walkingSequence = SKAction()
var attackingSequence = SKAction()
let restingAnimation = SKAction.animate(with: restingFrames, timePerFrame: 0.15)
let walkingAnimation = SKAction.animate(with: walkingFrames, timePerFrame: 0.1)
let attackingAnimation = SKAction.animate(with: attackingFrames, timePerFrame: 0.1)
restingSequence = SKAction.sequence([restingSequence])
walkingSequence = SKAction.sequence([walkingSequence])
attackingSequence = SKAction.sequence([attackingSequence])
if isSeeking && !isAttacking{
firstFrameTexture = walkingFrames[0]
player.run(SKAction.repeatForever(walkingAnimation), withKey: "walkingAction")
print("walking")
} else if isAttacking && !isSeeking {
firstFrameTexture = attackingFrames[0]
player.run(SKAction.repeatForever(attackingAnimation), withKey: "attackingAction")
print("attacking")
} else {
firstFrameTexture = restingFrames[0]
player.run(SKAction.repeatForever(restingAnimation), withKey: "restingAction")
print("resting")
}
}
func addPlayerToScene() {
player = SKSpriteNode(texture: firstFrameTexture)
player.position = CGPoint(x: (frame.midX), y: (frame.midY))
player.setScale(1.5)
player.zRotation = CGFloat(Double.pi / 2.0)
player.zPosition = 10
self.addChild(player)
playerSpawned = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func agentWillUpdate(_ agent: GKAgent) {
}
func agentDidUpdate(_ agent: GKAgent) {
if playerSpawned == false {
print("player has not spawned")
setupPlayer()
animatePlayer()
addPlayerToScene()
playerSpawned = true
} else {
print("player has spawned")
animatePlayer()
}
print("player isSeeking \(isSeeking)")
print("player isAttacking \(isAttacking)")
guard let agent2D = agent as? GKAgent2D else {
return
}
self.position = CGPoint(x: CGFloat(agent2D.position.x), y: CGFloat(agent2D.position.y))
self.zRotation = CGFloat(agent2D.rotation)
}
}
GameScene.swift
import SpriteKit
import GameplayKit
var isSeeking: Bool = false
var isAttacking: Bool = false
class GameScene: SKScene {
let trackingAgent = GKAgent2D()
var player = AgentNode()
var seekGoal : GKGoal = GKGoal()
let stopGoal = GKGoal(toReachTargetSpeed: 0.0)
var seeking : Bool = false {
willSet {
if newValue {
self.player.agent.behavior?.setWeight(5, for: seekGoal)
self.player.agent.behavior?.setWeight(0, for: stopGoal)
} else {
self.player.agent.behavior?.setWeight(0, for: seekGoal)
self.player.agent.behavior?.setWeight(5, for: stopGoal)
}
}
}
var agentSystem = GKComponentSystem()
var lastUpdateTime: TimeInterval = 0
override func didMove(to view: SKView) {
super.didMove(to: view)
self.trackingAgent.position = simd_float2(Float(self.frame.midX), Float(self.frame.midY))
self.agentSystem = GKComponentSystem(componentClass: GKAgent2D.self)
self.player = AgentNode(scene: self, radius: Float(20.0), position: CGPoint(x: self.frame.midX, y: self.frame.midY))
self.player.agent.behavior = GKBehavior()
self.agentSystem.addComponent(self.player.agent)
self.seekGoal = GKGoal(toSeekAgent: self.trackingAgent)
}
override func update(_ currentTime: CFTimeInterval) {
isSeeking = self.seeking
if lastUpdateTime == 0 {
lastUpdateTime = currentTime
}
let delta = currentTime - lastUpdateTime
lastUpdateTime = currentTime
self.agentSystem.update(deltaTime: delta)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.seeking = true
handleTouch(touches: touches)
}
override func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
self.seeking = false
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
self.seeking = false
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
handleTouch(touches: touches)
}
func handleTouch(touches:Set<UITouch>) {
guard let touch = touches.first
else {
return
}
let location = touch.location(in: self)
self.trackingAgent.position = simd_float2(Float(location.x), Float(location.y))
}
}
Well I figured it out. I updated the code as follows and everything is working great.
AgentNode.swift
import SpriteKit
import GameplayKit
class AgentNode: SKNode, GKAgentDelegate {
var agent = GKAgent2D()
var triangleShape = SKShapeNode()
var player = SKSpriteNode()
var walkingFrames: [SKTexture] = []
var restingFrames: [SKTexture] = []
var attackingFrames: [SKTexture] = []
var playerSpawned = false
override init() {
super.init()
}
init(scene:SKScene, radius: Float, position: CGPoint) {
super.init()
self.position = position
self.zPosition = 10
scene.addChild(self)
agent.radius = radius
agent.position = simd_float2(Float(position.x), Float(position.y))
agent.delegate = self
agent.maxSpeed = 100 * 2
agent.maxAcceleration = 500 * 4
}
func setupPlayer() {
setupRestingPlayerAnimation()
setupWalkingPlayerAnimation()
setupAttackingPlayerAnimation()
}
func setupWalkingPlayerAnimation() {
let walkingPlayerAtlas = SKTextureAtlas(named: "WalkingPlayer")
let numImages = walkingPlayerAtlas.textureNames.count
for i in 1...numImages {
let walkingPlayerTextureName = "walk_front\(i)"
walkingFrames.append(walkingPlayerAtlas.textureNamed(walkingPlayerTextureName))
}
}
func setupRestingPlayerAnimation() {
let restingPlayerAtlas = SKTextureAtlas(named: "RestingPlayer")
let numImages = restingPlayerAtlas.textureNames.count
for i in 1...numImages {
let restingPlayerTextureName = "still_frame\(i)"
restingFrames.append(restingPlayerAtlas.textureNamed(restingPlayerTextureName))
}
}
func setupAttackingPlayerAnimation() {
let attackingPlayerAtlas = SKTextureAtlas(named: "AttackingPlayer")
let numImages = attackingPlayerAtlas.textureNames.count
for i in 1...numImages {
let attackingPlayerTextureName = "attack_frame\(i)"
attackingFrames.append(attackingPlayerAtlas.textureNamed(attackingPlayerTextureName))
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func agentWillUpdate(_ agent: GKAgent) {
}
func agentDidUpdate(_ agent: GKAgent) {
guard let agent2D = agent as? GKAgent2D else {
return
}
self.position = CGPoint(x: CGFloat(agent2D.position.x), y: CGFloat(agent2D.position.y))
self.zRotation = CGFloat(agent2D.rotation)
}
}
GameScene.swift
import SpriteKit
import GameplayKit
var isSeeking: Bool = false
var isAttacking: Bool = false
class GameScene: SKScene {
let trackingAgent = GKAgent2D()
var player = AgentNode()
var seekGoal : GKGoal = GKGoal()
let stopGoal = GKGoal(toReachTargetSpeed: 0.0)
var seeking : Bool = false {
willSet {
if newValue {
self.player.agent.behavior?.setWeight(5, for: seekGoal)
self.player.agent.behavior?.setWeight(0, for: stopGoal)
} else {
self.player.agent.behavior?.setWeight(0, for: seekGoal)
self.player.agent.behavior?.setWeight(5, for: stopGoal)
}
}
}
var agentSystem = GKComponentSystem()
var lastUpdateTime: TimeInterval = 0
override func didMove(to view: SKView) {
super.didMove(to: view)
self.trackingAgent.position = simd_float2(Float(self.frame.midX), Float(self.frame.midY))
self.agentSystem = GKComponentSystem(componentClass: GKAgent2D.self)
self.player = AgentNode(scene: self, radius: Float(20.0), position: CGPoint(x: self.frame.midX, y: self.frame.midY))
self.player.agent.behavior = GKBehavior()
self.agentSystem.addComponent(self.player.agent)
self.seekGoal = GKGoal(toSeekAgent: self.trackingAgent)
player.setupPlayer()
//player.animatePlayer()
player.player = SKSpriteNode(imageNamed: "default_pose")
player.player.position = CGPoint(x: (frame.midX), y: (frame.midY))
player.player.setScale(1.5)
player.player.zRotation = CGFloat(Double.pi / 2.0)
player.player.zPosition = 10
player.player.run(SKAction.repeatForever(SKAction.animate(with: player.restingFrames, timePerFrame: 0.2)))
player.addChild(player.player)
}
override func update(_ currentTime: CFTimeInterval) {
isSeeking = self.seeking
if lastUpdateTime == 0 {
lastUpdateTime = currentTime
}
let delta = currentTime - lastUpdateTime
lastUpdateTime = currentTime
self.agentSystem.update(deltaTime: delta)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.seeking = true
player.player.run(SKAction.repeatForever(SKAction.animate(with: player.walkingFrames, timePerFrame: 0.1)))
handleTouch(touches: touches)
}
override func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
self.seeking = false
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
self.seeking = false
player.player.removeAllActions()
player.player.run(SKAction.repeatForever(SKAction.animate(with: player.attackingFrames, timePerFrame: 0.1)))
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
handleTouch(touches: touches)
}
func handleTouch(touches:Set<UITouch>) {
guard let touch = touches.first
else {
return
}
let location = touch.location(in: self)
self.trackingAgent.position = simd_float2(Float(location.x), Float(location.y))
}
}

Sprite kit contact problems

I am making a game that requires you to dodge falling objects. I have tried to make it it so that when the falling object hits the player certain code runs. But it is not working please show me what is wrong with my code.
import SpriteKit
struct physicsCatagory {
static let person : UInt32 = 0x1 << 1
static let Ice : UInt32 = 0x1 << 2
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var person = SKSpriteNode(imageNamed: "Person")
override func didMoveToView(view: SKView) {
physicsWorld.contactDelegate = self
person.position = CGPointMake(self.size.width/2, self.size.height/12)
person.setScale(0.4)
person.physicsBody = SKPhysicsBody(rectangleOfSize: person.size)
person.physicsBody?.affectedByGravity = false
person.physicsBody?.categoryBitMask = physicsCatagory.person
person.physicsBody?.contactTestBitMask = physicsCatagory.Ice
person.physicsBody?.dynamic = false
var IceTimer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: Selector("spawnFirstIce"), userInfo: nil, repeats: true)
self.addChild(person)
func didBeginContact(contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == physicsCatagory.person && secondBody.categoryBitMask == physicsCatagory.Ice || firstBody.categoryBitMask == physicsCatagory.Ice && secondBody.categoryBitMask == physicsCatagory.person{
NSLog ("Test Test") }
}
}
func spawnFirstIce(){
let Ice = SKSpriteNode(imageNamed: "FirstIce")
Ice.setScale(0.5)
Ice.physicsBody = SKPhysicsBody(rectangleOfSize: Ice.size)
Ice.physicsBody?.categoryBitMask = physicsCatagory.Ice
Ice.physicsBody?.contactTestBitMask = physicsCatagory.person
Ice.physicsBody?.affectedByGravity = false
Ice.physicsBody?.dynamic = true
let MinValue = self.size.width / 8
let MaxValue = self.size.width - 20
let SpawnPoint = UInt32(MaxValue - MinValue)
Ice.position = CGPoint(x: CGFloat(arc4random_uniform(SpawnPoint)), y: self.size.height)
self.addChild(Ice)
let action = SKAction.moveToY(-85, duration: 3.0)
let actionDone = SKAction.removeFromParent()
Ice.runAction(SKAction.sequence([action,actionDone]))
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
person.position.x = location.x
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
person.position.x = location.x
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
You have defined didBeginContact inside of didMoveToView method :)
Place didBeginContact outside of that method and make it a member of GameScene class.

Spritekit - Swift/ Multiple collisions. I'm having trouble with putting the cell and the bacteria in the same function

I'm having trouble getting the bacteria and the cell below together inside the didBeginContact function. It seems like I have to separate them from each other for them to have different outcomes when they collide with objects instead of getting mixed up together.
let virusMask:UInt32 = 0x1 << 0
let cellMask:UInt32 = 0x1 << 1
let finishMask:UInt32 = 0x1 << 2
let wallMask:UInt32 = 0x1 << 3
class GameScene: SKScene, SKPhysicsContactDelegate {
var touchLocation: CGPoint = CGPointZero
var boneCannon: SKSpriteNode!
var smoke: SKEmitterNode!
var Finish: SKSpriteNode!
var bacteria: SKScene!
override func didMoveToView(view: SKView) {
boneCannon = self.childNodeWithName("boneCannon") as! SKSpriteNode
Finish = self.childNodeWithName("FinishLine") as! SKSpriteNode
let bacteria:SKSpriteNode = SKScene(fileNamed: "bacterioP")!.childNodeWithName("bacteriophage") as! SKSpriteNode
bacteria.removeFromParent()
self.addChild(bacteria)
bacteria.zPosition = 2
bacteria.position = CGPointMake(600, 600)
bacteria.runAction(SKAction.moveToY(1920, duration: 5))
bacteria.physicsBody?.collisionBitMask = wallMask|cellMask|virusMask
bacteria.physicsBody?.contactTestBitMask = bacteria.physicsBody!.collisionBitMask | virusMask
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.smoke = SKEmitterNode(fileNamed: "FireFlies")!
self.smoke.position = CGPointMake(600, 600)
self.smoke.zPosition = 1
self.addChild(smoke)
let a1 = SKAction.moveByX(850.0, y: 0.0, duration: 0.75)
let a2 = SKAction.moveByX(-850.0, y: 0.0, duration: 0.75)
let seq = SKAction.sequence([a1,a2])
self.Finish.runAction(SKAction.repeatActionForever(seq))
self.physicsWorld.contactDelegate = self
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
touchLocation = touches.first!.locationInNode(self)
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
touchLocation = touches.first!.locationInNode(self)
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
let cell: SKSpriteNode = SKScene(fileNamed: "WhiteBloodCell")!.childNodeWithName("cell") as! SKSpriteNode
cell.removeFromParent()
self.addChild(cell)
cell.zPosition = 1
cell.position = boneCannon.position
let cellRadians = Float(boneCannon.zRotation)
let speed = CGFloat(20.0)
let vx: CGFloat=CGFloat(cosf(cellRadians)) * speed
let vy: CGFloat = CGFloat(sinf(cellRadians)) * speed
cell.physicsBody?.applyImpulse(CGVectorMake(vx, vy))
cell.physicsBody?.collisionBitMask = virusMask | cellMask | wallMask
cell.physicsBody?.contactTestBitMask = cell.physicsBody!.collisionBitMask | finishMask
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
let percent = touchLocation.x / size.width
let newAngle = percent * 180-180
boneCannon.zRotation = CGFloat(newAngle) * CGFloat(M_PI) / 180.0
}
func didBeginContact(contact: SKPhysicsContact) {
let cell = (contact.bodyA.collisionBitMask == cellMask) ? contact.bodyA: contact.bodyB
let other = (cell == contact.bodyA) ? contact.bodyB: contact.bodyA
if other.categoryBitMask == virusMask{
self.didHitVirus(other)
}
if other.categoryBitMask == finishMask{
let secondlevel:GameScene = GameScene(fileNamed: "SecondLevel")!
secondlevel.scaleMode = .AspectFill
self.view?.presentScene(secondlevel)
}
let bacteria = (contact.bodyA.collisionBitMask == virusMask) ? contact.bodyA: contact.bodyB
let object = (bacteria == contact.bodyA) ? contact.bodyB: contact.bodyA
if object.categoryBitMask == wallMask{
let fail:GameScene = GameScene(fileNamed: "ThirdLevel")!
fail.scaleMode = .AspectFill
self.view?.presentScene(fail)
}
func didHitVirus(virus:SKPhysicsBody){
let particleEffect: SKEmitterNode = SKEmitterNode(fileNamed: "ParticleScene")!
//if ((virus.node?.position) != nil) {}
particleEffect.position = CGPointMake(600, 600)
particleEffect.zPosition = 4;
self.addChild(particleEffect)
virus.node?.removeFromParent()
}
}

Adding multiple sprites to a screen

I am new to SpriteKit.
I started working on a game where I want a menu of sprites that I can select from. When I select a particular sprite I want to then be able to tap on the screen and produce copies of them.
Here is a copy of my code I have trying.
class GameScene: SKScene
{
override func didMoveToView(view: SKView)
{
let button1 = SKSpriteNode(imageNamed: "Monster1A.png")
button1.position = CGPointMake(500, 600)
button1.name = "Monster1A"
self.addChild(button1)
let button2 = SKSpriteNode(imageNamed: "Monster2A.png")
button2.position = CGPointMake(300, 600)
button2.name = "Monster2A"
self.addChild(button2)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
let touch = touches
let location = touch.first!.locationInNode(self)
let node = self.nodeAtPoint(location)
if (node.name == "Monster1A")
{
for touch in touches
{
let touchLocation = touch.locationInNode(self)
let sprite = SKSpriteNode(imageNamed:"Monster1A")
sprite.xScale = 0.5
sprite.yScale = 0.5
sprite.position = touchLocation
let action = SKAction.rotateByAngle(CGFloat(M_PI), duration:1)
sprite.runAction(SKAction.repeatActionForever(action))
self.addChild(sprite)
}
}
if (node.name == "Monster2A")
{
for touch in touches
{
let touchLocation = touch.locationInNode(self)
let sprite = SKSpriteNode(imageNamed:"Monster2A")
sprite.xScale = 0.5
sprite.yScale = 0.5
sprite.position = touchLocation
let action = SKAction.rotateByAngle(CGFloat(M_PI), duration:1)
sprite.runAction(SKAction.repeatActionForever(action))
self.addChild(sprite)
}
}
}
}
Try this :)
import SpriteKit
class GameScene: SKScene {
var isDuplicating: Bool = false
var selectedSpriteName: String!
override func didMoveToView(view: SKView) {
let button1 = SKSpriteNode(imageNamed:"Monster1A")
button1.position = CGPointMake(500, 600)
button1.name = "Monster1A"
self.addChild(button1)
let button2 = SKSpriteNode(imageNamed:"Monster2A")
button2.position = CGPointMake(300, 600)
button2.name = "Monster2A"
self.addChild(button2)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch in touches {
let location = touch.locationInNode(self)
let sprite = self.nodeAtPoint(location)
if sprite.name == "Monster1A" {
if self.isDuplicating == true {
// Deselect
self.isDuplicating = false
return
}
self.selectedSpriteName = "Monster1A"
self.isDuplicating = true
} else if sprite.name == "Monster2A" {
if self.isDuplicating == true {
// Deselect
self.isDuplicating = false
return
}
self.selectedSpriteName = "Monster2A"
self.isDuplicating = true
} else {
if self.isDuplicating == true {
let newsprite = SKSpriteNode(imageNamed: self.selectedSpriteName)
newsprite.position = location
addChild(newsprite)
}
}
}
}
}