Games I was addicted to in 2014

I posted on TekSide:

I don't consider myself a gamer anymore. I used to be. Countless, countless hours in Final Fantasy 6-9, Zelda, Tetris, Alleyway, Neverwinter, Halo, Fallout, Half life, Oblivion. The list goes on. I cut my teeth on a gameboy and SNES and kept going. Things dropped off after Halo 2. I surfaced for Halo  3 (a lot) and 4 (less so). I didn't play much on my phone during my years on Android; the games really weren't that great or polished.

Part of my commute is a 10 minute subway ride. Something quick to play is appreciated, but I've been looking for something a little more immersive. Something I can sit and get lost in for a few hours. The other part of my commute is a 30 min commuter train ride where I'm either reading instapaper, napping, or playing a game while listening to podcasts.

Baldur's Gate - I found this very late in the year. In fact I think I installed it at my in-laws on Christmas morning. I had never played either of the originals and was curious. It was one of the few games that consistently showed up on "best iOS RPG" when I was searching for something to play. The face that it looked like Neverwinter was a huge bonus for me. The tutorial for this game is very, very buggy and was very off-putting. Once I got past that though, everything changed. The game mechanics started making sense: pinching and zooming the map is fluid and tapping on your party to direct their targets just felt completely natural. The story quickly swept me in and I started questing. When I play RPGs, I try to do all the side quests. Baldur's Gate is no different. I'm currently grinding my way through a number of maps looking for someone's lost cloak. Perfect gameplay for listening to podcasts on the train. Outside of that though the music and sound effects are top notch. If you were ever a fan of D&D style point+click RPGs, this will feel right at home. If you've never tried them, I can't recommend this game enough.

1

Tiny TowerPocket Trains - I put these games together because while very different games, they have similar gameplay mechanics. Build out your empire! In Tiny Tower, this takes the form of expanding a single tower. Inside this tower are all your Bitizens live: Where they eat, where they work, and where they have fun. Ala Sim City, but in an enclosed environment. In Pocket trains, you expand your train line, going for a trans-continental goal. Pick the cargo for your trains, build tracks, repair the engines, and race against the clock. Both games have IAP to buy coins and bucks to get you through the game faster. I've never used real world money in either and it's just as enjoyable

RGB Express - This is a good puzzle game where you draw routes for your drivers, picking up packages and making sure that every house receives the correct package. Setup your route, press play, watch your trucks zoom, and hope you didn't create any collisions! Pro Tip: You can set the playback to run the trucks at a faster speed. Kudos to the iOSDocked crew for making this the GameCenter Showdown in episode 77.

Threes - Threes is a tiny puzzle that grows on you. It looks simple at first. But at some point you figure out you need a strategy to go higher. Match the same number, it triples and collapses. Keep going. Build higher and higher. Compete with your friends. It gets harder the higher you go and becomes addicting trying to get to that next score. I play tower defense style: Building into one of the top two corners and slowly growing numbers in those directions. What's your high score?

2

2048 - This game is very similar to threes (maybe too much so). But, it's still fun. I keep this one around because it takes a little less concentration than threes. It's more mindless and good for when I'm tired or need to think. It's a good distraction. 2048 is my checkers to my Threes chess.

3

Honorable Mention: Monument Valley - I can't stress enough that you NEED to go play this game. There is no other experience like it on iOS. Control your character through immersive M.C. Escher-like paintings. The levels are gorgeous. You'll spend time just staring at them, moving pieces around just to see what they do. It only gets Honorable Mention because of replay value. I played through it once in a few hours and that was that. But, it's magical. Everyone should play it

4

5

Reordering a NSFetchedResultsController

I’m working with a NSFetchedResultsController backed UITableView.  Up until now I’ve just been ordering the items by the time they were added.

I’m moving on to Delete and Edit.  Editing the content itself isn’t needed, once an item is added to this list, it can’t be changed. Deleting is straightforward in

(void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath
*)newIndexPath {

With reordering, I have a conundrum.  I have an approach for the actual re-order that will have the View and the data playing nice. But, now I need to persist the order.  I don’t have a property in Core Data for this (yet).  I’m trying to figure out what to set this property to. The brute force approach is to use the indexPath of the cell.  I have concerns with this.  Adding an item automatically puts it at the top of the list. This would give it an index of 0 (I only have 1 section).  But, then I would have to update the order property of every other item in the list. The same goes for moving: each item and every item in between (I can luckily skip the outer bounds) will have to be updated. I don’t like this. There has to be a better way, I just need to figure it out.

Some kind of indexPath+hash? indexPath+integer?

Eventually I’ll reach a list size where I run into performance problems with the brute force approach. The cop out would be to limit the size of the list. I don’t want to do that either.  I don’t know if I’ll go to the extreme of Brent Simmons’ data set of 30,000 items from Daring Fireball’s archive, but I want to shoot for that.

I’ll update this post with my progress

Update 2014-05-31 01:02 PM

This is a great starting point for dealing with reordering. I was on the right track with only dealing with the differences between items that get moved.  Dragging an item way down on a list may(?) not happen much, it’s annoying to do. I think I’m going with that assumption for now.  I still don’t feel great about the number of updates for an insert…

Batch fetch/update/save is my starting point

Update 2014-06-06 04:04 PM

It looks like iOS 8 might have better bulk update support. Downloading this session now

@inessential @brentsimmons You might like the Core Data video. new NSBatchUpdateRequest api with a “mark all as read” example as the demo

>

-- solsberg (@solsberg) June 6, 2014

AVSpeechSynthesizer's queue doesn't work

Sort of. It acts as a queue, but subsequent items have problems. Taken from the documentation of - (void)speakUtterance:(AVSpeechUtterance *)_utterance_

Calling this method adds the utterance to a queue; utterances are spoken in the order in which they are added to the queue. If the synthesizer is not currently speaking, the utterance is spoken immediately.

This is true. You can queue up as many AVSpeechUtterance objects as you want, and they will be spoken, in order.  The problem is if you try to act on the Synthesizer after the first Utterance has been spoken. Specifically, I'm having an issue with pausing. But, stopping has an issue as well. If I try to pause during the first utterance using pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate, I get the expected behavior. The speech stops and I can start it again with continueSpeaking. (Even on the first Utterance, AVSpeechBoundaryWord, is giving me issues so I'm putting that aside for now). However, if I try to pause on any of the subsequent Utterances, nothing happens.  The pausedSpeaking call is ignored. (The synthesizer isn't nil, I checked). So, why am I queuing up a lot of text? I plan on having AVSpeechSynthesizer speak a lot of text. This text is stored in CoreData.  Let's say my main object is called Read. Instead of storing all of the text for that object in Read.text I've split out the text into slices, stored in a separate Text entity. A Read object can have many of these.  This gives me control over how much text I load into memory at once.  My original plan was to load each slice into an Utterance.  When the speaking was done for that Utternace, queue up the next one (it should start immediatly or close to it). Fragments of this below:

    self.speechSynthesizer = [AVSpeechSynthesizer new];
    self.speechSynthesizer.delegate = self;

- (BOOL)addWordsToQueue:(NSString *)words
{
    if ( !words ) {
        return NO;
    }

    AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:words];
    utterance.rate = AVSpeechUtteranceMinimumSpeechRate;
    [self.speechSynthesizer speakUtterance:utterance];

    return YES;
}

//used in view
- (void)play
{
    [self.speechSynthesizer continueSpeaking];
}

- (void)pause
{
    [self.speechSynthesizer pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
}

- (BOOL)isPaused
{
    return self.speechSynthesizer.isPaused;
}

#pragma mark - AVSpeechSynthesizerDelegate

- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance
{
    NSString *words = [read getAndIncrementCurrentWordsAsString];

    if ( words != nil ) {
        [self addWordsToQueue:words];
    }
}

Again, the first Utterance works fine, the rest don't. I've also experimented with queueing multiple slices at once, as well as checking if the synthesizer I get in didFinishSpeechUtterance is the correct instance.

I'm not the first person to run into this issue. There are also a number of radars. I've added one as well.

There is a workaround, but it's dirty and shouldn't be needed. In didFinishSpeechUtterance I recreate my AVSpeechSynthesizer so I'm always dealing with the first item in the queue. I really don't like it.  This is still broken in 7.1 beta 5. Hopefully it gets fixed. I'd like to implement this properly.

- (void) resetSynth
{
    self.speechSynthesizer = [AVSpeechSynthesizer new];
    self.speechSynthesizer.delegate = self;
}

#pragma mark - AVSpeechSynthesizerDelegate

- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance
{
    [self resetSynth];
    NSString *words = [read getAndIncrementCurrentWordsAsString];

    if ( words != nil ) {
        [self addWordsToQueue:words];
    }
}

This unfortunately still happens in the 7.1 beta

Automate Adding to Trello on iOS with Launch Center Pro and Pythonista

I love using Trello to organize my life and work. While I kind of like it's iOS app, sometimes navigating to a board to add a card can be a little time consuming.  I want this process to be faster. I also use Launch Center Pro to get some quick actions that I miss from Android. Mostly around quick communication, adding events, and now, adding to Trello.  LCP uses x-callback-urls for inter-app communication, but Trello doesn't have any that I could see. Inspired by Federico Viticci's article on automating his iOS workflow, I decided to take a crack at it using pythonista. All code shown below can be found on GitHub.

2013-02-1114.32.57

2013-02-11
14.33.00

Pythonista lets you edit and run python scripts on your phone. There are a few ways to get scripts onto your device:

  • Edit right in the app
  • Import from a gist
  • Use pastebot. A great app that gives you multiple clipboards on your device that will also sync with your mac. This is my preferred method.

The endgame of all this: I want to be able to add a card to a specific board, with as few taps as possible. Check out this video for what we are going to build. Digging into the Trello API, we can see that to add a card, we'll need a name for the card and the ID of the list to add it to. We also see that we'll need a token for any of the API calls. To get all of our lists, we'll also need to know about all of our boards.  This breaks our tasks out as follows:

  1. Get an App API Key
  2. Get an API Token
  3. Get a list of every board we heve
  4. Get the IDs of every list on each of these boards
  5. Add a new card to our list of choice

To get an App API Key, you can generate one here.  In theory, the one I distribute with these scripts should be ok. Get this first script into Pythonista and run it. It will generate a permanant API token for you that you can leave in Launch Center Pro when running these scripts.

#GetTrelloToken

import webbrowser

url = 'https://trello.com/1/authorize?key=3e2cd730f3dcccbe15eaf0d39d219a37&name=PythonistaTrello&expiration=never&response_type=token&scope=read,write'

#open web browser to get a permanant Trello API Token
webbrowser.open(url)

2013-02-11 14.54.35

2013-02-1114.54.40

Now that we have our key and tokens, let's get get all of our boards and the lists on each one. Run this script and pass in your token and your email address as arguments. (In pythonista hold down run to get the "Run with arguments dialog"). Add your arguments separated by spaces. For me, this could look something like: "EGYlyiOdggDOaPoTUxaTQobmS6gtiX timothy.broder@gmail.com"

#List all lists by user

import urllib2
import urllib
import json
import sys

if len(sys.argv) != 3:
    raise Exception("Usage: list_trello_lists.py [token] [email]")

key = "3e2cd730f3dcccbe15eaf0d39d219a37"
args = { 'key': key,
    'token': sys.argv[1],
    'filter': 'open'}

#build out api url
username = sys.argv[2]
boards_url = "https://api.trello.com/1/members/%s/boards/?%s" % (username, urllib.urlencode(args))

#get board data from api
try:
    data = urllib2.urlopen(boards_url)
except urllib2.HTTPError as inst:
    raise Exception("Key or Token incorrect")

boards = json.loads(data.read())

#loop through each board
for board in boards:
    board_id = board['id']
    lists_url = "https://api.trello.com/1/boards/%s/lists?%s" % (board_id, urllib.urlencode(args))
    data = urllib2.urlopen(lists_url)
    lists = json.loads(data.read())

    print "-- %s" % board['name']
    #output each list in board
    for lizt in lists:
        print "\"%s\" %s" % (lizt['name'], lizt['id'])
    print "\n"

Running this, we'll get the IDs of the lists we need

2013-02-11 15.06.39

2013-02-1115.07.13

Finally, we'll need to take our key, the id of the list, what we want our card to say, and hit the API with them.  I also add in a position so the cards I add this way will appear at the top of their list. We'll pass these in as parameters:

"EGYlyiOdggDOaPoTUxaTQobmS6gtiX V12t3k6RQQ2r8X top the name of my card goes here"

Two things to point out inthis script:

  • we put the name of the card at the end so we can just loop through all the remaining words and not have to worry about wrapping the name in quotes to deal with spaces.
  • since the end game of this is to run from Launch center pro, we want to jump back to Launch Center Pro at the end using it's x-callback-url
#Add card to List

import urllib2
import urllib
import json
import sys
import webbrowser

arglen = len(sys.argv)

if arglen < 5:     raise Exception("Usage: list_trello_lists.py [token] [list_id] [position] [card_name]") name = sys.argv[4] #take care of spaces if arglen > 5:
    for i in range(5,arglen):
        name = "%s %s" % (name, sys.argv[i])

key = "3e2cd730f3dcccbe15eaf0d39d219a37"
token = sys.argv[1]
args = { 'key': key,
    'token': sys.argv[1],
    'name': name,
    'pos': sys.argv[3],
    'idList': sys.argv[2]
    }
card_add_url = "https://api.trello.com/1/cards"

try:
    data = urllib2.urlopen(card_add_url, urllib.urlencode(args))
except urllib2.HTTPError as inst:
    raise Exception("Key or Token incorrect")

#jump back to Launch Center Pro
webbrowser.open("launchpro:")

To run this in Launch Center Pro, Add an Action > Pythonista > Run Script with Arguments. Put in the name of the script, then in arguments, but everything from above except the name: "EGYlyiOdggDOaPoTUxaTQobmS6gtiX V12t3k6RQQ2r8X top," then hit the button that says input prompt. Now, when you run the script, Launch Center Pro will prompt you for text, enter the name of the card and hit go.

Add as many of these as you want! Just swap out the list ID.

iOS: Multiple Lines of Text in a UITableViewCell

Have you ever wanted to display multiple lines of text in your Table Cell? It's easy to do in your UITableViewController.

First, let's define the type of font we're going to use. We'll need this in 2 places:

*)fontForCell { return [UIFont boldSystemFontOfSize:18.0]; } [/c] 

Next, calculate the height of the cell by using the height of a Label:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellText = /* get your text */;
    UIFont *cellFont = [self fontForCell];
    CGSize constraintSize = CGSizeMake(280.0f, MAXFLOAT);
    CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];

    return labelSize.height + 20;
}

Finally, we'll set some attributes on the cell itself to change the height and tell the text to wrap:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @&quot;MyIdentifier&quot;;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
        cell.textLabel.numberOfLines = 0;
        cell.textLabel.font = [self fontForCell];
    }
    [cell.textLabel setText:/* get your text */;];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    return cell;
}

Adding Done and Cancel buttons to an iOS number pad

There are some cases when you may want to have a "Done" or "Cancel" button on an iOs number pad when editing a text field. This doesn't come by default, but is easy to add. See the example snippets below, or check out the code on github.

Sample Usage:

//In the view controller that's going ot use the component, put this in the header after the class being extended.
<DoneCancelNumberPadToolbarDelegate>

// Then instantiate your toolbar component where it's needed
DoneCancelNumberPadToolbar *toolbar = [[DoneCancelNumberPadToolbar alloc] initWithTextField:textField];
toolbar.delegate = self;
textField.inputAccessoryView = toolbar;

// Finally, implement the following two delegate methods

#pragma mark - DoneCancelNumberpadToolbar delegate
-(void)doneCancelNumberPadToolbarDelegate:(DoneCancelNumberPadToolbar *)controller didClickDone:(UITextField *)textField
{
    NSLog(@&quot;%@&quot;, textField.text);
}

-(void)doneCancelNumberPadToolbarDelegate:(DoneCancelNumberPadToolbar *)controller didClickCancel:(UITextField *)textField
{
    NSLog(@&quot;Canceled: %@&quot;, [textField description]);
}

DoneCancelNumberPadToolbar.h

#import <UIKit/UIKit.h>

@class DoneCancelNumberPadToolbar;

@protocol DoneCancelNumberPadToolbarDelegate <NSObject>

-(void)doneCancelNumberPadToolbarDelegate:(DoneCancelNumberPadToolbar *)controller didClickDone:(UITextField *)textField;
-(void)doneCancelNumberPadToolbarDelegate:(DoneCancelNumberPadToolbar *)controller didClickCancel:(UITextField *)textField;

@end

@interface DoneCancelNumberPadToolbar : UIToolbar
{
    UITextField* textField;
}

DoneCancelNumberPadToolbar.m

#import &quot;DoneCancelNumberPadToolbar.h&quot;

@implementation DoneCancelNumberPadToolbar

@synthesize delegate;

- (id) initWithTextField:(UITextField *)aTextField
{
    self = [super initWithFrame:CGRectMake(0, 0, 320, 50)];
    if (self) {
        textField = aTextField;
        self.barStyle = UIBarStyleBlackTranslucent;
        self.items = [NSArray arrayWithObjects:
                      [[UIBarButtonItem alloc]initWithTitle:@&quot;Cancel&quot;
                                                      style:UIBarButtonItemStyleBordered
                                                     target:self
                                                     action:@selector(cancelNumberPad)],
                      [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
                                                                   target:nil action:nil],
                      [[UIBarButtonItem alloc]initWithTitle:@&quot;Done&quot;
                                                      style:UIBarButtonItemStyleDone
                                                     target:self
                                                     action:@selector(doneWithNumberPad)],
                      nil];
        [self sizeToFit];

    }
    return self;
}

-(void)cancelNumberPad
{
    [textField resignFirstResponder];
    textField.text = @&quot;&quot;;
    [self.delegate doneCancelNumberPadToolbarDelegate:self didClickCancel:textField];
}

-(void)doneWithNumberPad
{
    [textField resignFirstResponder];
    [self.delegate doneCancelNumberPadToolbarDelegate:self didClickDone:textField];
}
@end

@property (nonatomic, weak) id <DoneCancelNumberPadToolbarDelegate> delegate;

- (id) initWithTextField:(UITextField *)textField;

@end

Special thanks to [akozl ik](http://www.reddit.com/r/iOSProgramming/comments/ydrzv/adding_done_and_canc el_buttons_to_an_ios_number/c5v4rpt) for the help with delegates.

iOS Game Engines

After playing Rovio's new Amazing Alex game for a while, and seeing this article on BGR this morning, it made me remember some old success stories that I had read about, and I got to thinking about what it would take to develop a game for iOS. More just to see what options were out there than anything else; I know nothing about game programming. Side note: Amazing Alex is great. If you have ever played the incredible machine, you'll feel right at home.

One success story I remember is Ethan Nicholas and iShoot, which made him over $800k. Check out how he did it, and how to get started with iOS here: iPhone developer in eight easy steps. If he can do it... why not? But, I digress. ManiacDev has great lists of both Open Source and Commercial graphic engines for iOS. As far as free goes, cocos2d and sparrow both jumped out at me. Sparrow seemed like the fastest ramp-up time and after a quick look at it's api, felt familiar. Without diving too much into the examples, it seems to follow similar patterns to some of the python/js UI frameworks I've used. Unfortunately, the forum seems pretty sparse. Cocos2d, while looking like a steeper learning curve, seems a little more mature and a much more engaged community. It's forum has 85% more posts than sparrow, which coming from a busy php/python community, I like to see. As for commercial engines, after reading about how Infinity Blade was Epic's most profitable game ever, and seeing that a license would only be $99, the Unreal Development Kit For iOS is totally the way I would go.

[sponsored post]