motd.co: My Two Shoes Weekend
When I decided to have the Two Shoes Weekend, it started as a personal goal. I was going to take a stab at using Shoes, which I had earmarked a long time ago as something I’d like to play with, and I was going to start and finish two projects within the span of the weekend.
I’m not sure how exactly, but telling someone that I was doing it turned into telling everyone that they should also do it. There was a bit of grumbling from people about my choice of toolkit, but I knew that the best way to make the goal attainable for me was to pick something that would end up feeling limiting— if the goal was “make as many things as possible using whatever you want to”, I would only half-finish one thing.
So why two? Well, basically because it wasn’t one and it wasn’t too much bigger than one. I wanted to push myself to see what I would do when I finished making something out of the first idea and had to move on to something else, but I wanted to make sure that I would reach my goal and was hoping to avoid feeling rushed to move on to other things before I was done with one idea just to meet my goal.
It worked pretty well! My first idea was something that I’m fairly used to— querying a website, pulling down some data, and formatting it. My second project involved implementing a physics equation, which is definitely not something I’m used to doing, as much as I’ve always liked the idea of making games and as much as “collision detection” is a basic concept within that world.
As promised, I made two things! One fetches data from Twitter to make you laugh and the other is a graphical tech demo.
Big Fan loads the last 50 tweets that I’ve starred on Twitter. I follow a lot of funny people— some are professional comedians, some self-styled funny internet personalities, and some are just my really funny friends. When I see something that makes me laugh, I star it, and sometimes by myself or with my wife I review the jokes that I’ve starred recently just to laugh again. I think Twitter is a really great platform for joke delivery.
When Big Fan loads, it shows the most recent tweet that I starred. You can use page down or the down arrow key to view the tweets before the currently displayed tweet, and page up/the up arrow key to view the tweet after it. The Home and End keys go to the first and last tweets respectively.
Dots puts a bouncing dot on the screen. You can press the ‘a’ key to add another dot, and another, and another. After that, any dots you add will cause the oldest one to fade away and disappear forever. It’s a metaphor for life (right?) and a proof of concept for modeling perfect inelastic collision across two dimensions using Shoes’ basic “Shape” objects.
Dots also comes with dot.rb, a set of classes that does the heavy lifting with regards to wrapping up the Shoes shapes and handling collision detection. dot.rb could be expanded and re-used for other projects involving modeling 2D objects in a Shoes app.
P.S.: Shoes from Vim
After working on my first project for a few hours, I got tired of saving in vim, then dragging my .rb file from Finder to the Shoes dock icon. I took a moment to write a keybinding in vim to make open the currently open .rb file in Shoes based on the default install location in Mac OS X. On Sunday afternoon I realized that it might be helpful to other people to have the same thing, so I put it up on Github, at which point [inky] suggested that using
open -a would make it even better. So I present to you the addition to your vimrc that will open the current .rb file in Shoes on Mac OS X:
How it Went
Pretty well; thanks for asking! I worked on this stuff for a decent chunk of the weekend, but I also saw a movie, went out for a few meals, hung out with my friend, drank some beers, talked to one of my college roommates, read a chapter of a book, and watched some TV with my wife, so it by no means dominated my weekend. Two things started and finished in that time! That’s pretty cool, right?
Gems & Shoes, Shoes & Gems
When I started on Friday night, I thought that I would just start using Ruby gems with wild abandon. Ruby has a wonderful community that has written a lot of code to make your life easier, so I was hoping to make use of that to make some really cool things. Unfortunately, I discovered that Shoes’ compatibility with gems is pretty limited.
The most obvious problem is that since Shoes is built with the purpose of packaging cross-platform applications in mind, you can’t use any gems that require “native extensions”, which is to say that installing the gems involves compiling any code for your specific platform (frequently it’s something that’s been written in pure C). This is regrettable, but it makes sense, and technically you can make it work on your own system at least if you’re familiar with the underpinnings of the Ruby environment and just copy gems into the right location for Shoes to find them.
Unfortunately, copying a gem into the right location isn’t enough— gems can have dependencies on other gems, which can obviously have dependencies of OTHER gems, and before you know it one pure-Ruby gem that you want to use requires getting 8 other gems set up within your Shoes environment, and 5 of those have native extensions, which means you can no longer package your app for other platforms.
This is a messy problem. I’m not sure that there’s a WHOLE lot that can be done about this, but I have a few ideas:
- Shoes should be better at reporting errors with the Shoes.setup process. A Shoes.setup block is how you tell Shoes to install gems, but if you try to install Gems with native extensions on Snow Leopard it thinks for a very long time before giving you a confusing error message. The process is even more broken if the problem lies within a DEPENDENCY of a gem that you are trying to install. It would be nice if Shoes could be upfront about what went wrong.
- We need some way to search for gems that are pure ruby and only depend on gems that are also pure ruby all the way through their dependency tree. This may exist somewhere already, but I don’t know how it works and I would really like this. That way you know which gems are safe to put in a Shoes.setup block if you’re trying to write a Shoes app with cross-platform packaging in mind.
- It would be nice if you could somehow install gems with native extensions anyway if you’re only planning on targeting one platform. It’s possible that this still wouldn’t work, since I don’t know a whole lot about the Shoes code itself, but I’d like to investigate that as a possibility.
- Last resort: make a script that, if you have a gem installed within your native Ruby environment, will copy it and all gems in its dependency tree into your Shoes environment so that you can use those gems on your computer (and give an easy way for other people to get their Shoes environment ready to run your app on their computers).
Shoes Error Logging
The error console in Shoes is really confusing. You frequently end up with no line number telling you where a problem is, and sometimes the program execution just seems to halt without ANY kind of error in the console. It took me half an hour to figure out that I was missing an “end” in one of my methods this afternoon because the method was being included from a different file via a ‘require’ directive. This is something that would have taken 60 seconds running a ruby program via the command line. The error console always reads “Debug in line 0” at the top even though the line number is sometimes mentioned within the error message below that— I’m not sure if that’s a problem with the MacOS X version or something I’m doing wrong, but it’s totally useless and needs to be fixed.
Teaching From Scratch
I was really happy that a few people took me up on the whole idea and spent part of their weekend working on making some things too. One was a veteran of doing creative things with computer science, one was a programmer who hasn’t coded outside of work in a long time, and a couple were people who had never written a line of code. These last two were tricky— the more I ran across weird issues in Shoes, the more worried I got that this was going to make it too difficult for them to accomplish anything. I spent a decent amount of time answering questions about syntax and trying to teach concepts like Arrays, Hashes, and how to make use of method calls returning a value. And it was great! I’m not sure if the non-programmers will ever program again, but I hope that amid the frustrations of “Shoes.app, not shoes.app” and “make sure all your do/ends match up” there were some flashes of “wow, I made that button do that!” I also got a few bug reports for the Windows version of Shoes that I managed to confirm on my work laptop that I’ll be reporting to the Shoes issue tracker on Github, and I’m glad that just within the scope of my friends’ learning about Shoes they managed to find some concrete ways we can improve Shoes.
I have some ideas for where to go from here based on what happened to me this weekend. I had never really played with Shoes before beyond stepping through a couple tutorials and filing it away as something I wanted to play with more later. Now I have played with it, and while I think it’s got some problems, I also think that what it DOES do right is pretty cool.
Dots!, my second project, wasn’t meant to take as long as it did. I had never written a collision detection engine before, let alone the physics of what to do when a collision does occur, and it took me longer to write that part than I would have liked. On Sunday I decided to spend some time refactoring the code to make it stand separate from any particular Shoes app and then did a little bit more work to pull common functionality into dot.rb so that more than one app could use it. Dots!, therefore, is just a tech demo, and I’d like to improve on dot.rb and play around with making games using it. I decided that rather than stress myself out this weekend with trying to make an entire game and have it in fully working order by Monday morning, I’d rather stick with something clean and polished that’s ready to be improved upon in the future.
The reason I’m so blunt about the problems I saw with Shoes in this post isn’t because I’m a jerk. Well, it’s not JUST because I’m a jerk. I really do think Shoes is a neat idea and there are things about it that work really great right now, and I want it to get better and be totally awesome. When it comes to Ruby specifics, I’m still learning, but I’m hoping to spend some time now that I’ve seen particular pain points in Shoes working on fixing them. If I want them to work, what better way to ensure that they get done than to do them myself?
In any past time, this would be made more daunting, but I feel lucky that in this day and age we have the tools we do to streamline the work of contributing to a communal codebase and discussing it efficiently. With things like git and the community that’s out there on Github, it should be much easier to make changes and have them reviewed by people who can catch my mistakes.
I know that at least 4 other people participated in the Two Shoes Weekend. I’ll be collecting their projects and will share as much information as they’re willing to let me share (definitely summaries, hopefully screenshots, maybe source code!) here on my blog. If you participated and you want to share, please email me.