What's the Best Way to Handle Multiple Skscenes

What's the best way to handle multiple SKScenes?

Having a Single View Controller and Multiple Scenes

You could use single view controller (which is actually a default state of SpriteKit game template) and have multiple scenes.

So you will have GameViewController and LandingScene, GameScene and possible some other scenes, like LevelSelect scene or something like that.

In GameViewController, you initialize your scene for the first time. So that is the point where you initialize your LandingScene (I guess that is the place where you implemented your navigation menu).

So, from that point, you are able to make a transition from any scene you want using SKView's presentScene: method (and optionally using SKTransition class).

Transitioning

Transition in SpriteKit can be generally done in two different ways:

1. Some might tell you that making a transition from a current scene, to the next scene is a "bad design" and that the current scene should notify the view controller about its ready-to-transition state, so that view controller can make needed transition. But in response to that, these are quotes from docs:

Transitioning Between Two Scenes

Typically, you transition to a new scene based on gameplay or user
input. For example, if the user presses a button in your main menu
scene, you might transition to a new scene
to configure the match the
player wants to play.

And the related code:

- (void)mouseUp:(NSEvent *)theEvent
{
[self runAction: self.buttonPressAnimation];
SKTransition *reveal = [SKTransition revealWithDirection:SKTransitionDirectionDown duration:1.0];
GameConfigScene *newScene = [[GameConfigScene alloc] initWithSize: CGSizeMake(1024,768)]];
[self.scene.view presentScene: newScene transition: reveal];
}

It can be clearly seen that transition to the next scene is done within current scene.

2. Using the method described above using delegation pattern, where scene delegates responsibility of transitioning to the view controller.

Both ways are perfectly fine, where the first method is a bit convenient IMO, and widely used. So that is how you can navigate between different scenes in SpriteKit in an easy way.

Hint:

Don't forget to override scene's dealloc (or deinit if you use Swift) method while in development phase, to make sure that all scenes are deallocated correctly.

Use one or multiple SKScenes for Level based Game

The best practice is to separate game data and assets from game code. This way, you can make changes to stuff without having to recompile (and is handy if you are working with another person who doesn't code).

Here is what apple has to say about it at WWDC 2014:
 :


When you transition between scenes, ARC will deallocate the prior scene, assuming you made no strong references to it. Since you're starting out it's unlikely you need to worry about this right now... it's mostly done with globals and closures, and you should be able to fix it if it becomes a problem (but likely won't).

You can use things like unowned self and weak var etc to ensure this doesn't happen when needed. Again this is a more advanced topic but it's good to be aware of them.

Really, making level changes is entirely up to you... if you want to make a state manager that swaps out stuff to one scene, you can certainly do that... or, you could make a bunch of scenes and transition to that. Again, the best practice here is separating game content from game code, not necessarily how you switch scenes.

Personally, I would used separate SKScenes-- because it's already built in with transitions, memory management--and you have the option of using the editor, and you get to give each scene it's own file if desired.

There is also GameplayKit which has a statemanager, in which case you could use one scene and have different states be the level.

here are some resources, buried in there are some nuggets pertaining to what you want.

https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/DesigningGameswithSpriteKit/DesigningGameswithSpriteKit.html

https://developer.apple.com/videos/play/wwdc2014/608/

https://developer.apple.com/library/content/samplecode/DemoBots/Listings/DemoBots_SceneManager_swift.html

Combine several SKScenes in Sprite Kit

For this purpose, consider using only one scene and for each game theme (i.e greeting, game, highscore) use an SKNode which will contain the required elements for its purpose (e.g. the greeting node will have its greeting elements).

This way you can easily keep a "constant" SKNode (i.e. add it once to the scene when the game is first loaded) which will contain your parallax clouds and add/remove required node for the greeting game and highscore when necessary

What's the cleanest way to call a method from one SKScene to another in Swift?

This is quite easy actually. When you segue to the new scene, you can also pass in a variable with it... Here is an example.

GameOverScene.swift

var score:Int = 0

GameScene.swift

var score:Int = THE USERS SCORE    

func segue(){
let gameScene = GameOverScene(size: self.size)
gameScene.score = score
let transition = SKTransition.doorsCloseHorizontalWithDuration(0.5)
gameScene.scaleMode = SKSceneScaleMode.AspectFill
self.scene!.view?.presentScene(gameScene, transition: transition)
}

How to properly encapsulate touch event handling in a SKSpriteNode and pass data back to a SKScene

I like to handle as much of the code in the object class as possible. So I would handle any of the object touch code inside of it's class file and send the touch back to the scene to be handle separately by the scene if needed, and use delegation to send the information regarding the touch to the scene.

There are no downsides to removing this code, and several upsides.

cleaner code
faster loading time in xcode if the scenes have less line (my own findings)
you don't have to pinpoint the node that the touch is landing on because it is encapsulated in a sublass

In subclass (cat)

protocol CatDelegate: class{
func catTouched(cat: Cat)
}

class Cat: SKSpriteNode {

weak var delegate: CatDelegate!

var isEnabled = true
var sendTouchesToScene = true
var color: SKColor = .white

override func touchesBegan(_ touches: Set, with event: UIEvent!) {

guard isEnabled else { return }

//send touch to scene if you need to handle further touches by the scene
if sendTouchesToScene {
super.touchesBegan(touches, with event)
}

//handle touches for cat
delegate?.catTouched(cat: self)
}
}

meanwhile in Game Scene...

class GameScene: SKScene {

private var cat1: Cat!
private var cat2: Cat!



func createCats() {

cat1 = Cat()
cat1.color = .magenta
cat1.delegate = self
addChild(cat1)

cat2 = Cat()
cat2.color = .green
cat2.delegate = self
addChild(cat2)
}
}

extension GameScene: CatDelegate {

func catTouched(cat: Cat) {
print("cat of color \(cat.color)")
}
}


Related Topics



Leave a reply



Submit