Showing posts with label html. Show all posts
Showing posts with label html. Show all posts

2012-02-13

Post Mortem: robotfindskitten.com

It's Been a While

I realize it has been a while since I last posted. Mostly that is because of my little one, work, and working on personal projects as opposed to writing articles for the blog. Today I will share with you my experiences with developing one of those personal projects: robotfindskitten.com.

robotfindskitten

If you're not familiar with robotfindskitten (which 99% of you probably are not), then as a brief introduction robotfindskitten is the name of a terminal-based (i.e. text) game (nee, "zen simulation"). The object is to move the "robot" character on the screen and touch other unidentified items until you find the one that represents "kitten." The game has been ported to nearly every platform known to man. For more history on the subject, consult the official website.

The Desire

I originally stumbled upon robotfindskitten when I was in college over half a decade ago. Back then I added creating a port of the game to my bucket list. I even registered the robotfindskitten.com domain name with the intention of posting a Java applet version of the game on the web. Sadly, life got in the way, and even though I started that version it was never completed.

Fast forward to sometime in the middle of last year. There were a variety of new technologies that I have been eager to learn, but I needed a project that would allow me to try them out. Here is a short list of the technologies I wanted to learn:
  • JavaScript
  • HTML5 Canvas
  • jQuery
  • Git
  • node.js
Finally it dawned on me that there was no port of robotfindskitten using HTML5 canvas (there are, however, JavaScript and jQuery ports). This was my opportunity to learn those technologies and contribute my personal port of robotfindskitten to the world.

The Goals

On top of learning those technologies, I set a few additional goals for myself for developing my JavaScript/Canvas robotfindskitten port:
  • The implementation would be completely open source and hosted on GitHub.
  • The implementation would be created using only free tools.
  • The implementation would be created using only online development environments. See my article on Cloud IDEs for more information.
  • The implementation would be deployed to a free hosting service.
  • The main code for the robotfindskitten game itself would be pure JavaScript without any dependencies.
  • The main JavaScript code would use a module approach.
  • The game would be playable with touch controls on tablet devices.
Learning the Technologies

As I mentioned in my article on language bigotry, JavaScript was a language I have looked down on in the past. With all of the buzz on HTML5 and server technologies such as node.js, I have quickly changed my stance on that and determined that JavaScript is something I REALLY need to learn. To further that goal, I read Douglas Crockford's wonderful JavaScript: The Good Parts and Stoyan Stephanof's JavaScript Patterns. I highly recommend both books for anyone looking to quickly get up to speed with JavaScript.

For HTML5 Canvas, Git, and node.js I read a variety of tutorials on the web; sadly I do not remember which ones otherwise I would link to them.

Choosing the Right IDE

In my article on Cloud IDEs I played with a lot of different options. My needs for this project was an online IDE that could interface with Git and had good support for HTML and JavaScript. In the end, I settled on using both Cloud9 IDE and eXo Cloud IDE. Most of the work was done in Cloud9 IDE, since I preferred the command line interface to Git, the GitHub integration, its text editors and testing environment, and its simple integration with Heroku. All of the code was written in one of those two editors, and never once have the files on the robotfindskitten.com website been on my local machine.

Choosing the Right Hosting Service

The hosting needs for the website are very simple. It is pretty much a single HTML page with some JavaScript dependencies. I wanted to deploy to a cloud hosting provider in case I wanted more services and I looked mostly into Heroku. Ruby and Rails would be massive overkill for a single page application, but I had been looking into node.js and it was perfectly lightweight enough to meet my needs and give me a new tool to play with. In the end I chose to use node for my application and deploy to Heroku (which recently started hosting node.js applications).

What I Learned

I learned a lot about JavaScript. The main source code file for the application went though a number of iterations. I had the game working pretty quickly, but there were no real objects and the code was a spaghetti mess. I had decided I wanted to use the module system described in JavaScript: The Good Parts and JavaScript Patterns, so I refactored out classes using the module approach until the game was very modular. I used jQuery on the HTML page itself, but I excluded it from the robotfindskitten code because I didn't want a dependency. In fact, to create a new game all you need is rfk.js and an HTML page with a canvas and a div for displaying messages.
var canvas = document.getElementById("yourcanvasid");
var messageDiv = document.getElementById("yourmessagediv");

var rfkGame = new com.robotfindskitten.Game(canvas, messageDiv);
rfkGame.startGame();

jQuery was pretty easy to pick up from a few examples, at least as much as I needed to use jQuery (basic references to existing tags on the page). I learned quite a bit about how to manage code with Git, and even how to do a merge.

What Went Right

Mostly everything. I was able to pick up JavaScript quite easily. Both web based IDEs worked quite well. GitHub was easy to use, as was deploying to Heroku. node.js is very simple to start up a quick application using the "Express" plugin. I learned to really like Git, except for at one point, when I really did not like Git (see below).

What Went Wrong

Most of my difficulties fell into three categories: not understanding Git, working with fonts on a Canvas, iOS quirks for touch controls.

Git

Don't get me wrong, Git is a great tool, but at one point I was switching between the two cloud based editors and had changes from both, forcing a merge. Manually merging source files with just a text editor is a painful process. I'm sure it would have been easier if I had a merge tool, but there were none available in the online IDEs, so the manual merging process was very difficult.  

Fonts on a Canvas

Since the "graphics" in robotfindskitten are just characters drawn to the Canvas, I had to learn a lot about how text is rendered. One of the biggest difficulties I had was that Canvas only supports font metrics in pixels, and I wanted to use "em" as my units. The conversion was tricky in order to calculate the actual width and height of a character drawn on the canvas. Canvas natively supports the width of a character (using context.measureText(character).width), but provides no means to measure the height. In the end, the following code was used to calculate the height of the area the characters would be drawn in:

function calculateHeight() {
  var heightElement = document.createElement("span");
  heightElement.style.fontFamily = "Courier, Monospace";
  heightElement.style.fontSize = "1em";
  heightElement.style.position = "absolute";
  heightElement.style.visibility = "hidden";

  heightElement.appendChild(document.createTextNode("M"));

  var body = document.getElementsByTagName("body")[0];

  body.appendChild(heightElement);

  var height = heightElement.offsetHeight;

  body.removeChild(heightElement);

  return height;
}

The capital letter "M" was used to calculate both the width and height because based on my research it is typically the widest and tallest character.

iOS Quirks

Late in development, after I already had the keyboard controls working, I started work on the touch controls. I used the Apple developer docs as well as several other sources to learn how 'touchstart', 'touchmove', and 'touchend' events work. My approach to determining which direction to move the robot involved three steps.
  1. When 'touchstart' was fired, I saved off a reference to the touch event so that I would know where the user initially touched the screen.
  2. When 'touchmove' was fired, I saved off a reference to that touch event so that I would know the last location where the user was touching the screen.
  3. When 'touchend' was fired, I would compare the coordinates from the start and move events to determine which direction the robot should move.
The actual code looked something like this:

  function handleTouchStart(event) {
    if (event.touches.length === 1)
    {
      this.firstTouch = event.touches[0];
    }
  }

  function handleTouchMove(event) {
    if (event.changedTouches.length === 1)
    {
      this.lastTouch = event.changedTouches[0];
      event.preventDefault();
    }
  }

  function handleTouchEnd(event) {

    var diffX = this.lastTouch.pageX - this.firstTouch.pageX;
    var diffY = this.lastTouch.pageY - this.firstTouch.pageY;

    // Code to move robot 
  }


I coded up my implementation for controlling the robot and tested it in my local browser using Phantom Limb to simulate the touch events. All was well, and the touch controls were working.

Later that night I tested my implementation on my iPad, and things were not as good as I had originally hoped. The robot would not move. I found out that if I moved my finger and released it, then tapped again without moving, then the robot would move. Weird. Based on that behavior I concluded that 'touchend' was not being fired after 'touchmove' was called. I tested the game on an Android tablet and confirmed it worked there, so the issue had to be related to iOS. I spent a couple of days searching on and off for 'touchend' not firing, but came up blank.

Finally, I got smart. I realized that you can turn on the developer console on Safari on the iPad. I turned that on and started adding debugging statements. Turns out, 'touchend' was firing. After adding a few more debugging statements, I realized that the robot wasn't moving because the difference in where the user initially touched and where they moved their finger to was always 0. More debugging statements. At last I realize that the reason the robot is not moving is because "firstTouch" and "lastTouch" are the exact same event. It turns out, iOS (presumably to save space in a mobile environment) does not create an new even object for each touch event, but instead reuses references to a single event. Thus, "firstTouch" and "lastTouch" both pointed to the same event in memory, only its values had changed when the 'touchmove' event was fired. The solution was to explicitly save off the coordinates of the events and not the events themselves.

The final code looked like this to work around the events being the same event:

  function handleTouchStart(event) {
    if (event.touches.length === 1)
    {
      this.firstX = event.touches[0].pageX;
      this.firstY = event.touches[0].pageY;
    }
  }

  function handleTouchMove(event) {
    if (event.changedTouches.length === 1)
    {
      this.lastX = event.changedTouches[0].pageX;
      this.lastY = event.changedTouches[0].pageY;
      event.preventDefault();
    }
  }

  function handleTouchEnd(event) {

    var diffX = this.lastX - this.firstX;
    var diffY = this.lastY - this.firstY;

    // Code to move robot 
  }

Conclusion

Crafting robotfindskitten.com was a wonderful experience. I learned a lot about JavaScript, Git, developing in the cloud, touch controls, and HTML5 canvas. I also scratched off an item from my bucket list. I hope you enjoy it and maybe have learned a bit from my experiences.

2011-08-29

Coding in the Cloud: Diving In with Online IDEs

It seems like everything today is moving to "the cloud," which is that nebulous term for software applications and data storage hosted remotely on some server far across the internet. So if all of our software is moving to the cloud, why not the tools used to create that software? Well, in some cases, those tools are rolling out right now. Heck, even GitHub recently added basic editing capability. This article will look at some of the up-and-coming online IDEs.

Pastebins: The Little Brothers of Online IDEs

The first category of online IDEs that we will explore can't really be called IDEs. These IDE-lite web tools are more like pastebins on steroids. Pastebins provide basic text editing capabilities and features such as syntax highlighting, but not support for version control or deployment. Instead, pastebins allow snippets of code to be saved and shared with other users. The following web tools extend beyond the basic premise of typical pastebins in that they also allow your code to be executed, something vital for testing. This category of IDE-lite is excellent for simple proof of concept work, but not for developing full applications. The main feature that these web tools support is quick and easy tinkering and the ability to share small snippets of code.  The three IDEs is in this space that we will be covering are JS Fiddle, Python Fiddle, and ideone.

JS Fiddle

JS Fiddle


JS Fiddle may not be a fully featured IDE, but for trying out quick ideas with HTML, JavaScript, and CSS it is a great place to start. The web site provides separate windows for HTML, JavaScript, and CSS, and another window that will display the final output. The editors support syntax highlighting. JS Fiddle allows you to choose from multiple versions of each of the major JavaScript libraries like jQuery, Mootools, Prototype, YUI, and Dojo when testing your JavaScript snippets. It even allows you to link in the URL to your own JavaScript and CSS files hosted remotely. Your "fiddles" can also be saved and shared with other users. JSLint is also integrated to ensure your JavaScript code is tip-top.

Python Fiddle

Python Fiddle


Python Fiddle is similar to JS Fiddle except it is focused on Python instead of the HTML/CSS/JavaScript combination. Python Fiddle provides a sandbox to test snippets of Python code, and provides support for many of the popular Python libraries. Like JS Fiddle, Python Fiddle supports syntax highlighting, and your snippets can be saved and shared with other users.

ideone

ideone


ideone is by far the most ambitious of the glorified pastebins. Much like JS Fiddle and Python Fiddle, ideone provides syntax highlighting and the ability to save and share snippets of code. Unlike the other two, however, ideone aims at supporting well over 20 different languages, including C, C++, C#, Java, JavaScript, Go, Groovy, Objective-C, Perl, Python, and Ruby. ideone aims to be a one-stop shop for all of your snippet testing needs.

Will the Real Cloud Based IDEs Please Stand Up

What separates the real cloud based IDE's from their little brothers is that they include support for importing projects, working with version controls systems (primarily Git), and in some cases support deployment. Of the fully-featured online IDEs we will be examining Eclipse Orion, Cloud 9 IDE, and eXo Cloud IDE.

Eclipse Orion

Eclipse Orion


Eclipse Orion is an online IDE effort being led by part of the Eclipse foundation. The IDE is primarily focusing on web development languages such as HTML, JavaScript, and CSS, but includes initial support for Java. Orion differs from the other online IDEs in that it is not necessarily meant as a hosted solution, but actually intended to be deployed into private environments. You can download Orion and host your own instance. For instance, you company might host an Orion instance for all of its developers, or even for specific projects.

Right from the start Orion lets you initialize new projects by cloning from Git (the only supported version control system), uploading a zip file of your project, or by creating a new HTML5 site using initializr.

For my testing I cloned a repository in Git. For some strange reason I had to use HTTP for Git instead of SSH, since I cannot find the SSH key listed anywhere in the IDE. Orion provides a GUI for interacting with Git, but it can be a bit confusing. While I understand it is a good practice to use Git's "status" command before performing a commit, Orion hides the commit interface under the Respository window's "Show Status" option, which is very confusing.

The editor is fairly nice. It supports line numbers and syntax highlighting. Support for outlining and content assistance is very spotty. Currently outlining is only supported for JavaScript and HTML, and content assist is only available for CSS. Basic editing commands such as Alt+Up/Down to move lines, Ctrl+D to delete a line, and Ctrl+L to go to a line number are supported.

For more information you should check out Eclipse's "Getting Started Guide" for Orion.

Cloud9 IDE

Cloud9 IDE


Cloud9 IDE is another web-based IDE specialized towards web development, and is the only one on the list with a paid solution. Cloud9 IDE is free for projects that will be publicly visible, but for private projects the cost is $15 a month. The IDE supports HTML, JavaScript, and CSS, but also includes support for Ruby and PHP. Of the online IDEs, Cloud9 is the only one on this list that supports Mercurial as well as Git. In fact, GitHub and BitBucket support is baked in from the start and you can actually create your Cloud9 IDE account by logging in through one of those services. In fact, when I created my account that was the only way (hopefully something that has been fixed, but I don't want to create another account to test the idea).

Provided you log in through GitHub or BitBucket, importing projects is a breeze. You will need to be familiar with the command line versions of Git and Mercurial though, as all version control support is implemented through a console at the bottom of the screen. The tool does provide an SSH key that you can register with GitHub so you won't be prompted every time you try to push code.

The editor is very responsive and supports some of the niceties I've come to expect from Eclipse (Alt+Up/Down to move lines of code, Ctrl+D to delete a line, Ctrl+L to go to a line). The syntax highlighter is nice, and there is support for code "beautification." The editor will also notify you of code errors as you type.

Your HTML pages can be tested right inside the interface. If you are looking to deploy to an outside host, Cloud9 IDE supports deployment to Joyent and Heroku.

eXo Cloud IDE

eXo Cloud IDE


eXo Cloud IDE is the last online IDE we will be looking at, and probably the most ambitious. eXo Cloud IDE aims to support the three web languages as well as Ruby, Java and JSP, and PHP. It also provides the most deployment options: CloudBees, CloudFoundry, Heroku, and Red Hat OpenShift.

eXo Cloud IDE supports Git for version control, and provides a nice menu at the top of the screen for all of the Git operations. A bit tucked away under the "Window" menu there is an "Ssh Key Manager" utility so you can set up an SSH key to use with your remote Git host (such as Github). Importing a project from Git was a bit more difficult with eXo Cloud IDE in that first you had to create a folder, initialize a repository in the folder, and then perform the clone. Most of the other services let you start with "clone" and took care of the rest for you.

The editor is nice enough. It supports syntax highlighting and line numbers. It doesn't have some of the text editing niceties I mentioned for the others (Alt+Up/Down is absent, but Ctrl+D for delete line and Ctrl+L for navigating to a line do exist). It does support a nice outline view though for navigating your code, which is very helpful. One extremely nice feature that eXo Cloud IDE supports is a minimal form of code completion (with the standard Ctrl+Space command). eXo Cloud IDE provides basic auto-completion for HTML, JavaScript, CSS, and Java, Ruby, and PHP code.

Comparison

The following table provides a comparison of the different features of the online IDE's mentioned:
IDE Cost Languages Version Control Deployment
JS Fiddle Free HTML, JavaScript, CSS None None
Python Fiddle Free Python None None
ideone Free 20+ Languages None None
Eclipse Orion Free HTML, JavaScript, CSS, Java Git None
Cloud9 IDE Free (Public), $15/mo (Private) HTML, JavaScript, CSS, Ruby, PHP Git, Mercurial Joyent, Heroku
eXo Cloud IDE Free HTML, JavaScript, CSS, Ruby, Java, PHP Git CloudBees, CloudFoundry, Heroku, OpenShift

Conclusion

While I don't see the online IDEs taking over for most developer's day-to-day tasks, I think that they are a welcome addition to any developer's toolset. Web developers will benefit the most at the moment, as most of the tools are geared towards HTML, JavaScript, and CSS development. Seeing as how most software is moving into "the cloud" and those are the technologies that are driving new web-based applications, that's not a bad thing. The pastebin style tools are useful for quickly testing new concepts and don't require a lot of the overhead of a full-blown IDE.

Git seems to be the clear winner when it comes to version control support in the online IDEs. GitHub in particular is favored (it is a great service so I can see why). Only one IDE offered support for Mercurial, and Subversion lovers are out of luck going forward into the online world.

Personally, robust code completion and refactoring tools are a must in my world, and support for those features is definitely lacking in the current generation of online IDEs.  I think that as the tools mature support for those features will increase. I could see that several years down the line there will be whole software teams that develop and deploy all of their code right from their web browser.