问题描述
解释
我正在尝试建立一个类似于Crossy Road的字符选择菜单(如你所见
提前致谢,
Luiz。
您可以使用NSNotifications显示您的角色选择器。您只需要观察 SKScene
发布的通知。您的 viewDidLoad
应如下所示:
覆盖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)
}
你需要实现 carousel(carousel:iCarousel,didSelectItemAtIndex index:NSInteger)
,这样你才能知道所选内容,这样你就可以返回游戏。例如:
func carousel(carousel:iCarousel,didSelectItemAtIndex index:NSInteger)
{
self。 gameScene.imageName = self.images [index] as!字符串
self.hideCarousel()
}
您还需要删除观察在取消分配视图控制器之前。
deinit
{
NSNotificationCenter.defaultCenter()。removeObserver(self )
}
您的 SKScene
然后可以发布通知:
import SpriteKit
class GameScene:SKScene {
var imageName =square1{
didSet {
self.hidden = false
self.childNode.texture = SKTexture(imageNamed:imageName)
}
}
让kShowNotification =showPicker
var childNode = SKSpriteNode()
覆盖func didMoveToView(查看:SKView){
/ *在这里设置场景* /
self.childNode = SKSpriteNode(imageNamed:imageName)
self.childNode.anchorPoint = CGPointZero
self.childNode.position = CGPoi ntZero
self.addChild(self.childNode)
}
覆盖func touchesBegan(触摸:设置< UITouch>,withEvent事件:UIEvent?){
self。 showCharPicker()
}
func showCharPicker()
{
self.hidden = true
NSNotificationCenter.defaultCenter()。postNotificationName(kShowNotification,object:零)
}
}
如果你想改变命中检测,您需要子类化您需要更改的视图。这种情况下你的 iCarousel
视图。
然后你可以覆盖 hitTest
或 pointInside
。我创建了一个 iCarousel
子类并覆盖了 pointInside
,只有当该点位于其中一个轮播内时才返回true code> contentView 的子视图。
class CarouselSubclass:iCarousel {
覆盖func pointInside(点:CGPoint,withEvent事件:UIEvent?) - > Bool {
var inside = false
for self.contentView.subviews中的视图
{
inside = CGRectContainsPoint(view.frame,point)
如果在$ b $内b {
返回
}
}
返回
}
}
您需要记住在界面构建器中更改轮播的类别并更新您的插座。
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?
Attempt (beyowulf)
You can download it here.
GameScene.swift
import SpriteKit
class GameScene: SKScene {
var show = SKSpriteNode()
var hide = SKSpriteNode()
func showCharPicker(){
NSNotificationCenter.defaultCenter().postNotificationName("showCharPicker", object: nil)
}
func hideCharPicker(){
NSNotificationCenter.defaultCenter().postNotificationName("hideCharPicker", object: nil)
}
override func didMoveToView(view: SKView) {
/* Setup your scene here */
print("didMoveToView")
show = SKSpriteNode(imageNamed: "show")
show.anchorPoint = CGPointZero
show.position = CGPointZero
addChild(show)
hide = SKSpriteNode(imageNamed: "hide")
hide.anchorPoint = CGPointZero
hide.position = CGPoint(x: self.frame.width / 2 - hide.frame.width / 2, y: 0)
addChild(hide)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches{
let location = touch.locationInNode(self)
let node = nodeAtPoint(location)
if node == show{
print("show")
showCharPicker()
}
else if node == hide{
print("hide")
hideCharPicker()
}
}
}
}
GameViewController.swift
import UIKit
import SpriteKit
class GameViewController: UIViewController, iCarouselDataSource, iCarouselDelegate{
var squaresArray : NSMutableArray = NSMutableArray()
@IBOutlet weak var carousel: iCarousel!
deinit{
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func showCarousel(){
self.carousel.hidden = false
}
func hideCarousel(){
self.carousel.hidden = true
}
override func viewDidLoad(){
super.viewDidLoad()
// Configure iCarousel
carousel.dataSource = self
carousel.delegate = self
carousel.type = .CoverFlow
carousel.reloadData()
self.carousel.hidden = true
// Register showCarousel and hideCarousel functions
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.showCarousel), name: "showCharPicker", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.hideCarousel), name: "hideCharPicker", object: nil)
// Configure view
let skView = SKView()
self.view.insertSubview(skView, belowSubview: self.carousel)
skView.frame = self.view.bounds
// Additionals
skView.showsFPS = true
skView.showsNodeCount = true
skView.ignoresSiblingOrder = true
// Configure scene
let scene = GameScene(size:self.view.bounds.size)
scene.scaleMode = .ResizeFill
scene.size = self.view.bounds.size
skView.presentScene(scene)
}
//iCarousel
override func awakeFromNib(){
super.awakeFromNib()
squaresArray = NSMutableArray(array: ["square1","square2","square3"])
}
func numberOfItemsInCarousel(carousel: iCarousel) -> Int{
return squaresArray.count
}
func carousel(carousel:iCarousel, didSelectItemAtIndex index:NSInteger){
//self.hideCarousel()
}
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: "\(squaresArray.objectAtIndex(index))")
return itemView
}
func carousel(carousel: iCarousel, valueForOption option: iCarouselOption, withDefault value: CGFloat) -> CGFloat{
if (option == .Spacing){
return value * 2
}
return value
}
}
What's happening:
Thanks in advance,
Luiz.
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)
}
}
If you want to change hit detection, you need to subclass the view for which you need it to change. This case your iCarousel
view.
You can then either override hitTest
or pointInside
. I've created an iCarousel
subclass and overrode pointInside
to only return true when the point is inside one of the carousel's contentView
's subviews.
class CarouselSubclass: iCarousel {
override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
var inside = false
for view in self.contentView.subviews
{
inside = CGRectContainsPoint(view.frame, point)
if inside
{
return inside
}
}
return inside
}
}
You need to remember to change the class of your carousel in interface builder and update your outlet as well.
这篇关于精灵套件中的iCarousel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!