我想用我的游戏(In SpriteKit)创建一个带有按钮和图像的商店,但是我需要这些项目可以滚动,这样玩家就可以在商店中上下滚动(就像一个UITableView,但每个都有多个SKSpriteNodes和SKLabelNodes)细胞).知道如何在SpriteKit中做到这一点吗?
cra*_*777 17
承诺的第二个答案,我只是想出了问题.
我建议总是从我的gitHub项目中获取此代码的最新版本,因为我做了更改,因为这个答案,链接在底部.
第1步:创建一个新的swift文件并粘贴此代码
import SpriteKit
/// Scroll direction
enum ScrollDirection {
case vertical // cases start with small letters as I am following Swift 3 guildlines.
case horizontal
}
class CustomScrollView: UIScrollView {
// MARK: - Static Properties
/// Touches allowed
static var disabledTouches = false
/// Scroll view
private static var scrollView: UIScrollView!
// MARK: - Properties
/// Current scene
private let currentScene: SKScene
/// Moveable node
private let moveableNode: SKNode
/// Scroll direction
private let scrollDirection: ScrollDirection
/// Touched nodes
private var nodesTouched = [AnyObject]()
// MARK: - Init
init(frame: CGRect, scene: SKScene, moveableNode: SKNode) {
self.currentScene = scene
self.moveableNode = moveableNode
self.scrollDirection = scrollDirection
super.init(frame: frame)
CustomScrollView.scrollView = self
self.frame = frame
delegate = self
indicatorStyle = .White
scrollEnabled = true
userInteractionEnabled = true
//canCancelContentTouches = false
//self.minimumZoomScale = 1
//self.maximumZoomScale = 3
if scrollDirection == .horizontal {
let flip = CGAffineTransformMakeScale(-1,-1)
transform = flip
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
// MARK: - Touches
extension CustomScrollView {
/// Began
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(currentScene)
guard !CustomScrollView.disabledTouches else { return }
/// Call touches began in current scene
currentScene.touchesBegan(touches, withEvent: event)
/// Call touches began in all touched nodes in the current scene
nodesTouched = currentScene.nodesAtPoint(location)
for node in nodesTouched {
node.touchesBegan(touches, withEvent: event)
}
}
}
/// Moved
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(currentScene)
guard !CustomScrollView.disabledTouches else { return }
/// Call touches moved in current scene
currentScene.touchesMoved(touches, withEvent: event)
/// Call touches moved in all touched nodes in the current scene
nodesTouched = currentScene.nodesAtPoint(location)
for node in nodesTouched {
node.touchesMoved(touches, withEvent: event)
}
}
}
/// Ended
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(currentScene)
guard !CustomScrollView.disabledTouches else { return }
/// Call touches ended in current scene
currentScene.touchesEnded(touches, withEvent: event)
/// Call touches ended in all touched nodes in the current scene
nodesTouched = currentScene.nodesAtPoint(location)
for node in nodesTouched {
node.touchesEnded(touches, withEvent: event)
}
}
}
/// Cancelled
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
for touch in touches! {
let location = touch.locationInNode(currentScene)
guard !CustomScrollView.disabledTouches else { return }
/// Call touches cancelled in current scene
currentScene.touchesCancelled(touches, withEvent: event)
/// Call touches cancelled in all touched nodes in the current scene
nodesTouched = currentScene.nodesAtPoint(location)
for node in nodesTouched {
node.touchesCancelled(touches, withEvent: event)
}
}
}
}
// MARK: - Touch Controls
extension CustomScrollView {
/// Disable
class func disable() {
CustomScrollView.scrollView?.userInteractionEnabled = false
CustomScrollView.disabledTouches = true
}
/// Enable
class func enable() {
CustomScrollView.scrollView?.userInteractionEnabled = true
CustomScrollView.disabledTouches = false
}
}
// MARK: - Delegates
extension CustomScrollView: UIScrollViewDelegate {
func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollDirection == .horizontal {
moveableNode.position.x = scrollView.contentOffset.x
} else {
moveableNode.position.y = scrollView.contentOffset.y
}
}
}
Run Code Online (Sandbox Code Playgroud)
这将构成UIScrollView的子类并设置它的基本属性.它有自己的触摸方法,它被传递到相关的场景.
第2步:在您想要使用它的相关场景中,您可以创建滚动视图和可移动节点属性
weak var scrollView: CustomScrollView!
let moveableNode = SKNode()
Run Code Online (Sandbox Code Playgroud)
并将它们添加到didMoveToView中的场景中
scrollView = CustomScrollView(frame: CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height), scene: self, moveableNode: moveableNode, scrollDirection: .vertical)
scrollView.contentSize = CGSizeMake(self.frame.size.width, self.frame.size.height * 2)
view?.addSubview(scrollView)
addChild(moveableNode)
Run Code Online (Sandbox Code Playgroud)
您在第1行中执行的操作是使用场景维度初始化滚动视图助手.您还可以传递场景以供参考,以及您在步骤2中创建的moveableNode.第2行是您设置scrollView的内容大小的位置,在这种情况下,它是屏幕高度的两倍.
步骤3: - 添加标签或节点等并定位它们.
label1.position.y = CGRectGetMidY(self.frame) - self.frame.size.height
moveableNode.addChild(label1)
Run Code Online (Sandbox Code Playgroud)
在此示例中,标签将位于scrollView的第2页上.这是您必须使用标签和定位的地方.
我建议如果滚动视图中有很多页面,并且有很多标签要执行以下操作.在滚动视图中为每个页面创建一个SKSpriteNode,并使每个页面都与屏幕大小相同.将它们称为page1Node,page2Node等.您可以将第二页上所需的所有标签添加到page2Node.这里的好处是你基本上可以像往常一样在page2Node中定位你所有的东西,而不仅仅是在scrollView中定位page2Node.
你也很幸运,因为垂直使用scrollView(你说你想要的)你不需要做任何翻转和反向定位.
我做了一些类func,所以如果你需要禁用你的scrollView,你可以在scrollView上覆盖另一个菜单.
CustomScrollView.enable()
CustomScrollView.disable()
Run Code Online (Sandbox Code Playgroud)
最后不要忘记在转换到新场景之前从场景中删除滚动视图.在spritekit中处理UIKit时的痛苦之一.
scrollView?.removeFromSuperView()
Run Code Online (Sandbox Code Playgroud)
对于水平滚动,只需将init方法上的滚动方向更改为.horizontal(步骤2).
而现在最大的痛苦是在定位东西时一切都在逆转.所以滚动视图从右到左.因此,您需要使用scrollView"contentOffset"方法重新定位它,并且基本上从右到左以相反的顺序放置所有标签.一旦了解了发生的事情,再次使用SkNodes可以更轻松.
希望这对大量的帖子有帮助和抱歉,但正如我所说,spritekit有点痛苦.让我知道它是怎么回事,如果我错过了什么.
项目在gitHub上
https://github.com/crashoverride777/SwiftySKScrollView
您有2个选择
1)使用UIScrollView
沿途,这是更好的解决方案,因为您可以免费获得动量滚动,分页,弹跳效果等功能。但是,您必须使用大量UIKit内容或进行一些子类化才能使其与SKSpritenodes或标签一起使用。
检查我在gitHub上的项目的示例
https://github.com/crashoverride777/SwiftySKScrollView
2)使用SpriteKit
Declare 3 class variables outside of functions(under where it says 'classname': SKScene):
var startY: CGFloat = 0.0
var lastY: CGFloat = 0.0
var moveableArea = SKNode()
Run Code Online (Sandbox Code Playgroud)
设置您的didMoveToView,将SKNode添加到场景中并添加2个标签,一个用于顶部,一个用于底部,以查看其工作情况!
override func didMoveToView(view: SKView) {
// set position & add scrolling/moveable node to screen
moveableArea.position = CGPointMake(0, 0)
self.addChild(moveableArea)
// Create Label node and add it to the scrolling node to see it
let top = SKLabelNode(fontNamed: "Avenir-Black")
top.text = "Top"
top.fontSize = CGRectGetMaxY(self.frame)/15
top.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMaxY(self.frame)*0.9)
moveableArea.addChild(top)
let bottom = SKLabelNode(fontNamed: "Avenir-Black")
bottom.text = "Bottom"
bottom.fontSize = CGRectGetMaxY(self.frame)/20
bottom.position = CGPoint(x:CGRectGetMidX(self.frame), y:0-CGRectGetMaxY(self.frame)*0.5)
moveableArea.addChild(bottom)
}
Run Code Online (Sandbox Code Playgroud)
然后设置您的触摸开始存储您的第一次触摸的位置:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
// store the starting position of the touch
let touch: AnyObject? = touches.anyObject();
let location = touch?.locationInNode(self)
startY = location!.y
lastY = location!.y
}
Run Code Online (Sandbox Code Playgroud)
然后使用以下代码设置移动的触摸,以设置的速度将节点滚动到设置的限制:
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
let touch: AnyObject? = touches.anyObject();
let location = touch?.locationInNode(self)
// set the new location of touch
var currentY = location!.y
// Set Top and Bottom scroll distances, measured in screenlengths
var topLimit:CGFloat = 0.0
var bottomLimit:CGFloat = 0.6
// Set scrolling speed - Higher number is faster speed
var scrollSpeed:CGFloat = 1.0
// calculate distance moved since last touch registered and add it to current position
var newY = moveableArea.position.y + ((currentY - lastY)*scrollSpeed)
// perform checks to see if new position will be over the limits, otherwise set as new position
if newY < self.size.height*(-topLimit) {
moveableArea.position = CGPointMake(moveableArea.position.x, self.size.height*(-topLimit))
}
else if newY > self.size.height*bottomLimit {
moveableArea.position = CGPointMake(moveableArea.position.x, self.size.height*bottomLimit)
}
else {
moveableArea.position = CGPointMake(moveableArea.position.x, newY)
}
// Set new last location for next time
lastY = currentY
}
Run Code Online (Sandbox Code Playgroud)
所有功劳归于本文
http://greenwolfdevelopment.blogspot.co.uk/2014/11/scrolling-in-sprite-kit-swift.html
| 归档时间: |
|
| 查看次数: |
7869 次 |
| 最近记录: |