Tic Tac Toe: Touches and Responses

Last time I set up the tic tac toe board with a set of nine tiles that will represent the board. This week, my goal is to make each tile responsive to touch so that we can connect our game logic to it.

I need to do the following steps:

  • Set up a touch observer to look for touches
  • Determine if the touch is located on a sprite representation of a tile
  • If so, which tile?
  • Figure out how that tile correlates to my array of game logic tiles
  • Change the state on the correlating game logic tile
  • Update the UI
  • Check for a win or a draw
  • Either end or continue the game

I have found that, for me personally, breaking tasks down into smaller chunks makes it easier to stay focused and get something done. Instead of worrying or freaking out about how I am going to set up multiple game scenes, which I intend to do later, I am focused on this one small chunk of the program. I am further dissecting this chunk into even smaller chunks so I don’t get confused about how I am going to get all of these things to work together.

Connecting the Model Game Tiles to the View Game Tiles

The first problem I would like to solve before I go any further is to figure out how to connect my model tiles to my view tiles. The view tiles are the objects that the player sees and can respond and detect touches, but they only know about what they look like and what is touching them. They don’t know that a certain color or image or state means anything outside of their own context. That is the responsibility of my model tiles. Those tiles know what state they are in and they provide data to my functions that determine if they are part of a win or not. I need some way to allow the model tiles to talk to the view tiles so they can both do their jobs.

There are a few ways to do this. I could have created a bunch of methods and structures to check the row and column of my board, but I only have nine objects to track. SpriteKit has a method of checking sprites by name, so I chose instead to create a single array of sprites and to give each a unique name that includes their index so that they can be found and tracked based on an identifier.

I created an array of model tiles that represent the state of the board. I am using their indices and positions in my game logic. I created a similar array to hold all of my sprite tiles. When I generated the sprite tiles, I generated them in the same order as I did for the model tiles and named them accordingly. The first tile in the sprite array should be the uppermost left tile, which correlates to the index and first tile in the model array. So the indices of each should line up. Keep that in mind as we walk through the rest of the steps.

I realized after I wrote this section when I was trying to get the next section to work that I don’t actually populate either of my arrays at this point in my explanation. I add the sprites to the board layer but I forget to add them to the array I created to hold them.

I added the following code within the nested loop in the initializer:

boardLayer.addChild(sprite)
tiles.append(sprite)

I had also added a method to populate the model array that I commented out because I wasn’t using it yet. It is this one:


board = resetBoard()

This is a good example of ways things can go wrong when you’re working with computers. You may intend to do something but unless you explicitly set it, then it won’t happen and you become frustrated. This is actually kind of true with people too…

Detecting Touches

UIKit has built in gesture recognition. One such gesture is touching. I generally haven’t used this because I use other elements, like buttons, that implement it automatically. But it’s useful for SpriteKit games, especially ones of a platform nature where you don’t necessarily need to hit a specific object in order to get a character to move on the screen. In fact, that would kind of defeat the purpose of having a touch screen over a controller of some kind.

One thing you have to remember (that I forgot and had to correct) is that you have to enable user interaction explicitly when you initialize the scene. You do this by putting this line of code somewhere after the call to super:

isUserInteractionEnabled = true

There are several methods for touch, but the default one is touchesBegan. This method kind of lurks around observing the screen waiting for a touch to happen. Once one does, it implements whatever game logic needs to be executed to respond to the touch.

The method doesn’t just bring in a single touch. It brings in an array of UITouch objects. So keep that in mind when you are using touchesBegan that it could potentially have many touches and not just one.

Here is my initial boilerplate touchesBegan method:

override func touchesBegan(_ touches: Set, with event: UIEvent?) {
	if let touch = touches.first {
		let location = touch.location(in: self)
		let tappedNodes = nodes(at: location)
	}
}

At this point I started adding a bunch of loops and conditional logic to get my code to work. It didn’t. I got confused and frustrated. I went to The Boyfriend to ask for help debugging my code. No, I am not sexist Computer Engineer Barbie. The Boyfriend has 30 years of programming experience to my five.

We debugged the array issue I mentioned above and came up with this much nicer method for checking for touches in our tiles:

override func touchesBegan(_ touches: Set, with event: UIEvent?) {
	guard let touch = touches.first else {return}
	let location = touch.location(in: self)
	let rawNodes = nodes(at: location)
	let tappedNodes = rawNodes.filter{return $0.name != nil}
		
	guard let node = tappedNodes.first as? SKSpriteNode else {
            return
        }
	node.color = UIColor.black
	board[tiles.index(of: node)!] = .playerA
}

First we are ensuring that we actually have a touch. If there isn’t an eligible touch, we want to break out of the method. Next, we need to store the location of the touch. This location is used to get an array of all nodes that exist at that location. One thing I had forgotten when putting the board together was that the background and the game board are also SKSpriteNode objects. This meant that when I touched the screen three nodes were added to the raw nodes. Since we only care about the one we named, we need to remove those other sprites from the array. We do that by checking for a name. Since the board and the background are not named, they are removed from the array. Lastly, we’re checking to make sure that any node that is left in the array can be cast to SKSpriteNode. If not, we break out of the method early.

Now that we have ensured that the only node we can possibly have at this point are SKSpriteNodes, we can now set properties on the node such as the color. We can also use the node to find its index within the array of sprite kit tiles. This directly correlates to the index within the model of the tile state that needs to be updated. Voila!

Can touch a tile and switch it from red to black

Updating the UI

Right now this isn’t particularly interesting. I can tap on a tile once and it changes from red to black. I can’t switch back and forth between players. Yet.

I modified the bottom of the touchesBegan() method to the following:

if board[tiles.index(of: node)!] == .notSelected {		
	switch currentPlayer {
	case .playerA:
		node.color = UIColor.black
		board[tiles.index(of: node)!] = .playerA
	case .playerB:
		node.color = UIColor.red
		board[tiles.index(of: node)!] = .playerB
	case .notPlaying:
		node.color = UIColor.white
		board[tiles.index(of: node)!] = .notSelected
	}
}

I changed the default unselected color of the tiles to white to make the different players a little more dynamic. I want to make sure that if a tile has already been selected that it can’t be selected again. I check the index of the correlating tile in the model to see if it’s been selected or not. If the current player is Player A, the tile switches to black. If the current player is Player B, it switches to red. To ensure an exhaustive switch statement I simply leave the node color white, but this should never be called.

I noticed that the first time I tested this that the first tile I touched didn’t do anything. I realized that the first time I touched the board I was still in the .NotPlaying state. I had commented out the switchPlayer call at the end of the initializer, so I just had to delete the comment and we are nearly ready to go.

Can switch between players now

Checking for Win and Ending the Game

Finally, after the move has been completed, we need to check for whether or not someone won the game. I set this logic up before, so all we have to do is call our game over method:

if let isWin = checkForWin(currentPlayer: currentPlayer, board: board) {
	switch isWin {
	case .playerAWin:
		print("Player A wins")
	case .playerBWin:
		print("Player B wins")
	case .draw:
		print("No one wins. Everyone gets a participation trophy")
	}		
}

currentPlayer = switchPlayer(currentPlayer: currentPlayer)

I thought about trying to get an alert view going for these win cases, but then I would have to remove them later when we have better UI, so for the time being I am not concerned with how to tell the player that the game is over. I am simply printing the result to the console and making it so no one can play anymore because I am mean.

Have fun reading the tiny print on the console!! :p

If isWin falls through because the game is not yet over, we need to switch players, which is the last bit that we do at the end of this method.

Conclusions

My project so far can be seen here.

This was far easier to set up that I originally anticipated. All of the work I did over the last few weeks to separate the model from the view really paid off here. I could focus on simply checking what state the game is in and update the UI accordingly.

Most of the SpriteKit games I have done tutorials for are ones that are running continuously and thus have all of their logic in a game loop. Turn based applications are similar except you only update the game once someone has made a move. As someone who is primarily interested in turn based games, this is something for me to keep in mind.

I have broken this game out into three more chunks that need to be done before I feel like I have completed this game adequately:

  • Graphics, Labels, and Sounds: I have an art tile set that I want to apply to the game so it looks like a real game and not a minimalist painting. I want to update labels that say what the current state of the game is. Lastly, at a minimum, I want some kind of background music.
  • Implementing an AI: This game isn’t very interesting without someone or something to play against. I want to look into how to implement some kind of AI for this game, be it using GKStrategist or me just rolling my own AI.
  • Multiple Scenes and Variations: I want an actual main menu screen to explicitly start the game. I would like a game over screen to take you back to the main menu. I also have some ideas for variations on tic tac toe for the player to be able to choose because the base game is pretty boring. I want those options to be selectable in the main menu.

So just three more blog posts left on this project! Then it’s on to actually attempting something that people might actually want to play. Stay tuned!

SpriteKit vs Unity: Scripts

One of my goals this year was to learn Unity. There is a local indie game developer meet up that I attend with some awesome accomplished game developers. I started going while I was working on the Metal book to ask how to break into the game industry. The primary thing they told me was to know Unity. I thought that knowing Metal and programming would be enough to get into the industry, but I have found a lot of people don’t really know what Metal is.

Additionally, knowing programming and knowing how to work with an incredibly powerful and complex tool are two entirely different skills. As someone who spent two years learning Pro Tools and Photoshop, I am painfully aware of how important it is to have an idea about what a tool can do and how to best utilize it.

Also, honestly, if you’re not going to bother to learn something in your spare time, then it’s probably not that important to you. I can understand the barrier to entry being at least having a working sample project in a skill as opposed to just saying “I want to be a game designer!!” I understand that not everyone has vast amounts of free time to spend dicking around with every cool game engine out there. A lot of people are parents and have family obligations and I am in no way shaming those people because family is way more important than mucking around with programming 24/7. But if you do have a lot of free time and you spend it partying or whatever, then the cool thing is really not that important to you. There’s nothing wrong with that. I want to be in better shape but not enough to actually make time to go to the gym.

If you’ve been reading my blog, you know that right now I am trying to build a game in SpriteKit. I have been interested in SpriteKit since it was released several years ago, but it took me a while to come to grips with how it works. You learn best by having a project that you try to get working, so that is the point of the tic tac toe project. So most of my background in game development is doing native Apple game development with their frameworks, languages, and workflow.

One thing that massively confused me when talking to people who primarily came from Unity was scripting. With SpriteKit, everything I do is done in code. They have an Interface Builder-esque tool that I have not yet used in any real capacity, but beyond that everything is done in code. Sprites are placed and skinned in code. They are moved in code. Labels are created in code.

I asked about the point of scripting over coding. I was told it is easier to edit a script than it is to change things in code. That made no sense to me because if you have to edit something in Xcode it doesn’t really matter where it is, the amount of work is the same.

So one big thing I wanted to get out of learning Unity was to get a better idea about what is meant by scripting as opposed to what I am familiar with from SpriteKit. I have only been working with Unity for about two weeks. I am working through the Unity Games by Tutorials book from Ray Wenderlich. There will probably be things that I am missing in this post about scripting because I still haven’t used it much, but these are kind of my initial thoughts coming in from another perspective.

SpriteKit

The approach I have seen most people take in SpriteKit programming is to approach solutions in a third-person, God-like perspective. There is a single update() method that you code with everything you want to happen on each iteration of the game loop. There is a method to detect touches and within that method to express what you want to have happen when the user touches the screen.

You create subclasses of game scenes, but not really of SKSpriteNode. You create instances of SKSpriteNode named for the different objects you have in the game with different sizes and textures, but you tend to generally not subclass SKSpriteNode.

I will be showing a few examples of what I mean using the first project from Ray Wenderlich’s SpriteKit book. Yes, I use a lot of his books. No, I am not getting paid to shill them. They are good examples of showing how to put a completed project together and I find it useful.

The first game you build in that book is a 2D platformer called Zombie Conga. The point of the game is to bite cats to turn them into zombies while avoiding crazy cat ladies. You win when you reach a certain number of cats or you lose if you collide with too many cat ladies.

The project is architected with a lot of small methods that involve explaining an action you want to occur. One such action is move:

func move(sprite: SKSpriteNode, velocity: CGPoint) {
	let amountToMove = velocity * CGFloat(dt)
	sprite.position += amountToMove
  }

This is a reusable method that can have any instance of SKSpriteNode and any point passed into it. Within the project, there is actually only one instance where you are using this method, and it’s on the zombie protagonist:

move(sprite: zombie, velocity: velocity)

The entire project is composed of small methods that are abstracted away from the main game loop so that it’s not cluttered by every little thing it needs to do. Here is an example of an update() method in a game scene in SpriteKit:

override func update(_ currentTime: TimeInterval) {
	if lastUpdateTime > 0 {
	  dt = currentTime - lastUpdateTime
	} else {
	  dt = 0
	}
	lastUpdateTime = currentTime

	move(sprite: zombie, velocity: velocity)
	rotate(sprite: zombie, 
               direction: velocity, 
               rotateRadiansPerSec: zombieRotateRadiansPerSec)

	boundsCheckZombie()
	moveTrain()
	moveCamera()

	if lives <= 0 && !gameOver {
	  gameOver = true
	  print("You lose!")
	  backgroundMusicPlayer.stop()
	}
  }

You don’t necessarily have to understand everything this is doing, but just look at how this is laid out. The update is nearly entirely composed of method calls to abstracted methods within the game scene. You pass in the sprite you want to modify for some of these. Other void methods such as moveCamera() directly mutate a specific SKSpriteNode instance that is not subclassed. The way of thinking about a SpriteKit project is from a God-like perspective where you think about all of the things you want to do and how to move your pieces around to make it happen. You abstract out methods even if they are only called once and only work on one instance of SKSpriteNode.

Unity Scripts

Unity takes a fundamentally different approach to game objects than SpriteKit does. I mentioned a few times that in SpriteKit you don’t really subclass SKSpriteNode. This is not how Unity deals with game objects.

In Unity, game objects tend to start out as meshes that you import from a tool like Blender. These objects have meshes, materials, and animations associated with them. These can be composed of multiple meshes that are imported separately. All of these aspects are collected together into a single game object called a prefab. Instead of creating a generic Unity sprite node, you create instances of these prefabs in your game. You can apply a change to a prefab universally among all the instances of the prefab or you can create changes locally to a single instance of a prefab.

One fidgety and highly powerful feature of Unity is the ability to add components to both the prefabs and instances of the prefabs. These components include physics, rendering, and scripting.

Scripting is more like a first person perspective as opposed to the third person God perspective utilized in SpriteKit. Instead of thinking of your methods globally, you think about them as being the internal monologue of your game object. These scripts watch for input and respond to it rather than creating a method around the input method.

I have a script for a gun in the learning project I am working on. The update method in it’s script looks like this:

void Update () {

    if (Input.GetMouseButtonDown (0)) {
        if (!IsInvoking ("fireBullet")) {

            InvokeRepeating ("fireBullet", 0f, 0.1f);

        }

    }



    if (Input.GetMouseButtonUp (0)) {
        CancelInvoke ("fireBullet");

    }

}

The script is actively observing the mouse button input and making a determination about its behavior based on the button’s state. The script only knows about itself and anything that impacts its ability to function. Rather than having an update method that is controlling the gun, the alien, and the protagonist, each of these objects has their own self-encapsulated update method.

This is a different way of doing things. I can see how this would be more efficient when you reach a certain scale of project. Even within the small SpriteKit projects I have worked on, I have found project organization to be difficult. My logic always looks messy and I actively look for ways to abstract logic away from my main game scene.

I am not certain if this a pattern that can be applied to SpriteKit or not. I know in programming there isn’t anything that is impossible, but there are ways of working with and against a framework. I could completely recreate Android’s UI in iOS using views and so forth, but why would I want to?

I do know that Apple also has a supplementary framework called GameplayKit that includes an entity-component system. Ray Wenderlich’s SpriteKit book used to have several chapters on this system, but those chapters were replaced with tile maps in the latest version. A few of GameplayKit’s functions, such as state machines, seem to have been coopted by Swift’s architecture. I am uncertain if Swift protocols could fulfill a similar function to entity-components or if SpriteKit and Unity have incompatible design patterns. Either way, it’s a different way of approaching the problem of coordinating actions and behaviors on game objects.

Components vs @IBInspectable

I would be remiss in not explaining the single biggest feature that make scripts easier to work with in Unity. One big aspect of game development is the ability to tweak variables to tune the game. The line between the game being fun and impossibly hard isn’t very wide.

Having to open up a script and dig around in code to change a time or a number of spawned objects is a bad design pattern, especially if you are considering that your user base isn’t necessarily composed of programmers. Unity is designed to be worked on by large teams of people who do things other than programming. It’s important for a designer to be able to change variables easily on the fly.

Unity gets around this by integrating the scripts with the user interface. In your script, you can make a determination about what variables you have that may need to be changed to tune the game. These can be made public within the script:

Unity looks in these scripts to see what variables are public and exposes them within the UI so they can be modified and edited without having to open the script editor:

People can sell scripts on the Unity marketplace, so it’s possible for someone who has no programming experience at all to be able to buy a script written by someone else and use it effectively without looking at it once. The programmer part of me feels dirty when thinking about this, but there are many roles on a game development team that don’t require programming. Creating a system that allows these people to work quickly and effectively by abstracting away that unnecessary complexity is smart. I can also see why it would be a lot easier to just change a value in a field within the IDE than it would be to open the code and find the variable and edit that crap by hand.

The closest thing I think Xcode has to this design pattern is @IBDesignable and @IBInspectable. If you are creating custom views/buttons/etc… in iOS, you can tag your subclass as @IBDesignable. You can then publicly expose properties you want to tweak by tagging them as @IBInspectable. Xcode will see these tags and modify itself to allow you to change these within Interface Builder. There is a great tutorial about doing this with Core Graphics here.

Conclusions

I have really been enjoying getting familiar with Unity. Before I got into programming I spent a lot of time learning Photoshop and Illustrator. It always astonished me how much you can do with these complex and powerful tools. I can appreciate the fact that a lot of work is abstracted away that doesn’t really matter.

For the last few years I have felt somewhat creatively shut down. I dwelled on implementation details and mechanics because they were a comfortable place to be. Something either works or it doesn’t. You spend a lot of time thinking about how something works rather than thinking about what you want to create with it.

Going back and doing Unity and SpriteKit, and to a more limited extent Illustrator, has stimulated areas of my brain that had kind of shut down. I abandoned design because I thought it was too subjective and that I would never be good at it. I forgot how wonderful it feels to understand a tool well enough to use it to express something you’re thinking or feeling or imagining.

I am glad that I have gotten over my stubbornness about learning Unity. It’s a large and complex tool. I needed some time to mentally process the idea of jumping into this tool and to organize myself so I don’t just curl up in a ball and sob. I feel actively excited about scripting in Unity and I’m looking forward to figuring out some sample projects I can do with it.

Tic Tac Toe: Setting up the Visual Game Board

My goal in 2018 was to post to this blog at least once a week, but life happens. I got sick and I had some obligations for others that prevented me from reaching my goal. Sometimes you have a bad week, but you do your best and keep trying. So in the spirit of that, here is my post for the week.

Now that I have most of my game logic somewhat hammered out, I am going to put it on the back burner and focus on my user interface elements. I am choosing to think of each element as an independent piece rather than focusing on how everything is going to work together. I am hoping if I get each piece working properly, by the time I need to bring them together as an actual game I won’t have to worry too much about their implementation details.

One big question I have with SpriteKit over UIKit is placing elements on a screen. In UIKit we use auto layout to apply rules to the elements to tell them what size they are and how they exist within relation to one another. I know SpriteKit has an Interface Builder-esque scene builder, but I am a masochist and want to do my layout in code.

Game Board Layout

My intention for the game is to only be able to play it in portrait mode and not landscape. I want to think of this layout algebraically to try and get around the lack of auto layout. (Note: It may be possible that auto layout coexists with SpriteKit, but I am stubborn and want to pretend it doesn’t as a thought exercise and to prove a point. Don’t judge me.)

Since the phone is always going to be taller than it is wide, the width is my limiting factor here. I want my board to take up a square amount of space that spans from one side of the screen to the other. I also want the board to be centered in the screen with some space at the top or bottom which will include labels and such at a later state of the game.

Game Layers

So looking at my mock up, I have a board layer that is square and varies based on the width of the screen. Within that board layer, I have nine subviews representing the tic tac toe tiles. Those tiles exist relative to one another within the board layer. So I want to create two separate layers. I also want the tiles in my tile layer to exist relative to that layer and basically know nothing about the larger screen they exist within.

The board layer should be relatively straightforward. We know the length and width of the layer will be the same and that they are both constrained by the width of the screen.

First I need to create the sprite node that will represent the board:

// View Properties
let boardLayer = SKSpriteNode()

To create the view, we simply need to figure out the width of the screen. Next, we want to make the anchor point of the board layer the middle rather than one of the edges. Finally, we need to set the position of the anchor to the middle of the screen.

override init(size: CGSize) {
	super.init(size: size)
		
	anchorPoint = CGPoint(x: 0.5, y: 0.5)
		
	let background = SKSpriteNode(color: UIColor.white, size: size)
	addChild(background)

	let boardSize = size.width
	boardLayer.anchorPoint = CGPoint.zero
	boardLayer.position = CGPoint(x: -(boardSize / 2.0), y: -(boardSize / 2.0))
	boardLayer.size = CGSize(width: boardSize, height: boardSize)
	boardLayer.color = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.2)
	addChild(boardLayer)
}
	
required init?(coder aDecoder: NSCoder) {
	super.init(coder: aDecoder)
}

If you try to build and run this… nothing happens.

I got super confused and did a bunch of color debugging and changing the anchor points and sizes, but nothing was happening. After some digging and breakpointing, I realized that the game scene was never actually loading and that I needed to make some changes to the GameViewController class.

Game View Controller

I assumed that since this was an Apple template that it would just work, but either it doesn’t or I accidentally changed something to prevent it from doing so. I have been referring to a few SpriteKit tutorials on Ray Wenderlich’s site and in the ones I have seen, you need to declare a game scene property and explicitly let it, so that is what I did.

var scene: GameScene!

override func viewDidLoad() {
	super.viewDidLoad()
		
	let skView = view as! SKView
	skView.isMultipleTouchEnabled = false
		
	scene = GameScene(size: skView.bounds.size)
	scene.scaleMode = .aspectFill
		
	skView.presentScene(scene)
			
	skView.ignoresSiblingOrder = true
	skView.showsFPS = true
	skView.showsNodeCount = true
}

This now loads the game scene and you get a nice boring white background with a grey square. Later in this process I will be adding nice graphics, but this works for now. Next, we need to populate the game board with some tiles.

Game Tiles

Since I don’t know how wide my screen is going to be at any point in time, I don’t want to set hard values for the size of my tic tac toe tiles. I want to set their size proportionally as a percentage of a whole rather than hoping that 150 pixels will work well on all screens and adjusting the spaces between them.

The board is a grid of nine tiles. The tiles are all the same size and they form a square. The tiles are closer to one another than they are to the border of the game board. I need to determine how large they need to be and also how to place them within this space.

To determine their width/height, I am going to create an algebraic equation. I know that I need to fit three tiles into the board’s width, so I will be dividing the width by three. However, I also need to account for the spaces between each tile and padding at the edge. So, to determine how large the tiles are I need to do the following calculation:

tileWidth = (boardWidth - (outerPadding * 2) - (innerPadding * 2)) / 3

We now know how to calculate the size of each tile, but we need to actually create each one and make sure we give each one an identifier so that when the player taps the middle square the program knows how to identify it.

Tile Sprites

Earlier in this project I created an array of tile states. This was the game model. We are now working on the game view, so we need analogous view objects that correlate to the model objects.

We will need nine sprite objects that represent a tile in our array of tile state. Each sprite needs to be given a size (which we calculated above), a position, and an identifier. The position is determined relative to the other tiles and relative to the board view. The identifier is the way we will be able to track which sprite has been tapped while the game is being played.

SpriteKit Coordinate System

In order to place objects in space, it’s important to understand SpriteKit’s anchor points and coordinate system. We know how to calculate the size and shape of our tiles, but we also need to know how to explain to Xcode where we want each tile to be placed.

Back when I learned algebra, I became familiar with Cartesian coordinates:

Generic Cartesian coordinate space

It’s the idea that you have an X and a Y axis that intersect at a center point, or origin. Every point in the coordinate plane can be expressed in relation to that center point. Any point that is above the X axis is thought of as positive and anything below the X axis is thought of as negative. Anything to the right of the Y axis is also positive and anything to the left is negative.

In SpriteKit, the center point/origin of the screen is oriented at the bottom left corner:

SpriteKit’s default coordinate orientation

What that means is that every point you look at is effectively going be positive. In this scenario, if you wanted to place an element at the bottom of the screen, offset by twenty pixels, you would set the y-position to 20. If you wanted to place it at the top, offset by twenty pixels, you would set the y-position to screen.size.height - 20.

Alternately, you could place your anchor point at the top right corner of the screen:

Inverted SpriteKit anchor point. Everything on the screen is negative in relation to the anchor point.

This would work the opposite of the default. Instead of thinking of everything positively, you think of things negatively. If you wanted to place an element at the bottom of the screen, offset by twenty pixels, you would set the y-position to -screen.size.height + 20. If you wanted to place it at the top, offset by twenty pixels, you would set the y-position to -20.

For my purposes, I care about building my application from the center out. I have no idea how tall the screen is that my app will appear on, so I need to build everything from the middle out. This means my anchor point will need to split the difference between SpriteKit’s default anchor point and the inverted one:

Center anchor point. Half the coordinates will be positive in relation to the anchor and half will be negative.

This makes placement slightly tricky. Some of my coordinates exist in positive coordinate space and some exist in negative space. Anything to the left of the center of the screen is negative while anything to the right is positive.

Embedded Nodes and Relative Positioning

I have no idea how tall the iPhone displaying my game is going to be. For the last few years Apple has tried to get people to think of screens proportionally rather than absolutely. I can’t position my tiles in relation to the height of the iPhone because that is variable. I went to a bunch of trouble to create a square area at the center of the screen that adjusts its size based on the height of the iPhone. I know this will always be square and I am basing the size and position of my tiles relative to that object.

SpriteKit utilizes a node graph. What this means is that you can add a sprite node as a child of either the scene or of another sprite. The tic tac toe board will have nine sprites that I want to control as one object and place within their own relative context.

Anchor points greatly impact positioning of embedded objects.

Tile Code

First I need variables for the padding around my tiles. I use this in a few places and if I don’t like the way it looks I only want to change the value in one place.

let outerBorderPadding:CGFloat = 30.0
let betweenTilesPadding:CGFloat = 15.0

I am going to use these to calculate the size of my tiles:

let padding = (outerBorderPadding * 2) + (betweenTilesPadding * 2)
let tileSize = (boardSize - CGFloat(padding)) / 3

Next I need to place and name my tiles. I had a creepy convoluted rats nest of code because I was trying to avoid rows and columns, but then I talked through this with The Boyfriend and we came up with something less busted:

var tileCounter = 0

for yIndex in 0..<3 {
	for xIndex in 0..<3 {
		let sprite = SKSpriteNode()
		sprite.color = UIColor.red
		sprite.size = CGSize(width: tileSize, height: tileSize)
		sprite.name = "Tile\(tileCounter)"
				
		let xPosition = CGFloat(outerBorderPadding) + CGFloat(xIndex) * (tileSize + betweenTilesPadding)
		let yPosition = CGFloat(outerBorderPadding) + CGFloat(2 - yIndex) * (tileSize + betweenTilesPadding)

		sprite.anchorPoint = CGPoint.zero
		sprite.position = CGPoint(x: xPosition, y: yPosition)
		boardLayer.addChild(sprite)

		tileCounter += 1
	}
}

There is a tile counter outside of the nested loops so that I can ensure that my tile name correlates to the index it represents in the data model.

We have nested loops for the rows and columns. I was concerned I would need to create persistent objects to keep track of the row and column of each square. That is a valid design pattern that would utilize if I was doing something more complex, but with only nine objects I had hoped to just keep things simple.

For each tile, I need to label the tile so I know which one we are dealing with and I also need to place it properly in relation to the ones around it. Later I will add logic for the squares to have graphics associated with selection and deselection, but for now I simply want to establish that my layout works properly.

In the nested loops, I am creating a tile for a row and column. There are a few ways this could have been placed. In this implementation, I kept the default SpriteKit coordinate system for these sprites, which means the origin is in the lower left corner. We need to account for that in our positioning of the sprites. I am counting the indices of the tiles starting in the top left while the origin is in the bottom left. This doesn’t affect the x-position, but it does affect the y-position. This is why I’m subtracting two from the y-index. The sprite is added to the board and the tile counter is incremented.

Final output of the board.

Conclusion

The current state of the project is available here.

For me, the challenge of figuring out how to place elements programmatically is an incredibly important problem. My aim with a lot of my game development is to do work in board/card games. Since the screens I am working with are variable and the number of elements are variable, it is tremendously important to me to figure out how to emulate auto layout in SpriteKit.

The game logic is relatively simple compared to the amount of programming that goes into the UI. I feel like when people think about programming a game, the thing they focus on is the mechanics and not the layout. Graphics are the most intensive part of game development and there are a lot of problems to solve that you don’t think about because you just kind of expect things to work.