whilst programming a SKAction.animateWithTextures(...) I came across this error ('String'is not convertible to 'DictionaryIndex') when I used the String keys of my 'states' to retrieve the SKTexture relevant. Can someone explain what might be the cause of the error?
import SpriteKit
class Player {
let states: Dictionary<String, SKTexture> = [
"standing": SKTexture(imageNamed: "standing"),
"right1": SKTexture(imageNamed: "right1"),
"right2": SKTexture(imageNamed: "right2"),
"right3": SKTexture(imageNamed: "right3"),
"left1": SKTexture(imageNamed: "left1"),
"left2": SKTexture(imageNamed: "left2"),
"left3": SKTexture(imageNamed: "left3")
]
let LEFT: UInt32 = 1 << 0
let FRONT: UInt32 = 1 << 1
let RIGHT: UInt32 = 1 << 2
var node: SKSpriteNode!
var status: UInt32!
let delay = SKAction.waitForDuration(NSTimeInterval(0.1))
var runLeft: SKAction!
var runRight: SKAction!
init(){
for state in states {
state.1.filteringMode = .Nearest
}
node = SKSpriteNode(texture: states["standing"])
node.physicsBody = SKPhysicsBody(rectangleOfSize: node.size)
node.physicsBody.dynamic = false
status = FRONT
runLeft = SKAction.animateWithTextures([states["left1"], states["left2"], states["left1"], states["left3"]]!, timePerFrame: 0.1)
runRight = SKAction.animateWithTextures([states["right1"], states["right2"], states["right1"], states["right3"]]!, timePerFrame: 0.1)
}
}
Dictionary lookups return optionals because the key might not exist. You need to unwrap each of the lookups since they are type SKTexture!:
runLeft = SKAction.animateWithTextures([states["left1"]!, states["left2"]!, states["left1"]!, states["left3"]!], timePerFrame: 0.1)
runRight = SKAction.animateWithTextures([states["right1"]!, states["right2"]!, states["right1"]!, states["right3"]!], timePerFrame: 0.1)
Related
I'm trying to get my player to play the jump animation when the touch begins. The player is in his own swift file and I have the GameScene.swift call his file so everything that deals with his movement is in player.swift file. Any help would be awesome!
import SpriteKit
struct ColliderType {
static let PLAYER: UInt32 = 0
static let GROUND: UInt32 = 1
static let ROCKET_AND_COLLECTABLES: UInt32 = 2
}
class Player: SKSpriteNode {
private var textureAtlas = SKTextureAtlas()
private var playerAnimation = [SKTexture]()
private var animatePlayerAction = SKAction()
let jumpAnimation1 = [SKTexture]()
let jumpAnimation2 = [SKTexture]()
var jumpAnimation = SKAction ()
func initializePlayer() {
name = "Player"
for i in 1...7 {
let name = "Player \(i)"
playerAnimation.append(SKTexture(imageNamed: name))
}
animatePlayerAction = SKAction.animate(with: playerAnimation,
timePerFrame: 0.08, resize: true, restore: false)
//Animate the player forever.
self.run(SKAction.repeatForever(animatePlayerAction))
physicsBody = SKPhysicsBody(rectangleOf: CGSize(width:
self.size.width-60, height: self.size.height-80))
physicsBody?.affectedByGravity = true
physicsBody?.allowsRotation = false
//Restitution is Boucniess
physicsBody?.restitution = 0
physicsBody?.categoryBitMask = ColliderType.PLAYER
physicsBody?.collisionBitMask = ColliderType.GROUND
physicsBody?.contactTestBitMask =
ColliderType.ROCKET_AND_COLLECTABLES
}
func move (){
self.position.x += 10
}
func reversePlayer() {
physicsBody?.velocity = CGVector(dx: 0, dy: 0)
physicsBody?.applyImpulse(CGVector(dx: 0, dy: 300))
playerNode?.removeAction(forKey:"animate") playerNode?.run(attackAnimation,completion:{
self.playerNode?.run(self.animation,withKey: "animate")
}
}
Replace the part where you set textures, create and run the action with the following code snippet. It works perfectly for me and is the simplest way to do it.
let hero = SKSpriteNode(imageNamed: "hero")
hero.size = CGSize(width: 45, height: 125)
let f1 = SKTexture.init(imageNamed: "h1")
let f2 = SKTexture.init(imageNamed: "h2")
let f3 = SKTexture.init(imageNamed: "h3")
let frames: [SKTexture] = [f1, f2, f3]
let hero = SKSpriteNode(imageNamed: "h1")
let animation = SKAction.animate(with: frames, timePerFrame: 0.1)
hero.run(SKAction.repeatForever(animation))
Also, it is possible that your animation action cannot be accessed as it is in another file. Declare the player and animations globally i.e. outside of any class or function. Hope it works for you!
When player body meet a monster body the function func didBeginContact(contact: SKPhysicsContact) is never called.
My class implement SKPhysicsContactDelegate
class GameScene: SKScene, SKPhysicsContactDelegate
the property collisionBitMask i commented it because i read that if we don't put it, node can collise with all node
I add my player like this :
bear.position = CGPoint(x:self.frame.width/20, y:self.frame.height/5)
bear.size = CGSize(width: self.frame.width/7, height: self.frame.height/5)
bear.physicsBody = SKPhysicsBody(rectangleOfSize: bear.frame.size)
bear.physicsBody?.dynamic = false;
bear.physicsBody?.categoryBitMask = PhysicsCategory.Player
bear.physicsBody?.contactTestBitMask = PhysicsCategory.Monster
//bear.physicsBody?.collisionBitMask = PhysicsCategory.Monster
I add monster like this:
let thePosition = CGPoint(x: positionX, y: (self.frame.height/7.4)*positionY)
let monster = SKSpriteNode(imageNamed: pattern as String)
monster.size = CGSize(width: self.frame.width/16, height: self.frame.height/11)
monster.name = name
monster.position = thePosition
monster.physicsBody = SKPhysicsBody(rectangleOfSize: monster.frame.size)
monster.physicsBody?.dynamic = false
monster.physicsBody?.categoryBitMask = PhysicsCategory.Monster // 3
monster.physicsBody?.affectedByGravity = false
monster.physicsBody?.contactTestBitMask = PhysicsCategory.Player // 4
//platformNode.physicsBody?.collisionBitMask = PhysicsCategory.Player // 5
addChild(monster)
my PhysicalCategory
struct PhysicsCategory {
static let None : UInt32 = 0
static let All : UInt32 = UInt32.max
static let Player: UInt32 = 0b1 // 1
static let Monster : UInt32 = 0b10 // 2
static let Projectile: UInt32 = 0b100 // 3
static let Plateforme: UInt32 = 0b1000 // 4
}
I have multiple Textures, for example when player walk i call this :
func walkingBear() {
bear.runAction( SKAction.repeatActionForever(SKAction.animateWithTextures(bearCoursFrames, timePerFrame: 0.1, resize: false, restore: true)), withKey:"cours")
}
I initlaise bearCoursFrames like this
var walkFrames = [SKTexture]()
var numImages : Int = bearAnimatedAtlas.textureNames.count
for var i=1; i<=numImages/2; i++ {
let bearTextureName = "cours\(i)"
walkFrames.append(bearAnimatedAtlas.textureNamed(bearTextureName))
}
bearCoursFrames = walkFrames
Where is my error please, i can't find a solution in other post
any help would be appreciated
---------------------------------EDIT------------------------------
Solution: I just add self.physicsWorld.contactDelegate = self and it works now.
The answer is simple. There is a rule which says that at least one body has to be defined as dynamic in order to register the contact.
Change either player or other body to be dynamic and contact will be detected.
As an addition, if you already haven't, enable physics visual representation ... It can be helpful because sometimes contact is not detected because the actual bodies are not intersecting each other eg. when node's anchor point is changed, so the texture and a body are misplaced (which is fixable, using appropriate initializers of SKPhysicsBody class, but this is a very common error).
I just add
self.physicsWorld.contactDelegate = self
and it works now.
I have a bullet that should be fired at block. Bullet has 6 different random textures to mimic different bullets. And block has 3 different textures chosen randomly to look like there are 3 different blocks. I want to specify in code that if bullet texture is red, and block texture is red then score should increase, but if bullet is red and block is green it will be the game over. I don't really know how to tell game to do so in didBeginContact.
By now I have this:
In the GameScene & didMoveToView:
struct PhysicsCategory {
static let None : UInt32 = 0
static let All : UInt32 = UInt32.max
static let CgyBlock : UInt32 = 0b1
static let Bullet : UInt32 = 0b10
}
bullet.physicsBody = SKPhysicsBody(texture: bullet.texture, size: self.bullet.size)
bullet.physicsBody?.categoryBitMask = PhysicsCategory.Bullet
bullet.physicsBody?.contactTestBitMask = PhysicsCategory.CgyBlock
bullet.physicsBody?.collisionBitMask = PhysicsCategory.None
bullet.physicsBody?.affectedByGravity = false
bullet.physicsBody?.usesPreciseCollisionDetection = true
In didBeginContact:
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
}
if ((firstBody.categoryBitMask & PhysicsCategory.CgyBlock != 0) &&
(secondBody.categoryBitMask & PhysicsCategory.Bullet != 0))
//and here I suppose I need to implement somehow something like
// && (bullet.texture = "redBullet") && (CgyBlock.texture = "greenBlock" || "blackBlock")
{
gameOver()
}
But I know it will not work. I also tried to make a switch statement inside curly brackets and it didn't work either. How to implement that?
Update: This is how a block is made:
var cgyBlock = SKSpriteNode()
let cgyArray = ["cyanBox", "greenBox", "yellowBox"]
func addCgyLine () {
cgyBlock = SKSpriteNode(imageNamed: "cyanBox")
var randomCGY = Int(arc4random_uniform(3))
cgyBlock.texture = SKTexture(imageNamed: cgyArray[randomCGY])
cgyBlock.physicsBody = SKPhysicsBody(texture: cgyBlock.texture, size: cgyBlock.size)
cgyBlock.physicsBody?.dynamic = true
cgyBlock.physicsBody?.categoryBitMask = PhysicsCategory.CgyBlock
cgyBlock.physicsBody?.contactTestBitMask = PhysicsCategory.Bullet
cgyBlock.physicsBody?.collisionBitMask = PhysicsCategory.None
cgyBlock.position = CGPointMake(size.width + cgyBlock.size.width/2, CGRectGetMidY(self.frame) + 60)
addChild(cgyBlock)
let actionMove = SKAction.moveTo(CGPoint(x: -cgyBlock.size.width/2, y: CGRectGetMidY(self.frame) + 60), duration: 3)
let actionDone = SKAction.removeFromParent()
cgyBlock.runAction(SKAction.sequence([actionMove, actionDone]))
SKActionTimingMode.EaseOut
}
And then I do runAction in didMoveToView.
Bullets:
var cannon = SKSpriteNode(imageNamed: "cannon")
var bulletInCannon = SKSpriteNode()
var bullet = SKSpriteNode()
let bulletArray = ["redBullet","magentaBullet", "blueBullet", "cyanBullet", "greenBullet", "yellowBullet"]
//didMoveToView:
var randomBullet = Int(arc4random_uniform(6))
bulletInCannon = SKSpriteNode(imageNamed: bulletArray[randomBullet])
bulletInCannon.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
addChild(bulletInCannon)
//touchesEnded:
var randomBullet = Int(arc4random_uniform(6))
bullet = SKSpriteNode(texture: bulletInCannon.texture)
bullet.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
bullet.name = bulletArray[randomBullet]
bullet.physicsBody = SKPhysicsBody(texture: bullet.texture, size: self.bullet.size)
bullet.physicsBody?.dynamic = true
bullet.physicsBody?.categoryBitMask = PhysicsCategory.Bullet
bullet.physicsBody?.contactTestBitMask = PhysicsCategory.CgyBlock
bullet.physicsBody?.collisionBitMask = PhysicsCategory.None
bullet.physicsBody?.affectedByGravity = false
bullet.physicsBody?.usesPreciseCollisionDetection = true
addChild(bullet)
bulletInCannon.texture = SKTexture(imageNamed: bulletArray[randomBullet])
Few ways to go :
You can use node's userData property.
bullet.userData = ["type" : "white"]
To access it:
println(bullet.userData?["type"])
You can create custom Bullet class which is subclass of SKSpriteNode and create property called "type", and in didBeginContact to access that property.
class Bullet: SKSpriteNode {
var type:String = ""
init(type:String) {
self.type = type //later you are accessing this with bulletNode.type
//This is just an simple example to give you a basic idea what you can do.
//In real app you should probably implement some kind of security check to avoid wrong type
let texture = SKTexture(imageNamed: type)
super.init(texture: texture, color: nil, size: texture.size())
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
You can use bullet.name property as well, and on creation to set it appropriately based on bullet/block colour. Later in didBeginContact you will check bullet.name to find out the bullet type. Same goes for blocks.
func spawnBulletWithType(type:String) -> SKSpriteNode{
//set texture based on type
//you can pass here something like white_bullet
let atlas = SKTextureAtlas(named: "myAtlas")
//here, if passed white_bullet string, SpriteKit will search for texture called white_bullet.png
let bullet = SKSpriteNode(texture:atlas.textureNamed(type))
bullet.name = type // name will be white_bullet, and that is what you will search for in didBeginContact
bullet.physicsBody = SKPhysicsBody(texture: bullet.texture, size: bullet.size)
bullet.physicsBody?.categoryBitMask = PhysicsCategory.Bullet
bullet.physicsBody?.contactTestBitMask = PhysicsCategory.CgyBlock
bullet.physicsBody?.collisionBitMask = PhysicsCategory.None
bullet.physicsBody?.affectedByGravity = false
bullet.physicsBody?.usesPreciseCollisionDetection = true
return bullet
}
EDIT:
Based on your recent comments you could probably go with this:
let bulletArray = ["redBullet","magentaBullet", "blueBullet", "cyanBullet", "greenBullet", "yellowBullet"]
//didMoveToView:
var randomBullet = Int(arc4random_uniform(6))
let bulletType = bulletArray[randomBullet]
bulletInCannon.name = bulletType
bulletInCannon = SKSpriteNode(imageNamed: bulletType )
bulletInCannon.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
addChild(bulletInCannon)
//touchesEnded:
var randomBullet = Int(arc4random_uniform(6))
bullet = SKSpriteNode(texture: bulletInCannon.texture)
bullet.name = bulletInCannon.name
bullet.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
bullet.physicsBody = SKPhysicsBody(texture: bullet.texture, size: self.bullet.size)
bullet.physicsBody?.dynamic = true
bullet.physicsBody?.categoryBitMask = PhysicsCategory.Bullet
bullet.physicsBody?.contactTestBitMask = PhysicsCategory.CgyBlock
bullet.physicsBody?.collisionBitMask = PhysicsCategory.None
bullet.physicsBody?.affectedByGravity = false
bullet.physicsBody?.usesPreciseCollisionDetection = true
addChild(bullet)
let bulletType = bulletArray[randomBullet]
bulletInCannon.texture = SKTexture(imageNamed: bulletType)
bulletInCannon.name = bulletType
First you need to define a class for bullets and Blocks
Then you may define a TextureTypes to store your texture types (red,green,…) and set whatever your random method generates into a class variable of this type.
Then you should manage the contact and find out what are the nodes for BodyA and BodyB. after that it is easy to do what ever you like according to the texturetype of your node,
to clarify the code I have defined Textures as a new Type
enum TextureTypes: String {
case Red,Green
var description:String {
switch self {
case Red:return “Red"
case Green:return “Green”
case Green:return “Blue"
}
}
}
Blockclass and BulletClass both hasto inherit from SKNode cause they are a node!
class BlockClass:SKNode {
var NodesTexture : TextureTypes = TextureTypes.Red
}
class BulletClass:SKNode {
var NodesTexture : TextureTypes = TextureTypes.Red
}
write the following codes into your didBeginContact method to detect the TextureType of your Node
if (contact.bodyA.categoryBitMask == PhysicsCategory.Bullet) &&
(contact.bodyB.categoryBitMask == PhysicsCategory.CgyBlock)
{
Ablock = (BlockClass *) contact.bodyB.node;
Abullet = (BulletClass *) contact.bodyA.node;
}
if (contact.bodyA.categoryBitMask == PhysicsCategory.CgyBlock) &&
(contact.bodyB.categoryBitMask == PhysicsCategory.Bullet)
{
Ablock = (BlockClass *) contact.bodyA.node;
Abullet = (BulletClass *) contact.bodyB.node;
if ( Ablock.NodesTexture = TextureTypes.Red )
{
NSLOG(“A Red Block Detected”)
}
}
Do not forget to define your blocks and bullets of type BlocksClass and BulletClass
Hey so I have a problem detecting collisions. I have this project I am making based on Ray Wenderlich's tutorial on How to Make a game like Mega Jump. So everything is works great at the beginning, where platforms and stars are static in one place. But as you go further in the game, stars and platforms start moving (I am using SKActions for this), tried to do this to make it a little harder. But when I get there, collision is NOT being detected at all, player just passes by through the objects like they weren't there. I've been reading everywhere online, I am using precise collision detection but still I see no difference. Any ideas on what can be wrong or what else can I do? Here is a bit of code on how I am doing this:
player = SKSpriteNode(texture: firstFrame)
player.position = (CGPoint(x: self.size.width / 2, y: 50.0))
player.physicsBody = SKPhysicsBody(circleOfRadius: player.size.width / 2)
player.physicsBody?.dynamic = true
player.physicsBody?.allowsRotation = false
player.physicsBody?.restitution = 1.0
player.physicsBody?.friction = 0.0
player.physicsBody?.angularDamping = 0.0
player.physicsBody?.linearDamping = 0.0
player.physicsBody?.usesPreciseCollisionDetection = true
player.physicsBody?.categoryBitMask = CollisionCategoryBitmask.Player
player.physicsBody?.collisionBitMask = 0
player.physicsBody?.contactTestBitMask = CollisionCategoryBitmask.Star | CollisionCategoryBitmask.Platform | CollisionCategoryBitmask.Monster
foregroundNode.addChild(player)
func createPlatformAtPosition(position: CGPoint, ofType type: PlatformType) -> PlatformNode {
let node = PlatformNode()
let thePosition = CGPoint(x: position.x * scaleFactor, y: position.y)
node.position = thePosition
node.name = "NODE_PLATFORM"
node.platformType = type
var sprite: SKSpriteNode
var spriteFrames : [SKTexture]!
if type == .Break {
let spriteAnimatedAtlas = SKTextureAtlas(named: "CloudBreak")
var cloudFrames = [SKTexture]()
spriteFrames = cloudFrames
let firstFrame = SKTexture(imageNamed: "Cloud02")
sprite = SKSpriteNode(texture: firstFrame)
let move = SKAction.moveToX(self.position.x - 160.0, duration:2.0)
let back = SKAction.moveToX(self.position.x, duration:2.0)
let sequence = SKAction.sequence([move, back, move, back])
sprite.runAction(SKAction.repeatActionForever(sequence))
} else {
let spriteAnimatedAtlas = SKTextureAtlas(named: "Cloud")
var cloudFrames = [SKTexture]()
spriteFrames = cloudFrames
let firstFrame = SKTexture(imageNamed: "Cloud")
sprite = SKSpriteNode(texture: firstFrame)
}
node.addChild(sprite)
node.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.size)
node.physicsBody?.dynamic = false
node.physicsBody?.categoryBitMask = CollisionCategoryBitmask.Platform
node.physicsBody?.contactTestBitMask = CollisionCategoryBitmask.Player
node.physicsBody?.collisionBitMask = 0
return node
}
func didBeginContact(contact: SKPhysicsContact) {
var updateHUD = false
let whichNode = (contact.bodyA.node != player) ? contact.bodyA.node : contact.bodyB.node
let other = whichNode as GameObjectNode
updateHUD = other.collisionWithPlayer(player)
}
struct CollisionCategoryBitmask {
static let Player: UInt32 = 0x00
static let Star: UInt32 = 0x01
static let Platform: UInt32 = 0x02
static let Monster: UInt32 = 0x03
}
Slow the objects down and see if they collide. I had an issue where I was moving my nodes too fast and they were past the collision points when the new frame was rendered. If they move so fast they pass each other's physics body in the frame cycle they will not register a hit.
To detect a collision in that case, you can compare where they are in each frame, and if they have passed each other or their x/y plane values overlap, you can execute your collision code.
The collision is not detected because you didn't set the collisionBitMask.
player.physicsBody?.collisionBitMask = CollisionCategoryBitmask.Star | CollisionCategoryBitmask.Platform | CollisionCategoryBitmask.Monster
node.physicsBody?.collisionBitMask = CollisionCategoryBitmask.Player
Contact and Collision aren't the same thing. You can find more information online.
If it still doesn't work, please show us your CollisionCategoryBitmask to make sure you created it properly.
Edit :
struct CollisionCategoryBitmask {
static let Player: UInt32 = 0
static let Star: UInt32 = 0b1
static let Platform: UInt32 = 0b10
static let Monster: UInt32 = 0b100
}
Here is a table I've made for another question, that might help you too :
http://goo.gl/7D8EGY
Check out my collision physics engine, it's very simple but has support for continuous/predicting/bullet collisions. You might learn something from the code, and it's written in javascript so it should be easy to read.https://github.com/Murplyx/AAE---Axis-Aligned-Engine
I'm fairly new to programming and can't seem to figure out this Physics World issue. When I add a physics body to my sprite node, i can no longer see the sprite node in the scene.
Code:
func createBird() {
let randomSpawn = Int(arc4random_uniform(2))
if randomSpawn == 1 {
let newX = Int(-20)
let newY = Int(arc4random_uniform(500) + 300)
var p = CGPoint(x: newX, y: newY)
var destination = CGPoint(x:Int(self.frame.width+21), y:newY)
var moverSpeed = Int(arc4random_uniform(5) + 3)
let birdRight = SKSpriteNode (imageNamed: "bird-right1")
birdRight.xScale = 0.6
birdRight.yScale = 0.6
birdRight.position = p
birdRight.zPosition = 2
//birdRight.physicsBody = SKPhysicsBody(rectangleOfSize: birdRight.size)
birdRight.physicsBody?.dynamic = true
birdRight.physicsBody?.categoryBitMask = birdCategory
birdRight.physicsBody?.contactTestBitMask = ballCategory
birdRight.physicsBody?.collisionBitMask = 0
let birdMoveRight = SKAction.animateWithTextures([
SKTexture(imageNamed: "bird-right1"),
SKTexture(imageNamed: "bird-right2"),
SKTexture(imageNamed: "bird-right3"),
SKTexture(imageNamed: "bird-right4"),
SKTexture(imageNamed: "bird-right5"),
SKTexture(imageNamed: "bird-right6"),
SKTexture(imageNamed: "bird-right7"),
SKTexture(imageNamed: "bird-right8"),
SKTexture(imageNamed: "bird-right9"),
SKTexture(imageNamed: "bird-right10")
], timePerFrame: 0.05)
let foreverAction = SKAction.repeatActionForever(birdMoveRight)
birdRight.runAction(foreverAction)
let duration = NSTimeInterval(moverSpeed)
let action = SKAction.moveTo(destination, duration: duration)
birdRight.runAction(action)
addChild(birdRight)
}
else {
let newX = Int(self.frame.width+20)
let newY = Int(arc4random_uniform(500) + 300)
var p = CGPoint(x: newX, y: newY)
var destination = CGPoint(x:-21, y:newY)
var moverSpeed = Int(arc4random_uniform(5) + 3)
let birdLeft = SKSpriteNode(imageNamed: "bird-left1")
birdLeft.xScale = 0.6
birdLeft.yScale = 0.6
birdLeft.position = p
birdLeft.zPosition = 2
let birdMoveLeft = SKAction.animateWithTextures([
SKTexture(imageNamed: "bird-left1"),
SKTexture(imageNamed: "bird-left2"),
SKTexture(imageNamed: "bird-left3"),
SKTexture(imageNamed: "bird-left4"),
SKTexture(imageNamed: "bird-left5"),
SKTexture(imageNamed: "bird-left6"),
SKTexture(imageNamed: "bird-left7"),
SKTexture(imageNamed: "bird-left8"),
SKTexture(imageNamed: "bird-left9"),
SKTexture(imageNamed: "bird-left10")
], timePerFrame: 0.05)
birdLeft.physicsBody = SKPhysicsBody(rectangleOfSize: birdLeft.size)
birdLeft.physicsBody?.dynamic = false
birdLeft.physicsBody?.categoryBitMask = birdCategory
birdLeft.physicsBody?.contactTestBitMask = ballCategory
birdLeft.physicsBody?.collisionBitMask = 0
let foreverAction = SKAction.repeatActionForever(birdMoveLeft)
birdLeft.runAction(foreverAction)
let duration = NSTimeInterval(moverSpeed)
let action = SKAction.moveTo(destination, duration: duration)
birdLeft.runAction(action)
addChild(birdLeft)
}
}
Maybe it is affected by gravity and get dragged all the way down before you even see the object on your screen?
Try this:
birdRight.physicsBody?.affectedByGravity = false