Very low level question but;
Why wont this compile for me? I copied it down exactly from a tutorial and it worked before I updated my xcode to a newer version to do things later in the tutorial but I guess it updated too far ahead. Thanks for any help you can offer.
import SpriteKit
class GameScene: SKScene {
let Mainball = SKSpriteNode(imageNamed: "Ball")
override func didMoveToView(view: SKView) {
/* Setup your scene here */
Mainball.size = CGSize(width: 100, height: 100)
Mainball.position = CGPoint(x: scene!.frame.width / 2, y: scene!.frame.height / 2)
self.addChild(Mainball)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch in touches {
let location = touch.locationInNode(self)
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
Related
I have been experimenting with mouse clicks. I am ok with left mouse clicks getting raw values etc etc. I now want to add right mouse clicks. I have setup a basic example. What i would like to achieve if there is one mouse right click it performs one function, and if there is two mouse right clicks it performs a different function. The problem is if you do two mouse clicks it obviously cannot differentiate between the two and so fire the one mouse click function before performing the second mouse function.
I was thinking of maybe using a timer of some sort to record the number of click. But i end up going round in circles as i just seem to start the timers over and over. I'm hoping some one might help. thanks for reading here is the code.
Xcode 8 Swift 3 Mac OSX Sierra NOT IOS.. NOT IOS
import Cocoa
class MainWindowController: NSWindowController {
#IBOutlet weak var MyView: NSView!
override func windowDidLoad() {
super.windowDidLoad()
//Initialize mouse for Right Click numberOfClicksRequired = 1
let recogRightClick1 = NSClickGestureRecognizer(target: self, action: #selector(oneMouseClick))
recogRightClick1.buttonMask = 0x2
recogRightClick1.numberOfClicksRequired = 1
MyView.addGestureRecognizer(recogRightClick1)
//Initialize mouse for Right ClicknumberOfClicksRequired = 2
let recogRightClick2 = NSClickGestureRecognizer(target: self, action: #selector(twoMouseClick(myrec:myRightClick:)))
recogRightClick2.buttonMask = 0x2
recogRightClick2.numberOfClicksRequired = 2
MyView.addGestureRecognizer(recogRightClick2)
}//EO Overide
func oneMouseClick(myrec: NSPanGestureRecognizer,myRightClick:NSClickGestureRecognizer){
let rightClick = myRightClick.state.rawValue
print("oneMouseClick",rightClick)
}
func twoMouseClick(myrec: NSPanGestureRecognizer,myRightClick:NSClickGestureRecognizer){
let rightClick = myRightClick.state.rawValue
print("twoMouseClick",rightClick)
}
}//EnD oF thE wORld
UPDATE
I have re generated the code following the advice given. Now the code reflects more of what i wanted to do. My only problem is that I would like all the mouse operations to be triggered only inside 'myView' rather than within the main window. I thought it might have something to do with first responder but that doesn't seem to work. Again any thought would be appreciated. Please excuse any bad code i'm self taught.
Xcode 8 Swift 3 Mac OSX Sierra NOT IOS.. NOT IOS
import Cocoa
class MainWindowController: NSWindowController {
#IBOutlet weak var myView: NSView!
var mouseX:CGFloat = 0
var mouseY:CGFloat = 0
override func windowDidLoad() {
myView.window?.becomeFirstResponder()
myView.window?.acceptsMouseMovedEvents = true
super.windowDidLoad()
myView.wantsLayer = true
myView.layer?.backgroundColor = CGColor(red: 0.05, green: 0.57, blue: 0.80, alpha: 0.6)
NSEvent.addLocalMonitorForEvents(matching:.leftMouseDown){
self.mouseEventFunction(data: 1)
return $0
}
NSEvent.addLocalMonitorForEvents(matching:.leftMouseUp){
self.mouseEventFunction(data:2)
return $0
}
NSEvent.addLocalMonitorForEvents(matching:.rightMouseDown){
self.mouseEventFunction(data: 3)
return $0
}
NSEvent.addLocalMonitorForEvents(matching:.rightMouseUp){
self.mouseEventFunction(data: 4)
return $0
}
NSEvent.addLocalMonitorForEvents(matching:.mouseMoved) {
self.mouseX = NSEvent.mouseLocation().x
self.mouseY = NSEvent.mouseLocation().y
return $0 }
}//EO Overide
func mouseEventFunction (data: Int){
switch data{
case 1 :
print("LeftMouseDown")
case 2 :
print("LeftMouseUp")
case 3 :
print("RightMouseDown")
case 3 :
print("RightMouseUP")
default: break
}
if data == 1 {print("mouseX",mouseX,"mouseY",mouseY)}
}//eo mouseEvent
}//EnD oF thE wORld
UPDATE 2
I have now updated subClassing the view controller, so the mouse clicks are now only working in myView. I'm still having problems with 'func mouseDragged' What i need to achieve is the bottom left of my view is x = 0 and Y = 0. I had a try with converting but thats not working. hoping someone might guide me. thanks for reading here is the updated code.
Xcode 8 Swift 3 Mac OSX Sierra NOT IOS.. NOT IOS
import Cocoa
class MainWindowController: NSWindowController {
#IBOutlet weak var myView: NSView!
override func windowDidLoad() {
myView.window?.becomeFirstResponder()
myView.window?.acceptsMouseMovedEvents = true
window?.contentView?.addSubview(myView)
super.windowDidLoad()
}//EO Overide
}//EnD oF thE wORld
class testView: NSView {
override func draw(_ dirtyRect: NSRect) {
let backgroundColor = NSColor.lightGray
backgroundColor.set()
NSBezierPath.fill(bounds)
}
override func mouseDragged(with theEvent: NSEvent) {
let myLocationInWindow = theEvent.locationInWindow
let location = convert(myLocationInWindow, to: self)
Swift.print("myLocationInWindow",myLocationInWindow,"location",location)
}
override func mouseDown(with theEvent: NSEvent) {
Swift.print("mouseDown")
}
override func mouseUp(with theEvent: NSEvent) {
Swift.print("mouseUp clickCount: \(theEvent.clickCount)")
}
}//eo testView
To define mouse inside view you use
let myLocationInWindow = theEvent.locationInWindow
let location = convert(myLocationInWindow, from: nil)
where nil is the window
here is the final code
import Cocoa
class MainWindowController: NSWindowController {
#IBOutlet weak var myView: NSView!
override func windowDidLoad() {
super.windowDidLoad()
}//EO Overide
}//EnD oF thE wORld
class testView: NSView {
override func draw(_ dirtyRect: NSRect) {
let backgroundColor = NSColor.lightGray
backgroundColor.set()
NSBezierPath.fill(bounds)
}
override func mouseDragged(with theEvent: NSEvent) {
let myLocationInWindow = theEvent.locationInWindow
let location = convert(myLocationInWindow, from: nil)
Swift.print("location",location)
}
override func mouseDown(with theEvent: NSEvent) {
Swift.print("mouseDown")
}
override func mouseUp(with theEvent: NSEvent) {
Swift.print("mouseUp clickCount: \(theEvent.clickCount)")
}
}//eo testView
hi I've been following some tutorials but this ones for swift 1.2
I'm on Xcode 7.2 think its swift 2.1
he uses a UITextfield with spriteKit
but this line causes an error
I've googled but can't find any help
so thought this is the place to help cheers
self.view!.addSubview(TextInput!)
the whole code is
import SpriteKit
class GameScene: SKScene
{ var TextInput:UITextField?
override func didMoveToView(view: SKView)
{
let myLabel = SKLabelNode(fontNamed:"Chalkduster")
myLabel.text = ""
myLabel.fontSize = 15
myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
self.addChild(myLabel)
TextInput?.frame = CGRect(x: 200, y: 300, width: 100, height: 40)
self.view!.addSubview(TextInput!)
TextInput?.backgroundColor = UIColor.whiteColor()
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch in touches
{
let location = touch.locationInNode(self)
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
} }
You don't seem to be initialising your UITextField anywhere.
Try adding this line to didMoveToView before you set the frame of TextInput:
self.TextInput = UITextField()
Just to note, variable names in Swift should be written in camel case (thisIsCamelCase), so it might be better to rename your variable as textInput. I can't actually find this in the Apple documentation right now, but this convention is used in all of Apple's example code, and is stated by various other sources, e.g.
https://github.com/raywenderlich/swift-style-guide
http://andybargh.com/variables-and-constants-in-swift/#Rules_for_Naming_Variables
I am having trouble with detecting a specific node being touched. Here is what i have to far.
let playagain = SKSpriteNode(imageNamed: "PlayAgain.png")
override func didMoveToView(view: SKView) {
super.didMoveToView(view)
}
then when the player dies these two nodes come up.
playagain.position = CGPoint(x:frame.size.width * 0.5, y: frame.size.height * 0.5)
addChild(playagain)
gameover.position = CGPoint(x:frame.size.width * 0.5, y: frame.size.height * 0.75)
addChild(gameover)
everything above works. the node comes on the screen where i asked i just can't seem to get it to show i clicked it.
as you can see the node is called playagain, when the playagain node is clicked i want to be able to refresh the game. what i have so far is below.
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch in touches {
let location = (touch as! UITouch).locationInNode(self)
let play = self.nodeAtPoint(location)
if play.name == "playagain" {
println("touched")
}
}
}
thanks!
Are you not using the latest Xcode? Your touches began code should not run with swift 2 and Xcode 7.
Try this
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
if playagain.containsPoint(location) {
/// playagain was pressed, do something
}
}
}
or this
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(location)
if touchedNode == playagain {
/// playagain was pressed, do something
}
}
}
I'm trying to drag a SKSpirteNode around the screen by touching the screen. But I want to be able to do a constant movement of the Sprite, currently my code only moves the sprite to the location of my touch but if I hold and move the sprite will not follow. Moreover I don't want to "have" to touch the SKSpriteNode to activate the movement, I want to touch anywhere on the screen and to have a movement response from that SKSpriteNode.
Here is my current code:
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
// SpriteNode I want to drag around
basket = SKSpriteNode(texture: basketTexture)
self.addChild(basket)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
var nodeTouched = SKNode()
var currentNodeTouched = SKNode()
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
nodeTouched = self.nodeAtPoint(location)
basket.position = location
}
Thank you any help appreciated.
I solved this by using the func touchesMoved instead of touchesBegan and works perfectly and smoothly. here is the final code:
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
// SpriteNode I want to drag around
basket = SKSpriteNode(texture: basketTexture)
self.addChild(basket)
}
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
var nodeTouched = SKNode()
var currentNodeTouched = SKNode()
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
nodeTouched = self.nodeAtPoint(location)
basket.position = location
}
Hi everyone i am making a sprite-kit app in which the user must be able to draw multiple lines. To do this I made the following code.
import SpriteKit
class GameScene: SKScene {
var line = SKShapeNode()
var path = CGPathCreateMutable()
var touch: UITouch!
var location:CGPoint!
override func didMoveToView(view: SKView) {
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
touch = touches.anyObject() as UITouch!
location = touch.locationInNode(self)
drawLine()
}
override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) {
self.delete(line)
}
func drawLine() {
CGPathMoveToPoint(path, nil, location.x, location.y)
CGPathAddLineToPoint(path, nil, 500.0, 500.0)
line.path = path
line.strokeColor = UIColor.redColor()
line.lineWidth = 5.0
self.addChild(line)
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
This works but when the users tries the draw the second line the application crashes.
Can someone explain to me why that is happening?
------Edit------
I think i need to use an array of lines so I did something like this:
var line: [[SKShapeNode]] = []
which gives me the following error:
[[SKShapeNode]] does not have a member named 'path'.
So I though I had to make the path variable an array as well but that only gave me a second error: GameScene does not have a member named 'path'. So I changed it all back but I still think I have to use an array although I can't really figure out how to make it work.
Copy and paste this..now you'll redefine your line every time
import SpriteKit
class GameScene: SKScene {
var line = SKShapeNode()
var path = CGPathCreateMutable()
var touch: UITouch!
var location:CGPoint!
override func didMoveToView(view: SKView) {
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
/* Called when a touch begins */
touch = touches.anyObject() as UITouch!
location = touch.locationInNode(self)
drawLine()
}
override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) {
self.delete(line)
}
func drawLine() {
CGPathMoveToPoint(path, nil, location.x, location.y)
CGPathAddLineToPoint(path, nil, 500.0, 500.0)
SKShapeNode *line = [SKShapeNode node]; //redfine line every time
line.path = path
line.strokeColor = UIColor.redColor()
line.lineWidth = 5.0
self.addChild(line)
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}