4

I want to setup my SpriteKit Game in a more ordered and clearer way, so I decided to make use of classes for each type of sprite node.

In my case I created a separate Player class in swift which looks like this

import SpriteKit

class Player: SKSpriteNode {

func initializePlayer() {        
    self.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.size.width, height: self.size.height))
    self.physicsBody?.affectedByGravity = true
}


func moveLeft () {
    print("left")
}

func moveRight () {
    print("right")
}   
}

I reference this Sprite Node in the Scene Editor´s Custom Class inspector correctly and I can trigger the class methods without any problem - so this works well.

I reference the Player class in my GameScene like this:

class GameplayScene: SKScene {   
var player: Player = Player()   
let myNode = SKSpriteNode(imageNamed: "player")   
override func didMove(to view: SKView) {       
    player.initializePlayer()           
}
}

But the physics body is not applied, and I can not figure out why this is the case.

After I added the physics body to the sprite node, I would expect the node to fall down off the screen. But this does not happen and I can not figure why.

Does anyone have a clue how I can apply a physics body from within the class?

Eric Aya
  • 68,765
  • 33
  • 165
  • 232
boehmatron
  • 705
  • 4
  • 13
  • what do you mean by _the physics body is not applied_? – Mina Dec 19 '16 at 19:31
  • After I added the physics body to the sprite node, I would expect the node to fall down off the screen. But this does not happen and I can not figure why. – boehmatron Dec 19 '16 at 19:46
  • i cannot see that on the posted code, you just added physics body to self. be more specific and post some more codes. – Mina Dec 19 '16 at 19:51
  • @Mina thank you for your feedback, I updated my description and hope my problem is now a little bit more clearer – boehmatron Dec 19 '16 at 20:10
  • Are you setting the size of the node before calling `initializePlayer()`? Maybe the physics body's size is 0x0 and it's causing an issue? – nathangitter Dec 19 '16 at 20:33
  • how do you implement the `initializePlayer()` ? what's in there? – Mina Dec 20 '16 at 05:04
  • @Mina you can see the initialization function in the Player class. I basically define the physics body with its size and set affectedByGravity to true. Since I can call the inizializePlayer I am confused why the physics don't get applied and the player does not fall off the screen. – boehmatron Dec 20 '16 at 16:42

2 Answers2

2

I could call your function with other name than initializePlayer, something more related to the code that implements :

func setPhysics() {        
    self.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.size.width, height: self.size.height))
    self.physicsBody?.affectedByGravity = true
}

After that, if you want to retrieve your sprite from Scene Editor you could use:

if let node = self.childNode(withName:"//mySpriteNodeName") as? Player {
            // Set up your sprite here
            node.setPhysics()
}

P.S.: I've added also //: this specifies that the search should begin at the root node and be performed recursively across the entire node tree. Otherwise, it performs a recursive search from its current position.

Alessandro Ornano
  • 31,579
  • 11
  • 90
  • 115
  • Thank you for your support. I tried your approach, but still I get the same error from the required init method. The solution that @Mina reffered me to is something I do not understand and I dont know how to solve this issues. Do you think you can have another look? – boehmatron Dec 31 '16 at 11:46
  • In the first part of the Mina code she explain to you how you could build your Player class as SKSpriteNode subclass, but you can decide also to don't override the init methods and build other custom functions leave the originals init functions untouched. – Alessandro Ornano Dec 31 '16 at 12:14
1

The problem is that you didn't initialize your player node in SKSpriteNode built in init function.

use the following code:

init() {
    let texture = SKTexture(imageNamed: "Spaceship")
    super.init(texture: texture, color: UIColor.blue, size: texture.size())
    self.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.size.width, height: self.size.height))
    self.physicsBody?.affectedByGravity = true
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    fatalError("init(coder:) has not been implemented")
}

instead of:

func initializePlayer() {        
    self.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: self.size.width, height: self.size.height))
    self.physicsBody?.affectedByGravity = true
}

it will solve your problem and apply the physics body correctly.

Mina
  • 1,928
  • 2
  • 19
  • 28
  • 1
    This does not work in my case. The compiler drops an error: "fatal error: init(coder:) has not been implemented: file / Player.swift Further I do not need and want to specify the texture when initiating the instance. Rather would I want to specifiy the texture from within the SceneEditor. – boehmatron Dec 21 '16 at 20:13
  • i've test it and it must not make any error. but you can use this [thread](http://stackoverflow.com/a/24036440/1724845) to solve the error. – Mina Dec 22 '16 at 04:49
  • @Mina Your code is correct, but OP experiencing that error because initWIthCoder: is called. That is happening because he loads Player from a .sks file. – Whirlwind Dec 28 '16 at 12:57
  • @Whirlwind What does this mean? can you explain? I can not figure out a solution on this :-/ – boehmatron Jan 01 '17 at 19:25