osx - Getting EXC_BAD_ACCESS in spritekit game in Swift 2.1 -
writting own game in swift using spritekit came on 1 problem seems cannot solve. game i'm writting os x platform (not mobile), using pretty standard code layout:
first here 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 size scene */ if let scene = mainmenu(filenamed:"mainmenu") { scene.size = cgsize(width: 1024, height: 768) /* set scale mode scale fit window */ scene.scalemode = .aspectfit scene.backgroundcolor = nscolor.blackcolor() self.skview!.presentscene(scene) /* sprite kit applies additional optimizations 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 } }
this opens mainmenu scene have many buttons each leads other scenes. buttons have made own subclass of 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 } } }
and main menu (not complete code) here:
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) } } }
i'm getting exc_bad_access thrown when click on quickgame button. click goes ok, new scene shows after second or 2 game crashes , error placed ainside appdelegate class declaration.
i'm suspecting have done wrong placement of call of mousedown inside button class.
what wish accomplish here have event-driven system , when event fires, message sent button scene class don't need iterate on buttons (because in scenes there lot of buttons , pressable/selectable elements), execute code (in current case switch scene).
i have done debugging , after changing scene in mainmenu class debugger went button class, i'm thinking problem lies there switching scenes mainmenenter code here
u instance destroyed along buttons , elements , when code returns button, instance of doesn't exists anymore. i'm not 100% , don't know how solve have jsut started work swift , spritekit.
the found solution on japanesse forum. custom button spritekit in swift
this can used on os x , ios.
the solution problem use protocol on scene class includes button functions , call functions button class via optional delegate (parent scene instance).
Comments
Post a Comment