Luiz Luiz - 5 months ago 161
Swift Question

Using iCarousel in a game

Explanation



I'm trying to build a character selection menu similar to Crossy Road's one (as you can see here). So I found this iCarousel, which would help me with all of it, but everything I read talk about implementing it to a
ViewController
, which isn't my case. I'm using
GameScene
and I didn't found anything talking about it. Is there anyway I could implement it to my game? or even another effect similar to the character selection menu I mentioned above?




Code



I made a project with 3 square images (to apply the effect) as an example. But since I didn't find how to do it, and I don't know how to do it (yes, I tried), there isn't much code. You can use it as a start or to lead me to the answer. You can download it here.



GameScene.swift

import SpriteKit

class GameScene: SKScene {
override func didMoveToView(view: SKView) {
/* Setup your scene here */

let square1 = SKSpriteNode(imageNamed: "square1")
square1.anchorPoint = CGPointZero
square1.position = CGPoint(x: self.frame.width / 2 - square1.frame.width / 2, y: self.frame.height / 2 - square1.frame.height / 2)
self.addChild(square1)

let square2 = SKSpriteNode(imageNamed: "square2")
square2.anchorPoint = CGPointZero
//square2.position = CGPoint(x: self.frame.width / 2 - square2.frame.width / 2, y: self.frame.height / 2 - square2.frame.height / 2)
self.addChild(square2)

let square3 = SKSpriteNode(imageNamed: "square3")
square3.anchorPoint = CGPointZero
//square3.position = CGPoint(x: self.frame.width / 2 - square3.frame.width / 2, y: self.frame.height / 2 - square3.frame.height / 2)
self.addChild(square3)
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
}

override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}





Attempt (beyowulf)



You can download it here.



GameScene.swift

import SpriteKit

class GameScene: SKScene {

var imageName = "square1"{
didSet{
self.hidden = false
self.childNode.texture = SKTexture(imageNamed: imageName)
}
}

let kShowNotification = "showPicker"

var childNode = SKSpriteNode()

override func didMoveToView(view: SKView) {
/* Setup your scene here */

self.childNode = SKSpriteNode(imageNamed: imageName)
self.childNode.anchorPoint = CGPointZero
self.childNode.position = CGPoint(x: self.frame.width / 2 - childNode.frame.width / 2, y: self.frame.height / 2 - childNode.frame.height / 2)
self.addChild(self.childNode)
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.showCharPicker()
}

func showCharPicker(){
self.hidden = false
NSNotificationCenter.defaultCenter().postNotificationName(kShowNotification, object: nil)
}
}


GameViewController.swift

import UIKit
import SpriteKit

class GameViewController: UIViewController, iCarouselDataSource, iCarouselDelegate{

var images : NSMutableArray = NSMutableArray()

@IBOutlet var carousel : iCarousel!

deinit{
NSNotificationCenter.defaultCenter().removeObserver(self)
}

func showCarousel(){
carousel.hidden = false
}
func hideCarousel(){
carousel.hidden = true
}

override func awakeFromNib(){
super.awakeFromNib()
images = NSMutableArray(array: ["square1","square2","square3"])
}

func carousel(carousel:iCarousel, didSelectItemAtIndex index:NSInteger){

let scene = GameScene(size:self.view.bounds.size)

scene.imageName = self.images[index] as! String
self.hideCarousel()
}

override func viewDidLoad(){
super.viewDidLoad()

carousel.type = .CoverFlow
carousel.reloadData()

let spriteKitView = SKView()
spriteKitView.frame = self.view.bounds
self.view.insertSubview(spriteKitView, belowSubview: self.carousel)

spriteKitView.showsFPS = true
spriteKitView.showsNodeCount = true
spriteKitView.ignoresSiblingOrder = true

let scene = GameScene(size:self.view.bounds.size)
scene.scaleMode = .AspectFill
scene.imageName = self.images[0] as! String

self.carousel.hidden = true
spriteKitView.presentScene(scene)

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.showCarousel), name: scene.kShowNotification, object: nil)
}

func numberOfItemsInCarousel(carousel: iCarousel) -> Int{
return images.count
}

func carousel(carousel: iCarousel, viewForItemAtIndex index: Int, reusingView view: UIView?) -> UIView{

var itemView: UIImageView

if (view == nil){
itemView = UIImageView(frame:CGRect(x:0, y:0, width:200, height:200))
itemView.contentMode = .Center
}
else{
itemView = view as! UIImageView;
}

itemView.image = UIImage(named: "\(images.objectAtIndex(index))")
return itemView
}

func carousel(carousel: iCarousel, valueForOption option: iCarouselOption, withDefault value: CGFloat) -> CGFloat{

if (option == .Spacing){
return value * 2
}

return value
}
}


This is happening:

enter image description here




Image example



enter image description here



Thanks in advance,

Luiz.

Answer

You can use NSNotifications to show your character picker. You just need to observe the notifications posted by your SKScene. Your viewDidLoad should look something like:

override func viewDidLoad(){
    super.viewDidLoad()

    carousel.type = .CoverFlow
    carousel.reloadData()

    let spriteKitView = SKView()
    spriteKitView.frame = self.view.bounds
    self.view.insertSubview(spriteKitView, belowSubview: self.carousel)

    spriteKitView.showsFPS = true
    spriteKitView.showsNodeCount = true
    spriteKitView.ignoresSiblingOrder = true

    self.gameScene = GameScene(size:self.view.bounds.size)
    self.gameScene.scaleMode = .AspectFill
    self.gameScene.imageName = self.images[0] as! String

    self.carousel.hidden = true
    spriteKitView.presentScene(self.gameScene)

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.showCarousel), name: gameScene.kShowNotification, object: nil)
}

You'll want to implementing carousel(carousel:iCarousel, didSelectItemAtIndex index:NSInteger) so you know what is selected, and so you can return to game play. For example:

func carousel(carousel:iCarousel, didSelectItemAtIndex index:NSInteger)
{
    self.gameScene.imageName = self.images[index] as! String
    self.hideCarousel()
}

You also need to remove observing before your view controller is deallocated.

deinit
{
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

Your SKScene can then post a notifications:

import SpriteKit

class GameScene: SKScene {
    var imageName = "square1"{
        didSet{
            self.hidden = false
            self.childNode.texture = SKTexture(imageNamed: imageName)
        }
    }

    let kShowNotification = "showPicker"

    var childNode = SKSpriteNode()
    override func didMoveToView(view: SKView) {
        /* Setup your scene here */

        self.childNode = SKSpriteNode(imageNamed: imageName)
        self.childNode.anchorPoint = CGPointZero
        self.childNode.position = CGPointZero
        self.addChild(self.childNode)
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.showCharPicker()
    }

    func showCharPicker()
    {
        self.hidden = true
        NSNotificationCenter.defaultCenter().postNotificationName(kShowNotification, object: nil)
    }

}