创建多个略有变化的精灵节点?
creating multiple sprite nodes with slight variations?
我有一个显示多个成就的游戏菜单,这些成就被定义为 SKSpriteNodes,其中有 18 个,它们在位置上只有轻微的变化,这里是代码片段:
Achievement1 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
Achievement1.position = CGPointMake(-120, 100)
page1ScrollView.addChild(Achievement1)
Achievement2 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
Achievement2.position = CGPointMake(0, 100)
page1ScrollView.addChild(Achievement2)
Achievement3 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
Achievement3.position = CGPointMake(120, 100)
page1ScrollView.addChild(Achievement3)
Achievement4 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
Achievement4.position = CGPointMake(-120, -25)
page1ScrollView.addChild(Achievement4)
我也竭尽全力将它们一一定义为变量,如下所示:
var Achievement1: SKSpriteNode!
var Achievement2 = SKSpriteNode()
var Achievement3 = SKSpriteNode()
var Achievement4 = SKSpriteNode()
var Achievement5 = SKSpriteNode()
var Achievement6 = SKSpriteNode()
var Achievement7 = SKSpriteNode()
var Achievement8 = SKSpriteNode()
它看起来一团糟,只是占用了太多空间 space。我希望能够定义所有的 sprite 节点,并让它们都能够被按下以显示一个框,说明成就是什么,如下所示:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch: UITouch = touches.first!
let location: CGPoint = touch.locationInNode(self)
let node: SKNode = self.nodeAtPoint(location)
if (node == Achievement1) {
//achievement details here
}
我对这种 swift 语言还是陌生的,我也不是很先进,但我很感激你的帮助。
你可以使用数组...
let achievements = [SKSpriteNode](repeating: SKSpriteNode(color: SKColor.white(), size: CGSize(width: 100, height: 100)), count: 8) // Swift 3 colour name
let positions = [CGPoint(x: -120, y: 100), CGPoint(x: 0, y: 100) /* ... */]
for i in 0 ..< min(achievements.count, positions.count) { // For safety - obviously these should be the same
achievements[i].position = positions[i]
}
// Then in your touch routine...
if let index = achievements.index(of: self.nodeAtPoint(location)) {
// do something with achievements[index]
}
...并且不要将变量大写 - Swift 惯例是只有类型才大写...
关于布局 当你有大量项目要显示时,你可以考虑使用 table 或页面控件。因为我很懒惰,所以我不喜欢滚动 table 只是为了查看所有游戏成就,所以通常我更喜欢使用 PageControl。
您可以构建 UIKit
您的 UIPageControl
并将其集成到您的游戏菜单中。
如果你不知道如何集成 UIPageControl
你可以使用这个 sprite-kit 项目 GBPageControl
import GBPageControl
var pageControl:PageControl!
//Add the page control to the scene. Add any content that will be paged directly to the pageControl:
override func didMoveToView(view: SKView) {
pageControl = PageControl(scene: self)
addContent()
pageControl.enable(4)
}
private func addContent() {
for var i = 0; i < 4; i++ {
let node = SKShapeNode(circleOfRadius: 10)
node.strokeColor = UIColor.blueColor()
let x = self.size.width / 2.0 + self.size.width * CGFloat(i)
let y = self.size.height / 2.0
node.position = CGPoint(x:x, y:y)
pageControl.addChild(node)
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
if pageControl.handleTouch(touch) {
//no op
}
else {
//handle touch
}
}
}
override func willMoveFromView(view: SKView) {
pageControl.willMoveFromView(view)
}
输出:
更新:
关于您的成就代码,您可以尝试这样做:
enum MedalType: Int {
case Gold = 1
case Silver = 2
case Bronze = 3
}
class Achievement:SKSpriteNode {
init(color:SKColor,size:CGSize,name:String,medalType:MedalType) {
super.init(texture: nil,color:color,size:size)
self.name = name
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class GameScene: SKScene {
var achievements:[Achievement]!
var aNames: [String]!
var totalAchievements: Int = 45
override func didMoveToView(view: SKView) {
var counter : Int = 0
let deltaX:CGFloat = 120
let deltaY:CGFloat = 10
for i in 0..<totalAchievements {
var aColor = SKColor.whiteColor()
var aSize = CGSizeMake(100,100)
var medal = MedalType.Bronze
switch i {
case 10:
aColor = SKColor.redColor()
aSize = CGSizeMake(100,150)
medal = MedalType.Silver
case 25:
aColor = SKColor.blueColor()
aSize = CGSizeMake(100,200)
medal = MedalType.Gold
default:
break
}
let name = "achievement\(i)"
let a = Achievement.init(color: aColor, size: aSize, name: name, medalType: medal)
aNames.append(name)
//handle your position has you wish with counter, deltaX e deltaY
//...
a.position = CGPointMake(deltaX, deltaY)
addChild(a)
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch: UITouch = touches.first!
let location: CGPoint = touch.locationInNode(self)
let node: SKNode = self.nodeAtPoint(location)
if (aNames.contains(node.name!)) {
print("You have touch achievement \(node.name)")
let currentAchievement = achievements[aNames.indexOf(node.name!)!]
// Use your currentAchievement touched
}
}
}
如果您认为您的代码一团糟,请尝试在您的代码中找到模式。
看到那些 Achievement1
、Achievement2
、Achievement3
、Achievement4
东西了吗?当你看到这种模式时,你可能应该创建一个数组来存储成就。
我相信你知道如何使用数组,所以我就不多说了。有关更多信息,您可以转到 Array
class.
的定义
您可能会注意到的另一种模式是您使用相同的参数来创建精灵节点。成就之间的唯一区别是他们的位置。
解决此问题的最佳方法是创建一个方法:
func createAchievement(location: CGPoint) -> SKSpriteNode {
let node = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
node.position = location
return node
}
而您只需要一行就可以将新成就添加到上述数组中:
someArray.append(createAchievement(CGPointMake(-120, 100)))
编辑:
如果您使用 indexOf(_:)
(或 swift 3 中的 index(of:)
),您可以创建一个 switch 语句而不是 if 语句:
switch someArray.indexOf(node) {
case 0:
// this means that the first achievement is tapped!
case 1:
// this means that the second achievement is tapped!
case 2:
// this means that the third achievement is tapped!
}
我有一个显示多个成就的游戏菜单,这些成就被定义为 SKSpriteNodes,其中有 18 个,它们在位置上只有轻微的变化,这里是代码片段:
Achievement1 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
Achievement1.position = CGPointMake(-120, 100)
page1ScrollView.addChild(Achievement1)
Achievement2 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
Achievement2.position = CGPointMake(0, 100)
page1ScrollView.addChild(Achievement2)
Achievement3 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
Achievement3.position = CGPointMake(120, 100)
page1ScrollView.addChild(Achievement3)
Achievement4 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
Achievement4.position = CGPointMake(-120, -25)
page1ScrollView.addChild(Achievement4)
我也竭尽全力将它们一一定义为变量,如下所示:
var Achievement1: SKSpriteNode!
var Achievement2 = SKSpriteNode()
var Achievement3 = SKSpriteNode()
var Achievement4 = SKSpriteNode()
var Achievement5 = SKSpriteNode()
var Achievement6 = SKSpriteNode()
var Achievement7 = SKSpriteNode()
var Achievement8 = SKSpriteNode()
它看起来一团糟,只是占用了太多空间 space。我希望能够定义所有的 sprite 节点,并让它们都能够被按下以显示一个框,说明成就是什么,如下所示:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch: UITouch = touches.first!
let location: CGPoint = touch.locationInNode(self)
let node: SKNode = self.nodeAtPoint(location)
if (node == Achievement1) {
//achievement details here
}
我对这种 swift 语言还是陌生的,我也不是很先进,但我很感激你的帮助。
你可以使用数组...
let achievements = [SKSpriteNode](repeating: SKSpriteNode(color: SKColor.white(), size: CGSize(width: 100, height: 100)), count: 8) // Swift 3 colour name
let positions = [CGPoint(x: -120, y: 100), CGPoint(x: 0, y: 100) /* ... */]
for i in 0 ..< min(achievements.count, positions.count) { // For safety - obviously these should be the same
achievements[i].position = positions[i]
}
// Then in your touch routine...
if let index = achievements.index(of: self.nodeAtPoint(location)) {
// do something with achievements[index]
}
...并且不要将变量大写 - Swift 惯例是只有类型才大写...
关于布局 当你有大量项目要显示时,你可以考虑使用 table 或页面控件。因为我很懒惰,所以我不喜欢滚动 table 只是为了查看所有游戏成就,所以通常我更喜欢使用 PageControl。
您可以构建 UIKit
您的 UIPageControl
并将其集成到您的游戏菜单中。
如果你不知道如何集成 UIPageControl
你可以使用这个 sprite-kit 项目 GBPageControl
import GBPageControl
var pageControl:PageControl!
//Add the page control to the scene. Add any content that will be paged directly to the pageControl:
override func didMoveToView(view: SKView) {
pageControl = PageControl(scene: self)
addContent()
pageControl.enable(4)
}
private func addContent() {
for var i = 0; i < 4; i++ {
let node = SKShapeNode(circleOfRadius: 10)
node.strokeColor = UIColor.blueColor()
let x = self.size.width / 2.0 + self.size.width * CGFloat(i)
let y = self.size.height / 2.0
node.position = CGPoint(x:x, y:y)
pageControl.addChild(node)
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
if pageControl.handleTouch(touch) {
//no op
}
else {
//handle touch
}
}
}
override func willMoveFromView(view: SKView) {
pageControl.willMoveFromView(view)
}
输出:
更新:
关于您的成就代码,您可以尝试这样做:
enum MedalType: Int {
case Gold = 1
case Silver = 2
case Bronze = 3
}
class Achievement:SKSpriteNode {
init(color:SKColor,size:CGSize,name:String,medalType:MedalType) {
super.init(texture: nil,color:color,size:size)
self.name = name
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class GameScene: SKScene {
var achievements:[Achievement]!
var aNames: [String]!
var totalAchievements: Int = 45
override func didMoveToView(view: SKView) {
var counter : Int = 0
let deltaX:CGFloat = 120
let deltaY:CGFloat = 10
for i in 0..<totalAchievements {
var aColor = SKColor.whiteColor()
var aSize = CGSizeMake(100,100)
var medal = MedalType.Bronze
switch i {
case 10:
aColor = SKColor.redColor()
aSize = CGSizeMake(100,150)
medal = MedalType.Silver
case 25:
aColor = SKColor.blueColor()
aSize = CGSizeMake(100,200)
medal = MedalType.Gold
default:
break
}
let name = "achievement\(i)"
let a = Achievement.init(color: aColor, size: aSize, name: name, medalType: medal)
aNames.append(name)
//handle your position has you wish with counter, deltaX e deltaY
//...
a.position = CGPointMake(deltaX, deltaY)
addChild(a)
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch: UITouch = touches.first!
let location: CGPoint = touch.locationInNode(self)
let node: SKNode = self.nodeAtPoint(location)
if (aNames.contains(node.name!)) {
print("You have touch achievement \(node.name)")
let currentAchievement = achievements[aNames.indexOf(node.name!)!]
// Use your currentAchievement touched
}
}
}
如果您认为您的代码一团糟,请尝试在您的代码中找到模式。
看到那些 Achievement1
、Achievement2
、Achievement3
、Achievement4
东西了吗?当你看到这种模式时,你可能应该创建一个数组来存储成就。
我相信你知道如何使用数组,所以我就不多说了。有关更多信息,您可以转到 Array
class.
您可能会注意到的另一种模式是您使用相同的参数来创建精灵节点。成就之间的唯一区别是他们的位置。
解决此问题的最佳方法是创建一个方法:
func createAchievement(location: CGPoint) -> SKSpriteNode {
let node = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
node.position = location
return node
}
而您只需要一行就可以将新成就添加到上述数组中:
someArray.append(createAchievement(CGPointMake(-120, 100)))
编辑:
如果您使用 indexOf(_:)
(或 swift 3 中的 index(of:)
),您可以创建一个 switch 语句而不是 if 语句:
switch someArray.indexOf(node) {
case 0:
// this means that the first achievement is tapped!
case 1:
// this means that the second achievement is tapped!
case 2:
// this means that the third achievement is tapped!
}