Controls

While SpriteKit provides some basic things (sprites, labels, etc.), it doesn’t provide true SpriteKit controls like pushbuttons, radio buttons, checkboxes, etc. If you search the internet you can find various solutions that folks have offered. I found many didn’t quite work the way I wanted them to or were a bit grandiose in their implementation.

I found my favored approach was to subClass SKSpriteNode and add to it any required children to support the desired control.  I needed a toggle switch control for my settings dialog.  A toggle switch would contain the image for selected or unselected state, the text for the description, and a touch panel over the top of it.  Add to that a couple of sounds for selecting and deselecting the toggle switch.

I chose the follow parameters for the initialization call:

    convenience init(name: String, text: String, isSelected: Bool, zPosition: CGFloat, fontName: String, fontSize: CGFloat, fontColor: UIColor, backColor: UIColor = UIColor.clear) {

 This gives me a name for the control, the text to be displayed, the vertical position of the control, the font to be used, the size of the font, the color of the font, and the color the base sprite node will have.

You may have noticed the size of the control is not specified.  This is determined by the size of the image and the font size.  First thing is to create a temp SKLabelNode and assign all the properties to it which allows us to get the size from the frame.

        let tempLabel = SKLabelNode.init(text: text)
        tempLabel.fontName = fontName
        tempLabel.fontSize = fontSize
        tempLabel.horizontalAlignmentMode = .left
        tempLabel.verticalAlignmentMode = .baseline

Now we have a frame to look at.  I added  what I’m calling a gutter, the space above and below the text.  This only becomes relevant when the image height is smaller than the text height.
        let tempLabelHeight: CGFloat = fontSize + 5     // (gutterSize of 3 * 2) – 1

Now we can create the base sprite.  The sprite width will be the width of the image, plus a small separator space, plus the label frame width.  The height will be the larger of the two heights;  tempLabelHeight and image height.

For my purposes, the image will always be on the left side.  A sprite is created to hold the image and added as a child of the base sprite.  Next a label is created for the text.  It is placed to the right of the image plus a small separator space.

The last thing I add is a touch panel.  This is a clear sprite the size of the base sprite that sits over the top.  I found this the easiest way to manage touches.

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if (!isEnabled) {
            return
        }
        
        guard let touch = touches.first else {
            return
        }
        
        let touchLocation = touch.location(in: self)
        if self.touchCover.contains(touchLocation) {
            self.isSelected = !self.isSelected
            
            if delegate != nil {
                delegate.selectedToggleSwitchState(toggleSwitch: self)
            }
        }
    }

Here is an example of what my toggle switch looks like:

toggle switch example

And here it is in the full Settings dialog:

settings panel example

Mojave misbehaves after waking from sleep

I bought a new Mac mini  and it came with Mojave preinstalled. It was what I would call my first “Windows experience” with a Mac and I was very disappointed.  After waking from sleeping my symptoms varied but fell into a few categories:

  1. My Apple Watch would not unlock it, it would try but then as for the password
  2. When I plugged in my iPad it would not auto-launch iTunes
  3. After a while when launching apps I’d get the message that says in the future this app will not be supported and the app owner need to update it
  4. Apps would not complete closing
  5. Shutdown would not complete

Eventually, I would end up doing a hard shutdown (holding the power switch until it shut off).  After that the first reboot, I would have to shutdown and restart again before it started behaving correctly.

I kept pushing though it but never really could find a solution.  I reinstalled Mojave, reset the NVM, and all the other standard suggestions with no change.  So I started going through the logs.  I saw a lot of activity going on where requests going out were getting errors or URLs not found, etc.

So, I decided to dump the apps doing this and see what happens.  I removed iHeart Radio and Avast anti-virus (free version) software.

I haven’t had a problem since (a little over one week now).  I lean towards Avast being the problem after I found one web page talking about to fix a problem you needed to shutdown hibernation mode.

I have not pursued it further and am using alternative apps.

Random Magic Mouse Disconnects

The new 2018 Mac Mini was released and I decided I needed to update my aging system.  Previously, I was using a Macbook Air which I still love.  Once I got the new  Mini set up I started using the Magic Mouse I had been using with the Air.  I started having issues almost immediately.  Sometimes it would just disconnect and then after some period of time it would reconnect.  Other times it would get “ratty” – the mouse would start lagging, etc.  It would almost always just disconnect if I had stopped using it for a bit (when typing for example).  I connected the mouse back to my Air and it worked perfectly.  That rules out the mouse as being the problem, so I started looking on the web for solutions.  Certainly, somebody had a solution for this.  Not so.  To my surprise, this is not an uncommon problem and goes back many years.

I found one particular entry that had a large number of possible solutions that had not worked for them and they didn’t work for me either.  Since my Mini was brand new and I had purchased AppleCare for it, I broke down and called the help line.  I talked with them for a while and was finally prompted to reinstall the operating system.  This seemed odd to me since the Mini was like this right out of the box, but I went along with the suggestion.  After finishing that, I found the problem still was happening.

I also have an old Microsoft mouse that uses an RF connection vs. a bluetooth connection.  I found that when the Magic Mouse started to get “ratty” if I switched on the Microsoft mouse, used it to disconnect and reconnect the Magic Mouse it would work again as is should for while.  I put up with this for a few days but it was becoming an issue when I was coding.  It would break my train of thought and became very distracting.  So back to the web.

One of the things I read was about is what I’ll call “signal conflict”.  I read that the mouse broadcasts on the 2.4GHz band.  My router does both 2.4GHz and 5.0GHz.  I find that the 2.4GHz has greater range in my house, while the 5.0GHz has faster through-put (if I get a good connection).  We do a lot of streaming in the living room upstairs so most everything is connected to the 2.4GHz side of the router.  On a whim, I disconnected the Mini from the 2.4GHZ side and connected it to the 5.0GHz side.  Lo and behold, my bluetooth mouse problems ceased.

My guess is I had a 2.4GHz conflict because both the router and the mouse were using the same channel.  I found this information on how change channels but decided if it’s working, don’t fix it.

Why this blog

I’ve been trying to fulfill a life-long dream of coding and publishing a computer game.  I’ve been active with PCs since the TRS-80 Model 1 came out.  Skip ahead to 2006 when I migrated from Microsoft to Apple.  After forcing myself to stick with learning the “Apply way” of doing things I found before long I was happy with my choice.  I can say that the regular experience of “it just works” solidified my thinking.

My first attempt at a game (and of course I chose a complex one) on the Apple platform began in early 2016 using Objective-C.  I plodded along but I was not really happy with the effort required to do the simplest things.  Along come Swift and I found this to be exactly what I was looking for.

On many occasions I find I want to do something in the game and do not have any idea how to accomplish this in Swift (or the “Apple way”).  I am constantly searching the web for help (thank you stackoverflow.com) and the majority of the time I find something close but it doesn’t really do what I need it to do but points me in the right direction so I can solve the problem.  So after nearly three years of chasing down this rabbit hole, I thought maybe it would be helpful if I shared some of my problems and solutions.

Note:  I’m new to this so for now, comments will be disabled.