Buttons in Sprite Kit using Swift · September 23, 2014

For all the helpful things that Apple added to Sprite Kit, one of the most glaring omissions is that most basic of user interface elements, the button. Not really sure why that is, but fortunately it’s pretty easy to create something that “just works.” The gist of the solution is to create a subclass of the SKNode class. Since each node in Sprite Kit can contain any number of other nodes, we just have to create a button container which holds two sprites: one for the default button state and one for the “active” button state.

import SpriteKit

class GGButton: SKNode {
    var defaultButton: SKSpriteNode
    var activeButton: SKSpriteNode
    var action: () -> Void
    
    init(defaultButtonImage: String, activeButtonImage: String, buttonAction: () -> Void) {
        defaultButton = SKSpriteNode(imageNamed: defaultButtonImage)
        activeButton = SKSpriteNode(imageNamed: activeButtonImage)
        activeButton.hidden = true
        action = buttonAction
        
        super.init()

        userInteractionEnabled = true
        addChild(defaultButton)
        addChild(activeButton)
    }

    /**
        Required so XCode doesn't throw warnings
    */
    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Here we create that subclass of SKNode and give it three properties: the default button image, the active button image, and the action that the button should take if pressed. Passing in two strings to the constructor handles initializing the button images, and we also store a reference to the button action function. Note of course that we hide the “active” button by default, waiting for user interaction to reveal it.

After the call to super.init(), the button container has access to methods inherited from SKNode. We then set the userInteractionEnabled property to true, which lets this node respond to input, and also add both buttons as children so they’ll be drawn to the screen.

Now let’s deal with user input. We want to handle three cases: user touches the button, user moves their finger around, user lifts their finger off the button. Fortunately the user interaction methods provided by SKNode give us exactly that, if you add the following three methods to the button class definition.

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    activeButton.hidden = false
    defaultButton.hidden = true
}

This first method is pretty obvious: if a user starts touching the button, show the “active” state.

override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
    var touch: UITouch = touches.allObjects[0] as UITouch
    var location: CGPoint = touch.locationInNode(self)

    if defaultButton.containsPoint(location) {
        activeButton.hidden = false
        defaultButton.hidden = true
    } else {
        activeButton.hidden = true
        defaultButton.hidden = false
    }
}

This next method is a bit more complex. We have to determine if a user moved their finger on or off the button, so as to show the appropriate highlight state. Fortunately, SKNode-derived objects have a method containsPoint(), which lets us do some easy collision detection.

override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
    var touch: UITouch = touches.allObjects[0] as UITouch
    var location: CGPoint = touch.locationInNode(self)

    if defaultButton.containsPoint(location) {
        action()
    }
    
    activeButton.hidden = true
    defaultButton.hidden = false
}

Finally, we re-use the containsPoint() method described earlier in order to determine if the button was actually tapped. If it was, we call the “action” function that was provided to the constructor. Then we set the highlighted button state back to hidden, ready to be shown again on the next tap. Put it all together, and here’s how you’d use the button in a game:

var button: GGButton = GGButton(defaultButtonImage: "button", activeButtonImage: "button_active", buttonAction: goToGameScene)
button.position = CGPointMake(self.frame.width / 2, self.frame.height / 2)
addChild(button)

I hope this was helpful. Feel free to ask questions in the comments section, and I’ll do my best to answer.

6 comments · Posted by in Programming, Tutorial · , , , ,

Intro to Sprite Kit using Swift · September 9, 2014

Have you started looking at Apple’s Objective-C replacement, Swift, yet? If not, now’s the time. You’ll use the same APIs with Swift, but the language syntax is similar to that of JavaScript or Ruby, which makes it a bit easier to write. While Apple provides some Swift tutorials, I’m mostly interested in using it with Sprite Kit, Apple’s home-grown casual game framework. The documentation provided on Apple’s developer gives an intro to using Sprite Kit with Objective-C, but I thought I’d translate that into Swift for your enlightenment and education.

Setup

To start off, open Xcode 6, and choose “Create a new Xcode project.” Select “Single View Application” for your application template, and then name your project. I’ll name mine “SwiftDemo.” Once you choose a location for the project files to be saved, you’ll be plopped into the “General” settings panel for the app. The next step is to add SpriteKit.framework to the project. Scroll to the bottom of the panel and find the section titled “Linked Frameworks and Libraries,” and click the plus icon. Type “SpriteKit” in the search input, select SpriteKit.framework, then click “Add.”

The next task is to set up the app’s view controller to use Sprite Kit. Select `Main.storyboard` from the project pane to open it. It has a single view controller and view. Click the large white box, which represents the view. In the Utilities pane on the right side of the window, change the class of the view to SKView. Next, select the ViewController.swift file from the project pane to open it. Change the import UIKit statement to import SpriteKit right below the copyright comment. Next, add some code to the controller’s viewDidLoad() method to show some Sprite Kit diagnostic info:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    var spriteView:SKView = self.view as SKView
    spriteView.showsDrawCount = true
    spriteView.showsNodeCount = true
    spriteView.showsFPS = true
}

We’re now ready to add the first SKScene to the app. Scenes correspond to the various sections of functionality in your game, such as title, level select, options, and actual game play. Right-click on the project pane and select “New File.” Select “Swift” for the file type, and name it HelloScene.swift. The newly created file will be empty, except for an import Foundation line. Change it to import SpriteKit, then create an empty subclass of SKScene:

class HelloScene:SKScene {
}

Now let’s go back to the view controller and have it present the newly-created (and empty) scene.

override func viewWillAppear(animated: Bool) {
    var helloScene:HelloScene = HelloScene(size: CGSizeMake(768, 1024))
    var spriteView:SKView = self.view as SKView
    spriteView.presentScene(helloScene)
}

Try to build and run the project. You should see a blank screen on the simulator with diagnostic information at the bottom.

Now we’ll work on actually adding content to the scene we just created. Add the following into the HelloScene class:

var contentCreated:Bool = false
    
override func didMoveToView(view: SKView!) {
    if !contentCreated {
        createSceneContents()
        contentCreated = true
    }
}

During the course of your game, scenes will be instantiated, and shuffled around, and deallocated when no longer needed. When the scene moves into view, you want to ensure that it contains your content, but only if it hasn’t yet been created. If the scene stays in memory and is re-presented, your initialization code could run twice, which is why we keep track of it with a boolean. Let’s implement the createSceneContents() method.

func createSceneContents() {
    backgroundColor = SKColor.blueColor()
    scaleMode = SKSceneScaleMode.AspectFit
    addChild(newHelloNode())
}

This function does a few things. It changes the background color (obvious), sets the scale mode, and then adds the return value of a newHelloNode() function to the scene. The scaleMode attribute can have two values, SKSceneScaleMode.AspectFit or SKSceneScaleMode.AspectFill. Both modes will ensure your game’s aspect ratio stays intact, but “AspectFit” will shrink the view to fit the scene (common side effect: letterboxing), while “AspectFill” fills the scene (but some content might be cut off). It’s up to you to decide what technique best fits your game.

Next let’s implement the newHelloNode function that adds actual content to the scene. It’s pretty straightforward, just creating a label, giving it some properties, then returning it.

func newHelloNode() -> SKLabelNode {
    var helloNode:SKLabelNode = SKLabelNode(fontNamed: "Chalkduster")
    helloNode.text = "Hello, World!"
    helloNode.fontSize = 42
    helloNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
    return helloNode
}

Now when you build and run the project, you should see a blue background with the text “Hello, World!” centered in the screen (notice the letterboxing due to our use of SKSceneScaleMode.AspectFit).

Animation

Fluid animation is absolutely necessary in any game. While it might not directly affect game play, its’ presence makes the game that much more engaging and “juicy.” We’ll add some animation to the label node in our scene. Add the following line to the newHelloNode() function:

helloNode.name = "helloNode"

All nodes have a “name” property, which you can use to identify or find them after they are initialized. Next, override the touchesBegan(touches: NSSet!, withEvent event: UIEvent!) method, and add the following:

override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) {
    var helloNode:SKNode = childNodeWithName("helloNode")
    if helloNode != nil {
        helloNode.name = nil
        
        var moveUp:SKAction = SKAction.moveByX(0, y: 100, duration: 0.5)
        var zoom:SKAction = SKAction.scaleTo(2, duration: 0.25)
        var pause:SKAction = SKAction.waitForDuration(0.5)
        var fadeAway = SKAction.fadeOutWithDuration(0.25)
        var remove = SKAction.removeFromParent()
        var moveSequence = SKAction.sequence([moveUp, zoom, pause, fadeAway, remove])
        helloNode.runAction(moveSequence)
    }
}

This method finds a node named “helloNode,” then runs a bunch of actions on it. Build and run the project, then click anywhere on the screen to make the method execute. There’s a good sampling of what’s available in the SKAction class here, but it’s always good to check out the SKAction class reference just to see what’s possible.

Scene Transitions

As I mentioned earlier, you’ll probably have multiple scenes in your game, and you’ll obviously need to switch between them. Fortunately, Sprite Kit allows you to do that quite easily, and add some fancy transition effects at the same time. Create a new scene called SpaceshipScene.swift and give it the following implementation:

class SpaceshipScene:SKScene {
    var contentCreated:Bool = false
    
    override func didMoveToView(view: SKView!) {
        if !contentCreated {
            createSceneContents()
            contentCreated = true
        }
    }
    
    func createSceneContents() {
        backgroundColor = SKColor.redColor()
        scaleMode = SKSceneScaleMode.AspectFit
    }
}

Now, go back to HelloScene.swift, comment out the code inside of touchesBegan(touches: NSSet!, withEvent event: UIEvent!), and replace it with the following:

var spaceshipScene:SKScene = SpaceshipScene(size: self.size)
var transition:SKTransition = SKTransition.doorsOpenVerticalWithDuration(0.5)
view.presentScene(spaceshipScene, transition: transition)

Build and run the project. You should see text on a blue background again. Click anywhere, and HelloScene will transition to SpaceshipScene with a cool “doors” effect. Again, check out the SKTransition class reference for a list of all the effects you can use.

Adding more content

Next we’re going to add an object to SpaceshipScene that’s comprised of multiple Sprite Kit “nodes.” Add the following code to the createSceneContents method in SpaceshipScene:

var spaceship:SKSpriteNode = newSpaceship()
spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) - 150)
addChild(spaceship)

Next, implement the newSpaceship() method:

func newSpaceship() -> SKSpriteNode {
    var hull = SKSpriteNode(color: SKColor.grayColor(), size: CGSizeMake(64, 32))
    var hover:SKAction = SKAction.sequence([
            SKAction.waitForDuration(1),
            SKAction.moveByX(100, y: 50, duration: 1),
            SKAction.waitForDuration(1),
            SKAction.moveByX(-100, y: -50, duration: 1)
        ])
    hull.runAction(SKAction.repeatActionForever(hover))
    return hull
}

Build and run the project to see a gray box moving back and forth indefinitely. Next let’s add “lights” to the spaceship. Insert the following right after declaring the hull variable in the newSpaceship method:

var light1:SKSpriteNode = newLight()
light1.position = CGPointMake(-28, 6)
hull.addChild(light1)

var light2:SKSpriteNode = newLight()
light2.position = CGPointMake(28, 6)
hull.addChild(light2)

Then implement the newLight() method:

func newLight() -> SKSpriteNode {
    var light:SKSpriteNode = SKSpriteNode(color: SKColor.yellowColor(), size: CGSizeMake(8, 8))
    var blink:SKAction = SKAction.sequence([
            SKAction.fadeOutWithDuration(0.25),
            SKAction.fadeInWithDuration(0.25)
        ])
    light.runAction(SKAction.repeatActionForever(blink))
    return light
}

Build and run the project. You should now see two blinking lights on the “spaceship.”

Physics

To wrap up, we’ll add some physics interactions to SpaceshipScene. I’ll leave the reasons why you might want a realistic physics simulation in your game as an exercise to the reader (*cough*Angry Birds*cough*). First of all, change the newSpaceship() method slightly to add a physics body to the ship hull:

hull.physicsBody = SKPhysicsBody(rectangleOfSize: hull.size)
hull.physicsBody.dynamic = false

We set dynamic = false so the ship isn’t affected by the physics system’s gravity. Otherwise it would fall off the screen, since there’s no floor in the game to stop it. Next add some code in createSceneContents() to generate rocks that will bounce off the ship.

var makeRocks:SKAction = SKAction.sequence([
        SKAction.runBlock(addRock),
        SKAction.waitForDuration(0.1, withRange: 0.15)
    ])
runAction(SKAction.repeatActionForever(makeRocks))

And implement addRock():

func addRock() {
    var rock:SKSpriteNode = SKSpriteNode(color: SKColor.brownColor(), size: CGSizeMake(8, 8))
    rock.position = CGPointMake(self.size.width / 2, self.size.height - 50)
    rock.name = "rock"
    rock.physicsBody = SKPhysicsBody(rectangleOfSize: rock.size)
    rock.physicsBody.usesPreciseCollisionDetection = true
    addChild(rock)
}

Build and run the project and you’ll see a bunch of rocks being generated and bouncing off the spaceship. While Apple’s tutorial has you manually removing rocks that fall off the screen, apparently some changes to the Sprite Kit API now do that for you automatically (you’ll notice the “node” count stays constant while the app is running).

And that’s it! A very basic overview to both Sprite Kit and Swift. Try playing around with the project and see what else you can come up with. Happy hacking!

1 comment · Posted by in Programming, Tutorial · , , ,

Vectr + Game Center for Cordova · June 14, 2013

It’s been a slow couple of months. A bit of “real life” upheaval (in the form of having to find a new job) has prevented blog updates. I haven’t been completely idle during this time, though, and have been working on a few small projects, two of which I’ll detail here.

The first is a Game Center plugin for Apache Cordova. I wanted to learn how to write a Cordova plugin, and as far as I know, no one else has written a plugin for Game Center. I’m probably the only person who is stupid enough to write such a thing. It’s not a 100% complete implementation, but has support for leaderboards, achievements, and turn-based multiplayer games. To test the plugin out, I wrote a simple reversi game, which will allow users to play via asynchronous multiplayer. The game itself isn’t quite done (I hit a roadblock in that I only had one iOS device to test on), but I’m hoping to get back in and finish it soon.

The other project is a minimalistic <canvas>-based game framework called Vectr (I’m not super enthusiastic about the name, so let me know if you can think of something better). What started as some experimentation with the canvas tag turned into something more like a full-fledged game framework. I use the term “full-fledged” pretty loosely, of course. It has support for game scenes, shape-based sprites, and particle emitters, and handles keyboard/mouse/touch input. My big source of inspiration was the Flash-based games of indie developer Kenta Cho. While it’s relatively easy to create a simple 2D game in Flash, a lot of the boilerplate code you might want is missing from JavaScript. This framework might help you out in creating prototypes that can be easily embedded into your website for quick feedback. If you end up wanting to publish the game (on mobile, for example), you can set an option when instantiating the game container that causes the canvas to scale to fit the size of the window, which means you could publish across multiple screen sizes pretty easily. I’m currently experimenting with making a simple dual-stick shooter using the framework.

As always, comments and suggestions are welcome. Keep programming!

Add a comment · Posted by in Games, Programming · , ,

Invading the Firefox Marketplace · April 11, 2013

Another day, another marketplace to list your apps in. This time it’s the Firefox Marketplace, the new hotspot for “HTML5″ apps. I recently registered as a developer and uploaded Nonogram Madness and Shikaku Madness.

Not really much to report, I had to make a few tweaks to both games to ensure they ran OK on the Firefox OS simulator, but aside from that it was easy to create an account and get both apps approved. Yes, your apps have to be vetted in the Firefox Marketplace, which is kind of annoying, but I guess it makes sense to have some level of curation to weed out malware, useless software, etc. My positive experience was that while both my apps had an initial bug (only counted iOS + Android as having touchscreen support, not Firefox OS), I fixed the problem and didn’t have to wait another week for them to be reviewed again; they were live that same day.

One kinda cool thing is that if you download Firefox Aurora (the “beta” version of the next Firefox release), you can install webapps locally on your computer; they get a native app wrapper, so you can launch them just like regular programs. Give it a shot, Mozilla has been doing a lot of cool things recently, so it’s worth checking out Firefox again.

Add a comment · Posted by in Games · , , ,

Nonogram Madness on Google Play and Mac App Store! · February 7, 2013

Been a quiet month or so since my last update. I haven’t been very productive in terms of new work, unfortunately. The purchase of my new Android phone got me thinking about doing some more work on my Android port of Shikaku Madness. Although it was released in June and priced at $0.99, I got maybe 10 sales in the course of 6 months, and I think 8 of those requested refunds. Probably my fault for not requiring a higher version of Android… since I have no idea how the game performs on anything less than Ice Cream Sandwich. In any case, I decided I would create a new, free version of the Android release, and integrate IAP so as to let players try the game out. Check it out on the Play Store. I don’t think it’s any more successful, but more people are downloading it, at least.

I also spent about two weeks porting over Nonogram Madness to Javascript, and released Android and Mac OS X versions. It’s kind of a simplified port, mostly due to the fact that Javascript DOM performance is terrible on mobile, but I think it turned out pretty well.

I’m not exactly sure what my next project will be; possibly something using Unity (which I’ve told myself I would do for about a year now). I have an app entry in iTunes Connect that is going to expire in less than a month, so you’ll see something soon. If you have any comments or suggestions about my Javascript games, drop me a line… I’d love to hear your feedback.

1 comment · Posted by in Games · , , , ,

Review: Nexus 4 · December 7, 2012

I was 100% certain this day would never come, but, as they say, “Never say never.” As you may have guessed from the title of this post, I’ve purchased an Android phone. As it might happen, for various reasons (read: $$$) I jumped ship from Verizon over to T-Mobile with an unlocked iPhone 4. Unfortunately, the iPhone 4 is getting a bit long in the tooth, and while I wanted something newer, spending $650 for an unsubsidized iPhone 5 wasn’t looking too appealing. I wasn’t having much luck finding a used iPhone 4S, either.

So, my thoughts turned to Android. Since I was running on prepaid GSM, my previous problems with Android phones (specifically the Nexus line) were somewhat mitigated. Plus, having a taste of Android 4.1 with my Nexus 7 was somewhat encouraging. The HSPA+ Galaxy Nexus at $350 new looked good, but I wasn’t keen on buying a year-old phone. As luck would have it, Google and LG partnered together to release an update to the Nexus line, the Nexus 4, sold unlocked for $350 ($300 for the 8 GB version).

I’ve always been a fan of the iPhone, but the Nexus 4 seemed to hit enough of the sweet spots for me to give it a shot. First of all, it’s an inexpensive, unlocked phone, perfect for prepaid service. Second of all, it supports the AWS frequencies that T-Mobile use for 3G, as opposed to the glacial EDGE speeds you get with an iPhone. Another plus is the larger screen… I’ve been feeling that the 3.5 inches of the iPhone is just a bit tiny for really doing any sort of web browsing or reading.

So, having owned the phone for about a week, what are my thoughts?

First of all, the Nexus 4 is noticeably larger than an iPhone. In fact, it’s about the maximum size I’d ever want in a phone. It’s not quite as thin as an iPhone 5, but feels thin since the screen is so much larger. It fits in a pocket without too much trouble, but don’t try to pocket it while wearing skinny jeans. The screen is suitably high resolution; I’ve actually been reading on it using the Kindle Android app, and it’s not bad.

The design of the phone is quite appealing. It’s two glass pieces sandwiched together with rubberized plastic. It’s very grippy, and feels good the way the back of the Nexus 7 feels good (i.e. even though it’s plastic). Underneath the back of the phone there’s a pseudo-holographic pattern of dots that appears when light hits it at just the right angle. It adds a touch of personality to what would otherwise be a black slab. Unfortunately, the back also contains the most annoying hardware elements as well. The phone’s speaker is flush on the back of the phone, which means that if it’s lying flat (which it will be 99% of the time) the speaker will be incredibly muffled. I can’t hear SMS alerts, even when the phone is right in front of me, when the volume is set at 50%. So be sure to turn vibration on, or else jack the volume way up. The other annoying element on the back of the phone is simply aesthetic, but annoying nonetheless. The LED camera flash is ringed with plastic, and is slightly recessed from the rest of the glass back. It is incredibly ugly; seriously it bugs me just to look at it. I’m not sure why LG decided to do this, but it mars the design of the phone.

There’s a little LED that sits in the bezel below the screen that lights up whenever you have a notification pending. Apparently BlackBerry phones have something similar (never owned a BlackBerry), but now I can see the appeal: it’s super easy to just glance at your phone to see if anything has happened since you put it down. Of course, that might be a downside in your book if you’re addicted to checking your phone.

The HSPA+ network connection on T-Mobile is killer. One of the first things I did was download the SpeetTest.net app to test the data connection. I get about 2.5 MBps/second on my Time-Warner cable connection (sad, I know), while the Nexus 4 was able to pull down 20 MBps/second. That being said, I’m still not sure in what situations you’d need such a fast connection, aside from using your phone as a mobile hotspot (which requires an additional fee). I guess if you really need that 200 MB app while out and about, you’ll be able to snag it relatively quickly.

Battery life is an area that the Nexus 4 falls a bit short, in my opinion. It charges slowly, and discharges quickly. You’ll have to get used to plugging it in for at least a few minutes every day. The Nexus 4 does support wireless charging, however, and I could definitely see myself plunking down some cash for the Nexus-branded charging orb… whenever it eventually is released.

As I mentioned in my Nexus 7 review, I feel that the Android 4 OS is basically on par with iOS in terms of functionality, and even ahead in some areas. For example, even though iOS took inspiration from Android’s notification pulldown, the Android version is clearly superior. App updates are also much less annoying in Android; you’ll never have to see the alert badge that always hovers over the App Store icon in iOS. Speaking of badges, they don’t exist in Android, which is totally awesome. Although some people hate Android’s “back,” “home,” and “apps” buttons, I actually really like them. While the “back” button doesn’t always work consistently, many times it saves you from having to scan the UI of a particular app in order to return to the preview screen (although that may be saying something about Android UI design). The Android app switcher is also a bit nicer than its’ iOS counterpart (and more discoverable). All that being said, there are a few things I’ll definitely miss about iOS. iMessage is simply great as an SMS replacement that “just works,” and unfortunately there isn’t a ubiquitous game-centered (see what I did there) social network on Android.

After having used the Nexus 4 for a while, I have to say that I’m pretty satisfied. It’s not perfect, but for half the price of competing smartphones, I’m willing to overlook a few quibbles.

Add a comment · Posted by in Hardware, Reviews · , , ,

Prepaid Adventures, starring T-Mobile · October 19, 2012

While it’s true that this site is for the most part an iOS development blog, I branch out from time to time when I feel like writing about a particular topic. Today’s topic is cell phone service providers. I have to imagine that most of the readers of this blog own a cell phone (hopefully an iPhone), so hopefully I’ll stay somewhat relevant.

I’ve been a Verizon Wireless customer for the past three years, mostly because my wife had a 20% discount there. The coverage was great. However, I was never really satisfied with their prices. You’ll never really get any sort of a “deal” from service companies. For example, with Verizon, you can pay $5/month for 250 text messages (which you’re guaranteed to exceed, to the sound of $0.25 a pop), or $20/month for unlimited. There’s no middle ground, where the average customer would actually land. For smartphones, Verizon’s “shared data” plans start (for two lines) at $130/month. That’s with 1GB of data. What. The. $@#%? So even though I had an iPhone, it was pretty unlikely that my wife would ever want one, due to the added expense on the monthly bill.

Being generally disgruntled, I kept my eye open for better deals. Recently, there’s been a lot more noise about prepaid cell phone service, especially from T-Mobile. In particular, they have a killer “web-only” plan: $30/month for unlimited text/data and 100 voice minutes. Since I hardly use my phone for voice (irony, eh?), this seemed perfect. I even convinced my wife to go for it, even though she was worried about going over the voice allotment. At $0.10/minute, an extra two hours is only $12, and still cheaper than the basic “unlimited everything” plan T-Mobile offers, which starts at $50/month.

$30/month (for any device!) seems too good to be true, especially after being used to paying $30/month just for data. There are a few caveats, however. The first is that you can’t buy an iPhone (the discerning customer’s smartphone of choice) from T-Mobile, you have to either buy one unlocked at full price or scrounge a used one on the cheap. Fortunately, there’s a glut of iPhone 4’s floating around at the moment, since people who bought a subsidized iPhone 4 at launch now have the option to upgrade to a 5. I bought two unlocked, used ones for less than $400.

The second problem isn’t quite as easy to solve. While T-Mobile does offer 3G service, it does so on the 1700 MHz frequency. The GSM iPhone only supports 3G at 1900 MHz (which is what AT&T uses). This means that an unlocked iPhone will only get data at EDGE speeds (aka the data speed of the original iPhone). Nowadays when LTE is starting to become a viable option, EDGE seems positively glacial.

There are two mitigating factors, however. The first is that for the average customer, a faster data connection isn’t super important (to a point, of course). When you consider your regular daily routine, how often do you really use your phone for data? My main use case is for GPS and mapping, and that’s basically it. Fortunately, with iOS 6, Apple’s new Maps application uses vectors instead of bitmap tiles to display map data, which drastically reduces the data requirement. This means that for my primary use case, a slower data connection isn’t as much of a concern. Your milage may vary, of course.

The second point to consider with the slower data connection is that T-Mobile has recently started upgrading their network to offer 3G/4G service on the 1900 MHz band (basically because AT&T was forced to pay $4 billion and give up wireless spectrum after the failed merger). This means your iPhone will start getting much, much faster speeds in the near future, especially if you live in a larger city. There’s an unofficial map of 1900 MHz coverage at airportal.de (I haven’t yet verified the one reported sighting in Columbus). But I feel relatively confident that Columbus will be getting that new coverage. I’m putting down a vote of confidence in T-Mob’s future.

If you’re fed up with paying a crapload for cell phone service, now could be the right time to try something new. And hey, if you decide it’s not for you, don’t worry. It’s a no-contract service, so you can quit and go back to 2-year contract slavery whenever you want.

Add a comment · Posted by in Bizness · , , ,

Object-oriented programming with JavaScript · September 10, 2012

So, here’s how to easily create your own prototype-based classes in JavaScript. Seems confusing to lots of folks, and there are multiple ways to do it. If you use CoffeeScript, you can write your classes in a more traditional OO style. However, it’s really not too complicated in plain JavaScript.

Step One: Write Your Constructor

A common convention is to capitalize variables that refer to classes that need to be instantiated with the “new” keyword.

var MyClass,
    instance;

MyClass = function () {
    // This is the constructor - do any initialization here!
    // "this" refers to the current instance of the class
    this.instanceVariable = 42;
};

instance = new MyClass();
console.log(instance.instanceVariable);  // 42

Step Two: Write Instance Methods

Available to all instances of the class, even ones created before the method was written!

MyClass.prototype.instanceMethod = function (argument) {
    // "this" refers to the class instance
    this.instanceVariable = argument;
};

instance.instanceMethod("Wut?");

console.log(instance.instanceVariable);  // "Wut?"

Step Two ½: Wrong Way to Write Instance Methods

It can be tempting to write instance methods inside your constructor function, perhaps for style/organizational purposes. However, it’s inefficient to do so, because each method is created every time you create an instance of your class.

// Wrong!
var MyClass = function () {
    this.instanceMethod = function (argument) {
        // "this" refers to the class instance
        this.instanceVariable = argument;
    };
};

Step Three: Write Static Class Methods

These methods can be used without creating an instance of the class. For example, if you’ve ever used the Math object, you’ve used a static method (for example, Math.cos(Math.PI)).

MyClass.staticMethod = function (argument) {
    var results = "Hello " + argument;
    console.log(results);
};

MyClass.staticMethod("World");  // "Hello World"

Step Four: Inheritance

Say I want to create a subclass of the MyClass class. This part is a bit awkward, but doable.

var otherInstance,
    MyOtherClass;

MyOtherClass = function (argument) {
    MyClass.call(this);  // Invokes MyClass's constructor
    this.otherInstanceVariable = argument;
};

// Set up prototype (inheritance) chain
MyOtherClass.prototype = new MyClass();

// Instantiate new object
otherInstance = new MyOtherClass("What?");

console.log(otherInstance.instanceVariable);  // 42 (inherited from MyClass)
console.log(otherInstance.otherInstanceVariable);  // "What?"

otherInstance.instanceMethod("Wut?");  // (inherited from MyClass)
console.log(otherInstance.instanceVariable);  // "Wut?"

// Extend the "instanceMethod" method
MyOtherClass.prototype.instanceMethod = function (argument) {
    MyClass.prototype.instanceMethod.call(this, argument);  // Equivalent of calling "super"
};

Hope that helps get you started. JavaScript is really not a bad little language once you get the hang of it. The fact that it can be run in any browser and accessed with interactive developer consoles makes it an easy language to learn and play around with. It’s also by far the language du jour on the internets, so learning it could have a beneficial effect for your job opportunities!

Add a comment · Posted by in Programming · , ,

RequireCS project boilerplate on GitHub · August 16, 2012

So I finally got around to creating a repository on GitHub. I thought it might be useful for others to see the project structure I used to build Shikaku Madness, so I ripped out most of the guts and uploaded it. It uses Backbone for structure, and loads dependencies using RequireJS. I also used James Burke’s CoffeeScript plugin for RequireJS, which means you can write CoffeeScript and it’ll be interpreted on page load, without having a separate compilation step.

It’s pretty bare bones at the moment, with just two “views” and buttons to transition between them. I haven’t decided how much additional code I’ll put in, but it’s definitely a work in progress. If you have any interest in what a simple “modern” Javascript project might look like, you should definitely check it out on GitHub.

Add a comment · Posted by in Programming · , ,

Review: Nexus 7 · July 27, 2012

Whatever your opinion about Google, they are among the companies leading the way forward in computer & internet technology. With that in mind, this year I watched the Google I/O keynote livestream, not really sure of what to expect. While there were some interesting announcements and demos, what I was really interested in was the tablet that was supposed to be announced. Details had been leaked pretty heavily beforehand, but of course there’s nothing like an actual product demo to fill in the gaps. Long story short: I was seduced by Hugo Barra’s swarthy accent into pre-ordering a Nexus 7. The form factor looked interesting, and at $200, it seemed like a low-risk way to try out the Android OS and ecosystem. So, a week or so into owning the device, I thought I’d write up my impressions.

When comparing the Nexus 7 and the iPad, the first obvious difference is the size. While 7″ vs. 9.7″ doesn’t seem like a big difference on paper, when you lay both devices together, the Nexus 7 is about 1/3 of the size of the iPad. The smaller size makes the device seem a bit more personal. There are instances where a larger screen might be more desirable, but after using the Nexus, I feel that the iPad is too large to use as comfortably. The Nexus can be easily gripped with one hand, and typing using the on-screen keyboard while in portrait mode is just about the same as using your phone. The only advantage I can see with the iPad in terms of screen size is for watching video and using content-creation apps. For example, my wife and I watch Netflix almost exclusively on our iPad, using the Smart Cover as a stand to prop it up on the bed or coffee table. You couldn’t really do that with the Nexus’ smaller screen. Another example is using a writing or music-making app; in those cases, more screen real estate means a more usable interface.

The Nexus 7 screen, while not quite Retina-caliber, is still very nice. It’s bright and has a decently high resolution. The back of the device is a textured plastic, which (somehow) feels like leather. It’s pleasant to touch, and makes it easier to hold the Nexus 7 for long periods of time. The only hardware buttons on the device are on the right side, and include a sleep/wake button and volume rocker. I find the buttons awkwardly placed. Since both buttons on the Nexus 7 are placed close together, there have been a few times where I accidentally put the device to sleep instead of adjusting the volume. In addition, the buttons are difficult to press unless you hold the Nexus with your left hand and press the buttons with your right. I guess if you’re left handed, no big deal. I think iPhone has its’ volume rocker on the left side because its’ easier for right handed people to use. The Nexus is built very solidly, but there were a few times when I could feel the case creak a bit when applying any sort of pressure to the screen.

The last part of the puzzle is Android 4.1, Jellybean. Even though the UI paradigms of Android and iOS are mostly similar, there were a few unfamiliar things that took me some time to get used to, mostly relating to app management. Basically, I don’t really have anything to say about Android. It seems to just work. There are a few differences, like the ability to add “widgets” to your home screen, but it’s seriously not the big deal that the frothing fanboys seem to think it is. Both platforms really work in a similar manner, each having access to more or less the same apps. Strangely, the one thing that I missed the most when using Android is a hardware “home” button. I’m so used to waking my iOS devices with the home button, it’s like a muscle memory.

In conclusion, the Nexus 7 is a nice device. If you’re an Android user, it’s probably a no-brainer to pick one up. It’s for sure the first tablet that can compete at all with the iPad on any level. That being said, it’s hard to recommend over the iPad, unless “not Apple” is your primary consideration for buying new hardware. If Apple releases a smaller iPad, any sort of advantage that the Nexus has will be eliminated. But for now, the Nexus seems to be the best “small tablet” you can buy.

Add a comment · Posted by in Hardware, Reviews