使用SpriteKit在swift中编写我自己的游戏我遇到了一个似乎无法解决的问题。 我正在编写的游戏是针对OS X平台(非移动),使用非常标准的代码布局:
首先是我的AppDelegate:
import Cocoa
import SpriteKit
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate
{
@IBOutlet weak var window: NSWindow!
@IBOutlet weak var skView: SKView!
func applicationDidFinishLaunching(aNotification: NSNotification)
{
/* Pick a size for the scene */
if let scene = MainMenu(fileNamed:"MainMenu")
{
scene.size = CGSize(width: 1024, height: 768)
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFit
scene.backgroundColor = NSColor.blackColor()
self.skView!.presentScene(scene)
/* Sprite Kit applies additional optimizations to improve rendering performance */
self.skView!.ignoresSiblingOrder = true
self.skView!.showsFPS = true
self.skView!.showsNodeCount = true
window.acceptsMouseMovedEvents = true
}
}
func applicationShouldTerminateAfterLastWindowClosed(sender: NSApplication) -> Bool
{
return true
}
}
这会打开MainMenu场景,我有很多按钮,每个按钮都会导致其他场景。对于按钮,我已经创建了自己的SPriteKitNode子类:
import Foundation
import SpriteKit
class Button: SKSpriteNode
{
var isHighLighted = false
var isPressed = false
var normal: SKTexture
var highlighted: SKTexture
var pressed: SKTexture
var disabled: SKTexture
var isDisabled = false
init(normal: SKTexture, highlighted: SKTexture, pressed: SKTexture, disabled: SKTexture)
{
self.normal = normal
self.highlighted = highlighted
self.pressed = pressed
self.disabled = disabled
super.init(texture: normal, color: NSColor.clearColor(), size: normal.size())
}
required init?(coder aDecoder: NSCoder)
{
normal = SKTexture()
highlighted = SKTexture()
pressed = SKTexture()
disabled = SKTexture()
super.init(coder: aDecoder)
}
func disableButton()
{
self.texture = disabled
isDisabled = true
}
func enableButton()
{
self.texture = normal
isDisabled = false
}
//overrides
override func mouseEntered(theEvent: NSEvent)
{
if !isDisabled
{
isHighLighted = true
self.texture = highlighted
}
}
override func mouseExited(theEvent: NSEvent)
{
if !isDisabled
{
isHighLighted = false
self.texture = normal
}
}
override func mouseDown(theEvent: NSEvent)
{
if !isDisabled
{
isPressed = true
self.texture = pressed
scene?.mouseDown(theEvent)
}
}
override func mouseUp(theEvent: NSEvent)
{
if !isDisabled
{
isPressed = false
self.texture = highlighted
}
}
}
主菜单(不是完整的代码)在这里:
import SpriteKit
class MainMenu: SKScene
{
let quickGame = Button(normal: SKTexture(imageNamed: "quick"), highlighted: SKTexture(imageNamed: "quick-high"), pressed: SKTexture(imageNamed: "quick-down"), disabled: SKTexture(imageNamed: "quick-dis"))
override func didMoveToView(view: SKView)
{
let options = NSTrackingAreaOptions.MouseMoved.union(NSTrackingAreaOptions.ActiveInKeyWindow)
let trackingArea = NSTrackingArea(rect: view.frame, options: options, owner: self, userInfo: nil)
view.addTrackingArea(trackingArea)
let background = SKSpriteNode(imageNamed: "splash")
background.position = CGPoint(x: background.size.width, y: background.size.height)
background.userInteractionEnabled = true
background.position = CGPoint.zero
background.anchorPoint = CGPoint.zero
background.zPosition = 0
//background.setScale(1.0)
self.addChild(background)
//let background = self.childNodeWithName("splash")
//let quickGame = Button(normal: textureAtlas.textureNamed("quick"), highlighted: textureAtlas.textureNamed("quick-high"), pressed: textureAtlas.textureNamed("quick-down"))
quickGame.name = "quick game"
quickGame.anchorPoint = CGPoint.zero
quickGame.position = CGPoint(x: 230, y: 97)
quickGame.userInteractionEnabled = true
quickGame.zPosition = 100
background.addChild(quickGame)
… rest of init here…
}
override func mouseDown(theEvent: NSEvent)
{
if newGame.isPressed
{
}
else if quickGame.isPressed
{
if let quickGameScene = QuickGame(fileNamed: "QuickGame")
{
quickGameScene.scaleMode = self.scaleMode
let transition = SKTransition.fadeWithDuration(1.0)
self.removeAllChildren()
self.removeAllActions()
view?.presentScene(quickGameScene, transition: transition)
}
}
else if quitGame.isPressed
{
NSApp.terminate(self)
}
}
}
当我点击quickGame按钮时,我收到了EXC_BAD_ACCESS。点击确定,新场景显示但是在第二次或第二次游戏崩溃后,错误被放置在Ainside AppDelegate类声明中。
我怀疑我在Button类中调用mouseDown做错了。
我希望在这里完成的是事件驱动系统,当事件触发时,消息从按钮发送到场景类,我不需要遍历所有按钮(因为在某些场景中会有很多按钮和可按下/可选元素),但只执行代码(在我目前的情况下切换场景)。
我做了一些调试,在MainMenu类调试器中更改场景之后回到了Button类,所以我认为问题就在于切换场景这个MainMen enter code here
u实例可能与所有按钮一起被破坏和元素,当代码返回Button时,它的实例不再存在。我不是100%,也不知道如何解决这个问题,因为我已经开始使用swift和SPriteKit了。
答案 0 :(得分:-1)
在一些日本论坛上找到了解决方案。 custom button for spritekit in swift
这可以在OS X和iOS上使用。
解决问题的方法是使用包含按钮函数的Protocol on Scene类,并通过可选委托(父场景实例)从按钮类调用这些函数。