I have a NSViewController/NSView with a SpriteKit Scene filling the whole view. Here are the events I need to handle:
override func mouseDown(with event: NSEvent) {
override func rightMouseDown(with event: NSEvent) {
override func otherMouseDown(with event: NSEvent) {
override func mouseDragged(with event: NSEvent) {
override func rightMouseDragged(with event: NSEvent) {
override func otherMouseDragged(with event: NSEvent) {
But they are very inconsistent, and I'm not able to get rightMouseDragged working at all.
mouseDown works fine in the SKScene
rightMouseDown works fine in the SKScene
otherMouseDown had to be implemented in the viewController and passed on to the scene
mouseDragged worked fine in the SKScene
rightMouseDragged is not working at all
otherMouseDragged had to be implemented in the viewController and passed on to the scene
My main need is to fix rightMouseDragged. It doesn't receive any dragged events either in the view controller or the scene controller.
Ok, I don't understand why, but the rightMouseDragged was being delivered to the SKView. So here's where I needed to implement my event handlers:
mouseDown in the SKScene
rightMouseDown in the SKScene
otherMouseDown in the viewController and passed on to the scene
mouseDragged in the SKScene
rightMouseDragged in the SKView and be passed to the scene
otherMouseDragged in the viewController and passed on to the scene
Related
I'm new to SpriteKit and starting to collect some experience.
What I currently can not understand is how to mix a GameScene with my own code?
So, there is a way to do all manually like this:
class GameScene: SKScene {
override func didMove(to view: SKView) {
//...
}
override func update(_ currentTime: TimeInterval) {
//...
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//...
}
}
And then pass it to my SpriteView:
SpriteView(scene: GameScene())
This is fine, so I can do everything in Swift by code. To use a .sks GameScene file its also easy by using:
SpriteView(scene: SKScene(fileNamed: "MyScene")!)
BUT what I need to do to override the methods in MyScene and access the Sprites I created via the editor?
I found it in the example. I can use the Custom Class property in the .sks file
I'm trying to make a first person game where moving the mouse changes the camera angle, similar to in Roblox in first person mode or in Minecraft. How to do that? I'm asking how to do basic functionality so there is no code to provide. I just need to know how to hide and lock the cursor position in Swift or more specifically Metal or Cocoa.
You can subclass NSView, add a tracking area for mouse entered and exited, override NSView mouseEntered and mouseExited methods and just hide and unhide the cursor there:
import Cocoa
class HiddenCursorView: NSView {
override func awakeFromNib() {
addTrackingArea(NSTrackingArea(rect: bounds, options: [.activeAlways, .mouseEnteredAndExited], owner: self, userInfo: nil))
}
override func mouseEntered(with event: NSEvent) {
NSCursor.hide()
}
#objc override func mouseExited(with event: NSEvent) {
NSCursor.unhide()
}
}
this probably has something to do with the fact that I am overriding touchesBegan in my custom subclass:
class myCustomButton: UIButton {
override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
print("TOUCHES BEGAN OVERRIDE CALLED")
originalColor = self.backgroundColor ?? .red
self.backgroundColor = .white
self.animateScale()
setNeedsDisplay()
}
//...
}
touchesEnded is similarly overridden, and both of these functions are called and print debug statements to console on button press. however, the code in the button pressed IBAction from my view controller is never run
#IBAction func nextButtonPressed(_ sender: Any) {
print("this is never executed")
//...
}
I have double checked that the IBOutlet is not broken and changed the (_ sender: Any) to (_ sender: AnyObject) both to no avail. any insights would be appreciated
ah ok, figured it out. in my custom button initializer I added a subview which, by default, had userInteractionEnabled set to true. setting userInteractionEnabled = true on my custom button object and userInteractionEnabled = false on my view before adding it as a subview allows my custom button to capture the touch and handle it properly rather than the view capturing the touch
Instead of overriding touchesBegan, try overriding the sendAction function of your UIButton:
override func sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
super.sendAction(action, to: target, for: event)
//Insert your code here
}
Everything works fine,but then when I add the apple,it only stays on screen for a very short amount of time, and then it goes away/disappears. Why is this? any help would be much appreciated.
import SpriteKit
class GameScene: SKScene {
var bg=SKSpriteNode()
var apple=SKSpriteNode()
override func didMoveToView(view: SKView) {
/* Setup your scene here */
let bg_texture=SKTexture(imageNamed: "wood-texture-pattern.jpg")
bg=SKSpriteNode(texture: bg_texture)
bg.position=CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
bg.size.height=self.frame.height
bg.size.width=self.frame.width
self.addChild(bg)
let applePic=SKTexture(imageNamed:"apple.png")
apple=SKSpriteNode(texture:applePic)
apple.position=CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame))
// apple.size.height=50
// apple.size.width=50
apple.setScale(0.25)
self.addChild(apple)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
Change the zPosition of the skspritenode
In my GameScene, when I update variables using 'touchesBegan()' it works fine, but when I pass 'pressesBegan()' from the GameViewController to the GameScene, the code gets excited, but the changes get ignored.
GameViewController:
class GameViewController: UIViewController {
...
override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
let scene = GameScene(fileNamed: "GameScene")
scene?.pressesBegan(presses, withEvent: event)
}
GameScene:
class GameScene: SKScene {
var test = true
...
override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
test = false
print(test)
}
override func update(currentTime: CFTimeInterval) {
print(test)
}
}
This code will result in "false" then "true" in the console.
Every time you call pressesBegan, you are creating a new Gamescene, you need to do
override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
if let skView = self.view as? SKView
{
skView.scene?.pressesBegan(presses, withEvent: event)
}
}