Author: Matt

  • A Productive Christmas Break?

    There’s just so much work to be done that I’m really going to have to strive for a very productive month of programming.

    I need to update all my apps for the new year and hopefully launch a few new ones.

    To that end I’m planning on taking some more time off work over the next couple weeks and months to push through some coding projects.

    In the pipeline now are one new website, a redesign of another website, update 7 of my iPhone Apps with improvements aimed at increasing retention and ad revenue, and making a lot of progress on my big social game.

    The social game is what has been on my mind the most and I have very high hopes that it is going to be amazing when finished. I expect I will have to hire some artists in March to help bring a level of polish I haven’t yet been able to achieve on my own.

    Will it be possible to have a productive Christmas break or will there be too many distractions?

  • Progress on New Game

    So the new game is going to be called Tycho City. It’s based on building a lunar base and battling other bases for the moon’s valuable resources. There’s a mix of two styles of gameplay the first is the simulation of the moon base with building and upgrading mines and energy collectors. The second is a defence game where you attack other bases by landing your troops/robots and taking on their defences.

    Unlike my previous games this time I’m taking some good advice and modeling other successful games. Rather than try to invent something brand new I am going to try to put my spin on a popular and profitable game concept.

    One thing about this type of game is just how much data there is to manage.

    This game will be heavily dependant on web servers to deliver almost everything. All of the costs, upgrade paths, graphics, assets, music, rules, build times, and store menus will be defined and controlled from my web backend. It will allow us to dynamically update and tweak the game play to optimize things after it’s released and keep it fresh with new content. But it’s a lot of Data. And that’s just on the static side of things. The server will also keep and save the game state of every player’s game in real-time.

    Organizing all of this information in a way that is going to be easy to understand and work with is not easy. But it’s a fun challenge.

    This game is going to take several more months to finish. But it’s going to be my best chance of getting a major hit.

  • iAd Download Script

    Unfortunately Apple doesn’t have a nice easy API for downloading your revenue numbers from iAds. The only way around that right now is screen scraping the information, or manually downloading the reports.

    Thanks to the awesome python requests library I was able to put something together in just 50 lines of code.

    It’s a function you can integrate with your project to download daily iAd report files.

    It is also simple enough that it should be relatively robust against future website changes by Apple. (hopefully)

    If you decide to use this I would recommend storing your account’s publisherID to avoid having to get it each time which will speed it up.

    (this code is also on github: https://github.com/mfwarren/iAdDownload)

    import requests
    import re, os, datetime
    
    url_base = 'https://itunesconnect.apple.com%s'
    signin_url = url_base % '/WebObjects/iTunesConnect.woa'
    download_csv_url = 'https://iad.apple.com/itcportal/generatecsv'
    
    def getPublisherID(session):
        """
        publisher ID is a number that is buried deep... lets hope
        this code doesn't break often
        """
        headers = {'Content-type': 'text/x-gwt-rpc; charset=UTF-8'}
        iad_service_url= 'https://iad.apple.com/itcportal/service/startup?requestId=GUEST_1331628761939_0__1331628761950__null'
        body = '5|0|4|https://iad.apple.com/itcportal/itcportal/|E8DB97D87973D76A7C9096DCF8A83BB5|com.qwapi.portal.itc.client.rpc.IITCStartupService|getStartupData|1|2|3|4|0|'
        r = session.post(iad_service_url, data=body, headers=headers)
        endpos = r.text.find('com.qwapi.portal.client.rpc.dto.UserDTO')
        endpos = r.text.find('"', endpos-4)
        startpos = r.text.rfind('"', endpos-20, endpos-4)
        pubID = r.text[startpos+1:endpos]
        if not int(pubID):
            raise Exception("Failed to get publisher ID")
        return pubID
    
    
    def downloadiAdFiles(appleId, password, publisherId=None, outputDirectory='.', daysToDownload=14, outputFormat='iAd_D_%m-%d-%Y.txt'):
    
        session = requests.session()  #session used to maintain cookies etc.
    
        #get signin page to find url for posting signin credentials
        r = session.get(signin_url)
        match = re.search('" action="(.*)"', r.text)
    
        #login to ITC
        params = {'theAccountName':appleId,
                'theAccountPW':password,
                '1.Continue.x':'10',
                '1.Continue.y':'10',
                'theAuxValue':''}
        r = session.post(url_base % match.group(1), params=params, headers={'Content-Length':'0'})
        r = session.get('https://iad.apple.com/itcportal')
    
        if publisherId is None:
            publisherId = getPublisherID(session)
    
        reportDates = [datetime.date.today() - datetime.timedelta(i + 1 ) for i in range(daysToDownload)]
    
        filenames = []
        for downloadReportDate in reportDates:
            filename = os.path.join(outputDirectory, downloadReportDate.strftime(outputFormat))
            if (os.path.exists(filename)):
                continue
    
            dateString = downloadReportDate.strftime('%m/%d/%Y')
            params = {'pageName': 'app_homepage',
                'dashboardType':'publisher',
                'publisherId':publisherId,
                'dateRange':'customDateRange',
                'searchTerms':'Search Apps',
                'adminFlag':'false',
                'fromDate':dateString,
                'toDate':dateString,
                'dataType':'byName'
            }
            r = session.get(download_csv_url, params=params)
            if r.status_code != 200:
                raise Exception("Script failed to dowload - check login credentials & publisher ID")
    
            with open(filename, 'wb') as f:
                f.write(r.content)
            filenames.extend([filename])
    
        return filenames
    
    
  • “Good Artists Copy, Great Artists Steal”

    That quote from Steve Jobs in 1996 holds true for more reasons than are apparent at first thought.

    I’m currently working towards completing my first ‘real’ game on iOS but with a 2 person team it will take an exhaustive amount of work to produce something that fulfils our vision.

    Cutting scope is the easiest thing to do but also shortsighted. Chopping off features limits your ability to compete in this highly competitive market. You need to ship something, but can’t afford to cut vital features.

    Originality is overrated. It is high risk and an uphill battle. People (for the most part) cling to the familiar so producing a game that is utterly unique and original is like trying to replace thanksgiving turkey dinner with tofu and seaweed salad. Thank you for trying but what I really wanted was turkey.

    The better approach is to take what you can from the existing best of the best and find areas you would like to improve upon and then work towards that goal. Having actual physical manifestations of similar products and features vastly reduces the burden of figuring out how to steal them for yourself.

    Starting with the reference for 90% of the work removes the need to communicate how every detail needs to work and so you can get right to implementing it. The few unique parts you bring to the table serve to evolve the platform and make your game even better.

  • Painted Living Room

    Sometimes all that’s needed is a little bit of paint.

    Last weekend Heather and I started painting our living room in an effort to make the space more liveable. By painting over the brown and beige walls with white the furniture becomes more of a focus and the room feels brighter and bigger.

    With a couple of new floor lamps, an airport express box for playing music, and possibly a new couch in the room it should get more use.

    We’ll put on the last coat of paint this weekend and I’ll post a picture.

  • Virility

    Having a game that naturally promotes itself is a challenge. The old techniques of tweeting your score or sharing the app on facebook are not enough to make something popular or have it go viral. The mechanic to make something go viral has to be much more deeply integrated.

    The virility of games like Draw Something was astounding, but it was also a natural extension of the type of gameplay. In order to play you needed to get your friends in the game. It’s growth was astounding because of that.

    I started to dissect another popular game recently called Clash Of Clans made by SuperCell which takes things to a new level. The live in game chat and team gameplay create a fascinating dynamic that works extremely well on a mobile device.

    It’s clear that the bar has been raised. Creating a top game now requires a complex server side backend, a massive amount of content, depth of gameplay which can attract new players but keep existing ones playing for a long time and a polished high quality look.

    Thinking now about creating a great game to be released in 6 months is a real challenge. How much more complexity will be expected by then?

    The added complexity of making a game naturally viral rather than tacking on twitter and facebook buttons is hard. It requires thought about how to change the game mechanics to work these things into the core of the game. Making games that are inherently social will be a fun challenge for game designers. A challenge I’m looking forward to.

  • Learning from Games

    For the past few weeks I have been playing a lot of games and trying to learn a few things about how to make better ones.

    I’ve been dissecting games like Simpsons Tap Out, Pocket Planes, Skylanders, Paradise Cove and DragonVale. And it’s been very educational. Besides learning about what makes them tick technically I have also put some effort into reverse engineering the game play elements and reducing them to the core game mechanics.

    When coming from a perspective of how to program one of these types of games myself there are a lot of questions that come up. Every small detail requires work to program so it has to be justified.

    One of the surprising things I’ve been learning from playing these games is actually more of a real life lesson. The value of investing revenue producing assets.

    In an effort to get up through the game levels as quickly as possible and unlock everything to learn more about these games I have had to strategize and play them as best as I can. Optimizing cash flow is a big part of these games and it’s been re-affirming a key idea which is just how important it is to have a multitude of ways to make a steady flow of income. It is quite amazing to see how quickly money accumulates.

    My real-life comparison is with the apps that I’ve been making. Each app that I publish is a small asset that I have to invest time into which then will make a small amount back each month. In many ways it’s a lot like building a house or store in these games. The importance of these assets in the game is obvious, real-life is a lot more complex, but I believe the payback is still there.

  • Winter Bike Riding

    So I decided that rather than paying for driving/parking to get to work this winter I am going to bike.

    I picked up a cheap bike from canadian tire last night that should be able to survive the -30 degree temperatures outside and should be sturdy enough to not break down on the 6KM ride each way to the office.

    It’s a fixed gear urban bike with disc brakes. The rims are pretty beefy and it should hold up to a lot of pounding.

     

    It’ll be nice to be back on a casual bike again.  I can start brushing up on all the tricks I learned growing up.

    This is how I plan on getting to work:

     

  • Loading iOS Assets From The Web

    One of the big challenges with making a big iPhone game is that to do the graphics justice at the caliber expected by gamers these days is hard. There’s just too much data to package the iPhone/Retina iPhone/4 inch iPhone/iPad/Retina iPad assets all together in one bundle.

    So for my latest game I’m kicking things up a notch and adding a fairly complex loading screen which will connect to my web server API and download much of the content of the game from there.

    There are of course some downsides to doing this. It requires that my web servers have great uptime, and are performant enough to support all the players connecting. The added complexity means more code to maintain and debug.

    However it gives a ton of options for tweaking things on players and improving the game without deploying new versions it through the App Store. It opens the door for the opportunity to split test game play options to find what values create more engagement.

    If the game code is flexible enough I will be able to download new assets, change prices, run sales and promotions, and add more complex multi-player interaction.

    The mobile gaming market is becoming more sophisticated very quickly and the quality required to stand out in the crowd is amazingly high. Developing something that is just OK will be a waste of your time and flop. Being an indie game developer for mobile is now a difficult undertaking.

    When the code for the loading screen is done I may make it available as a component for other developers to use in their projects.