I am trying to reload the GameScene from my EndScene. The idea is the player will hit the "Restart" Button, reloading the GameScene allowing them to try again. Here is my code for the two scenes. Does anyone have a solution? Please give me the exact code I would need, this is my first time using Xcode, and I am new to using code. It would help me understand better how to deal with a problem like this in the future.
Here is the code for the GameScene:
var Highscore = Int()
var Score = Int()
var Player = SKSpriteNode (imageNamed: "good.png")
var ScoreLbl = UILabel()
override func didMoveToView(view: SKView) {
var HighscoreDefault = NSUserDefaults.standardUserDefaults()
if (HighscoreDefault.valueForKey("Highscore") != nil){
Highscore = HighscoreDefault.valueForKey("Highscore") as! NSInteger
}
else {
Highscore = 0
}
physicsWorld.contactDelegate = self
self.scene?.backgroundColor = UIColor.blackColor()
self.addChild(SKEmitterNode(fileNamed: "Rain"))
Player.position = CGPointMake(self.size.width / 2, self.size.width / 6)
Player.physicsBody = SKPhysicsBody(rectangleOfSize: Player.size)
Player.physicsBody?.affectedByGravity = false
Player.physicsBody?.categoryBitMask = PhysicsCategory.Player
Player.physicsBody?.contactTestBitMask = PhysicsCategory.Enemy
Player.physicsBody?.dynamic = false
var Timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: Selector("SpawnBullets"), userInfo: nil, repeats: true)
var EnemyTimer = NSTimer.scheduledTimerWithTimeInterval(0.8, target: self, selector: Selector("SpawnEnemies"), userInfo: nil, repeats: true)
self.addChild(Player)
ScoreLbl.text = "\(Score)"
ScoreLbl = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
ScoreLbl.backgroundColor = UIColor(red: 0.1, green: 0.1, blue: 1.0, alpha: 0.3)
ScoreLbl.textColor = UIColor.whiteColor()
self.view?.addSubview(ScoreLbl)
}
func didBeginContact(contact: SKPhysicsContact) {
var firstBody : SKPhysicsBody = contact.bodyA
var secondBody : SKPhysicsBody = contact.bodyB
if ((firstBody.categoryBitMask == PhysicsCategory.Enemy) && (secondBody.categoryBitMask == PhysicsCategory.Bullet) || (firstBody.categoryBitMask == PhysicsCategory.Bullet) && (secondBody.categoryBitMask == PhysicsCategory.Enemy)){
CollisionWithBullet(firstBody.node as! SKSpriteNode, Bullet: secondBody.node as! SKSpriteNode)
}
else if ((firstBody.categoryBitMask == PhysicsCategory.Enemy) && (secondBody.categoryBitMask == PhysicsCategory.Player) || (firstBody.categoryBitMask == PhysicsCategory.Player) && (secondBody.categoryBitMask == PhysicsCategory.Enemy)){
CollisionWithPerson(firstBody.node as! SKSpriteNode, Person: secondBody.node as! SKSpriteNode)
}
}
func CollisionWithBullet(Enemy: SKSpriteNode, Bullet: SKSpriteNode){
Enemy.removeFromParent()
Bullet.removeFromParent()
Score++
ScoreLbl.text = "\(Score)"
}
func CollisionWithPerson(Enemy: SKSpriteNode,Person: SKSpriteNode){
var ScoreDefault = NSUserDefaults.standardUserDefaults()
ScoreDefault.setValue(Score, forKey: "Score")
ScoreDefault.synchronize()
if (Score > Highscore){
var HighscoreDefault = NSUserDefaults.standardUserDefaults()
HighscoreDefault.setValue(Score, forKey: "Highscore")
}
Enemy.removeFromParent()
Person.removeFromParent()
self.view?.presentScene(EndScene())
ScoreLbl.removeFromSuperview()
self.removeAllActions()
}
func SpawnBullets() {
var Bullet = SKSpriteNode (imageNamed: "bullet.png")
Bullet.zPosition = -5
Bullet.position = CGPointMake(Player.position.x, Player.position.y)
let action = SKAction.moveToY(self.size.height + 30, duration: 1.0)
let actionDone = SKAction.removeFromParent()
Bullet.runAction(SKAction.sequence([action, actionDone]))
Bullet.physicsBody = SKPhysicsBody(rectangleOfSize: Bullet.size)
Bullet.physicsBody?.categoryBitMask = PhysicsCategory.Bullet
Bullet.physicsBody?.contactTestBitMask = PhysicsCategory.Enemy
Bullet.physicsBody?.affectedByGravity = false
Bullet.physicsBody?.dynamic = false
self.addChild(Bullet)
}
func SpawnEnemies () {
var Enemy = SKSpriteNode (imageNamed: "bad.png")
var MinValue = self.size.width / 8
var MaxValue = self.size.width - 15
var Spawnpoint = UInt32(MaxValue - MinValue)
Enemy.position = CGPointMake(CGFloat(arc4random_uniform(Spawnpoint)), self.size.height)
Enemy.physicsBody = SKPhysicsBody(rectangleOfSize:Enemy.size)
Enemy.physicsBody?.categoryBitMask = PhysicsCategory.Enemy
Enemy.physicsBody?.contactTestBitMask = PhysicsCategory.Bullet
Enemy.physicsBody?.affectedByGravity = false
Enemy.physicsBody?.dynamic = true
let action = SKAction.moveToY(-70, duration: 2.5)
let ActionDone = SKAction.removeFromParent()
Enemy.runAction(SKAction.sequence([action, ActionDone]))
Enemy.runAction(SKAction.repeatActionForever(action))
self.addChild(Enemy)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
Player.position.x = location.x
}
}
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
Player.position.x = location.x
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
And here is the code for the EndScene:
var RestartBtn : UIButton!
var Highscore : Int!
var ScoreLbl : UILabel!
var HighscoreLbl : UILabel!
override func didMoveToView(view: SKView) {
scene?.backgroundColor = UIColor.blackColor()
RestartBtn = UIButton(frame: CGRect(x: 0, y: 0, width: view.frame.size.width / 3, height: 30))
RestartBtn.center = CGPoint(x: view.frame.size.width / 2, y: view.frame.size.width / 7)
RestartBtn.setTitle("Restart", forState: UIControlState.Normal)
RestartBtn.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
RestartBtn.addTarget(self, action: Selector("Restart"), forControlEvents: UIControlEvents.TouchUpInside)
self.view?.addSubview(RestartBtn)
var ScoreDefault = NSUserDefaults.standardUserDefaults()
var Score = ScoreDefault.valueForKey("Score") as! NSInteger
var HighscoreDefault = NSUserDefaults.standardUserDefaults()
Highscore = HighscoreDefault.valueForKey("Highscore") as! NSInteger
ScoreLbl = UILabel(frame: CGRect(x: 0, y: 0, width: view.frame.size.width / 3, height: 30))
ScoreLbl.center = CGPoint(x: view.frame.size.width / 2, y: view.frame.size.width / 4)
ScoreLbl.text = "\(Score)"
self.view?.addSubview(ScoreLbl)
ScoreLbl.textColor = UIColor.whiteColor()
HighscoreLbl = UILabel(frame: CGRect(x: 0, y: 0, width: view.frame.size.width / 3, height: 30))
HighscoreLbl.center = CGPoint(x: view.frame.size.width / 2, y: view.frame.size.width / 2)
HighscoreLbl.text = "\(Highscore)"
self.view?.addSubview(HighscoreLbl)
HighscoreLbl.textColor = UIColor.whiteColor()
}
func Restart(){
self.view?.presentScene(GameScene(), transition: SKTransition.crossFadeWithDuration(0.3))
RestartBtn.removeFromSuperview()
ScoreLbl.removeFromSuperview()
HighscoreLbl.removeFromSuperview()
}
}
Thank you so much to anyone who can help! It means a lot! :)
Related
I'm working on a 2-d Platformer style game. I'm very new to IOS and Swift development. I'm attempting to use a button (a different node) to move my character across the screen from left to right. It works fine until I reach the halfway point then it speeds up dramatically and letting go of the touch of the button doesn't always stop it. Sometimes it requires another touch. Also the background doesn't appear to keep up with the player. Once the player hits mid screen the background should shift as the player continues moving.
I've pieced what I've done together from multiple tutorials SO examples but I'm stuck on this point.
class StoryModeScene: SKScene, SKPhysicsContactDelegate {
var tileMap = JSTileMap(named: "legend1Level1.tmx")
var tileSize:CGSize!
var xPointsToMovePerSecond:CGFloat = 0
var rightMoveButton = SKSpriteNode(imageNamed: "right-move")
var leftMoveButton = SKSpriteNode(imageNamed: "left-move")
var jumpButton = SKSpriteNode(imageNamed: "a-button")
var fireButton = SKSpriteNode(imageNamed: "b-button")
var forwardMarch:Bool = false
var mightAsWellJump:Bool = false
var onGround:Bool = true
//CREATE THE PLAYER ATLAS FOR ANIMATION
let playerAtlas = SKTextureAtlas(named:"legend1")
var playerSprites = Array<Any>()
var player = SKSpriteNode(imageNamed: "legend1")
var repeatActionPlayer = SKAction()
override func didMove(to view: SKView) {
/* Setup your scene here */
setupScene()
addPlayer()
//PREPARE TO ANIMATE THE PLAYER AND REPEAT THE ANIMATION FOREVER
let animatedPlayer = SKAction.animate(with: self.playerSprites as! [SKTexture], timePerFrame: 0.1)
self.repeatActionPlayer = SKAction.repeatForever(animatedPlayer)
leftMoveButton.position.x = 64
leftMoveButton.position.y = 64
leftMoveButton.name = "moveLeft"
addChild(leftMoveButton)
rightMoveButton.position.x = 124
rightMoveButton.position.y = 64
rightMoveButton.name = "moveRight"
addChild(rightMoveButton)
jumpButton.position.x = 771
jumpButton.position.y = 64
jumpButton.name = "jumpButton"
addChild(jumpButton)
fireButton.position.x = 836
fireButton.position.y = 64
fireButton.name = "fireButton"
addChild(fireButton)
}
override func update(_ currentTime: TimeInterval) {
if (forwardMarch) {
//let moveAction = SKAction.moveBy(x: 3, y: 0, duration: 1)
//let repeatForEver = SKAction.repeatForever(moveAction)
//let seq = SKAction.sequence([moveAction, repeatForEver])
//run the action on your ship
//player.run(seq)
player.position.x = player.position.x + 3
setViewpointCenter(player.position)
}
if (mightAsWellJump) {
let jumpForce = CGPoint(x: 0.0, y: 310.0)
let jumpCutoff: Float = 150.0
if mightAsWellJump && onGround {
player.physicsBody!.velocity = CGVector(dx: player.physicsBody!.velocity.dx + jumpForce.x, dy: player.physicsBody!.velocity.dy + jumpForce.y)
onGround = false
} else if !mightAsWellJump && player.physicsBody!.velocity.dy > CGFloat(jumpCutoff) {
player.physicsBody!.velocity = CGVector(dx: player.physicsBody!.velocity.dx, dy: CGFloat(jumpCutoff))
}
player.position = CGPoint(x: player.position.x, y: player.position.y + 5);
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches) {
let positionInScene = touch.location(in: self)
let touchedNode = self.atPoint(positionInScene)
if let name = touchedNode.name {
if name == "jumpButton" {
mightAsWellJump = true
player.texture = SKTexture(imageNamed: "legend1_jump")
}
if name == "moveRight" {
forwardMarch = true
self.player.run(repeatActionPlayer)
}
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first!
if rightMoveButton.contains(touch.location(in: self)) {
forwardMarch = false
player.removeAllActions()
player.texture = SKTexture(imageNamed: "legend1")
}
if jumpButton.contains(touch.location(in: self)) {
mightAsWellJump = false
player.removeAllActions()
player.texture = SKTexture(imageNamed: "legend1")
}
}
func setViewpointCenter(_ position: CGPoint) {
var x = max(position.x, size.width / 2)
var y = max(position.y, size.height / 2)
x = min(x, (tileMap!.mapSize.width * tileMap!.tileSize.width) - size.width / 2)
y = min(y, (tileMap!.mapSize.height * tileMap!.tileSize.height) - size.height / 2)
let actualPosition = CGPoint(x: CGFloat(x), y: CGFloat(y))
let centerOfView = CGPoint(x: size.width / 2, y: size.height / 2)
let viewPoint = CGPoint(x: (centerOfView.x - actualPosition.x) * 3, y: centerOfView.y - actualPosition.y)
tileMap!.position = viewPoint
}
func setupScene() {
playerSprites.append(playerAtlas.textureNamed("legend1_0"))
playerSprites.append(playerAtlas.textureNamed("legend1_1"))
playerSprites.append(playerAtlas.textureNamed("legend1_2"))
playerSprites.append(playerAtlas.textureNamed("legend1_3"))
playerSprites.append(playerAtlas.textureNamed("legend1_4"))
playerSprites.append(playerAtlas.textureNamed("legend1_5"))
backgroundColor = UIColor(red: 165.0/255.0, green: 216.0/255.0, blue: 255.0/255.0, alpha: 1.0)
physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
anchorPoint = CGPoint(x: 0, y: 0)
position = CGPoint(x: 0, y: 0)
let point = tileMap!.calculateAccumulatedFrame()
print (point)
tileMap!.position = CGPoint(x: 0, y: 0)
addChild(tileMap!)
addFloor()
}
func addFloor() {
for a in 0..<Int(tileMap!.mapSize.width) {
for b in 0..<Int(tileMap!.mapSize.height) {
let layerInfo:TMXLayerInfo = tileMap!.layers.firstObject as! TMXLayerInfo
let point = CGPoint(x: a, y: b)
let walls = tileMap!.layerNamed("Walls")
let wallInfo:TMXLayerInfo = walls!.layerInfo
let wallGIDs = wallInfo.layer.tileGid(at: wallInfo.layer.point(forCoord: point))
if wallGIDs > 0 {
//print (wallGIDs)
//let node = walls
let node = wallInfo.layer.tile(atCoord: point)
node!.physicsBody = SKPhysicsBody(rectangleOf: node!.size)
node!.physicsBody?.isDynamic = false
}
}
}
}
func addPlayer() {
tileSize = tileMap?.tileSize
player.position = CGPoint(x: tileSize.width + player.size.width/2, y: tileSize.height + player.size.height*8)
let rect = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 50, height: 95))
player.physicsBody = SKPhysicsBody(rectangleOf: rect.size)
player.physicsBody!.velocity = CGVector(dx: 0.0, dy: 0.0)
player.physicsBody!.isDynamic = true
player.physicsBody!.restitution = 0
player.physicsBody!.allowsRotation = false
player.physicsBody!.friction = 1.0
addChild(player)
}
}
Holding the rightMoveButton should move at a consistent pace to the right. As the player gets to mid screen the view point of the background should shift until it reaches the end of the background at which point the player can move off screen and complete the level. Releasing the button should allow the player to stop.
You can move the scene as the character moves by creating an SKCameraNode. You then can choose when to move the camera to create the right affect. Make sure to set the camera as your game’s camera. You can learn about cameras here. As for the speeding up, I assume it has something to do with your physicsBody. If you’re interested about player movement, you could look here or here. There are many other great videos and sites online, which you could find by searching “SpriteKit player movement.”
Eli Front's answer pointed me in the right direction. I still have some issues with this code but the answer to my question was using SKCamera node as Eli pointed out. I just wanted to post the code that works so if anyone has a similar question there's a code example as far as camera moving with the player. The speed issue was essentially an optical illusion with the background moving too fast.
Note that the controls are children of the camera. That is so they move with the camera as well otherwise as your node moves the controls would move off screen.
import UIKit
import SpriteKit
import GameKit
class StoryModeScene: SKScene, SKPhysicsContactDelegate {
var tileMap = JSTileMap(named: "legend1Level1.tmx")
var tileSize:CGSize!
var xPointsToMovePerSecond:CGFloat = 0
var rightMoveButton = SKSpriteNode(imageNamed: "right-move")
var leftMoveButton = SKSpriteNode(imageNamed: "left-move")
var jumpButton = SKSpriteNode(imageNamed: "a-button")
var fireButton = SKSpriteNode(imageNamed: "b-button")
var forwardMarch:Bool = false
var mightAsWellJump:Bool = false
var onGround:Bool = true
//CREATE THE Player ATLAS FOR ANIMATION
let playerAtlas = SKTextureAtlas(named:"legend1")
var playerSprites = Array<Any>()
var player = SKSpriteNode(imageNamed: "legend1")
var repeatActionPlayer = SKAction()
let cam = SKCameraNode()
var previousUpdateTime: TimeInterval = 0
override func didMove(to view: SKView) {
// SETUP CAMERA
self.camera = cam
scene?.addChild(cam)
cam.position.x = 448
cam.position.y = 212
setupScene()
addPlayer()
//PREPARE TO ANIMATE THE PLAYER AND REPEAT THE ANIMATION FOREVER
let animatedPlayer = SKAction.animate(with: self.playerSprites as! [SKTexture], timePerFrame: 0.1)
self.repeatActionPlayer = SKAction.repeatForever(animatedPlayer)
// SETUP CONTROLS
leftMoveButton.position.x = -338
leftMoveButton.position.y = -112
leftMoveButton.name = "moveLeft"
leftMoveButton.zPosition = 5
cam.addChild(leftMoveButton)
rightMoveButton.position.x = -278
rightMoveButton.position.y = -112
rightMoveButton.name = "moveRight"
cam.addChild(rightMoveButton)
jumpButton.position.x = 278
jumpButton.position.y = -112
jumpButton.name = "jumpButton"
jumpButton.zPosition = 5
cam.addChild(jumpButton)
fireButton.position.x = 338
fireButton.position.y = -112
fireButton.name = "fireButton"
cam.addChild(fireButton)
}
override func update(_ currentTime: TimeInterval) {
if (forwardMarch) {
if player.position.x > 448 && player.position.x < 1800 {
cam.position.x = player.position.x
} else if player.position.x >= 1800 {
cam.position.x = 1800
}
setViewpointCenter(player.position)
player.position.x = player.position.x + 3
}
if (mightAsWellJump) {
let jumpForce = CGPoint(x: 0.0, y: 310.0)
let jumpCutoff: Float = 150.0
if mightAsWellJump && onGround {
player.physicsBody!.velocity = CGVector(dx: player.physicsBody!.velocity.dx + jumpForce.x, dy: player.physicsBody!.velocity.dy + jumpForce.y)
onGround = false
} else if !mightAsWellJump && player.physicsBody!.velocity.dy > CGFloat(jumpCutoff) {
player.physicsBody!.velocity = CGVector(dx: player.physicsBody!.velocity.dx, dy: CGFloat(jumpCutoff))
}
player.position = CGPoint(x: player.position.x, y: player.position.y + 5);
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches) {
let positionInScene = touch.location(in: self)
let touchedNode = self.atPoint(positionInScene)
if let name = touchedNode.name {
if name == "jumpButton" {
mightAsWellJump = true
player.texture = SKTexture(imageNamed: "legend1_jump")
}
if name == "moveRight" {
player.physicsBody!.velocity.dy = 0.0
forwardMarch = true
self.player.run(repeatActionPlayer)
}
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches) {
let positionInScene = touch.location(in: self)
let touchedNode = self.atPoint(positionInScene)
if let name = touchedNode.name {
if name == "jumpButton" {
mightAsWellJump = false
player.removeAllActions()
player.texture = SKTexture(imageNamed: "legend1")
player.physicsBody!.velocity = CGVector(dx: 0.0, dy: 0.0)
}
if name == "moveRight" {
player.removeAllActions()
player.texture = SKTexture(imageNamed: "legend1")
forwardMarch = false
}
}
}
}
func setViewpointCenter(_ position: CGPoint) {
var x = max(position.x, size.width / 2)
var y = max(position.y, size.height / 2)
x = min(x, (tileMap!.mapSize.width * tileMap!.tileSize.width) - size.width / 2)
y = min(y, (tileMap!.mapSize.height * tileMap!.tileSize.height) - size.height / 2)
let actualPosition = CGPoint(x: CGFloat(x), y: CGFloat(y))
let centerOfView = CGPoint(x: size.width / 2, y: size.height / 2)
let viewPoint = CGPoint(x: centerOfView.x - actualPosition.x, y: centerOfView.y - actualPosition.y)
if (actualPosition.x > 1800) {
tileMap!.position = tileMap!.position
} else {
tileMap!.position = viewPoint
}
}
func setupScene() {
// ADD PLAYER SPRITES #TODO MAKE THIS DYNAMIC
playerSprites.append(playerAtlas.textureNamed("legend1_0"))
playerSprites.append(playerAtlas.textureNamed("legend1_1"))
playerSprites.append(playerAtlas.textureNamed("legend1_2"))
playerSprites.append(playerAtlas.textureNamed("legend1_3"))
playerSprites.append(playerAtlas.textureNamed("legend1_4"))
playerSprites.append(playerAtlas.textureNamed("legend1_5"))
backgroundColor = UIColor(red: 165.0/255.0, green: 216.0/255.0, blue: 255.0/255.0, alpha: 1.0)
anchorPoint = CGPoint(x: 0, y: 0)
position = CGPoint(x: 0, y: 0)
// let point = tileMap!.calculateAccumulatedFrame()
tileMap!.position = CGPoint(x: 0, y: 0)
addChild(tileMap!)
addFloor()
}
func addFloor() {
for a in 0..<Int(tileMap!.mapSize.width) {
for b in 0..<Int(tileMap!.mapSize.height) {
// let layerInfo:TMXLayerInfo = tileMap!.layers.firstObject as! TMXLayerInfo
let point = CGPoint(x: a, y: b)
let walls = tileMap!.layerNamed("Walls")
let wallInfo:TMXLayerInfo = walls!.layerInfo
let wallGIDs = wallInfo.layer.tileGid(at: wallInfo.layer.point(forCoord: point))
if wallGIDs > 0 {
let node = wallInfo.layer.tile(atCoord: point)
node!.physicsBody = SKPhysicsBody(rectangleOf: node!.size)
node!.physicsBody?.isDynamic = false
}
}
}
}
func addPlayer() {
tileSize = tileMap?.tileSize
player.position = CGPoint(x: tileSize.width + player.size.width/2, y: tileSize.height + player.size.height*8)
let rect = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: 50, height: 95))
player.physicsBody = SKPhysicsBody(rectangleOf: rect.size)
player.physicsBody!.velocity = CGVector(dx: 0.0, dy: 0.0)
player.physicsBody!.isDynamic = true
player.physicsBody!.restitution = 0
player.physicsBody!.allowsRotation = false
player.physicsBody!.friction = 1.0
player.physicsBody!.mass = 1.0
addChild(player)
}
}
As I mentioned I still have some issues like the player node floating/flying when I jump/run at the same time. The 1st jump is the correct height and all subsequent jumps are smaller etc but I'm working on figuring those out.
he problem is that when the player collides with the enemy the health of the enemy in healthBar does not decrease the indicated amount. it simply decreases in its entirety
I can not find a way to update the enemy's healthbar in the func update and try the func didBegin (_ contact: SKPhysicsContact)
enter code here
func initZombie(){
let enemy = Enemigo(imageNamed: "zombie1")
var textures:[SKTexture] = []
for i in 1...2 {
textures.append(SKTexture(imageNamed: "zombie\(i)"))
}
let anima:SKAction = SKAction.animate(with: textures, timePerFrame: 15.0)
enemy.run(SKAction.group([
SKAction.repeatForever(anima),
SKAction.speed(to: 60.0, duration: 0)
]),withKey: "animation")
enemy.healt = 300
enemy.exp = 100
enemy.barraEnemy = SKSpriteNode(color: SKColor.green, size: enemy.barravidaSizeE)
enemy.barraEnemyBack = SKSpriteNode(color: SKColor.red, size: CGSize(width: enemy.barravidaSizeE.width + 300, height: enemy.barravidaSizeE.height + 30))
enemy.barraEnemy.position = CGPoint(x: enemy.position.x , y: enemy.position.y - 150)
enemy.barraEnemy.zPosition = 101
enemy.barraEnemy.anchorPoint = CGPoint(x: 0.0 , y: 0.5)
enemy.addChild(enemy.barraEnemy)
enemy.barraEnemyBack.position = CGPoint(x: enemy.position.x , y: enemy.position.y - 150)
enemy.barraEnemyBack.zPosition = 100
enemy.barraEnemyBack.anchorPoint = CGPoint(x: 0.0, y: 0.5)
enemy.addChild(enemy.barraEnemyBack)
enemy.barraEnemy.size = CGSize(width: enemy.barravidaSizeE.width + CGFloat(enemy.healt) , height: enemy.barravidaSizeE.height + 30)
enemy.zPosition = 100
//enemy.position = CGPoint(x: size.width/2, y: size.height/2)
enemy.position = CGPoint(x:random(min: -1100 , max: 1100), y: random(min: -400 , max: 400))
enemy.name = "zombie"
enemy.setScale(0.4)
addChild(enemy)
enemy.physicsBody = SKPhysicsBody.init(rectangleOf: enemy.size)
enemy.physicsBody?.allowsRotation = true
enemy.physicsBody?.affectedByGravity = false
enemy.physicsBody?.categoryBitMask = 3
enemy.physicsBody?.collisionBitMask = 1
enemy.physicsBody?.contactTestBitMask = 1
enemy.physicsBody?.isDynamic = true
}
enter
code
here
func didBegin(_ 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
}
if firstBody.categoryBitMask == 1 && secondBody.categoryBitMask == 2 {
life += 100
secondBody.node?.removeFromParent()
}
if firstBody.categoryBitMask == 1 && secondBody.categoryBitMask == 3 {
score += 1
if let myEnemy = secondBody.node as? Enemigo {
myEnemy.healt -= playerAtack
life -= zombieAtack
myEnemy.barraEnemy.size = CGSize(width: myEnemy.barravidaSizeE.width + CGFloat(myEnemy.healt), height: myEnemy.barravidaSizeE.height)
print(myEnemy.healt)
if myEnemy.healt <= 0 {
playerAtack += 10
life += 100
spawnItem(point: secondBody.node!.position)
secondBody.node?.removeFromParent()
}
}
}
}
I have a sprite node which moves left to right with user touch.
However currently it will exit the screen, I want to add a node either side so if the sprite node touches the node on either side it hugs it and remains there until user touch to make it travel the opposite direction.
This is what I thought of doing but it isn't working currently.
let shipTexture = SKTexture(imageNamed: "ship.png")
ship = SKSpriteNode(texture: shipTexture)
ship.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
ship.zPosition = 3
ship.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 30, height: 100))
ship.physicsBody!.isDynamic = true
ship.physicsBody?.collisionBitMask = 0b1
ship.physicsBody?.contactTestBitMask = 0b1
ship.physicsBody!.collisionBitMask = 0b1
ship.physicsBody?.affectedByGravity = false
self.addChild(ship)
let side = SKNode()
side.position = CGPoint(x: self.frame.width / 2, y: self.frame.midY)
side.physicsBody = SKPhysicsBody(edgeLoopFrom: CGRect(x: -240, y: -160, width: 480, height: 320))
side.physicsBody!.isDynamic = false
side.physicsBody?.collisionBitMask = 0b1
side.physicsBody?.contactTestBitMask = 0b1
side.physicsBody!.collisionBitMask = 0b1
self.addChild(side)
func didBegin(_ contact: SKPhysicsContact) {
print("Collision")
}
}
//var moveLeft = SKAction.moveBy(x: 800, y: 0, duration: 2)
//frame.size.width
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
ship.removeAllActions()
switch direction ?? .left {
case .left:
ship.run(SKAction.moveBy(x: -frame.size.width, y: 0, duration: 3))
case .right:
ship.run(SKAction.moveBy(x: frame.size.width, y: 0, duration: 3))
}
direction = direction == nil || direction == .right ? .left : .right
}
I got it. The reason is - you use action to move your node, but should use physics - force and impulse
Try this one:
import SpriteKit
import GameplayKit
var ship = SKSpriteNode()
var bg = SKSpriteNode()
class GameScene: SKScene, SKPhysicsContactDelegate {
override func didMove(to view: SKView) {
let bgTexture = SKTexture(imageNamed: "bg.png")
let moveBGanimation = SKAction.move(by: CGVector(dx: 0, dy: -bgTexture.size().height), duration: 4)
let shiftBGAnimation = SKAction.move(by: CGVector(dx: 0, dy: bgTexture.size().height), duration: 0)
let moveBGForever = SKAction.repeatForever(SKAction.sequence([moveBGanimation, shiftBGAnimation]))
var i: CGFloat = 0
while i < 3 {
bg = SKSpriteNode(texture: bgTexture)
bg.position = CGPoint(x: self.frame.midX, y: bgTexture.size().height * i)
bg.size.width = self.frame.width
bg.run(moveBGForever)
self.addChild(bg)
i += 1
}
let shipTexture = SKTexture(imageNamed: "ship.png")
ship = SKSpriteNode(texture: shipTexture)
ship.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
ship.zPosition = 3
ship.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 30, height: 100))
ship.physicsBody!.isDynamic = true
ship.physicsBody?.collisionBitMask = 0b1
ship.physicsBody?.contactTestBitMask = 0b1
ship.physicsBody!.categoryBitMask = 0b1
ship.physicsBody?.affectedByGravity = false
self.addChild(ship)
let side = SKNode()
side.position = CGPoint(x: 0, y: 0)
side.physicsBody = SKPhysicsBody(edgeLoopFrom: CGRect(x: -self.frame.width/2, y: -self.frame.height/2, width: self.frame.width, height: self.frame.height))
side.physicsBody!.isDynamic = false
side.physicsBody?.collisionBitMask = 0b1
side.physicsBody?.contactTestBitMask = 0b1
side.physicsBody!.categoryBitMask = 0b1
self.addChild(side)
self.physicsWorld.contactDelegate = self
func didBegin(_ contact: SKPhysicsContact) {
print("Collision")
}
}
//var moveLeft = SKAction.moveBy(x: 800, y: 0, duration: 2)
//frame.size.width
enum Direction: Int {
case left = 0
case right
}
var direction: Direction?
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
ship.removeAllActions()
switch direction ?? .left {
case .left:
ship.physicsBody?.applyImpulse(CGVector(dx: -20, dy: 0))
//ship.run(SKAction.moveBy(x: -frame.size.width, y: 0, duration: 3))
case .right:
ship.physicsBody?.applyImpulse(CGVector(dx: 20, dy: 0))
//ship.run(SKAction.moveBy(x: frame.size.width, y: 0, duration: 3))
}
direction = direction == nil || direction == .right ? .left : .right
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func update(_ currentTime: TimeInterval) {
}
}
I am trying to delete an object (an orb node) when the character comes into contact but it just acts like a circle and the character falls off when it gets on top. I deleted the code for the collision detection because I have no idea if it is right.
Here is my code for GameScene.swift:
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
override init(size:CGSize){
super.init(size:size)
let CollisionCategoryPlayer
: UInt32 = 0x1 << 1
let CollisionCategoryPowerUpOrbs
: UInt32 = 0x1 << 2
character.physicsBody?.categoryBitMask = CollisionCategoryPlayer
character.physicsBody?.contactTestBitMask = CollisionCategoryPowerUpOrbs
character.physicsBody?.collisionBitMask = 0
orbNode.physicsBody?.categoryBitMask = CollisionCategoryPowerUpOrbs
orbNode.physicsBody?.collisionBitMask = 0
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
//variables
let character = SKSpriteNode(imageNamed:"square_red.png")
let floor = SKSpriteNode(imageNamed: "platform.jpg")
let platform1 = SKSpriteNode(imageNamed: "platform2.png")
let platform2 = SKSpriteNode(imageNamed: "platform2.png")
let orbNode = SKSpriteNode(imageNamed: "PowerUp.png")
var characterSize:CGFloat = 0.2
var foodCount = 0
override func didMoveToView(view: SKView) {
//World Physics
self.physicsWorld.gravity = CGVectorMake(0.0, -5.0)
self.physicsWorld.contactDelegate = self
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
//Character
character.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
character.setScale(characterSize)
character.physicsBody = SKPhysicsBody(rectangleOfSize: character.size)
character.physicsBody?.allowsRotation = false
self.addChild(character)
//floor
floor.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)*0.2)
floor.setScale(2.0)
floor.physicsBody = SKPhysicsBody(rectangleOfSize: floor.size)
floor.physicsBody?.dynamic = false
self.addChild(floor)
//platform one
platform1.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)*0.7)
platform1.setScale(0.4)
platform1.physicsBody = SKPhysicsBody(rectangleOfSize: platform1.size)
platform1.physicsBody?.dynamic = false
self.addChild(platform1)
//platform two
platform2.position = CGPoint(x: CGRectGetMidX(self.frame)*1.4, y: CGRectGetMidY(self.frame)*1)
platform2.setScale(0.4)
platform2.physicsBody = SKPhysicsBody(rectangleOfSize: platform2.size)
platform2.physicsBody?.dynamic = false
self.addChild(platform2)
//orbNode
orbNode.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
orbNode.setScale(0.2)
self.addChild(orbNode)
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
character.removeActionForKey("moveAction")
character.removeActionForKey("shrink")
character.removeActionForKey("rotate")
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch:AnyObject in touches {
let location = touch.locationInNode(self)
if location.x < CGRectGetMidX(self.frame) && location.y < CGRectGetMidY(self.frame)*0.7{
//shrinks with each movement
characterSize-=0.005
let moveAction = SKAction.repeatActionForever(SKAction.moveByX(-30, y: 0, duration: 0.1))
let shrink = SKAction.repeatActionForever(SKAction.scaleTo(characterSize, duration: 0.1))
character.runAction(moveAction, withKey: "moveAction")
character.runAction(shrink, withKey: "shrink")
} else if location.x > CGRectGetMidX(self.frame) && location.y < CGRectGetMidY(self.frame)*0.7{
//shrinks with each movement
characterSize-=0.005
let moveAction = SKAction.repeatActionForever(SKAction.moveByX(30, y: 0, duration: 0.1))
let shrink = SKAction.repeatActionForever(SKAction.scaleTo(characterSize, duration: 0.1))
character.runAction(moveAction, withKey: "moveAction")
character.runAction(shrink, withKey: "shrink")
} else if location.y > character.position.y + 15 {
//shrinks with each movement
characterSize-=0.005
character.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 50))
let shrink = SKAction.repeatActionForever(SKAction.scaleTo(characterSize, duration: 0.1))
character.runAction(shrink, withKey: "shrink")
}
}
func didBeginContact(contact: SKPhysicsContact){
}
func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
}
You should group your physics body, you code seems to be all over the place. Also the reason you get the error is because you are settings the physics body before setting the player and missing some for the Orbs.
Here is your same code rewritten and I think a bit more readable and understandable.
import SpriteKit
/// Physics category
struct PhysicsCategory {
static let player: UInt32 = 0x1 << 0
static let orb: UInt32 = 0x1 << 1
static let floor: UInt32 = 0x1 << 2
static let platform: UInt32 = 0x1 << 3
}
/// Image names
struct ImageName {
static let platform1 = "platform2.png"
static let platform2 = "platform2.png"
// can do this for other images as well, but because you create loads of platforms its nice to have a refernce like this
}
/// Always put your keys for removing actions etc into structs to avoid typos
struct Key {
static let moveAction = "moveAction"
static let shrink = "shrink"
static let rotate = "rotate"
}
/// GameScene
class GameScene: SKScene, SKPhysicsContactDelegate {
//variables
let character = SKSpriteNode(imageNamed:"square_red.png")
let floor = SKSpriteNode(imageNamed: "platform.jpg")
var platform1 = SKSpriteNode()
var platform2 = SKSpriteNode()
let orbNode = SKSpriteNode(imageNamed: "PowerUp.png")
var characterSize:CGFloat = 0.2
var foodCount = 0
//didMoveToView
override func didMoveToView(view: SKView) {
//World Physics
self.physicsWorld.gravity = CGVectorMake(0.0, -5.0)
self.physicsWorld.contactDelegate = self
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
//Character
character.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
character.setScale(characterSize)
character.physicsBody = SKPhysicsBody(rectangleOfSize: character.size)
character.physicsBody?.allowsRotation = false
character.physicsBody?.dynamic = true // must be true for collision to fire
character.physicsBody?.affectedByGravity = false
character.physicsBody?.categoryBitMask = PhysicsCategory.player
character.physicsBody?.contactTestBitMask = PhysicsCategory.orb
character.physicsBody?.collisionBitMask = PhysicsCategory.floor | PhysicsCategory.platform
self.addChild(character)
//floor
floor.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)*0.2)
floor.setScale(2.0)
floor.physicsBody = SKPhysicsBody(rectangleOfSize: floor.size)
floor.physicsBody?.dynamic = false
floor.physicsBody?.affectedByGravity = false
floor.physicsBody?.categoryBitMask = PhysicsCategory.floor
///floor.physicsBody?.contactTestBitMask = not needed for now as character is set
///floor.physicsBody?.collisionBitMask = not needed for now as character is set
self.addChild(floor)
//platform one
platform1 = createPlatform(ImageName.platform1)
platform1.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)*0.7)
platform1.setScale(0.4)
self.addChild(platform1)
//platform two
platform2 = createPlatform(ImageName.platform2)
platform2.position = CGPoint(x: CGRectGetMidX(self.frame)*1.4, y: CGRectGetMidY(self.frame)*1)
platform2.setScale(0.4)
self.addChild(platform2)
//orbNode
orbNode.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
orbNode.setScale(0.2)
orbNode.physicsBody = SKPhysicsBody(rectangleOfSize: character.size)
orbNode.physicsBody?.allowsRotation = false
orbNode.physicsBody?.dynamic = false
orbNode.physicsBody?.affectedByGravity = false
orbNode.physicsBody?.categoryBitMask = PhysicsCategory.orb
//orbNode.physicsBody?.contactTestBitMask = // not needed for now because pla
orbNode.physicsBody?.collisionBitMask = PhysicsCategory.platform //
self.addChild(orbNode)
}
/// Create platform (this way you can crate multiple platforms and save yourself tones of code)
func createPlatform(imageNamed: String) -> SKSpriteNode {
let platform = SKSpriteNode(imageNamed: imageNamed)
platform.physicsBody = SKPhysicsBody(rectangleOfSize: platform.size)
platform.physicsBody?.dynamic = false
platform.physicsBody?.affectedByGravity = false
platform.physicsBody?.categoryBitMask = PhysicsCategory.platform
//platform.physicsBody?.contactTestBitMask = /// not needed unless you want didBeginContact
platform.physicsBody?.collisionBitMask = 0 /// Not needed if you tell character to collide with it
return platform
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
character.removeActionForKey(Key.moveAction)
character.removeActionForKey(Key.shrink)
character.removeActionForKey(Key.rotate)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
if location.x < CGRectGetMidX(self.frame) && location.y < CGRectGetMidY(self.frame)*0.7{
//shrinks with each movement
characterSize-=0.005
let moveAction = SKAction.repeatActionForever(SKAction.moveByX(-30, y: 0, duration: 0.1))
let shrink = SKAction.repeatActionForever(SKAction.scaleTo(characterSize, duration: 0.1))
character.runAction(moveAction, withKey: Key.moveAction)
character.runAction(shrink, withKey: Key.shrink)
} else if location.x > CGRectGetMidX(self.frame) && location.y < CGRectGetMidY(self.frame)*0.7{
//shrinks with each movement
characterSize-=0.005
let moveAction = SKAction.repeatActionForever(SKAction.moveByX(30, y: 0, duration: 0.1))
let shrink = SKAction.repeatActionForever(SKAction.scaleTo(characterSize, duration: 0.1))
character.runAction(moveAction, withKey: Key.moveAction)
character.runAction(shrink, withKey: Key.shrink)
} else if location.y > character.position.y + 15 {
//shrinks with each movement
characterSize-=0.005
character.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 50))
let shrink = SKAction.repeatActionForever(SKAction.scaleTo(characterSize, duration: 0.1))
character.runAction(shrink, withKey: Key.shrink)
}
}
}
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
}
/// Player with Orb
if (firstBody.categoryBitMask == PhysicsCategory.player) && (secondBody.categoryBitMask == PhysicsCategory.orb) {
///Player hit orb, remove Orb
secondBody.node?.removeFromParent()
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
I learn how to create games on iOS. And now I create a Flappy bird clone.
Flappy Bird Clone
And I'm stack on that - when bird touch some pipe it begin rotate. And game of course is over. But when I start a new game Bird still rotates.
If I put this line
bird.physicsBody?.allowsRotation = false
in the GameScene.swift then bird stop rotate at all. That is not what I want. I want to allow rotation. But when start a new game Bird should be in default position and do not rotate.
What should I do to make it work? Thanks for help.
//
// GameScene.swift
// Flappy Bird
//
// Created by Admin on 10.10.15.
// Copyright (c) 2015 Alex. All rights reserved.
//
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var score = 0
var gameOver = false
var gameOverLabel = SKLabelNode()
var scoreLabel = SKLabelNode ()
var bird = SKSpriteNode()
var bg = SKSpriteNode()
var movingObjects = SKSpriteNode()
var labelContainer = SKSpriteNode()
var pipe1 = SKSpriteNode()
var pipe2 = SKSpriteNode()
enum ColliderType: UInt32 {
case Bird = 1
case Object = 2
case Gap = 4
}
func makeBg () {
let bgTexture = SKTexture(imageNamed: "bg.png")
let movebg = SKAction.moveByX(-bgTexture.size().width, y: 0, duration: 10)
let replacebg = SKAction.moveByX(bgTexture.size().width, y: 0, duration: 0)
let movebgForever = SKAction.repeatActionForever(SKAction.sequence([movebg,replacebg]))
for var i: CGFloat = 0; i<2; i++ {
bg = SKSpriteNode(texture: bgTexture)
bg.position = CGPoint(x: bgTexture.size().width / 2 + bgTexture.size().width * i, y: CGRectGetMidY(self.frame))
bg.zPosition = -5
bg.size.height = self.frame.height
bg.runAction(movebgForever)
movingObjects.addChild(bg)
}
}
override func didMoveToView(view: SKView) {
self.physicsWorld.contactDelegate = self
self.addChild(movingObjects)
self.addChild(labelContainer)
makeBg()
scoreLabel.fontName = "Helvetica"
scoreLabel.fontSize = 60
scoreLabel.text = "0"
scoreLabel.position = CGPointMake(CGRectGetMidX(self.frame), self.frame.size.height - 70)
addChild(scoreLabel)
let birdTexture = SKTexture(imageNamed: "flappy1.png")
let birdTexture2 = SKTexture(imageNamed: "flappy2.png")
let animation = SKAction.animateWithTextures([birdTexture,birdTexture2], timePerFrame: 0.1)
let makeBirdFlap = SKAction.repeatActionForever(animation)
bird = SKSpriteNode(texture: birdTexture)
bird.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
bird.runAction(makeBirdFlap)
bird.physicsBody = SKPhysicsBody(circleOfRadius: birdTexture.size().height/2)
bird.physicsBody!.dynamic = true
bird.physicsBody!.categoryBitMask = ColliderType.Bird.rawValue
bird.physicsBody?.contactTestBitMask = ColliderType.Object.rawValue
bird.physicsBody?.collisionBitMask = ColliderType.Object.rawValue
self.addChild(bird)
var ground = SKNode()
ground.position = CGPointMake(0, 0)
ground.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.size.width, 1))
ground.physicsBody!.dynamic = false
ground.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
ground.physicsBody?.contactTestBitMask = ColliderType.Object.rawValue
ground.physicsBody?.collisionBitMask = ColliderType.Object.rawValue
self.addChild(ground)
_ = NSTimer.scheduledTimerWithTimeInterval(3, target: self, selector: Selector("makePipes"), userInfo: nil, repeats: true)
}
func makePipes () {
let gapHeight = bird.size.height * 4
let movementAmount = arc4random() % UInt32(self.frame.size.height / 2)
let pipeOffset = CGFloat(movementAmount) - self.frame.size.height / 4
let movePipes = SKAction.moveByX(-self.frame.size.width * 2, y: 0, duration: NSTimeInterval (self.frame.size.width / 100))
let removePipes = SKAction.removeFromParent()
let moveAndRemovePipes = SKAction.sequence([movePipes,removePipes])
let pipeTexture1 = SKTexture(imageNamed: "pipe1.png")
let pipe1 = SKSpriteNode(texture: pipeTexture1)
pipe1.position = CGPoint(x: CGRectGetMidX(self.frame) + self.frame.size.width, y: CGRectGetMidY(self.frame) + pipeTexture1.size().height/2 + gapHeight/2 + pipeOffset)
pipe1.runAction(moveAndRemovePipes)
pipe1.physicsBody = SKPhysicsBody(rectangleOfSize: pipeTexture1.size())
pipe1.physicsBody?.dynamic = false
pipe1.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
pipe1.physicsBody?.contactTestBitMask = ColliderType.Object.rawValue
pipe1.physicsBody?.collisionBitMask = ColliderType.Object.rawValue
movingObjects.addChild(pipe1)
let pipeTexture2 = SKTexture(imageNamed: "pipe2.png")
let pipe2 = SKSpriteNode(texture: pipeTexture2)
pipe2.position = CGPoint(x: CGRectGetMidX(self.frame) + self.frame.size.width, y: CGRectGetMidY(self.frame) - pipeTexture2.size().height/2 - gapHeight/2 + pipeOffset)
pipe2.runAction(moveAndRemovePipes)
pipe2.physicsBody = SKPhysicsBody(rectangleOfSize: pipeTexture2.size())
pipe2.physicsBody!.dynamic = false
pipe2.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
pipe2.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
pipe2.physicsBody!.collisionBitMask = ColliderType.Object.rawValue
movingObjects.addChild(pipe2)
var gap = SKNode()
gap.position = CGPoint(x: CGRectGetMidX(self.frame) + self.frame.size.width, y: CGRectGetMidY(self.frame) + pipeOffset)
gap.runAction(moveAndRemovePipes)
gap.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(pipe1.size.width, gapHeight))
gap.physicsBody?.dynamic = false
gap.physicsBody!.categoryBitMask = ColliderType.Gap.rawValue
gap.physicsBody!.contactTestBitMask = ColliderType.Bird.rawValue
gap.physicsBody!.collisionBitMask = ColliderType.Gap.rawValue
movingObjects.addChild(gap)
}
func didBeginContact(contact: SKPhysicsContact) {
if contact.bodyA.categoryBitMask == ColliderType.Gap.rawValue || contact.bodyB.categoryBitMask == ColliderType.Gap.rawValue {
score++
scoreLabel.text = String(score)
} else {
if gameOver == false {
gameOver = true
self.speed = 0
gameOverLabel.fontName = "Helvetica"
gameOverLabel.fontSize = 30
gameOverLabel.text = "Game is over. Tap to play again."
gameOverLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
labelContainer.addChild(gameOverLabel)
}
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if gameOver == false {
bird.physicsBody!.velocity = CGVectorMake(0, 0)
bird.physicsBody!.applyImpulse(CGVectorMake(0, 50))
} else {
score = 0
scoreLabel.text = "0"
bird.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
bird.physicsBody?.velocity = CGVectorMake(0, 0)
bird.physicsBody!.allowsRotation = false
movingObjects.removeAllChildren()
makeBg()
self.speed = 1
gameOver = false
labelContainer.removeAllChildren()
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
An easy solution is to reset the bird's angular speed and rotation angle. Modify the code in touchesBegan which is invoked when game is over:
bird.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
bird.physicsBody?.velocity = CGVectorMake(0, 0)
bird.physicsBody?.angularVelocity = 0
bird.zRotation = 0