Categories
Comic Books iOS App Software Design

Book Binder App Update: Variant Chaos!

I’m still working on that comic book collecting app! It’s starting to look and feel like a real app but still has a long journey of test driven development ahead of it!

Here’s what it looks like so far…

On the left is the Summary View and on the right is the Detail View. The summary view displays all the series and all the issues in each series that you are tracking. The detail view displays a particular issue, selected from the summary view. As I’ve complained, comic book publishers have little or no organizing skills and important identifying metadata is driven by marketing and whims. My app has to shoehorn a seriously fuzzy world of comic book print editions into data structures that can be sorted. This requires hard choices about how to organize comic book data so the user gets a usable app.

One of the biggest puzzles is what to do with variant covers!

Purchase a recent issue of any popular comic book, especially from Marvel, and you’re just as likely to get a variant cover edition as not. Marvel, as far a I can tell, doesn’t identify variant additions with a signifier. This is probably great marketing. There is some unknown number of variant covers for Fantastic Four #1 (volume 6, started this year 2018). I’ve counted 28 so far!

Hunting variants is like hunting Pokemon! You never know what is lurking in the next comic book shop. Some variant covers are created by famous artists, others feature famous moments or particular characters, some are specific to a comic book shop, and others are created for the dramatic effect of displaying all the covers side-by-side.

Faced with no official designation and a need to figure out what you may or may not own, comic book collectors and sellers have developed their own, local, ways of identifying variants, usually a single letter or string of letters, but also potentially any printable character.

After considering all this madness here is what my super sophisticated user experience for recording variant identifiers looks like…

There’s not much I can do to help the user other than provide some examples in the prompt and make sure she doesn’t add the same variant twice. I’ll probably find a way to list the current tracked variants, if any, and a way to add cover photo as well. But for now the simple text field does the job!

I think this is why general purpose productivity tools, that give people the work of organizing information in to a structure, usually seem easier to use than specialized apps like Book Binder. A simple spreads sheet could be built in minutes the job that my app is taking months to figure out.

I can’t easily use a spread sheet with my iPhone. I tried the iOS versions of Excel and Numbers and they are great for viewing but not so great for data entry or creation. Spread sheet are famous for being so open that errors in data and formulas are hard to detect. Squishy data like variant edition covers is easy to put in a spreadsheet but hard to test, hard to verify, and hard to maintain.

My long term hope is to use Apple’s MLCore Vision framework to identify variant editions on the user’s behalf. But that will only work if I work with a comic shop or collector who can tag all known variant editions and provide me with that data–or just make it available for free on a nicely scalable web server.

As always you can find the Book Binder Code on GitHub: https://github.com/jpavley/Book-Binder

Categories
Programming Uncategorized

Swift Programming: Filtering vs For Loops

The current version 3.1 has come a long way from the Yet-Another-C-Based-Syntax of the 1.0 version of Swift.

One of the best features of Swift is how functional programming idioms are integrated into the core of the language. Like JavaScript, you can code in Swift in several methodologies, including procedural, declarative, object-oriented, and functional. I find it’s best to use all of them all simultaneously! It’s easy to become a victim of the law of diminishing returns if you try to stick to one programming idiom. Swift is a very expressive coding language and it’s economical to use different styles for different tasks in your program.

This might be hard for non-coders to understand but coding style is critical for creating software that functions well because a good coding style makes the source easy to read and easy to work with. Sometimes you have to write obscure code for optimization purposes but most of the time you should err of the side of clarity.

Apple has made a few changes to Swift that help with readability in the long term but remove traditional C-based programming language syntax that old-time developers like me have become very attached to.

The most famous example was the increment operator:

x++ // add one to the value of x

In modern Swift you have to write:

x += 1 // add one to the value x in Swift

As much as I loved to type ++ to increment the value of a variable there was a big problem with x++! Most coders, including me, were using it the wrong way! The correct way for most use cases is:

++x // add one to the value of x before using x

Most of the time the difference in side effects between ++x and x++ were immaterial, except when it wasn’t and it created hard to track down bugs in code that looked perfectly ok.

So now I’m used to typing += to increment values even in programming languages where ++ is legal. (Also, C++ should rebrand itself as C+=1.)

Another big change for me was giving up for-loops for functional expressions like map, reduce, and filter. As a young man when I wanted to find a particular object in an array of objects I would loop through the array and test for a key I was interested in:

for o in objects {
  if o.id == 12345 {
    // do something
    break;
  }
}

Nothing is wrong with this code—it works. Well, actually there is a lot wrong with it:

  • It’s not very concise
  • I should probably have used a dictionary and not an array
  • What if I accidentally try to change o or objects inside this loop?
  • If objects is a lengthy array it might take some time to get to 12345
  • What if there is more than one o with the id of 12345?
  • This for-loop works but like x++: it can be the source of subtle, hard to kill bugs while looking so innocent.

But I’ve learned a new trick! In Swift I let the filter expression do all this work for me!

let o = objects.filter { $0.id == 12345 }.first!

In that single line of code o will be the first object that satisfies the test id == 12345. Pretty short and sweet!

At first, I found the functional idiom of Swift to be a little weird looking. By weird I mean it looks a lot like the Perl programming language to me! But I learned to stop being too idiomatic and to allow myself to express functional syntax as needed.

For you JavaScript or C programmers out there here is a cheat sheet to understanding how this functional filtering works:

  • let means o is a constant, not a mutable variable. Functional programing prefers constants because you can’t change them accidentally!
  • The { } represents a closure that contains a function and Swift has special syntactic sugar that allows you to omit a whole bunch of typing if the function in the closure is the last or only parameter of the calling function. (Remember in functional programming functions are first class citizen and can be pass around like variables!)
  • $0 is a shortcut for the first parameter passed to your closure. So you don’t have to bother with throw away names like temp or i,j,k,x, or y.
  • .first! is a neat way to get [0], the first element of an array. The ! means you know it can’t fail to find at least one element. (Don’t use the ! after .first unless you are 100% sure your array contains what you are looking for!)

I’m working on a new project, a game that I hope to share with you soon. The game itself won’t be very interesting. I find that I enjoy creating games more than I enjoy playing them so I’m not going to put too much effort in creating the next Candy Crush or Minecraft. But I will blog about it as I work thought the problems I’ve set for my self.

Categories
Programming

Identity used to sign executable no longer valid

The last thing I wanted to do on a Sunday morning is write a blog post about an an Xcode executable problem. What I had planned to do is test my most recent Swift 2.0 SpriteKit game on my iPad and iPhone. Last night I got a “Identity used to sign the executable is no longer valid” error when attempting to run my code on a real device. Since it was around midnight I took the message a notification that bedtime had arrived. Besides, a quick search on StackOverflow would surely solve the problem and if I got on SO now I would be up all night nosing around.

This morning I got the same message and found a post on SO that started  four years ago with two pages of answers: The identity used to sign the executable is no longer valid. It’s been viewed 66K times and covers many ancient versions of Xcode. The top answer simply said to restart Xcode. Indeed, restarting, rebooting, or re-installing is always a great answer! So I tried the first two (restarting Xcode and rebooting all my devices) but no joy. And it’s a cheap answer. 99% of computer problems are temporarily solved by powering down and up the server or device but the root cause sits like a malignant elf in the machine, biding it’s time, ready to strike again.

So I figured it out. My problem, in any case.

Last week I was giving a talk at SUNY Buffalo (shout out to Prof. Hartloff). It’s just far enough away from NYC that I had to stay overnight. I took a MacBook Pro that I don’t ordinarily use for development. When I was working on my new game and testing it my iPad and iPhone (to get actual frame rates and the feel of touching the screen) Xcode discovered that I didn’t have an iOS development certificate on that MacBook and asked me if I wanted to revoke my current cert or copy it over from another machine. Since I didn’t have it I said revoke. Xcode did what ever it does and created me a new iOS dev cert associated with that particular MacBook Pro.

Note to Apple: There has to be a better way for Apple certified developers to manage their certificates in this age of clouds and connectivity. Can’t these certs reside on Infinite Loop server?

Enough backstory!

If you get the dreaded “Identity used to sign executable no longer valid” error and restarting your Xcode doesn’t work here are the steps that should fix it for good.

Go to your Apple developer account certificate overview and read carefully and completely about how to manually manage certs and provision devices. Once you understand what you need to do it’s relatively simple.

  1. Revoke and delete all the could certs and profiles of devices you no longer own that have build up over the years. Clean it all up.
  2. Then, following the instructions from Apple recreate your iOS development and distribution certificates.
  3. Re-provision your iOS devices.
  4. Download your certs and provisioning files and reinstall them into your Mac’s keychain.
  5. Clean and build your app.
  6. Now it should run on the iOS devices you’ve provisioned nicely.

Note to You: Xcode is no longer managing your certs and profiles. But that’s OK. It was doing a bad job anyway.

Post Script

Why didn’t I post this info to Stack Overflow? Because this is a pretty radical solution, not without risk. SO, for better or worse, has been come the place for copy and paste solutions that have not aged gracefully over time. Don’t get me wrong–I love Stack Overflow, recommend it, and use it all the time. But sometimes it’s not safe to post an answer to a problem that requires reading comprehension.

Lucky for you and me, my unpopular blog post will probably be the last item in your search for solutions to apple certification problems.

Categories
Nerd Fun Programming

Fun with Core Graphics and Swift Part 2

Hey, you have 10 minuets, don’t you?

Then you can add pinch and rotate gestures to our fake-genigraphics app. I didn’t realize it would be this easy. But sometimes Apple’s developer tools engineering team does something amazing–and gesture recognizers are super amazing.

A good way to start is to read the UIGestureRecognizer Tutorial on Ray Wenderlich’s website. I’ve said good things about Ray before. I don’t know him. However, Ray and his team of technical authors just have a way of spelling things out 100 times more clearly than Apple’s developer documentation.

After you’ve read the tutorial open up ViewController.swift in the fake-genigraphics project. Delete the boilerplate code in the ViewController class and replace it with the following code (from the tutorial):

    @IBAction func handlePinch(recognizer : UIPinchGestureRecognizer) {
        if let view = recognizer.view {
            view.transform = CGAffineTransformScale(view.transform,
                recognizer.scale, recognizer.scale)
            recognizer.scale = 1
        }
    }
    
    @IBAction func handleRotate(recognizer : UIRotationGestureRecognizer) {
        if let view = recognizer.view {
            view.transform = CGAffineTransformRotate(view.transform, recognizer.rotation)
            recognizer.rotation = 0
        }
    }

Each of these functions is decorated with the @IBAction tag. That means we’re going to hook them up to events from our project’s Main.storyboard. This part still vexes me. I want to do everything in code and not use drag and drop to wire up events with functions (and properties with variables). Especially since I am left handed and to do a key part of the drag and drop I have to use the control key which only exists on the left side of my nifty Apple Magic Keypad.

Enough whining. Time to drag and drop!

Open up your Main.storyboard in the fake-genigraphics project. In the Object Library on the right find the section near the bottom with all the gesture recognizers. Drag a Pinch Gesture Recognizer out from the library and drop it on the BackgroundView in the storyboard. Now for the hard part: In the Document Outline on the left control-drag the Pinch Gesture Recognizer entry up and drop it on the ViewController entry. On the pop-up menu that suddenly appears choose Sent Actions Handle Pinch. (So weird).

Do these same steps again with the Rotation Gesture Recognizer. What you are doing is connecting events from the gesture recognizers to the functions in the ViewController marked with @IBAction.

Guess What? You’re done! Run your app in the simulator and on your iPhone or iPad. You can now zoom in and out and rotate the Background View like a pro. Notice how responsive and smooth the animation is. Alas there seems to be limits on how far you can zoom out. And you can’t rotate and zoom at the same time. I have trouble with rotating with my left hand. I’m convinced that nobody at Apple is left handled!

Categories
Nerd Fun Programming

Fun with Core Graphics and Swift

A long time ago in a galaxy far, far away… I was a computer graphics artist. Specifically I was a Genigraphics
console operator. I worked the night shift creating illustrations and slides with vector graphics for big corporations. This was the early 1980s and fast, cheap personal computers with color graphics had not quite been invented yet. Later when I learned to program the Apple Macintosh I had a head start–I had created hundreds of vector images using computer graphic primitives by hand! The ability to draw lines, circles, and rectangles with code blew my mind.

I’m thinking it would be fun to do some graphics exercises with Swift and Apple’s Core Graphics. Maybe recreate some of those Genigraphics images from 30 years ago. Somewhere in the basement I have a box of 35mm slides and 8″ floppy disks. Probably not readable but I should be able to create a few images from memory. Genigraphics was the ancient ancestor of PowerPoint and Keynote. Every element in an illustration or on a slide had to be created from a graphic primitive. A gradient color fill was created with 30 or 40 overlapping rectangles, each with an incrementally different color.  And remember all the primitives were created by a human hand!

One of the most time consuming effects involved creating a grid for a background. It involved much duplicating, aligning, and counting.

So let’s create a clunky Genigraphcis grid in Swift using Core Graphics and display it in a UIView on and iOS device!

Launch Xcode and create a new iOS single view application. Make sure you choose Swift as the language. It doesn’t matter what you call your app. Run the new blank app just to make sure Xcode did it’s job.

Kill the app and go back to Xcode. Create a new iOS Cocoa Touch Class source file. Call it BackgroundView and make it a subclass of UIView. Go to your main.storyboard and select the View in your View Controller. In the Identity Inspector set the class of the View to BackgroundView.

Run the app again just make sure it builds and then kill it and return to Xcode.

Select BackgroundView.swift. You should see a drawRect function provided by Apple. Delete all the comments so it’s ready for some grid code…

override func drawRect(rect: CGRect) {

}

This function is called whenever iOS needs to paint your view on the screen. The rect is the area that needs to be painted. The first time drawRect is called the rect is the same size as your view. Later on when drawRect is called the rect is just the area of the view that needs to be updated. So I get the view width and height from the bounds. I’m also assuming the origin (left, top corner) is always 0,0. Add the following code to your drawRect function so you can get the the bounds width and height and compare it to the rect (technically called the “dirty rect” because that is the part of the view that needs to redrawn).

        let viewWidth:CGFloat = self.bounds.width
        print("viewWidth \(viewWidth)")
        print("rect.size.width \(rect.size.width)")
        
        let viewHight:CGFloat = self.bounds.height
        print("viewHight \(viewHight)")
        print("rect.size.height \(rect.size.height)")

I like to define all my important variables together near the top of my functions because I always know where to find them. Swift let’s you declare and define variable throughout the code. (I only use that freedom for unimportant “throw away” variables that are used inside loops and other control structures.)

Add the code to define your gridlines starting points, lengths, and line width.

        let x1:CGFloat = 0.0
        let x2:CGFloat = viewWidth
        
        let y1:CGFloat = 0.0
        let y2:CGFloat = viewHight

Core Graphics likes all your coordinates to be CGFloats. Since the resolution of an iOS device can be just about anything size these coordinates represent an idealize space as points. On a high resolution iOS device, like an iPhone 6s Plus you’re going to get 3 pixels for every point. My iPhone 6 Plus has a resolution of 1242 × 2208 but Core Graphics gives me 414 × 736 to work with. I’m just going to live with that for now.

I want a nice square grid so I use the either the viewWidth or viewHeight (which ever is smaller) divided 15 as the length of a grid cell.

        let cellLength:CGFloat = min(viewHight, viewWidth) / 15
        print("rowHeight \(cellLength)")

Now it’s time to set the style of our lines: color and width. As I recall Genigraphics only had 64 colors or maybe 128. I’ll figure that out next weekend. In the meantime I choose blue with a width of 2.

        let lineWidth:CGFloat = 2.0
        
        let context = UIGraphicsGetCurrentContext()
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        
        let components: [CGFloat] = [0.0, 0.0, 1.0, 1.0]
        let color = CGColorCreate(colorSpace, components)
        
        CGContextSetLineWidth(context, lineWidth)
        CGContextSetStrokeColorWithColor(context, color)

Wow! That’s a lot of code just to set the color and line width. It’s a little complicated because Core Graphics is context-based. You have to get the current graphics context and modify it to draw. In the code above I’m also creating a color the hard way via a color space and RGBA (Red Green Blue Alpha) color values. All this work will let me have a fine degree of control of the color of the gridlines later on.

Finally, I’m going to draw my horizontal and vertical gridlines!

        // draw horizontal lines
        var i:CGFloat = 0.0
        repeat {
          
            CGContextMoveToPoint(context, x1, cellLength + i)
            CGContextAddLineToPoint(context, x2, cellLength + i)
            
            i = i + cellLength
            
        } while i < rect.height - cellLength
        
        
        // draw vertical lines
        var j:CGFloat = 0.0
        repeat {
            
            CGContextMoveToPoint(context, cellLength + j, y1)
            CGContextAddLineToPoint(context, cellLength + j, y2)
            
            j = j + cellLength
            
        } while j < rect.width - cellLength

I’m just fooling around at this point so I don’t know if two repeat loops is the most efficient way to draw a grid. Right now I’m just happy to see a grid show up. I’ll optimize it later–if needed! To draw my lines I start at 0 and draw each line a cellLengh apart. CoreGraphics is a bit like Logo’s turtle graphics: I have to add drawing commands to the context, building up the image step by step behind the scenes.

If you run the code that this you will see nothing! Go ahead… I dare you!

That’s because you need to tell the graphics context to blast your drawing commands from the context on to the view. One line of code does it.

        CGContextStrokePath(context)

If you have been typing along you now have a custom UIView that draws a grid properly no matter now you hold your iPhone.

If you want to see the grid on your storyboard add

@IBDesignable

just above the class declaration. But be careful! Buggy Core Graphics rendering can freeze up Xcode. (It happened to me while writing this code.) I keep @IBDesignable commented out until I know my drawing code is working.

You can find all the code on GitHub.

Next week I’ll add some more complex drawing in the OG Genigraphics style. This is a good start for your own explorations. Have fun and don’t worry! You can’t blow up your computer by writing code.

Categories
Programming

Nothing Changes More Swiftly than Apple’s Swift Syntax

Look at that beautiful Apple Swift code on the right with closures and shorthand argument names! Make’s me smile every time!

I’m enjoying the Stanford University class CS193P: Developing iOS 8 Applications with Swift. It’s free on iTunes U and the instructor Paul Hegarty knows his stuff. He’s a great explainer. I like how first he writes some code in a naive way and then fools around with it, getting it to work and then reworking it like a sculptor with clay. That’s how real programmers work. We write a rough draft of the code, make sure we understand it and then “refactor” it until we’re no longer embarrassed to share it on GitHub.

But even though the class was recorded in 2014 and updated in June of 2015 it’s aging rapidly. We’re already working with Xcode 7 and iOS 9. And all the little minor changes and improvements are adding up.

One problem you might run into is with the second video: More Xcode and Swift, MVC. In this lesson Professor Hegarty wants to show how we can use a form of polymorphism to write clean code. Specifically with Swift supports something that Objective-C did not! In Swift we can have class functions with the same name but different signatures. In the example in the lesson he shows how we can write two versions of performOperation–one that takes two Doubles as arguments and another that takes only a single Double as an argument. Very cool…

Unfortunately this code no longer compiles.

There is an explanation on Stack Overflow (if you can find it). But it’s not really clear as there are a couple of solutions. Perhaps the best solution, like so much on the human side of computer programming, is a matter of taste.

Here is the code and the fix:

    // these functions won't compile with Swift 1.2 and above
    func performOperationWith(operation: (Double, Double) -> Double) {
        if operandStack.count >= 2 {
            displayValue = operation(operandStack.removeLast(), operandStack.removeLast())
            enter()
        }
    }
    
    func performOperationWith(operation: Double -> Double) {
        if operandStack.count >= 1 {
            displayValue = operation(operandStack.removeLast())
            enter()
        }
    }
    // these functions will happily compile
    func performOperationWithTwoOperands(operation: (Double, Double) -> Double) {
        if operandStack.count >= 2 {
            displayValue = operation(operandStack.removeLast(), operandStack.removeLast())
            enter()
        }
    }
    
    func performOperationWithOneOperand(operation: Double -> Double) {
        if operandStack.count >= 1 {
            displayValue = operation(operandStack.removeLast())
            enter()
        }
    }

Because Swift is smart about classes written in Objective-C that you are subclassing from, it forces those subclasses, in this case UIViewController, to obey Objective-C’s limitations. One of those limitation was not allowing polymorphism for methods with the same name but different arguments.

The code is a little uglier, because there is slightly more of it, but it smart of Apple to be as compatible with Objective-C as possible. At least for a few more years 🙂

Categories
Cocos2d-iPhone Programming

Cocos2D-Swift 3.0: A great way to get started developing iOS games!

If you’re new to iOS game development now is a great time to get started. In 2008 a brilliant engineer named Ricardo Quesada rewrote his 2D game engine for Apple’s iOS and released it as open source. It’s no exaggeration to say that hundreds of games, like my own, were developed using Cocos2D—including dozens of hits. Now it’s 2014 and the newbie game developer has several versions of Quesada’s Cocos2D framework to choose from. But for me the branch of Cocos2D devoted to the iPhone and iPad will always have a special place in my heart. Clearly Cocos2D-iPhone (now called Cocos2D-Swift) was the inspiration for Apple’s SpriteKit framework. And once you learn the fundamentals of Cocos2D on iOS you can easily transfer these skills to Android, Windows, and HTML5 versions of the Cocos2d family. Working with Cocos2d-Swift is like “reading Shakespeare in the original Klingon.”

Learning iPhone Game Development with Cocos2d 3.0 by Kirill Muzykov is a book I wish I had when I was learning to develop my first iPhone game. Muzykov patiently covers all the basics (nodes, sprites, actions, text, sound, buttons, menus) and jumps into advanced topics (particles, physics, tile maps, iTunesConnect, Game Center, and in-app purchases) while guiding the reader though creating a game called CocosHunt and using important tools (Particle Designer, Texture Packer, Tiled) and websites (freesound.org, media.io).

Along the way the reader also learns about Objective-C, Xcode, and iOS APIs. You’re still a beginner by the time you finish Muzykov’s book but you’re a well informed beginner and ready to tackle larger and more complex projects—like the next Candy Crush.

One of the best things I like about Muzykov’s book is it’s structure. A typical chapter starts with setting up a project and cycles through segments entitled “time for action” and “what just happened?”. This alternating rhythm becomes a reliable way to digest the material and ensure the author doesn’t wave his hands over new concepts. Almost every chapter includes a pop-quiz. I’m not a big fan of quizzes but if that’s what you need to re-enforce the material Muzykov provides them.

The source code is clean and clearly written with good comments. Muzykov keeps the syntax simple, using “typedef enum” instead of “typedef NS_ENUM” and “#define” instead of “FOUNDATION_EXPORT NSString *const” which is probably for portability. Much of a game is managing state and game developer who follow Muzykov examples in his classes won’t get into trouble.

If you’re new to mobile game development and you want to focus on iOS then Learning iPhone Game Development with Cocos2d 3.0 is a good book for you.

Categories
Programming Sprite Kit

Sprite Kit, Retina, iOS7 and Getting It Right

I spent more time that I care to admit figuring out how to reconcile my old Dungeonators code with Apple’s Sprite Kit, Retina displays, and iOS 7. Along the way I searched the web for help and ran into tons of tutorials and advice for indy game developers (I highly recommend  www.raywenderlich.com for a great set of systematic and well written tutorials). But I learned to be wary of advice on some sites that is confused or actually wrong. For example I came across this macro in one of Ray’s tutorials that originated from a Stack Overflow conversation:

#define IS_WIDESCREEN ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) &lt; DBL_EPSILON )

This macro was written by a floating point math C macro professional. It’s used to determine if the resolution of an iPhone screen is 4 inches. iOS 7 only runs on iPhone’s with Retina displays but there are still  millions of iPhone 4 and 4s models in use with 3.5 inch screens. The iPhone 5, 5c, and 5s has a widescreen of 4 inches.

But why do I need a fancy macro for that? It’s code that I’m only going to run once. And it’s not a particularly CPU intensive calculation. And really, I want to understand what every line of code in my game does. Copy and paste code is always a bad idea.

It’s not hard to figure out what this macro does: It gets the height of the screen, subtracts the resolution of the 4 inch iPhone from it and makes sure the result is less than a number that is as close to zero as the phone’s floating point system can represent. However, there is no reason that we have to go to this level of complexity!

My feeling about macros is that you almost never need to use them. And if you do, call in a pro C programmer. Macros can optimize your code but if you don’t use the right number of parens you could end up with subtle side effects and bugs that are hard to track down.

As an added bonus this macro is only useful if you have determined that the iOS device your game is running on is an iPhone. Taken out of context this speedy line of code could give your game the wrong idea.

To do it right, as in doing it with code that is safe, maintainable, and as efficient as it needs to be, you have to understand how Apple internally represents the resolution of an iOS device. (I’m assuming you want your game to be universal across the Apple universe.)

So let’s say you want to write a universal iOS game in Objective-C using Sprite Kit. Here are the consequences of your decision:

  • Your game can only run on iOS devices running iOS7. This fact eliminates the original non-Retina iPhones but not non-Retina iPads
  • Your game must support both 3.5 and 4 inch iPhones.
  • Your game must support iPad and iPad Retina devices.
  • Don’t worry about model names! The name of the device (iPad, iPad Air, iPhone 5, iPhone 4s, iPadophone 7xyz) doesn’t tell you anything reliable about the number of pixels you have to play with.

Here’s the non-obvious part: You’re going to create your game with pixels in mind but Apple is going to give coordinates in points. I wish Apple had not done it this way. I guess they were trying to be helpful. At lest let developers turn of the points paradigm if like me, they find it unhelpful. But we can’t turn it off so we have to live with it!

Apple says there are 2 pixels in a point. This table should help:

Device Type    Pixels        Points      Models
iPhone 3.5"    960 x 640     480 x 320   iPhone 4, 4s
iPhone 4"      1136 x 640    568 x 320   iPhone 5, 5c, 5s
iPad           1024 x 768    1024 x 768  iPad, iPad Mini
iPad Retina    2048 x 1536   1024 x 768  iPad with Retina

Apple gives us a macro of it’s own to figure out if we’re running on an iPhone or iPad, UI_USER_INTERFACE_IDIOM() and a way to discover the screen’s dimensions in points,
[UIScreen mainScreen].bounds.size.height

Thus, here is a simple method that you can add to your game projects to figure out what sort of iOS device you’re running on based on it’s screen real estate.

- (NSString *)figureOutScreen {
    // Call once during initialization!
    NSString *result;
    
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
        
        // iPhone
        
        if ([UIScreen mainScreen].bounds.size.height==568.0f) {
            
            // iPhone Retina 4-inch
            result = @"iPhone Retina 4-inch";
        } else {
            
            // iPhone filename 3.5-inch            
            result = @"iPhone Retina 3.5-inch";
        }
    } else {
        
        // iPad (Can't tell if it is mini, standard, or Retina 'cause all the dimensions in points are the same
        result = @"iPad";
    }
    return result;
}
Categories
Cocos2d-iPhone Programming Sprite Kit

Re-doing Dungeonators

One thing I think all software developers love to do is to make software for “the heck of it.” Hacking something together without having to worry about users, open source community members, and code reviews, is something devs don’t get to do often in these days of test-driven, agile, minimum viable products. Back in 2011 I created an iPhone game just for the heck of it. I wanted to learn about the indy game development process and there isn’t a better way of learning than by doing. I accomplished my mission and uploaded the first version of Dungeonators to Apple’s iTunes App Store in October of 2011. While the game is not very playable, I learned a lot:

  • How to design and implement a realtime game with Objective-C and the Cocos2d-iPhone framework
  • How to create all the art, fonts, sprites, and a spite atlas
  • How to record (or buy) all the sounds and music and use open source tools to transcode audio for a game
  • How to create the mechanics of a game with objects and callbacks while ref counting to manage memory
  • How to test and deploy an iOS game and get something approved in the App Store

Now it’s 2014 and much has changed in the world of indy game development for iOS. Apple’s iOS 7 introduced Sprite Kit which reduces the need for a framework like Cocos2d. Apple also introduced the iPhone 5 and the iPad with Retina, which mean there are four iOS screen resolutions/aspect ratios in common use. Oh, and let’s not forget Flappy Bird and 2048. While writing a hit indy game is still harder than winning the lottery it looks like a couple of people have done it!

Since I’m taking a break between adventures, I thought it would be fun to update Dungeonators for iOS 7 and Sprite Kit. Plus it would be good to make the game universal (available on all iOS devices) and global (available in more than just the United States edition of the App Store). And I should probably make it playable!

The technical part of this plan is relatively easy. iOS 7 is easier to develop with than previous versions of iOS. I can use ARC (automatic reference counting)in addition to manual ref counting. All the music and sound effects should just work fine. My custom Objective-C classes just need some simplifying (I wrote too much code–that’s my bad coding habit). The original Dungeonator’s artwork is all vector-based so rendering it in different resolutions for each iOS device shouldn’t be too hard. Finally, Sprite Kit is remarkably similar to Cocos2d. Porting the scenes, sprites, transitions, and actions will also be easy.

High resolution Dungeonators under development (1136 x 640 pixel rendering)

The hard part is creating a playable game. If you download original version of Dungeonators from the App Store you’ll find it really confusing. How do you play? Where to you touch? What is the goal? I don’t know what I was thinking!

Actually I do know what I was thinking. I was thinking about the inside not the outside. Inside there are classes for characters, strategies, spells, payloads, and matches. Way too much to fit in a casual game. So while I’m porting everything over I’m going to tear out hundreds of lines of code. I’m going to simplify Dungeonators to the point where it doesn’t require a personal demo from me to learn how to play!

I still might not have a playable game but at least it won’t crash anymore!

Categories
Cocos2d-iPhone Product Design

Dungeonators Battle UI Redesign


There is nothing quite like real user feedback. The Dungeonators game that I started coding about a year ago has been through several design iterations. Before I wrote a line of code I mocked up the whole UI and tested that on my friends and kids (paper prototype, an honorable UI design tradition). And with each development build I tested everything again and even enlisted strangers. I must have played though the final release candidate a 100 times. (It was then that I realized that game programmers must get sick of their games if they properly test them!)

When I uploaded Dungeonators to the App Store on 14 October 2011 I was pretty confident about the game play and the user interface. Famous last words as they say 🙂

After an initial healthily growth curve Dungeonators installs tanked:


The message I get from this user adoption curve was simple: Dunegonators stinks!

So I went back to the drawing board to search for the stinky bits. After much reflection I realized three things:

  1. Dungeonators is too hard for casual users and too easy/dumb for hardcore gamers. People who play MMORPGs like World of Warcraft punch through my game. People who play Angry Birds get stuck around level 1.6. (Which is as far as you can go if you don’t know what you’re doing.)
  2. People don’t know what to touch. They want to touch the avatars and not the raid and spell frames. If you don’t know what raid frames and spell frames are then you are not going to get my game.
  3. I was going to have to fix this. I could fix this problem with a lengthy tutorial or FAQs. But Dungeonators is causal game not productivity software. I never read manuals and skip tutorials. I expect my audience to have the same level of self respect!
So here is the new battle UI that tries to clean this mess up:
  • The good guy raid frames (on the left) are no longer touchable: They just display status. I couldn’t find a casual user who knew what a raid frame was so I got rid of raid frames.
  • Good guy spell frames are no longer associated with good guy raid frames: Spell frames are now modeless and never hidden. Each good guy has two spells available 24/7. As the game progress the spell are automatically upgraded. I’ll have to rewrite the game mechanics to handle the fact that the total number of available spells has gone from 4 x 6 (which I understand is 24) to a mere 8. But that actually makes Dungeonators a heck of lot simpler to program and to play.
  • The bad guy raid frames are still touchable and still enable the player to switch targets. But in the original UI you could have separate bad guy targets for every good guy. In the revised UI all the Dungeonators are synchronized. It’s a gross simplification that is all for the best.
  • Touching the center of the screen, where the avatars live, is still not part of the game play but if you do, the game will pause and bring up the main menu. I was able to kill two birds with one stone: No main menu button and a valid response to a user touch. Feedback is everything thing: In the original design touching the center of the screen was ignored and could have been interpreted as the game freezing up.
In general I learned what I thought I always knew: iPhone games have to be simple and causal gamers don’t have the time or energy for complex mechanics. But in practice I learned a lesson that every battled hardened game developer must know after their first game is released: There is no better test case than the real world!