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()
}
}
}
}
Related
I have 2 categories
enum ColliderType:UInt32 {
case bulletCategory = 1
case bossCategory = 2
}
I made my class use the SKPhysicsContactDelegate and created a node
class PlayScene: SKScene, SKPhysicsContactDelegate {
var charBullets :[SKSpriteNode] = [SKSpriteNode]()
var charBulletTexture = SKTexture(imageNamed: "Bullet1.png")
var boss = SKSpriteNode()
var bossTexture = SKTexture(imageNamed: "BossImage.png")
And set the physicsWorld.contactDelegate and created a node in the didMove(to view: SKView) function
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
boss.name = "boss"
boss = SKSpriteNode(texture: bossTexture)
boss.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 300, height: 300))
boss.physicsBody?.usesPreciseCollisionDetection = true
boss.physicsBody!.isDynamic = true
boss.physicsBody!.affectedByGravity = false
boss.size = CGSize(width: 300, height: 300)
boss.physicsBody!.categoryBitMask = ColliderType.bossCategory.rawValue
boss.physicsBody!.collisionBitMask = 0
boss.physicsBody!.contactTestBitMask = ColliderType.bulletCategory.rawValue
boss.position = CGPoint(x: 0, y: self.size.height/4)
addChild(boss)
}
I created another node in the touchesBegan function
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
charBullet.name = "bullet"
charBullet.physicsBody = SKPhysicsBody(circleOfRadius: charBullet.size.width/64)
charBullet.physicsBody!.isDynamic = true
charBullet.physicsBody!.usesPreciseCollisionDetection = true
charBullet.physicsBody!.affectedByGravity = false
charBullet.physicsBody!.velocity = CGVector.init(dx: 0, dy: 450)
charBullet.physicsBody!.categoryBitMask = ColliderType.bulletCategory.rawValue
charBullet.physicsBody!.collisionBitMask = 0
charBullet.physicsBody!.contactTestBitMask = ColliderType.bossCategory.rawValue
charBullet.position = CGPoint(x: character.position.x, y: character.position.y + 100)
addChild(charBullet)
charBullets.append(charBullet)
}
Then I have a didBegin(_ contact: SKPhysicsContact) but it isn't called when the bullet and boss collide
func didBegin(_ contact: SKPhysicsContact) {
//not printed
print("contact!")
if(charBullets.count > 0) {
var firstBody = SKPhysicsBody()
var secondBody = SKPhysicsBody()
if(contact.bodyA.node?.name == "bullet") {
print("test1")
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
print("test2")
firstBody = contact.bodyB
secondBody = contact.bodyA
print(secondBody)
}
if(firstBody.node?.name == "bullet") {
print("bulletname")
}
if(firstBody.node?.name == "boss") {
print("bossname")
}
if(secondBody.node?.name == "bullet") {
print("bulletname2")
}
if(secondBody.node?.name == "boss") {
print("bossname2")
}
if(firstBody.node?.name == "bullet" && secondBody.node?.name == "boss") {
print("hit the boss!")
charBullets[i].removeFromParent()
bossHealth -= 1
bossHealthLabel.text = "Boss Health \(bossHealth)"
}
}
}
}
Update: I fixed it by changing their physicsBodys' to use the image texture size as opposed to a set value and by setting their names under the creation of the node by using
boss = SKSpriteNode(texture: bossTexture)
boss.name = "boss"
boss.physicsBody = SKPhysicsBody(texture: bossTexture, size: bossTexture.size())
and
let charBullet = SKSpriteNode(texture: charBulletTexture)
charBullet.name = "bullet"
charBullet.physicsBody = SKPhysicsBody(texture: charBulletTexture, size: charBulletTexture.size())
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
}
}
}
I am trying to program a game with Spritekit in Swift. The aim is to escape with his character oncoming rectangles. Now I've made a mistake with the SKPhysicsContactDelegate (didBegin ()) method, so the figure's contact with one of the rectangles is not recognized. Can someone help me find the mistake? This isn't a duplicate because this time I used a different code!
import SpriteKit
struct PhysicsCategory {
static let none : UInt32 = 0
static let all : UInt32 = UInt32.max
static let rechteck : UInt32 = 0b1 // 1
static let figur : UInt32 = 0b10 // 2
}
class PlayScene: SKScene, SKPhysicsContactDelegate{
let figur = SKSpriteNode(imageNamed: "Punkt.jpg")
#objc func addRechteck(){
let rechteckRechts = SKSpriteNode(imageNamed: "Rechteck.gif")
rechteckRechts.physicsBody = SKPhysicsBody(rectangleOf: rechteckRechts.size) // 1
rechteckRechts.physicsBody?.isDynamic = true // 2
rechteckRechts.physicsBody?.categoryBitMask = PhysicsCategory.rechteck // 3
rechteckRechts.physicsBody?.contactTestBitMask = PhysicsCategory.rechteck // 4
rechteckRechts.physicsBody?.collisionBitMask = PhysicsCategory.none // 5
let rechteckLinks = SKSpriteNode(imageNamed: "Rechteck.gif")
rechteckLinks.physicsBody = SKPhysicsBody(rectangleOf: rechteckLinks.size) // 1
rechteckLinks.physicsBody?.isDynamic = true // 2
rechteckLinks.physicsBody?.categoryBitMask = PhysicsCategory.rechteck // 3
rechteckLinks.physicsBody?.contactTestBitMask = PhysicsCategory.rechteck // 4
rechteckLinks.physicsBody?.collisionBitMask = PhysicsCategory.none // 5
let groesse = arc4random_uniform(5)+1
print(groesse)
switch groesse {
case 1:
rechteckLinks.xScale = 0.5
rechteckRechts.xScale = 1.5
case 2:
rechteckLinks.xScale = 1.5
rechteckRechts.xScale = 0.5
case 3:
rechteckLinks.xScale = 1
rechteckRechts.xScale = 1
case 4:
rechteckLinks.xScale = 1.25
rechteckRechts.xScale = 0.75
case 5:
rechteckLinks.xScale = 0.75
rechteckRechts.xScale = 1.25
default:
print("Fehler in der Wahrscheinlichkeit!!!")
}
rechteckRechts.position = CGPoint(x: frame.minX + (rechteckRechts.size.width / 2), y: frame.maxY)
rechteckLinks.position = CGPoint(x: frame.maxX - (rechteckLinks.size.width / 2), y: frame.maxY)
let moveDown = SKAction.moveBy(x: 0, y: -5000, duration: 20.0)
rechteckLinks.run(moveDown)
rechteckRechts.run(moveDown)
self.addChild(rechteckRechts)
self.addChild(rechteckLinks)
}
override func didMove(to view: SKView) {
physicsWorld.gravity = .zero
physicsWorld.contactDelegate = self
figur.xScale = 0.4
figur.yScale = 0.4
figur.position = CGPoint(x: frame.midX, y: frame.maxY / 4)
figur.physicsBody = SKPhysicsBody(rectangleOf: figur.size)
figur.physicsBody?.isDynamic = true
figur.physicsBody?.categoryBitMask = PhysicsCategory.figur
figur.physicsBody?.contactTestBitMask = PhysicsCategory.rechteck
figur.physicsBody?.collisionBitMask = PhysicsCategory.none
figur.physicsBody?.usesPreciseCollisionDetection = true
self.addChild(figur)
self.backgroundColor = SKColor.white
let wait1 = SKAction.wait(forDuration: 3)
let timer = SKAction.repeatForever(SKAction.sequence([wait1, SKAction.run {
self.addRechteck()
}]))
self.run(timer, withKey: "addRechteck")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches ){
let location = touch.location(in: self)
if figur.contains(location){
figur.position = location
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches ) {
let location = touch.location(in: self)
if figur.contains(location){
figur.position = location
}
}
}
}
func figurDidColissionWithRectangle(figur: SKSpriteNode, rechteck: SKSpriteNode) {
print("Hit")
figur.removeFromParent()
rechteck.removeFromParent()
}
extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
// 1
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
}
// 2
if ((firstBody.categoryBitMask & PhysicsCategory.rechteck != 0) &&
(secondBody.categoryBitMask & PhysicsCategory.figur != 0)) {
if let rechteck = firstBody.node as? SKSpriteNode,
let figur = secondBody.node as? SKSpriteNode {
figurDidColissionWithRectangle(figur: figur, rechteck: rechteck)
}
}
}
}
In the method addRecktech(), you've told rechteckRechts' physics body to only test for contact with itself:
rechteckRechts.physicsBody?.contactTestBitMask = PhysicsCategory.rechteck //4
I suggest changing this line of code to the following, to tell it to test for contact with figur:
rechteckRechts.physicsBody?.contactTestBitMask = PhysicsCategory.figur //4
I believe because there's only a 'one-way' test for contact between rechTeck and figur in your current code, some contact events are being missed.
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)"
}
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