The enemy's healthbar decreases in its entirety with a single collision - ios

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()
}
}
}
}

Related

Sprite Kit how to apply boundaries

I am currently new for sprite kit and I am very confused my player goes all the way right outside of the frame, however I have included this part of code
let frame = SKPhysicsBody(edgeLoopFrom: self.frame)
frame.friction = 0
frame.restitution = 1
frame.categoryBitMask = bitMask.frame.rawValue
frame.contactTestBitMask = bitMask.player.rawValue
frame.collisionBitMask = bitMask.player.rawValue
self.physicsBody = frame
The full code is bellow
class GameScene : SKScene, SKPhysicsContactDelegate {
let background = SKSpriteNode(imageNamed: "bg")
let player = SKSpriteNode(imageNamed: "PlayerJump")
let ground = SKSpriteNode(imageNamed: "ground")
let gameOverLine = SKSpriteNode(color: .red, size: CGSize(width: 900, height: 10))
let rightBorderLine = SKSpriteNode(color: .red, size: CGSize(width: 10, height: 900))
let scoreLabel = SKLabelNode()
let bestScoreLabel = SKLabelNode()
let defaults = UserDefaults.standard
let cam = SKCameraNode()
let motionManager = CMMotionManager()
var firstTouch = false
var score = 0
var bestScore = 0
var multi: CGFloat = 0.0
enum bitMask: UInt32 {
case player = 0b1
case platform = 0b10
case gameOverLine
case frame
}
override func didMove(to view: SKView) {
self.size = CGSize(width: UIScreen.main.bounds.width * 2, height: UIScreen.main.bounds.height * 2)
self.anchorPoint = .zero
background.position = CGPoint(x: size.width / 2, y: size.height / 2)
background.zPosition = 1
addChild(background)
physicsWorld.contactDelegate = self
ground.position = CGPoint(x: size.width / 2, y: 10)
ground.zPosition = 5
ground.setScale(2.5)
ground.physicsBody = SKPhysicsBody(rectangleOf: ground.size)
ground.physicsBody?.isDynamic = false
ground.physicsBody?.allowsRotation = false
ground.physicsBody?.affectedByGravity = false
addChild(ground)
player.position = CGPoint(x: size.width / 2, y: size.height/8)
player.zPosition = 10
player.setScale(1.8)
player.physicsBody = SKPhysicsBody(circleOfRadius: player.size.height / 2)
player.physicsBody?.isDynamic = false
player.physicsBody?.restitution = 1
player.physicsBody?.friction = 0
player.physicsBody?.angularDamping = 1
player.physicsBody?.categoryBitMask = bitMask.player.rawValue
player.physicsBody?.collisionBitMask = 0
player.physicsBody?.contactTestBitMask = bitMask.platform.rawValue | bitMask.gameOverLine.rawValue
// player.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
addChild(player)
gameOverLine.position = CGPoint(x: player.position.x, y: player.position.y - 240)
gameOverLine.zPosition = -1
gameOverLine.physicsBody = SKPhysicsBody(rectangleOf: gameOverLine.size)
gameOverLine.physicsBody?.affectedByGravity = false
gameOverLine.physicsBody?.allowsRotation = false
gameOverLine.physicsBody?.categoryBitMask = bitMask.gameOverLine.rawValue
gameOverLine.physicsBody?.contactTestBitMask = bitMask.platform.rawValue | bitMask.player.rawValue
addChild(gameOverLine)
scoreLabel.position.x = 125
scoreLabel.zPosition = 20
scoreLabel.fontColor = .black
scoreLabel.fontSize = 32
scoreLabel.fontName = "Helvectica"
scoreLabel.text = "Score: \(score)"
addChild(scoreLabel)
bestScore = defaults.integer(forKey: "best")
bestScoreLabel.position.x = 625
bestScoreLabel.zPosition = 20
bestScoreLabel.fontColor = .black
bestScoreLabel.fontSize = 32
bestScoreLabel.fontName = "Helvectica"
bestScoreLabel.text = "Bestscore: \(bestScore)"
addChild(bestScoreLabel)
makePlatform()
makePlatform2()
makePlatform3()
makePlatform4()
makePlatform5()
makePlatform6()
// if motionManager.isAccelerometerActive == true {
// motionManager.accelerometerUpdateInterval = 20/60
//
// motionManager.startAccelerometerUpdates(to: OperationQueue()) { data, error in
//
// self.multi = Float(data!.acceleration.x) * 10
// self.player.position = CGPoint(x: self.player.position.x + CGFloat(self.multi), y: self.player.position.y)
// }
// }
if motionManager.isAccelerometerAvailable {
motionManager.accelerometerUpdateInterval = 0.10
motionManager.startAccelerometerUpdates(to: .main) {
(data, error) in
guard let data = data, error == nil else {
return
}
let currentX = self.player.position.x
self.multi = currentX + CGFloat(data.acceleration.x * 1300)
}
}
let frame = SKPhysicsBody(edgeLoopFrom: self.frame)
frame.friction = 0
frame.restitution = 1
frame.categoryBitMask = bitMask.frame.rawValue
frame.contactTestBitMask = bitMask.player.rawValue
frame.collisionBitMask = bitMask.player.rawValue
self.physicsBody = frame
cam.setScale(3)
cam.position.x = player.position.x
camera = cam
}
override func update(_ currentTime: TimeInterval) {
cam.position.y = player.position.y + 350
background.position.y = player.position.y
if player.physicsBody!.velocity.dy > 0 {
gameOverLine.position.y = player.position.y - 600
}
scoreLabel.position.y = player.position.y + 1050
bestScoreLabel.position.y = player.position.y + 1050
let action = SKAction.moveTo(x: multi, duration: 1)
player.run(action)
}
func didBegin(_ contact: SKPhysicsContact) {
let contactA: SKPhysicsBody
let contactB: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
contactA = contact.bodyA //Player
contactB = contact.bodyB //Platform
} else {
contactA = contact.bodyB //Player
contactB = contact.bodyA //Platform
}
if contactA.categoryBitMask == bitMask.platform.rawValue && contactB.categoryBitMask == bitMask.gameOverLine.rawValue {
contactA.node?.removeFromParent()
}
if contactA.categoryBitMask == bitMask.player.rawValue && contactB.categoryBitMask == bitMask.platform.rawValue {
if player.physicsBody!.velocity.dy < 0 {
player.physicsBody?.velocity = CGVector(dx: player.physicsBody!.velocity.dx, dy: 1400)
contactB.node?.removeFromParent()
makePlatform5()
makePlatform6()
addScore()
}
}
if contactA.categoryBitMask == bitMask.player.rawValue && contactB.categoryBitMask == bitMask.gameOverLine.rawValue {
gameOver()
}
}
// override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
// for touch in touches {
// let location = touch.location(in: self)
//
// player.position.x = location.x
// }
// }
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
player.physicsBody?.isDynamic = true
if firstTouch == false {
player.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 1800))
}
firstTouch = true
}
func makePlatform() {
let platform = SKSpriteNode(imageNamed: "ground")
platform.position = CGPoint(x: GKRandomDistribution(lowestValue: 70, highestValue: 700).nextInt(), y: GKRandomDistribution(lowestValue: 140, highestValue: 300).nextInt() + Int(player.position.y))
platform.zPosition = 5
platform.setScale(0.30)
platform.physicsBody = SKPhysicsBody(rectangleOf: platform.size)
platform.physicsBody?.isDynamic = false
platform.physicsBody?.allowsRotation = false
platform.physicsBody?.affectedByGravity = false
platform.physicsBody?.categoryBitMask = bitMask.platform.rawValue
platform.physicsBody?.collisionBitMask = 0
platform.physicsBody?.contactTestBitMask = bitMask.player.rawValue
addChild(platform)
}
func makePlatform2() {
let platform = SKSpriteNode(imageNamed: "ground")
platform.position = CGPoint(x: GKRandomDistribution(lowestValue: 70, highestValue: 700).nextInt(), y: GKRandomDistribution(lowestValue: 350, highestValue: 550).nextInt() + Int(player.position.y))
platform.zPosition = 5
platform.setScale(0.30)
platform.physicsBody = SKPhysicsBody(rectangleOf: platform.size)
platform.physicsBody?.isDynamic = false
platform.physicsBody?.allowsRotation = false
platform.physicsBody?.affectedByGravity = false
platform.physicsBody?.categoryBitMask = bitMask.platform.rawValue
platform.physicsBody?.collisionBitMask = 0
platform.physicsBody?.contactTestBitMask = bitMask.player.rawValue
addChild(platform)
}
func makePlatform3() {
let platform = SKSpriteNode(imageNamed: "ground")
platform.position = CGPoint(x: GKRandomDistribution(lowestValue: 70, highestValue: 700).nextInt(), y: GKRandomDistribution(lowestValue: 600, highestValue: 800).nextInt() + Int(player.position.y))
platform.zPosition = 5
platform.setScale(0.30)
platform.physicsBody = SKPhysicsBody(rectangleOf: platform.size)
platform.physicsBody?.isDynamic = false
platform.physicsBody?.allowsRotation = false
platform.physicsBody?.affectedByGravity = false
platform.physicsBody?.categoryBitMask = bitMask.platform.rawValue
platform.physicsBody?.collisionBitMask = 0
platform.physicsBody?.contactTestBitMask = bitMask.player.rawValue
addChild(platform)
}
func makePlatform4() {
let platform = SKSpriteNode(imageNamed: "ground")
platform.position = CGPoint(x: GKRandomDistribution(lowestValue: 70, highestValue: 700).nextInt(), y: GKRandomDistribution(lowestValue: 850, highestValue: 1050).nextInt() + Int(player.position.y))
platform.zPosition = 5
platform.setScale(0.30)
platform.physicsBody = SKPhysicsBody(rectangleOf: platform.size)
platform.physicsBody?.isDynamic = false
platform.physicsBody?.allowsRotation = false
platform.physicsBody?.affectedByGravity = false
platform.physicsBody?.categoryBitMask = bitMask.platform.rawValue
platform.physicsBody?.collisionBitMask = 0
platform.physicsBody?.contactTestBitMask = bitMask.player.rawValue
addChild(platform)
}
func makePlatform5() {
let platform = SKSpriteNode(imageNamed: "ground")
platform.position = CGPoint(x: GKRandomDistribution(lowestValue: 70, highestValue: 700).nextInt(), y: GKRandomDistribution(lowestValue: 1100, highestValue: 1300).nextInt() + Int(player.position.y))
platform.zPosition = 5
platform.setScale(0.30)
platform.physicsBody = SKPhysicsBody(rectangleOf: platform.size)
platform.physicsBody?.isDynamic = false
platform.physicsBody?.allowsRotation = false
platform.physicsBody?.affectedByGravity = false
platform.physicsBody?.categoryBitMask = bitMask.platform.rawValue
platform.physicsBody?.collisionBitMask = 0
platform.physicsBody?.contactTestBitMask = bitMask.player.rawValue
addChild(platform)
}
func makePlatform6() {
let platform = SKSpriteNode(imageNamed: "ground")
platform.position = CGPoint(x: GKRandomDistribution(lowestValue: 70, highestValue: 700).nextInt(), y: GKRandomDistribution(lowestValue: 1350, highestValue: 1550).nextInt() + Int(player.position.y))
platform.zPosition = 5
platform.setScale(0.30)
platform.physicsBody = SKPhysicsBody(rectangleOf: platform.size)
platform.physicsBody?.isDynamic = false
platform.physicsBody?.allowsRotation = false
platform.physicsBody?.affectedByGravity = false
platform.physicsBody?.categoryBitMask = bitMask.platform.rawValue
platform.physicsBody?.collisionBitMask = 0
platform.physicsBody?.contactTestBitMask = bitMask.player.rawValue
addChild(platform)
}
func gameOver() {
let gameOverScene = GameOverScene(size: self.size)
let transition = SKTransition.crossFade(withDuration: 0.5)
view?.presentScene(gameOverScene, transition: transition)
if score > bestScore {
bestScore = score
defaults.set(bestScore, forKey: "best")
}
}
func addScore() {
score += 1
scoreLabel.text = "Score: \(score)"
}
}

How do I make an object bounce off the edges in swift

I am trying to make my 'Enemy' bounce off all the boundaries. For example, when the Enemy collides with the left, right, top and bottom of the screen, it should change direction.
This is my current code:
import SpriteKit
import GameplayKit
struct Physics {
static let Enemy: UInt32 = 0x1 << 1
let BorderCategory : UInt32 = 0x1 << 2
let BottomCategory : UInt32 = 0x1 << 3
let BallCategory : UInt32 = 0x1 << 4
}
class GameScene: SKScene {
var Enemy = SKSpriteNode()
var gameStarted = Bool()
var gameState = "running"
var destX : CGFloat = 0.0
var destY : CGFloat = 0.0
var score = 0
override func didMove(to view: SKView) {
let borderBody = SKPhysicsBody(edgeLoopFrom: self.frame)
borderBody.friction = 0
self.physicsBody = borderBody
let screenSize: CGRect = UIScreen.main().bounds // get the screen size
let screenWidth = screenSize.width //get the width
let screenHeight = screenSize.height //get the height
Enemy = SKSpriteNode(imageNamed: "red2")
Enemy.size = CGSize(width: 60, height: 70)
Enemy.position = (CGPoint(x: self.frame.width / 6 - Enemy.frame.width, y: self.frame.height / 10))
Enemy.physicsBody = SKPhysicsBody(circleOfRadius: Enemy.frame.height / 2)
Enemy.physicsBody?.categoryBitMask = Physics.Enemy
//Enemy.physicsBody?.categoryBitMask = Physics.Ground | Physics.wall
//Enemy.physicsBody?.contactTestBitMask = Physics.Ground | Physics.wall
Enemy.physicsBody?.affectedByGravity = false
Enemy.physicsBody?.isDynamic = true
self.addChild(Enemy)
Enemy.physicsBody?.velocity = CGVector(dx: 50, dy: 50)
if (Enemy.position.x == screenWidth) {
Enemy.physicsBody?.velocity = CGVector(dx: -50, dy: 0) // change direction at edge DOESN'T WORK
}
if(Enemy.position.y == screenHeight){
Enemy.physicsBody?.velocity = CGVector(dx: 0, dy: -50) //change direction at edge DOESN'T WORK
}
}
OK, based on your code I've written a working bouncing sprite. It uses the physics-engine to achieve this, rather than manually changing the direction (which I guess is how you should go about doing this).
override func didMove(to view: SKView) {
let borderBody = SKPhysicsBody(edgeLoopFrom: frame)
borderBody.friction = 0
borderBody.categoryBitMask = Physics.wall
physicsBody = borderBody
let enemy = enemySprite(size: CGSize(width: 60, height: 70), position: CGPoint(x: frame.size.width/2, y: frame.size.height/2))
addChild(enemy)
let force = SKAction.applyForce(CGVector(dx: 300, dy: 300) , duration: 0.1)
enemy.run(force)
}
func enemySprite(size: CGSize, position: CGPoint) -> SKSpriteNode {
let enemy = SKSpriteNode(color: SKColor.red(), size: CGSize(width: 60, height: 80))
enemy.position = CGPoint(x: frame.width/2, y: frame.height/2)
enemy.physicsBody = SKPhysicsBody(circleOfRadius: enemy.frame.height / 2) // A bit silly with circle, but you seem to have an image for this use
enemy.physicsBody?.categoryBitMask = Physics.enemy
enemy.physicsBody?.restitution = 1
enemy.physicsBody?.friction = 0
enemy.physicsBody?.collisionBitMask = Physics.wall
enemy.physicsBody?.affectedByGravity = false
enemy.physicsBody?.angularDamping = 0
enemy.physicsBody?.linearDamping = 0
return enemy
}
A question to consider is also how you set up the scene? Is the scene-size the same as the view-size? Otherwise the scene's physicsBody will not make the ball bounce where you expect it to...
It won't (in most cases) because of your conditions - using equal to operators instead of greater/lower than.
import SpriteKit
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
// Create enemy with physics body attached and add it to the scene
let enemy = SKSpriteNode(color: SKColor.greenColor(), size: CGSize(width: 20, height: 20))
enemy.name = "enemy"
enemy.position = CGPoint(x: size.width / 2, y: size.height / 2)
enemy.physicsBody = SKPhysicsBody(rectangleOfSize: enemy.size)
enemy.physicsBody!.affectedByGravity = false
enemy.physicsBody!.linearDamping = 0
enemy.physicsBody!.mass = 0.1
enemy.physicsBody!.velocity = CGVector(dx: 150, dy: 0)
addChild(enemy)
}
override func didSimulatePhysics() {
let enemy = childNodeWithName("enemy")!
if (enemy.position.x > size.width && enemy.physicsBody!.velocity.dx > 0)
|| (enemy.position.x < 0 && enemy.physicsBody!.velocity.dx < 0) {
enemy.physicsBody!.velocity.dx *= -1
}
}
}

How to detect collisions in Sprite Kit?

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 */
}
}

flappy bird clone Xcode 7 Swift 2 how to reset rotation

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

Xcode 6 SpriteKit Scene not Refreshing

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! :)

Resources