How to have a collision reset an image to a different location and update score - swift

I would like to know what im doing wrong with my collision detection. I'm trying to make a game where the user controls a character using a virtual joystick and tries to catch donuts that fall from the top of the screen. The joystick works and having the donut fall works but when the two object collide the score isn't updated and the donut location isn't reset to its default location like I want it to. I have looked at several tutorials but can't seem to find my mistake.
import SpriteKit
import GameplayKit
struct BodyType {
static let Character: UInt32 = 1
static let Knife: UInt32 = 2
static let Donut: UInt32 = 4
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var score: Int = 0
var level: Int = 0
var scoreLabel: SKLabelNode = SKLabelNode(text: "Score: 0")
var BoostButton: SKSpriteNode = SKSpriteNode(imageNamed: "boost")
var Knife: SKSpriteNode = SKSpriteNode(imageNamed: "knife")
var Donut: SKSpriteNode = SKSpriteNode(imageNamed: "donut")
var velocityMultiplier: CGFloat = 0.15
var BoostActive: Bool = false
var KnifeVel: CGFloat = 3
var KnifeX: CGFloat = 0
var KnifeY: CGFloat = 0
var FoodX: CGFloat = 0
var FoodY: CGFloat = 0
var FoodVel: CGFloat = 3
enum NodesZPosition: CGFloat {
case Character, joystick
}
var Character: SKSpriteNode = SKSpriteNode(imageNamed: "character")
var analogJoystick: AnalogJoystick = {
let js = AnalogJoystick(diameter: 90, images: (UIImage(named: "substrate"), UIImage(named: "stick")))
js.position = CGPoint(x: 480, y: 75)
js.zPosition = NodesZPosition.joystick.rawValue
return js
}()
override func didMove(to view: SKView) {
self.physicsWorld.contactDelegate = self
backgroundColor = UIColor.blue
self.anchorPoint = CGPoint(x: 0, y: 0)
Character.position = CGPoint(x: 100,y: 200)
Character.size = Donut.size
Character.physicsBody = SKPhysicsBody(texture: Character.texture!, size: Character.size)
Character.physicsBody?.affectedByGravity = false
Character.name = "Character"
Character.physicsBody?.isDynamic = true
Character.physicsBody?.categoryBitMask = BodyType.Character
Character.physicsBody?.collisionBitMask = BodyType.Knife | BodyType.Donut
Character.physicsBody?.contactTestBitMask = BodyType.Knife | BodyType.Donut
self.addChild(Character)
self.addChild(BoostButton)
BoostButton.position = CGPoint(x: 75, y: 75)
Knife.position = CGPoint(x: self.frame.width + 100, y: 200)
Knife.name = "Knife"
self.addChild(Knife)
Donut.position = CGPoint(x: 200, y: self.frame.height + 150)
Donut.name = "Donut"
self.addChild(Donut)
scoreLabel.position = CGPoint(x: 65, y: self.frame.height - 40)
scoreLabel.fontSize = 30
scoreLabel.fontColor = UIColor.black
self.addChild(scoreLabel)
setupJoystick()
let border = SKPhysicsBody(edgeLoopFrom: self.frame)
border.friction = 0
self.physicsBody = border
}
func setupJoystick (){
addChild(analogJoystick)
analogJoystick.trackingHandler = {[unowned self] data in
self.Character.position = CGPoint(x: self.Character.position.x + (data.velocity.x * self.velocityMultiplier),y: self.Character.position.y + (data.velocity.y * self.velocityMultiplier))
self.Character.zRotation = data.angular
}
}
private func didBegin(_ contact: SKPhysicsContact) {
var firstBody = SKPhysicsBody()
var secondBody = SKPhysicsBody()
if contact.bodyA.node?.name == "Character" {
firstBody = contact.bodyA
secondBody = contact.bodyB
}
else{
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if firstBody.node?.name == "Character" && secondBody.node?.name == "Donut"{
print("collison")
score += 20
scoreLabel.text = "Score \(score)"
Donut.position.y = self.frame.height + 150
Donut.position.x = CGFloat.random(in: 100..<(self.frame.width - 100))
}
else if firstBody.node?.name == "Donut" && secondBody.node?.name == "Character"{
print("collison")
score += 20
scoreLabel.text = "Score \(score)"
Donut.position.y = self.frame.height + 150
Donut.position.x = CGFloat.random(in: 100..<(self.frame.width - 100))
}
}
func touchDown(atPoint pos : CGPoint) {
}
func touchMoved(toPoint pos : CGPoint) {
}
func touchUp(atPoint pos : CGPoint) {
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches ){
let location = touch.location(in: self)
if (BoostButton.frame.contains(location)){
BoostActive = true
}
else{
BoostActive = false
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func update(_ currentTime: TimeInterval) {
// if (BoostActive == true){
// velocityMultiplier = velocityMultiplier * 1.5
// }
// else{
// velocityMultiplier = 0.15
//}
FoodY = Donut.position.y
KnifeX = Knife.position.x
if (Knife.position.x < (self.frame.width - 20) && Knife.position.x > 20){
Knife.physicsBody = SKPhysicsBody(texture: Knife.texture!, size: Knife.size)
Knife.physicsBody?.affectedByGravity = false
Knife.physicsBody?.restitution = 0
Knife.physicsBody?.pinned = false
Knife.physicsBody?.isDynamic = true
Knife.physicsBody?.allowsRotation = false
Knife.physicsBody?.categoryBitMask = BodyType.Knife
Knife.physicsBody?.collisionBitMask = BodyType.Character
Knife.physicsBody?.contactTestBitMask = BodyType.Character
}
else{
Knife.physicsBody = nil
}
if (Donut.position.y < self.frame.height && Donut.position.y > 50){
Donut.physicsBody = SKPhysicsBody(texture: Donut.texture!, size: Donut.size)
Donut.physicsBody?.affectedByGravity = false
Donut.physicsBody?.isDynamic = false
Donut.physicsBody?.categoryBitMask = BodyType.Donut
Donut.physicsBody?.collisionBitMask = BodyType.Character
Donut.physicsBody?.contactTestBitMask = BodyType.Character
}
else{
Donut.physicsBody = nil
}
if (FoodY < 30){
Donut.position.y = self.frame.height + 150
Donut.position.x = CGFloat.random(in: 100..<(self.frame.width - 100))
}
else{
Donut.position.y = Donut.position.y - FoodVel
}
if (KnifeX < 0){
Knife.position.x = self.frame.width + 150
Knife.position.y = CGFloat.random(in: 50..<(self.frame.height - 50))
}
else{
Knife.position.x = Knife.position.x - KnifeVel
}
}
}

Related

Child nodes inside SKNode disappears with fast shaking device with CMMotionManager applied to move balls

I've create a SKNode with physicsBody edgeFromLoop circular inside which i've added 8 small circular nodes. and 8 circular nodes are moving with CMMotionManager inside Parent circular node. with fast motion shake some balls disappears from screen. SKScene Class given below
Balls only disappears when anyone shake mobile hard randomly.
There are 8 balls initially but after some hard shake reduced.
class GameScene: SKScene {
let motionManager = CMMotionManager()
var Circle = SKShapeNode(circleOfRadius: 108)
var sound = SKAction.playSoundFileNamed(getRandomSound(), waitForCompletion: false)
var collisionBitmasks: [UInt32] = [UInt32]()
override func didMove(to view: SKView) {
Circle.fillTexture = SKTexture.init(image: UIImage.init(named: "img_Ball") ?? UIImage())
Circle.position = CGPoint.init(x: 0, y: 0)
Circle.name = "defaultCircle"
Circle.lineWidth = 0.0
Circle.fillColor = SKColor.lightGray.withAlphaComponent(0.8)
Circle.physicsBody = SKPhysicsBody.init(edgeLoopFrom: UIBezierPath.init(ovalIn: CGRect.init(x: Circle.frame.minX + 12,
y: Circle.frame.minY + 12,
width: Circle.frame.width - 24,
height: Circle.frame.height - 24)).cgPath)
Circle.physicsBody?.isDynamic = true
Circle.physicsBody?.affectedByGravity = false
Circle.physicsBody?.allowsRotation = false
addChild(Circle)
self.physicsWorld.contactDelegate = self
startAcceleroMeter()
for index in 1...8 {
addBalls(index)
}
}
func stop() {
motionManager.stopAccelerometerUpdates()
Circle.children.forEach { (ball) in
ball.physicsBody?.isDynamic = false
ball.physicsBody?.affectedByGravity = false
}
}
func startAcceleroMeter() {
Circle.children.forEach { (ball) in
ball.physicsBody?.isDynamic = true
ball.physicsBody?.affectedByGravity = true
}
motionManager.startAccelerometerUpdates()
motionManager.accelerometerUpdateInterval = 0.1
motionManager.startAccelerometerUpdates(to: .main) { (motionData, error) in
let gravity = CGVector.init(dx: (motionData?.acceleration.x ?? 0.0) * 20, dy: (motionData?.acceleration.y ?? 0.0) * 20)
print(gravity)
self.physicsWorld.gravity = gravity
}
}
func stopPlaying() -> [String] {
var dictionary = [String]()
for (_, ball) in (Circle.children).enumerated() {
dictionary.append("\(ball.position.x), \(ball.position.y), 0.0")
}
return dictionary
}
func addBalls(_ ballNo: Int) {
let ball = SKShapeNode.init(circleOfRadius: 12)
ball.name = "ball\(ballNo)"
ball.fillTexture = SKTexture.init(linearGradientWithAngle: CGFloat.pi, colors: [BallColors(rawValue: ballNo)?.toUIColor(false) ?? UIColor(), BallColors(rawValue: ballNo)?.toUIColor(true) ?? UIColor()], locations: [0, 1], size: ball.frame.size)
ball.fillColor = UIColor.white
ball.physicsBody = SKPhysicsBody.init(circleOfRadius: 12)
ball.physicsBody?.isDynamic = true
ball.physicsBody?.affectedByGravity = true
ball.physicsBody?.allowsRotation = true
ball.physicsBody?.friction = 0.2
ball.physicsBody?.restitution = 0.9
ball.physicsBody?.linearDamping = 0.1
ball.physicsBody?.angularDamping = 0.1
ball.physicsBody?.mass = 0.349065870046616
ball.physicsBody?.usesPreciseCollisionDetection = true
ball.position = CGPoint(x: Circle.frame.midX - CGFloat(ballNo), y: Circle.frame.midY - CGFloat(ballNo))
ball.physicsBody?.fieldBitMask = 1
ball.physicsBody?.categoryBitMask = UInt32.init(ballNo + 100)
let collisionBitMask = UInt32.init(ballNo + 20) | UInt32.init(ballNo + 100)
collisionBitmasks.append(collisionBitMask)
ball.physicsBody?.collisionBitMask = collisionBitMask //To be different for each
ball.physicsBody?.contactTestBitMask = UInt32.init(ballNo + 20)
Circle.addChild(ball)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
if collisionBitmasks.contains(contact.bodyA.collisionBitMask) && collisionBitmasks.contains(contact.bodyB.collisionBitMask) {
run(sound)
}
}
}
You need a hidden magic here. Each small ball adds a constraint that can prevent any accident from high speeds:
ball.constraints = [SKConstraint.distance(SKRange(upperLimit: 108 - 12), to: Circle)]

My initial pipes are different from the following pipes

I'm making a game where the ball is suppose to go through some pipes, and when the player touches the pipes, the game stops. Kind of like flappy bird. The only problem I have is that the initial pipes blocks the entire screen, while the rest of the pipes are placed and randomized exactly as I want. How is this possible?
This is the ball class:
import SpriteKit
struct ColliderType {
static let Ball: UInt32 = 1
static let Pipes: UInt32 = 2
static let Score: UInt32 = 3
}
class Ball: SKSpriteNode {
func initialize() {
self.name = "Ball"
self.zPosition = 1
self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
self.physicsBody = SKPhysicsBody(circleOfRadius: self.size.height /
2)
self.setScale(0.7)
self.physicsBody?.affectedByGravity = false
self.physicsBody?.categoryBitMask = ColliderType.Ball
self.physicsBody?.collisionBitMask = ColliderType.Pipes
self.physicsBody?.contactTestBitMask = ColliderType.Pipes |
ColliderType.Score
}
}
This is the Random Class:
import Foundation
import CoreGraphics
public extension CGFloat {
public static func randomBetweenNumbers(firstNum: CGFloat, secondNum:
CGFloat) -> CGFloat {
return CGFloat(arc4random()) / CGFloat(UINT32_MAX) * abs(firstNum -
secondNum) + firstNum
}
}
This is the GameplayScene:
import SpriteKit
class GameplayScene: SKScene {
var ball = Ball()
var pipesHolder = SKNode()
var touched: Bool = false
var location = CGPoint.zero
override func didMove(to view: SKView) {
initialize()
}
override func update(_ currentTime: TimeInterval) {
moveBackgrounds()
if (touched) {
moveNodeToLocation()
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event:
UIEvent?) {
touched = true
for touch in touches {
location = touch.location(in:self)
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event:
UIEvent?) {
touched = false
}
override func touchesMoved(_ touches: Set<UITouch>, with event:
UIEvent?) {
for touch in touches {
location = touch.location(in: self)
}
}
func initialize() {
createBall()
createBackgrounds()
createPipes()
spawnObstacles()
}
func createBall() {
ball = Ball(imageNamed: "Ball")
ball.initialize()
ball.position = CGPoint(x: 0, y: 0)
self.addChild(ball)
}
func createBackgrounds() {
for i in 0...2 {
let bg = SKSpriteNode(imageNamed: "BG")
bg.anchorPoint = CGPoint(x: 0.5, y: 0.5)
bg.zPosition = 0
bg.name = "BG"
bg.position = CGPoint(x: 0, y: CGFloat(i) * bg.size.height)
self.addChild(bg)
}
}
func moveBackgrounds() {
enumerateChildNodes(withName: "BG", using: ({
(node, error) in
node.position.y -= 15
if node.position.y < -(self.frame.height) {
node.position.y += self.frame.height * 3
}
}))
}
func createPipes() {
pipesHolder = SKNode()
pipesHolder.name = "Holder"
let pipeLeft = SKSpriteNode(imageNamed: "Pipe")
let pipeRight = SKSpriteNode(imageNamed: "Pipe")
pipeLeft.name = "Pipe"
pipeLeft.anchorPoint = CGPoint(x: 0.5, y: 0.5)
pipeLeft.position = CGPoint(x: 350, y: 0)
pipeLeft.xScale = 1.5
pipeLeft.physicsBody = SKPhysicsBody(rectangleOf: pipeLeft.size)
pipeLeft.physicsBody?.categoryBitMask = ColliderType.Pipes
pipeLeft.physicsBody?.affectedByGravity = false
pipeLeft.physicsBody?.isDynamic = false
pipeRight.name = "Pipe"
pipeRight.anchorPoint = CGPoint(x: 0.5, y: 0.5)
pipeRight.position = CGPoint(x: -350, y: 0)
pipeRight.xScale = 1.5
pipeRight.physicsBody = SKPhysicsBody(rectangleOf: pipeRight.size)
pipeRight.physicsBody?.categoryBitMask = ColliderType.Pipes
pipeRight.physicsBody?.affectedByGravity = false
pipeRight.physicsBody?.isDynamic = false
pipesHolder.zPosition = 5
pipesHolder.position.y = self.frame.height + 100
pipesHolder.position.x = CGFloat.randomBetweenNumbers(firstNum:
-250, secondNum: 250)
pipesHolder.addChild(pipeLeft)
pipesHolder.addChild(pipeRight)
self.addChild(pipesHolder)
let destination = self.frame.height * 3
let move = SKAction.moveTo(y: -destination, duration:
TimeInterval(10))
let remove = SKAction.removeFromParent()
pipesHolder.run(SKAction.sequence([move, remove]), withKey: "Move")
}
func spawnObstacles() {
let spawn = SKAction.run({ () -> Void in
self.createPipes()
})
let delay = SKAction.wait(forDuration: TimeInterval(1.5))
let sequence = SKAction.sequence([spawn, delay])
self.run(SKAction.repeatForever(sequence), withKey: "Spawn")
}
func moveNodeToLocation() {
// Compute vector components in direction of the touch
var dx = location.x - ball.position.x
// How fast to move the node. Adjust this as needed
let speed:CGFloat = 0.1
// Scale vector
dx = dx * speed
ball.position = CGPoint(x:ball.position.x+dx, y: 0)
}
}

Integer is not being updated

I am making a game that includes a high score label that comes up once the player dies, along with a restart button. Overall the high score, which is an integer, works fine but there is one problem. If you reach a new high score in that round you just finished you have to die again for it to show the new high score. Lets say I play the game while the high score is already 15 and I score 17 when the high score label comes up it still shows 15. After I restart the game and the high score comes up again it will now show 17. The high score is not updating when I want it to.
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 {
var Highscore = Int()
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()
var Highscorelabel = SKLabelNode()
let BackGround = SKSpriteNode (imageNamed: "BackGround")
var restartButton = SKSpriteNode()
var Died = Bool()
func restartScene(){
self.removeAllChildren()
self.removeAllActions()
scorenumber = 0
lifenumber = 0
createScene()
random()
//spawnThirdIce()
Died = false
timeOfLastSpawn = 0.0
timePerSpawn = 1.2
}
func createScene(){
physicsWorld.contactDelegate = self
if (scorenumber > Highscore){
var Highscoredefault = NSUserDefaults.standardUserDefaults()
Highscoredefault.setValue(scorenumber, forKey: "HighScore")
}
var Highscoredefault = NSUserDefaults.standardUserDefaults()
if (Highscoredefault.valueForKey("HighScore") != nil){
Highscore = Highscoredefault.valueForKey("HighScore") as! NSInteger
}
else{
Highscore = 0
}
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/9.5)
person.setScale(0.6)
person.physicsBody = SKPhysicsBody (rectangleOfSize: CGSize(width: 1000, 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
self.addChild(person)
ScoreLable = SKLabelNode()
ScoreLable.fontName = "Arial"
ScoreLable.position = CGPoint(x: self.frame.width / 2, y: 1700)
ScoreLable.text = "\(scorenumber)"
ScoreLable.fontColor = UIColor.yellowColor()
ScoreLable.fontSize = 150
self.addChild(ScoreLable)
Highscorelabel.fontName = "Arial"
Highscorelabel.position = CGPoint(x: self.frame.width / 2, y: 1400)
Highscorelabel.text = "HighScore: \(Highscore)"
Highscorelabel.fontSize = 150
Highscorelabel.fontColor = UIColor.yellowColor()
Highscorelabel.zPosition = -7
self.addChild(Highscorelabel)
}
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")
}
override func didMoveToView(view: SKView) {
createScene()
}
func createButton(){
restartButton = SKSpriteNode(imageNamed: "Restart Button")
restartButton.position = CGPoint(x: 768, y: 1024)
restartButton.zPosition = 6
restartButton.setScale(2.3)
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{
// self.addChild(Highscorelabel)
Highscorelabel.zPosition = 5
createButton()
person.zPosition = -6
person.texture = SKTexture (imageNamed: "Person1")
//person.removeFromParent()
Died = true
}
}
}
func CollisionWithPerson (Ice: SKSpriteNode, Person: SKSpriteNode){
Person.removeFromParent()
// if (scorenumber > Highscore){
// var Highscoredefault = NSUserDefaults.standardUserDefaults()
// Highscoredefault.setValue(scorenumber, forKey: "HighScore")
//}
}
func spawnThirdIce(){
if Died == true {
} else
{
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
}
}
}
Ok this is what I added to if life number = 3:
if lifenumber == 3{
if (scorenumber > Highscore){
var Highscoredefault = NSUserDefaults.standardUserDefaults()
Highscoredefault.setValue(scorenumber, forKey: "HighScore")
}
var Highscoredefault = NSUserDefaults.standardUserDefaults()
if (Highscoredefault.valueForKey("HighScore") != nil){
Highscore = Highscoredefault.valueForKey("HighScore") as! NSInteger
}
else{
Highscore = 0
}
self.addChild(Highscorelabel)
createButton()
person.zPosition = -6
person.texture = SKTexture (imageNamed: "Person1")
Died = true
}
It appears you only set the text property of Highscorelabel when you initialize it. If you want the Highscorelabel to be updated immediately upon death then you should update it at such time.
if lifenumber == 3 {
/* Check if new highscore, update HighscoreLabel */
I think you must add just this:
after scorenumber++ in func didBeginContact(contact: SKPhysicsContact)
//ADD THIS
if scorenumber > Highscore {
Highscore = scorenumber
Highscorelabel.text = "HighScore: \(Highscore)"
}

didBeginContact not working in Swift 2 + SpriteKit

I'm working on a game, and I'm using spritekit and Swift.
This is my code:
import SpriteKit
struct collision {
static let arrow:UInt32 = 0x1 << 1
static let runner:UInt32 = 0x1 << 2
static let target:UInt32 = 0x1 << 3
static let targetCenter:UInt32 = 0x1 << 4
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var person = SKSpriteNode()
var box = SKSpriteNode()
var screenSize:CGSize!
var gameScreenSize:CGSize!
var gameStarted:Bool = false
var moveAndRemove = SKAction()
var boxVelocity:NSTimeInterval = 5.5
override func didMoveToView(view: SKView) {
self.physicsWorld.gravity = CGVectorMake(0, -1.0)
self.physicsWorld.contactDelegate = self
screenSize = self.frame.size
gameScreenSize = view.frame.size
createPerson()
}
func createPerson() -> Void {
person.texture = SKTexture(imageNamed:"person")
person.setScale(1.0)
person.size = CGSize(width: 80, height: 80)
person.position = CGPoint(x: screenSize.width / 2, y: 150)
person.physicsBody = SKPhysicsBody(rectangleOfSize: person.size)
person.physicsBody?.affectedByGravity = false
person.physicsBody?.dynamic = false
self.addChild(person)
}
func createTarget() -> Void {
box = SKSpriteNode()
box.size = CGSize(width: 70, height: 100)
box.setScale(1.0)
box.position = CGPoint(x: (screenSize.width / 3) * 2, y: screenSize.height + box.size.height)
box.texture = SKTexture(imageNamed: "box")
box.physicsBody? = SKPhysicsBody(rectangleOfSize: box.size)
box.physicsBody?.categoryBitMask = collision.target
box.physicsBody?.collisionBitMask = collision.arrow
box.physicsBody?.contactTestBitMask = collision.targetCenter
box.physicsBody?.affectedByGravity = false
box.physicsBody?.dynamic = true
box.physicsBody?.usesPreciseCollisionDetection = true
self.addChild(box)
let distance = CGFloat(self.frame.height - box.frame.height)
let moveTargets = SKAction.moveToY(-distance, duration: boxVelocity)
let removeTargets = SKAction.removeFromParent()
moveAndRemove = SKAction.sequence([moveTargets,removeTargets])
box.runAction(moveAndRemove)
}
func createBall() ->Void {
let ball = SKSpriteNode()
ball.size = CGSize(width: 20, height: 22)
ball.zPosition = 5
let moveToXY = CGPoint(x: self.size.width, y: self.size.height)
ball.texture = SKTexture(imageNamed: "ball")
ball.position = CGPointMake(person.position.x + ball.size.width, person.position.y + ball.size.height)
ball.physicsBody? = SKPhysicsBody(rectangleOfSize: ball.size)
ball.physicsBody?.categoryBitMask = collision.arrow
ball.physicsBody?.collisionBitMask = collision.target
ball.physicsBody?.affectedByGravity = false
ball.physicsBody?.dynamic = true
ball.physicsBody?.usesPreciseCollisionDetection = true
let action = SKAction.moveTo(moveToXY, duration: 1.5)
let delay = SKAction.waitForDuration(1.5)
ball.runAction(SKAction.sequence([action,delay]))
self.addChild(ball)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if gameStarted == false {
gameStarted = true
let spawn = SKAction.runBlock { () in
self.createTarget()
}
let delay = SKAction.waitForDuration(1.5)
let spawnDelay = SKAction.sequence([spawn, delay])
let spanDelayForever = SKAction.repeatActionForever(spawnDelay)
self.runAction(spanDelayForever)
} else {
createBall()
boxVelocity -= 0.1
}
}
func didBeginContact(contact: SKPhysicsContact) {
print("Detect")
}
func didEndContact(contact: SKPhysicsContact) {
print("end detect")
}
override func update(currentTime: CFTimeInterval) {
}
}
But when I run the game, the collision between objects does not. I'm trying to solve a while, but found nothing. Can someone help me?
Project files.
Try with these to modifications:
box.physicsBody = SKPhysicsBody(rectangleOfSize: box.size)
box.physicsBody?.categoryBitMask = collision.target
box.physicsBody?.collisionBitMask = collision.arrow
box.physicsBody?.contactTestBitMask = collision.targetCenter
and
ball.physicsBody = SKPhysicsBody(rectangleOfSize: ball.size)
ball.physicsBody?.categoryBitMask = collision.arrow
ball.physicsBody?.collisionBitMask = collision.target
ball.physicsBody?.contactTestBitMask = collision.target
Note the absence of "?" while you init the physicsBody and the new contactTestBitMask

Pong-after a restart no ball on screen

I'm a newbee in Swift and SpriteKit. I have made a simple one player version of Pong. After a score the game restarts. Switches to the Game Over scene and returns. After that I cannot get the ball back on the screen. I do not understand that the spawnBall() does not reply, while the spawnPaddle, and the spawnBottom() do. Please help.
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
override init(size: CGSize) { super.init(size: CGSize()) }
var gameScene: GameScene!
let BallCategoryName = "ball" let BottomCategoryName = "bottom" let PaddleCategoryName = "paddle"
var isFingerOnPaddle = false
let BallCategory: UInt32 = 0x1 << 0
let BottomCategory : UInt32 = 0x1 << 1
let PaddleCategory : UInt32 = 0x1 << 3
var score = 0
var start: UIButton!
var isRunning = false
var scoreLabel = SKLabelNode()
var ball = SKSpriteNode()
var paddle = SKSpriteNode()
var bottom = SKSpriteNode()
var isBall = false
func spawnBall() {
ball = SKSpriteNode(imageNamed: "ball")
ball.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
ball.xScale = 0.1
ball.yScale = 0.1
ball.hidden = false
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height/2)
ball.physicsBody?.categoryBitMask = BallCategory
ball.physicsBody?.contactTestBitMask = BottomCategory
ball.physicsBody?.restitution = 1.0
ball.physicsBody?.linearDamping = 0.0
ball.physicsBody?.angularDamping = 0.0
addChild(ball)
isBall = true
println("***")
}
func spawnPaddle() {
paddle = SKSpriteNode(imageNamed: "wit")
paddle.position = CGPointMake(200, 50)
paddle.xScale = 0.09
paddle.yScale = 0.09
paddle.physicsBody = SKPhysicsBody(rectangleOfSize: paddle.size)
paddle.physicsBody?.categoryBitMask = PaddleCategory
paddle.physicsBody?.contactTestBitMask = BottomCategory
paddle.physicsBody?.restitution = 1.0
paddle.physicsBody?.linearDamping = 0.0
paddle.physicsBody?.angularDamping = 0.0
paddle.physicsBody?.dynamic = false
paddle.name = "paddle"
addChild(paddle)
}
func spawnBottom() {
bottom = SKSpriteNode(imageNamed: "wit")
bottom.position = CGPointMake(0, -111)
bottom.physicsBody = SKPhysicsBody(rectangleOfSize: bottom.size)
bottom.physicsBody?.dynamic = false
bottom.physicsBody?.restitution = 1
bottom.physicsBody?.angularDamping = 0
bottom.physicsBody?.linearDamping = 0.0
bottom.physicsBody?.categoryBitMask = BottomCategory
addChild(bottom)
println("Bottom")
}
override func didMoveToView(view: SKView) {
super.didMoveToView(view)
physicsWorld.gravity = CGVectorMake(0, 0)
physicsWorld.contactDelegate = self
backgroundColor = UIColor.blackColor()
scoreLabel.fontColor = UIColor.whiteColor()
scoreLabel.fontName = "Avenir"
scoreLabel.fontSize = 25
scoreLabel.text = "0"
scoreLabel.position = CGPoint(x:CGRectGetMidX(frame) + 140, y: CGRectGetMidY(frame))
addChild(scoreLabel)
//////THE LOOP/////////////////////////////////////////////
let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
borderBody.friction = 0
self.physicsBody = borderBody
spawnPaddle()
spawnBottom()
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
var touch = touches.anyObject() as UITouch
var touchLocation = touch.locationInNode(self)
if let body = physicsWorld.bodyAtPoint(touchLocation) {
if body.node?.name == PaddleCategoryName {
println("On the paddle")
isFingerOnPaddle = true
}
}
}
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
if isFingerOnPaddle {
var touch = touches.anyObject() as UITouch
var touchLocation = touch.locationInNode(self)
var previousLocation = touch.previousLocationInNode(self)
var paddleX = paddle.position.x + (touchLocation.x - previousLocation.x)
paddleX = max(paddleX, paddle.size.width/2)
paddleX = min(paddleX, size.width - paddle.size.width/2)
paddle.position = CGPointMake(paddleX, paddle.position.y)
}
}
func random(x: Int) -> Int {
var y = arc4random_uniform(UInt32(x))
return Int(y)
}
func start(sender: AnyObject) {
if isBall == false {
spawnBall()
ball.physicsBody?.applyImpulse(CGVectorMake(12, 40))
println("ball")
}
}
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
isFingerOnPaddle = false
}
func didBeginContact(contact: SKPhysicsContact) {
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
func changeScene() {
let gameOverScene = GameOverScene(size: size)
gameOverScene.scaleMode = scaleMode
let reveal = SKTransition.flipHorizontalWithDuration(0.5)
view?.presentScene(gameOverScene, transition: reveal)
}
if firstBody.categoryBitMask == BallCategory && secondBody.categoryBitMask == BottomCategory {
println("Hit bottom.")
ball.physicsBody?.velocity = CGVectorMake(0, 0)
isBall = false
ball.removeFromParent()
score++
println(score)
scoreLabel.text = String(score)
isRunning = false
if score >= 3 {
ball.physicsBody?.velocity = CGVectorMake(0, 0)
isBall = false
ball.removeFromParent()
println("Game Over")
changeScene()
}
}
}
}