Land of Misfit Frameworks

Right now I am in the process of writing a book on Metal. Metal came out the same year as Swift. One thing that has caused a lot of frustration among people like myself who are interested in Metal is the fact that there is not a lot of material out there on the framework. It’s gotten much better. Ray Wenderlich has released a video series on Metal. Apple dedicated a whopping five videos to Metal in 2016. If you’ve been checking the docs between when Metal came out and now, they have increased dramatically in both quantity and quality. Metal has come a long way over the last year.

There are frameworks that Apple released in the last few years that make Metal dramatically more useful. It integrates well with SceneKit, which makes it far easier to work with 3D graphics. In 2015, Apple introduced the Model I/O framework to make it easier to import 3D models from programs like Blender and Maya. Before that, you had to parse all these files by hand like a savage.

I had a sample project I wanted to do today that I didn’t realize I needed to import a model for. Most of the things that I need to do with Metal are made infinitely easier by Model I/O and SceneKit. But I don’t see people clamoring for more books on SceneKit or tutorials on Model I/O. There is almost no information out there about it outside of the Apple documentation. There is one piece of sample code and only one video from 2015.

I am not picking at Apple for not having more documentation. They have a lot on their plate and they’re doing the best they can. I am simply confused as to why I don’t see more people complaining about the lack of information about Model I/O. I don’t know if the lack of adoption of Model I/O is clamping the adoption of Metal or if it goes the other way.

I feel like there is a lack of understanding about what is out there and what the most optimal way is to get things done as efficiently as possible.

I know that SceneKit never got the amount of attention that it may have deserved. Everyone I talk to that would use SceneKit don’t want to because it’s not available on Android. I feel like most people I interact with use Unity because it was the best thing available five years ago and it’s just the thing they’re most comfortable with.

Apple has a lot of misfit frameworks. Gameplay Kit. Model I/O. SceneKit. These all work together and support one another. I want to see more stuff out in the world about these frameworks.

I am hoping that I can incorporate learning these frameworks into my exploration of Metal. I think that knowing these tools and using them in my projects will make my experience with Metal far richer and more productive than it would have been otherwise. I know this runs the risk of being a rabbit hole I fall down that prevents me from focusing and getting projects done. However, I think if I don’t raise my awareness of these frameworks, I will be missing the forrest for the trees. I will wind up wasting a bunch of time reinventing the wheel or creating useless things that don’t accomplish what they are capable of.

I am trying to remember that these are large topics. These take time to learn and adopt. Rome wasn’t built in a day. It’s important to remember this is a large topic and to not get frustrated when I realize things are large.

Game Development Journal 6: GKRandom

As of my last blog post, I now have a deck of flower cards. It is represented in an array of various struct instances that all conform to a Card protocol.

Games would not be very interesting if we didn’t have random elements. In order for me to proceed with my game, I need to implement a method to “shuffle” my deck of cards.

Initially, my plan was to do some research into various randomization algorithms. I was looking for an excuse to do more research into computerized randomization, but I don’t feel this application will fit the bill. My research yielded two results:

  1. iOS has a built in framework specifically for randomization
  2. Other languages have this functionality built directly into their Array class

One thing I am trying to avoid with this project is falling down rabbit holes. I thought it would be interesting to compare rolling my own randomization against the ones that are built into Gameplay Kit, but that is a waste of time. I am not rolling my own cryptography, so the built in randomization tools are fine.

Additionally, I feel that there are a lot of aspects of Gameplay Kit that people are completely unaware of. It seems to be something of a lost framework that I see very few people actually talk about or show in production. In the spirit of trying to figure out the best way to solve problems, I have decided that I would like to try and implement Gameplay Kit whenever possible so that awareness of this framework can improve.

GKRandom

Apple has a nice overview of the various options they have for their randomization components.

GKRandom is a protocol that has two classes that conform to it: GKRandomSource and GKRandomDistribution.

GKRandomDistribution is set up to generate random numbers based on a range. This would be ideal for doing something like rolling a dice. There are even built in functions based on both six-sided dice and twenty-sided dice. Good news if you are and Dungeons and Dragons fan!

I could write an algorithm to implement this to force it to suit my needs, but it’s worthwhile to see if the other class would work better.

Looking at GKRandomSource’s documentation shows that there is a built in method called arrayByShufflingObjects(in: [Any]). Since I decided to turn my deck into an array and not a dictionary, this seems ideal.

GKRandomSource is not meant to be used directly. It is a super class that has three different subclasses based on different random algorithms:

  • GKARC4RandomSource: This is the default randomization algorithm. This works well with just about any game scenario.
  • GKLinearCongruentialRandomSource: This is a more performant algorithm. It’s less random, but also less resource intensive. If you’re counting the milliseconds in your game loop and you don’t need something super random, you might want to consider this.
  • GKMersenneTwisterRandomSource: This is the most random of the random source classes, but it is also the slowest.

Since all three of these inherit from GKRandomSource, they all have the method to shuffle an array. It’s just a question of which one suits my purposes.

I think any of them would work. Shuffling a deck of cards tends to be less random than rolling a die by the nature of how difficult it is to get a genuinely random distribution, so having the most random distribution is probably overkill.

I am tentatively going to choose the fastest algorithm, the GKLinearCongruentialRandomSource. I don’t think that the performance aspect is an issue. The deck is only generated at the beginning of a hand, along with all other setup steps. If this were being run every single frame then performance would be an issue.

Instead, I am trying to mimic an actual game playing experience. If you are shuffling decks of cards, you’re not going to get super random distributions. Additionally, the way that I have initialized the deck by grouping the cards by class rather than suit, the initial deck layout is fairly mixed up anyway.

My final code to add shuffling functionality is as follows:

// Random Functions: Need to generate a "shuffled" deck of cards

func shuffleDeck(deck: [Card]) -> [Card] {
    let randomGenerator = GKLinearCongruentialRandomSource()
    return randomGenerator.arrayByShufflingObjects(in: deck) as! [Card]
}

let shuffledDeck = shuffleDeck(deck: deck)

By using Gameplay Kit, I was able to get the functionality I needed with one function that uses two lines of code.

Conclusions

It feels kind of anticlimactic to write a whole blog post to end saying I resolved the issue with two lines of code. But I feel like it’s important to emphasize the value of simple solutions.

I feel like we, as a community, feel the need to implement more complicated solutions. If I don’t write out my random algorithm in Swift, then I am not a real programmer. Except that’s not true.

First off, implementing my algorithm in Swift will result in me having more code that I have to maintain. Swift is still rapidly changing. Swift 2.2 is legacy code. More lines of pure Swift means more things that change that I have to go back and update a few times a year. No thank you.

Second, it would have taken up more lines of code. Right now the algorithm is abstracted away and I don’t have to have it in my code.

Third, there is no point in reinventing the wheel. My need to shuffle an array of objects is a common enough problem that Apple provided me a simple solution for it. They will maintain it and ensure that it keeps working. If it’s deprecated then it’s on me to go back and find what it changed to, but for all intents and purposes I never have to touch this again.

Fourth, I know that this algorithm is accurate because Apple gave it to me. They have people who know more about this stuff than I do who wrote and tested this so I don’t have to.

Fifth, if I ever for some reason bring on another person onto my project, it’s much simpler for that person to read that code snippet than it would be to walk through the programming logic associated with the algorithm. It’s plain what the function does and if they have questions they can read Apple’s documentation.

I have added this new playground here. It’s basically the same as the refactored playground but with the added random function and its call. Those lines are at the bottom.

Moral of the story is, if someone gives you the ability to do something in two lines of code, for the love of God just take it!!

god