- January 2006 (1)
- January 2007 (1)
- July 2007 (8)
- August 2007 (3)
- September 2007 (3)
- October 2007 (2)
- November 2007 (3)
- January 2008 (5)
- February 2008 (4)
- March 2008 (1)
- April 2008 (5)
- June 2008 (3)
- July 2008 (2)
- August 2008 (1)
- September 2008 (6)
- November 2008 (3)
- December 2008 (1)
- January 2009 (4)
- March 2009 (1)
- April 2009 (14)
- May 2009 (9)
- June 2009 (7)
- July 2009 (6)
- August 2009 (4)
- September 2009 (4)
- October 2009 (2)
- November 2009 (23)
- December 2009 (23)
- January 2010 (4)
- February 2010 (3)
- March 2010 (2)
- May 2010 (3)
- July 2010 (4)
PowerShell and Unicode
Wed, 07/21/2010 - 07:01 | by KrisAfter being away from the Windows developer world for a few years, I have been pleased to find some of the nice things that Microsoft has given us. Visual Studio has some really nice refactoring capabilities. The Windows 7 user experience rivals OS X. And as an alternative to the venerable cmd.exe, we now have a much better command-line shell: PowerShell.
What I like most about PowerShell is that it feels more like a UNIX shell. It supports a lot of UNIXy commands (ls, echo, cat). It lets you use either forward slashes or backslashes in paths This is good for someone like me who can never remember what OS I'm using when I start typing a command.
But of course, Microsoft can't give us something new without throwing in some surprisingly inappropriate behavior. A couple of days ago, I needed to create a patch for a Subversion repository, and so I typed the typical command to do so (which works fine in UNIX shells and with cmd.exe):
svn diff > my_patch.diff
I then looked at my patch to verify that it looked good:
cat my_patch.diff | more
Everything looked fine. However, when I later tried to apply the patch to another Subversion workspace:
patch -p0 -i my_patch.diff
I got errors. I opened up my_patch.diff in Vim, and realized it was a UTF-16-encoded file.
Neither svn nor patch know how to deal with Unicode. How did this happen?
After wasting an hour trying various svn command-line options and diff utilities, I finally stumbled onto the answer. It turns out that, in PowerShell, svn diff > my_patch.diff is equivalent to this command:
svn diff | out-file my_patch.diff
and (get this), the out-file cmdlet encodes its output as Unicode by default.
This default behavior makes sense for out-file, but it is counter-intuitive that the > redirection operator would take ASCII and convert it to Unicode.
To make PowerShell do the right thing, you have to do this:
svn diff | out-file -encoding ascii my_patch.diff
Grrr.
Workflow for Remote CVS, Local Git
Fri, 07/02/2010 - 08:31 | by KrisMy current employer uses a CVS repository for all its source code. People recognize that there are better options available than CVS, but it's been cranking along fine for 15 years, and there is no compelling reason to change.
However, I really like being able to commit incremental changes often in my own personal branches, and while not connected to the company network (I work from home). So I've been checking out files from the CVS repository, using Git locally to manage modifications, and then periodically committing those changes back to the remote CVS repository.
I figured I'd write up what I'm doing, in case others want to try the same thing, or others can tell me a better way to do what I'm doing. I'm still a bit of a Git newbie, so if I'm doing something stupid, please let me know.
I'm assuming the reader has a basic understanding of CVS and Git. If not, see the CVS manual and/or the Git tutorial. I predominantly work on Windows, but I use PowerShell, so there is no difference between the commands I use on Windows and those I use on Mac OS X or Linux.
In the examples, I'll use a few variables:
USER=myusername
CVSROOT=:pserver:$USER@cvsserver:2401/cvsrepository
PROJECT=myprojectname
DROPBOX=mydropboxfolder
($DROPBOX refers to my Dropbox directory, where I keep all sorts of little files that I want synched to all my computers. If you haven't looked at Dropbox, do.)
First, we need to get the CVS repository. Git does have a git-cvsimport command that I could use to suck all the CVS stuff into a local Git repository, but the CVS repository is huge, so that would be very slow, and frankly, I don't really trust git-cvsimport. So I just do what I would normally do to get stuff from CVS:
cvs login
cd ~/work
cvs checkout $PROJECT
Next, I set up the local Git repository:
cd ~/work/$PROJECT
git init
The working directory contains a lot of files that I don't want or need to track with Git, so I've got a standard .gitignore file that looks like this:
CVS
.#*
.hg
.hgignore
bin
obj
Debug
Release
TestResults
*.obj
*.suo
*.ncb
*.user
*.tli
*.tlh
*.idb
*.pdb
build
*.pbxuser
*.perspectivev3
.DS_Store
*.old
*.log
*.out
*.cache
I just copy it from my Dropbox:
cp $DROPBOX/.gitignore .
Now, I'm ready to import everything into the Git repository:
git add .
git commit -m "Initial commit"
I keep a local tag cvssync that indicates the last time that the Git and CVS repositories matched.
git tag cvssync
Now I'm ready to do some work. I always want the master Git branch to match CVS, so I create a topic branch where I do my work:
git checkout -b work
After very efficiently and productively adding all the error-free code needed to implement whatever I'm implementing, I'm ready to commit on my work branch.
git commit -a -m "Implemented the whosey-whatsit"
Now my boss calls and asks when the thing is going to be ready, and I tell him I'll check it into CVS right away.
First, I quit Visual Studio or whatever editor(s) I'm using, because the next few operations will cause the contents of files to change, and IDE's often don't handle that gracefully. This step also ensures that I don't forget to save all my changed files.
I have to merge the work branch back into the master branch:
git checkout master
git merge work
Then, I pull in whatever changes others have added to CVS
cvs update
git commit -a -m "Sync with CVS"
(I skip the git commit here if there were no changes from CVS.)
I check what I've changed since the cvssync tag, to remind myself and to verify it is right:
git log cvssync..
cvs diff
Finally, I can push my changes to CVS:
cvs commit -m "Implemented the whosey-whatsit"
My employer likes to put the $Id$ tag into source files, so after a cvs commit, any changed files are going to have new identifiers, so I need to commit those changes to my master branch
git commit -m "Sync with CVS"
I update my cvssync tag:
git tag -f cvssync
If, while I'm doing my work, others check things into CVS, and I need those changes, here is what I generally do (after quitting Visual Studio):
git commit -a -m "Check in work branch"
git checkout master
cvs update
git commit -a -m "Pull from CVS"
git checkout work
git rebase master
It may seem like a lot of work, but it's saved me a couple of times already. I have some aliases and scripts that automate some of the steps, so my actual workflow is not as verbose as what I've written here.
Core Animation Performance Tips
Tue, 05/18/2010 - 05:36 | by KrisIn my copious free time, I've been working on a videogame for the iPad. Friends and family may interject here that it seems like I'm always working on a videogame in my free time, but I've never actually finished one. This time is different. Really.
All of my personal projects are intended primarily to be interesting and fun for me. I gave myself a couple of technical constraints to keep things challenging:
- All the code is well-factored idiomatic Objective-C. Unlike a lot of iPhone/iPad game programmers, I'm not writing all the guts in low-level C or C++ and then sprinkling a minimal amount of Cocoa on top to interface with the OS.
- I'm using Core Animation as my "engine", rather than the OpenGL ES API or an off-the-shelf gaming engine. (Note: My game only needs a couple dozen sprites.)
So far, things have worked out well. I was worried that using Objective-C and Core Animation might lead to performance issues on the iPad, but that hasn't been the case. I have run into a couple of issues with Core Animation that were pretty easy to fix.
Layer Creation Is Expensive
My game's "sprites" are just Core Animation layers. When I initially implemented the game, I was creating layers and adding them to the view as needed, and then deleting them when they were no longer needed. This turned out to cause problems; a few frames would get dropped whenever a layer was created.
The fix for this was to create a pool of layers and add them all to the view at startup, and reuse those layers as needed. Unused layers get their hidden property set false.
Watch Out for Misaligned Images
If you run an app with Instruments with the Core Animation tool, it has an option to highlight "misaligned images." I couldn't find a lot of information on this, but apparently if you give layers positions that are not perfectly aligned to pixels, Core Animation does some anti-aliasing when rendering those layers, which degrades performance.
The easy fix is to just round all positions to whole pixels, via something like this:
- (void) setSpritePosition:(CGPoint)position {
CGPoint alignedPosition;
alignedPosition.x = floorf(0.5f + position.x);
alignedPosition.y = floorf(0.5f + position.y);
sprite.position = alignedPosition;
}
This got rid of most of my misaligned images, but I do still have some sprites that get rotated or scaled via a transform, and such images are always misaligned, unless they are rotated by some multiple of 90 degrees. Thankfully, I only have a few such sprites.
My iPad Review
Sun, 05/16/2010 - 09:30 | by KrisSo, I've had an iPad for about a month and a half. Here are my impressions:
Overall, it's really nice. It fills the need for a little Internet-connected device that lets me watch video, read books, read online news, and browse the web. I used to keep my old 13-inch MacBook next to the couch for these purposes, but that MacBook is now in a closet. I've also put away my Sony Reader that I kept on the nightstand.
I'm using it at work a lot more than I expected. My workstation has two monitors, but I find it handy to have programming documentation or technical books open on my iPad for reference. It essentially gives me a third monitor.
We take a lot of long car trips, and my wife really likes reading and web browsing with her 3G iPad in the passenger seat. It's a better experience than her MacBook Air.
The iPad is not a replacement for a laptop. When I need to do a lot of typing, or switch back and forth between applications, then I put down the iPad and pick up my laptop. But picking up a laptop is starting to seem like a chore. The iPad is not heavy, it's not hot, it doesn't have a whirring fan, it doesn't require me to assume an uncomfortable posture.
If you want a "computer," don't get an iPad: you'll be disappointed. Think of it more as a portable videogame console, or a Kindle on steroids. Saying that it is just a big iPhone is essentially correct, although many of the people who say that seemingly have no idea how useful a big iPhone could be.
The iPad is heavier than I expected. This is usually not a problem, but when playing any of those accelerometer-based games for an extended period, my arms get tired. On the plus side, I guess this gives me some exercise that I've been missing.
I use the Amazon Kindle app for iPad more than I use iBooks. I like the fact that with Kindle, I'm not locked in to Apple-only platforms. iBooks is prettier than the Kindle app, but the Kindle app is good enough. I need to stress here that I am talking about the Kindle application for iPad, not a Kindle device, which looks laughably archaic next to an iPad.
My only real complaint about the iPad is lack of multitasking, but that should be addressed in a few months with a new iPhone OS revision. (I have the iPhone OS 4 beta on my phone, and really, really miss the new features when using my iPad.)
In the month-and-a-half I've had the iPad, there has only been one instance where I went to a web page that didn't work due to lack of Flash. So that's not really a problem.
I've got the Apple iPad case. It is functional, but it is ugly.
My iPad has survived one fall from a countertop to the floor, without any ill effects.
I hope that some nice Android or Palm tablets appear soon. Competition and choice would be good, but right now, there is really no competitor to the iPad. It does what it does better than anything else can.
As a software developer, I'm excited by the new user-interface expectations being ushered in by the iPad. This will finally get us away from the 1984 Macintosh-style WIMP interfaces that we've been stuck with for so long. I don't like a lot of Apple's policies, but they are leading the way here, and other vendors will copy the good stuff, so we will all benefit.
Some must-try apps:
Looking for iPad Application Beta Testers
Sat, 05/15/2010 - 09:20 | by KrisSome time in the next few weeks, I hope to have an iPad game ready for submission to the App Store. I am looking for people to help me test the app.
You need to have the following:
- An iPad
- Somebody with whom to play the game (it's a two-player game, but you only need one iPad)
To be a beta tester, you will have to give me your iPad's UDID (unique device identifier). To get that, follow these steps:
- Launch iTunes on your computer
- Plug your iPad into the USB port and wait for iTunes to indicate it is connected
- Select your iPad in the Devices list in iTunes and click the Summary tab
- Click the word "Serial Number" next to the picture of your iPad. It will change to "Identifier (UDID)" and there will be a long string of letters and digits after it
- From the Edit menu, choose the Copy command. (This will copy the letters and digits to the clipboard.)
- Paste the UDID into an email to me, saying that you want to be a beta tester. If you don't know my email address, use the Contact Me form.
Internet Emergency Checklist
Tue, 03/30/2010 - 16:06 | by KrisWhen the power goes out, nobody asks me how to make it work again. But if the Internet goes down for three seconds, everyone in the house is yelling at me, telling me I need to MAKE IT WORK! NOW!
Most Internet problems are due to issues that have nothing to do with me. I don't have any magical Internet-fixing powers. I just calmly go through a few steps until everything works. Most often, the steps I take don't really fix anything. The Internet generally fixes itself, without any help from me, but family members yell at me less if it looks like I'm taking action. (My grouchy "leave me alone; I'm working" demeanor helps too.)
I have a dream: I would like to watch an entire episode of Lost uninterrupted. I'm going to try to empower my family to "fix" these problems themselves, and I encourage others in my shoes to do the same.
In the spirit of the xkcd Tech Support Cheat Sheet, here is the checklist that I plan to post next to each computer in the house. It's very simple; I don't expect anyone to check network settings, enter wi-fi passwords, or interpret blinking lights. It's really just a matter of turning things off and back on. Fill in the blanks as needed.
Internet Emergency Checklist
In the event that the Internet stops working, please take the following steps:
- Remain calm. It may seem like the end of the world, but remember that this has already happened 83 times this year, and somehow we survived.
- Slowly count to 100, then try whatever you were doing again.
- Close all the web browser windows you have open (Internet Explorer, Firefox, Safari, Mozilla). Also close any other programs you know are using the Internet (e-mail, online games, Twitter clients, etc.). Wait 30 seconds, then open your web browser to see if your home page appears.
- Reboot your computer, and try again.
- Check other computers in the house. If the Internet is working for them, but not on your computer, then turn off your computer, wait five minutes, turn it back on, wait five more minutes, and then try again.
- Turn off the cable modem, the router, and your computer. The cable modem is the box that says ________________ on it. The router is the box that says ________________ on it. (If you can't find an on/off switch, just unplug the power cord.) Wait 60 seconds, then turn the cable modem back on. Wait 60 seconds, then turn the router back on. Wait 60 more seconds, then turn on your computer and try to do whatever you want to do.
- If things still don't work, you can ask for help from the resident tech support expert. If help isn't available, call the Internet service provider's tech support at ________________. When they ask for your phone number, don't give them your mobile phone number; give them the number associated with our account, which is ________________.
New Job, Old Job
Fri, 03/26/2010 - 08:31 | by KrisFor the last seven years, I've been working with a company that does gaming-related stuff (lotteries, casinos, race tracks). I worked for a few years as an employee, and later as a contractor. Like all jobs, it's had its ups and downs, but on the whole it was a good experience.
I would have been happy to continue it, but a few weeks ago the company announced a "strategic partnership" with a European gaming company, with the intent of selling that other company's products in the US. That's probably good news for the company and its shareholders, but it's not good news for those of us who develop the products that are to be phased out.
It was pretty clear we would eventually be laid off, but it wasn't clear when that would happen in a few weeks, a few months, or a few years. I started putting out feelers, hoping I'd be able to jump before getting pushed.
Lucky for me, a former boss was enthusiastic about re-hiring me, and so I'm now back at TransCore, my first employer. Right now, I'm working as a contractor, but the plan is to go permanent.
It's nice to see my former co-workers again. Their hair is a little grayer, but otherwise it doesn't seem much different from how it was when I left. They are still using the wiki I created. They are still using CVS (eeaagh!). The two guys who I hired are still working there. Code I wrote back in the early 1990's is still in production.
I'm looking forward to working again with a team of people I like, but another big plus to this job is that I'll be able to do most of it from home. I live in Dahlonega, GA, which is about fifty miles north of where any Atlanta-area programming jobs are, so this is a very good thing. My boss and other team members work a lot from home too, so I won't be the oddball guy who seems to never be around.
It's a Microsoft-heavy shop, so I'm having to re-learn a lot of the Windows development skills that I haven't used for a few years. Luckily (or unluckily), writing Win32 code with C++ hasn't changed much in the last decade, so I'm getting back up to speed in that area pretty quickly. I didn't do too much with .NET, but it looks like .NET has gotten a lot better during those years, so I'm looking forward to playing with that too.
I really hope this works out. I'm done with the "switch jobs every few years to get a wide range of experience" part of my career, and want to find a place where I can do good work and have influence over the company's direction. This company has smart people who care about the quality of their work, and managers who put value on experience and talent. That's exactly the kind of place where I'd like to stay.
Shiny iPhone Buttons Without Photoshop
Sat, 02/27/2010 - 07:16 | by Kris
Newcomers to iPhone development are sometimes surprised at how ugly the standard button controls are. They quickly learn that they need a graphics person to create a nice-looking button image in Photoshop and then attach that to the buttons. However, in this tutorial, I'll show how to create nice shiny buttons in code, without any image files, by using a CAGradientLayer.
JacksOrBetter for iPhone Updated
Tue, 02/16/2010 - 20:10 | by Kris
Version 1.1 of JacksOrBetter for the iPhone and iPod Touch is now available, and it's still free. If you have an iPhone or iPod Touch, you can get it from the App Store.
This version has a lot of cosmetic improvements over version 1.0. Version 1.0 was, frankly, a little embarrassing, and I'm glad I finally got around to fixing it.
I created JacksOrBetter back in September 2008, when the App Store had only existed for a couple of months, and the iPhone App Store Gold Rush was on. The news was full of stories of iPhone developers who were making tens of thousands or hundreds of thousands of dollars from simple games. I wanted in on that action.
JacksOrBetter wasn't intended to make me a fortune; it was my first learning-how-to-write-an-iPhone-app exercise. I figured I'd whip it out, learn what I needed to learn to make and sell an iPhone app, and then I'd get to work on the apps I really wanted to write. (Those other apps are still in the conceptual stage, a year and a half later.)
At that time, there were only a few hundred apps in the App Store, and many were little better than JacksOrBetter. I initially charged $1.99 for it, and after a couple of weeks dropped the price to $0.99. I made about $280 over the next few months. Initially I was selling a dozen or so copies per day, but sales eventually fell to only a few per week, so I decided to make it free.
Since then, I've seen a lot of really nice iPhone apps, and I've learned a lot more about how to make them, so I finally decided to sit down and make JacksOrBetter what it should have been.
So now, it has nicer looking cards, a nicer background, and some cool animations of cards being dealt, discarded, and cleared at the end.
It's still pretty simple, but it no longer has that first-app stink.
There are a few more changes I want to make, but I've got this idea for an iPad app...
