Thursday, May 13, 2010

Deep Sea Descent - Afterthoughts

Earlier today, I went ahead and pulled the trigger on releasing Deep Sea Descent. This project is the largest-scoped one I've been on in terms of personal time and effort, and I think it would be a good idea to reflect on it now. My thoughts on what I would do and what it would be changed several times, and in the end, while I like the result as a game(the commercial success is still uncertain right now), I see tons of things that can still be addressed or expanded upon through a sequel.

The Early Concepts

This is the third time I've made DSD. The first two were college projects. The earliest one was a Game Maker game thrown together in a three day weekend. I started by attempting to capture the feeling of exploring the ocean, with drone gameplay and collection being one of the earliest features. When I threw shooting gameplay on top of this the experience became extremely lively and interesting. It was essentially a small demo, one large level with a boss at the end; after collecting all the bombs the path opened to the boss. I knew I had to go back to this and expand it - there was something thrilling in there.

My second attempt was also a technology exercise - I built a 2D engine with SDL, Lua, and Object Pascal(a language choice done on a whim) and with some help from a classmate brought it to completion over the course of a little over a quarter. It was much worse in several ways - the technology was poor, with some fairly janky collision and barebones gameplay - and the scope was way too high; I wanted to start adding some storytelling elements, but discovered fairly quickly that game stories are extremely time-consuming. I played with the mechanics, dropping drones and the one-level layout, and adding inventory and shops, giving it more of an open, Metroidvania feel. The open-ended aspects were appealing, but the game was overall a less distinctive and refined one, despite taking months instead of days.

For this game, I had combat in mind; I wanted to make a game which turned the conventions of shmup combat on its head. I also decided to bring back drones, but I didn't have a clear plan for how they would be used or drive gameplay. I also made a decision early on to use linear levels to help push along a story concept. This was the genesis of the current DSD.

Technology

My thinking at the outset of the project was that tools and technology were essential to make the game stand out. They did, but not in the way I had expected. I did several experiments; I had some in-engine editing for a while; I built a fairly sophisticated external map editor, and then a second, thinking that when I got it right, it would be a great help and reusable. I was wrong, in several ways!

First of all, I discovered that my tools didn't exactly fit the gameplay. I definitely did one thing right, which was to make the editor aware of relationships between entities(typically used as targeting between doors and switches, or groups of enemies being controlled by a single invisible "choreographer" entity). This is a feature that pays off over and over and is the #1 reason for the levels being distinctive all the way through.

But on the other hand, I spent a lot of time on making a graphics system that let you "stamp" terrain with rotation and scaling. Stamp systems worked for the earlier games, but proved to be terrible in this one for two reasons: my collision system used tiles and didn't line up exactly, and then couldn't actually exploit the full power of the stamps anyway, because the 3D models I was using had to look somewhat flat to present a clear boundary to the player, and I didn't have enough time to make lots of assets and detail levels in a way that would use the system properly. So I almost never used rotation or scaling in the project. It's funny, since I figured to myself "it worked for the earlier ones, it worked for Aquaria too, why not this?" In the future I'm planning to "regress" to tile-based backgrounds because it will let me speed up level design through procedural generation and aid in gameplay clarity - both of which are more important to me than the best-case-scenario of being able to obsessively detail every inch of the game.

I also was mistaken in thinking I would make a reusable tool. The lesson here is: if your tool is reusable, it's probably mediocre for any particular task. By engineering it to be an external thing, I just made it harder to iterate. I wanted to stick to human-readable formats because one of the issues I had seen working as a studio designer was formats that were "locked up" to be tied with the properietary tool - if the tool sucks(which, if the project has little programmer time to spare, is likely) you're SOL. But here I was doing it all, so that use case wasn't actually worth consideration. Whoops.

Another area in which technology failed me was in going off and inventing a mini-scripting language to help with the enemy choreography. It worked, but I don't have a clue as to whether it was actually useful, because I just found myself getting ultra-conservative about what I actually did with it and when it came time to write the boss code I didn't use it at all. The problem was that I didn't actually know my requirements for the language, so I couldn't add the kind of "slam-dunk" features that would actually make the designing part easier, I just stumbled around with it and kept running into bugs of my own creation due to low error-checking. If I had stuck to the native source language(haXe), where the tooling support was better, I could probably have done more in-depth customizations. The same language proved fairly useful for dialogue, fortunately, but not so much that it was worth the effort, I think.

Lastly, there were some general engine quality issues that I had to learn by "taking the blows," so to speak. I've now studied up and incorporated everything into my new engine project, Fireball. But in the meantime I had to deal with those problems for the entire project. With smaller scoped games you can "bleed less," maybe too much so, and ignore problems that would be terrifying on a bigger game - but a lot of the lessons can still be learned.

The brightest part of the technology side of things were that I did, in the end, do things I didn't think were going to happen. I didn't think I'd have lighting, but then one day I was like, "man, it wouldn't be so hard to just dump two giant bitmaps on top of each other to get the effect." So I tried it and it worked. Some refinements and optimizations later and the game looks like it does now - things like subtle procedurals are being used to provide ambient light that isn't completely flat. Similarly, I didn't have particles until the very end, and I thought, "nah, they're too hard," but I got goaded into it after several playtest sessions where it came up. It wasn't that hard. I had my particle effects done within a week and they made all the difference in making the world look lively with fish and trails and all those things going off.

Story and Gameplay

The storyline and characters presented in the game now were iterated on dozens(hundreds?) of times. I wanted something that would be intreguing and present new ideas, not just color for the action. I would sit down at a coffeeshop and write "the story," and it would always leave a lot of things out about specifically how it would work into the gameplay. And then I'd do it again another day, and again, etc. Every time, when the story hit the test of "describe a level actually using this story," it would tend to get stretched and distorted and lose the original intent. The broad ideas of the characters were figured out fairly early, but their exact relationships to each other and "reason for being," per-se, weren't. It was more than half-way through the project by the time I realized that the game worked as a post-apocalyptic tale of rediscovering the past. This let me avoid a traditional story arc of conflict and rising action, which tends to fall flat in games and become a farce: "Ha ha ha, you will not defeat me - oh, I am defeated! *shock*" By the end I had something as engaging as I could hope for, but it was a messy, tangled plotline that wasn't completely resolved. I'll clean it up in the sequel, I promise.

I also ended up doing some unexpected things with the gameplay. Again, a little over halfway through, when content development had begun in earnest, I was going to myself, "man, this gameplay just isn't good enough yet, what am I gonna do *panic*" so I dumped on the fire control features, which made it more lively, and then I added the sonar and invisible stuff, and then I added secrets, and with each addition it got a little richer and more satisfying - but the guided shot was a pain to tune and took months before my feedback was coming back all thumbs up on that. Getting mechanics right is an expensive thing. The gameplay of 1-1 turned out quite a bit differently than everything else because I was still thinking in terms of the original DSD game, but didn't succeed in making the "collect things with the drone to advance" concept tie into the rest of the story. I also found that the linear levels came out feeling claustrophobic, when I was hoping for a more free-flowing feeling.

I'll say this right now: I'm going to make the sequel way more open-ended, with upgrades and exploration aplenty, and more "AI" than "choreography." I want to make the experience bigger, and I think I can do this without ridiculously high scope or a complete upending of the current gameplay, by taking on more procedural elements and carefully developing them so that they provide a similar level of quality and more variation.

Business

I knew from the beginning that this game wasn't going to end up with a traditional Flash sponsorship deal. I got Gamersafe integrated from a very early stage and proceeded with the "sell content" angle for the remainder of the project, though I shifted the scope and price I thought I was going for several times. I still did due diligence and investigated the sponsoring angle, but I didn't go out of my way to market the game to sponsors, and eventually got antsy after two weeks of waiting and seeing no bids, which is why the game is out on the 13th and not the 15th, when I had originally thought I would go ahead with it. In the meantime, I watched the marketplace and saw Captain Forever and VVVVVV come out, I saw a sequel to Robokill come out, and I figured that if these games were succeeding, I was probably on the right track too. We'll see if I'm right.

The game has been somewhat engineered to encourage a fandom - that was a big rational to have a major storytelling component. I want to see what fans can do with the world, and hopefully incorporate that to make a stronger sequel.

It got frustrating to not have a track record as an indie to fall back on whenever I talked to people, online or at GDC or wherever. I could even sense a bit of snubbing going on at times, but I don't think this was actually so bad; all I have to do to correct that is to keep shipping stuff.

Even though I think I got enough feedback to know how I was doing, I wish I had had more of it, and I wish I had taken the effort to build in more data-collection features. When you put up a game on "random forum X" and only get the one-liner comments of "it didn't work" or "it sucked," you learn almost nothing, but if you can see what they did when they played, it reveals a whole lot more. Most of my biggest changes came from one-on-one sessions where someone played through the tutorial and broke it and started flailing and showing increasing discomfort - it wasn't what they said that mattered so much, it was the microscopic things in their play and reactions.

Assets

I really dragged on asset creation, in part because I had to learn a lot to pull off what I wanted to do. And I did learn - I developed a process using Poser as a reference for the characters, and Wings and Blender to do 3D work. I agonized over the music, which I always do with music, and am now finding ways to speed that process up. But overall, I felt overwhelmed and was forced to cut the scope and change the story around simply because assets were taking too long, with the level design taking the most time of all. It's amazing how often the dialogue was forced in a particular direction because I only did one pose for each character and thus could not depict strongly varying emotion - the clash of pictures and words looked ridiculous. (I had wanted to do lots of poses, of course.)

I also had the integration process to deal with, and while I got that down to a reasonable time length, it's something I think my technology is going to be a lot better at from here on out.

I'm going to lean a lot more on procedural methods in the future because they can cut the time spent on assets so dramatically. I also want to get more confident at the art side of things, generally - I should at least feel less "dread" about doing it.

Final Thoughts

I've made a lot of discoveries about the creative process in making this game, and I've done a lot to try to focus my lifestyle around becoming a great indie game maker.

More specifically, I developed a few rules of thumb about creative works: Maximally polished products have to be made in layers, not all at once and the more "process" you add to this, the more consistent the final work is likely to be; 10 hours of practice is sufficient to make breakthroughs in a lot of skills; using references saves a lot of time and doesn't usually impede your own thinking; everything can be iterated on, you just have to decide whether it's worth it.

I also developed lifestyle guidelines: Health(primarily sleep, stress and diet) is tremendously essential to your motivation and clear-headedness, and it is at the core of productivity. Purchases for learning and process improvement are usually worth the money, even if a particular purchase doesn't pan out. Practice time can pay off more than any monetary expenditure by expanding your "horizon of possibility." And don't be afraid to relax: it usually stimulates ideas.

Hopefully, this is just the beginning.

Posted by James Hofmann at 7:29 PM Comments
Edited on: Friday, May 14, 2010 2:10 AM
Categories: Articles

Friday, March 12, 2010

Politically Motivated Games

Yesterday, at GDC's award ceremonies, a recorded message from a White House spokesperson was played, outlining a plan for game developers to compete for prize money by making games about nutrition and fitness education, to fight obesity.

Correct me if I'm wrong, but as far as I know, video games have previously been used by the U.S. government in the context of specific simulations for internal training/education needs; they have not been used as part of a national propoganda effort before. As innocuous as this particular competition may seem, it points towards a future where game designers are employing their talents to massively sway public opinion. It's not just Jesse Schell's future of universial points systems, but something perhaps more insidious and worrisome - a form of mass-media manipulation that distorts factual behavior in favor of gameplay biased towards the administration's viewpoints. Imagine the government forcing developers to avoid "anti-American" gameplay.

I do not have a strong opinion one way or the other about whether this is a future we want; I think that the medium can be employed equally well in both rebellious and nationalistic contexts. I am compelled by self-interest, however, to enjoy the limelight, as it is one further indication of the rising stock of game makers these days. I might even participate in this competition, if I can think of a good sixteen-week game to make for it. I do support the goal of healthy lifestyle habits, after all.

Posted by James Hofmann at 10:24 PM Comments
Categories: Articles

Monday, March 08, 2010

Liberation - haXe/Flash asset framework

This project was intended to make iteration over assets in Flash content fast and simple. It was successful but has been superseded by my new engine project, Fireball. The wiki page has some documentation.

http://bitbucket.org/triplefox/liberation/

Posted by James Hofmann at 10:26 AM Comments
Edited on: Thursday, May 13, 2010 7:29 PM
Categories: Projects

Thursday, February 04, 2010

Flash 10 versus JS/HTML5: The Tour Guide

I have seen an enormous amount of uninformed speculation regarding what the Flash and JS/HTML5 platforms are each capable of as of right now(February 2010). This post is an attempt to comprehensively round up the differences by going through the Flash API and filtering through it to create a "FAQ" of features worthy of direct comparison, with the focus being "what does Flash offer that is not covered in existing or proposed spec?" I used a variety of sources to research this info and linked to them as appropriate; I offer this with the disclaimer that my expertise mostly lies on the Flash side of things, and even there, I have probably made mistakes and omissions in attempting this ambitious piece of documentation. Please help me improve this overview by telling me what's wrong, what's inaccurate, or if there's a side of the story I'm missing.

Features

Name of Flash API class, namespace or feature Notes Can JS/HTML5 Do It?
Accessibility, AccessibilityProperties Display objects on the Flash stage can provide descriptions, keyboard shortcuts, and different behavior for screen readers. This is a wide-ranging issue and deserves to be addressed with its own post. HTML5 introduces several new accessability concerns, most notably Canvas and its ability to replace traditional layout entirely. Not all issues are resolved. The best answer I've found on the subject is in this Stack Overflow thread.
BitmapData An API for low-level manipulation of bitmaps. Yes, Canvas contains similar bitmap-manipulation methods, albeit performance may differ.
Graphics A set of methods you can use to create a vector shape. Yes, with SVG or Canvas.
Loader A class used to load SWF and image files. Yes, with URI resources and DOM manipulation.
flash.filters A set of classes for bitmap filter effects(glow, blur, convolution, etc.) Emulatable, possibly with lower performance. SVG contains a filter effects spec which could potentially be applied to all document elements. WebGL also allows programmable shaders.
Camera, Microphone Captures video/audio from a local webcam or microphone. Proposed post-HTML5: device tag
Sound Loads and plays back MP3 and WAV audio from files or streams. Besides built-in pan and volume controls, real-time inspection and manipulation via Actionscript are allowed. audio tag plays back sound and streams; however, as currently specified it is a black box and does not allow inspection/maniplation. An extension to <audio> in Firefox for these features has been prototyped.
Video Displays live or recorded video via embedding, streaming, or progressive download. Sorenson Spark, ON2 VP6, H.264 codecs are supported for video, and ADPCM, HE-AAC, and MP3 are supported for audio. Source
video tag plays back video, and allows for a scriptable user interface using HTML/JS equivalent to any Flash interface. However, codec support differs across existing implementations due to patent considerations; however, interest in an open video standard is extremely high now, so I expect this problem to resolve itself soon.
Continuous streaming(as opposed to progressive download of a file) is not discussed in detail in the current spec.
The FileReference class provides a means to upload and download files between a user's computer and a server. An operating-system dialog box prompts the user to select a file to upload or a location for download. FileReference may also be used to read and write local files. the "file" input type supports custom upload behavior, and the DOM now supports drag and drop elements. File download triggers from JS already exist.
The SWF format, LocalConnection, Security, ApplicationDomain SWF files are independent namespaces that can run simultaneously, sandboxed from each other, and may optionally open themselves up to intercommunicate. Each SWF's namespace may contain fields representing various resources. SWF interconnectivity is primarily used in applications to provide a lightweight front-end or preloader for other content.
While the overall nature of the SWF format is a foreign concept, iframes have a similar namespace access ability.
DisplayObject and Stage Flash builds its runtime display around the "Stage," which is a tree-structure of DisplayObjects and DisplayObjectContainers; all the kinds of things Flash can display(vectors, bitmaps, video...) are inherited from DisplayObject. Elements on the Stage can attach input event listeners and use the visual display to inform functionality(e.g. overlayed elements will take a mouse click topmost-first). DisplayObjects are able to access all of the available effects and filters, making it easy to apply effects to both single elements and deeply nested groups. The DOM bears broad similarity to the Stage, both being tree structures and using event listeners attached to nodes, but being focused on a document rather than a display makes the actual implementation far different. Nothing prevents the overall functionality from being emulated, however.
Socket, XMLSocket
The Socket class enables code to make socket connections and to read and write raw binary data. Socket is a "raw" TCP/IP connection with user-definable endianness. XMLSocket is the precursor to the general Socket and allows ASCII data to be sent, delimited by \00 markers.
Since Flash 7, server-side policy files have been used to control cross-domain interactions; one policy file is used for loading data, and a second is used for sockets. The overall system is called the meta-policy system.
WebSocket is most similar to XMLSocket in nature; i.e. it is text-oriented, not a low level TCP socket.
Cross-domain access control is being added to HTTP.
ByteArray The ByteArray class provides methods and properties to optimize reading, writing, and working with binary data: endianness control, string conversions, and assistance in reading and writing a variety of formats(8, 16, 32-bit ints, floats, UTF, etc.) The present spec does not include an explicit byte array; strings and numeric arrays can be used to get equivalent results, but with some difficulty, as shown for example here. The WebGL spec has proposed a typed array format that would encompass ByteArray's core functionality.
PrintJob The PrintJob class lets you create content and print it to one or more pages. Browsers have "print page" built in; Canvas elements can save to an image with toDataUrl(). Similar functionality to the Flash API should be possible with window.print().
Shader, ShaderFilter, ShaderJob A Shader instance represents a Pixel Bender shader kernel in ActionScript. Pixel Bender implements image processing algorithms(filters or effects) in a hardware-independent manner. Pixel Bender uses a parallelized, XML-based graph language. Documentation Filters and shaders can be emulated in JS; SVG contains filtering options. WebGL allows programmable shaders. WebWorkers provide a more general-purpose paralleization method.
setClipboard Copies string data to the operation system clipboard. "getClipboard" is not allowed for security reasons. Firefox and WebKit presently provide internal APIs for clipboard use. The draggable attribute includes some language dealing with drag+drop events and the clipboard. Access to the clipboard is a tricky problem because of security risks surrounding its contents and the potential of data theft from an unaware user. HTML5 also has a proposed Undo API.
TextField and Text Layout Framework
TextField provides an API to print and input text with options for formatting, selection, and HTML text.
Text Layout Framework is a "next-gen" text implementation in Flash, containing new features for layout, UI controls, and internationalization.
Two issues here: Input and output. Output will come first.
In the past web developers have resorted to using Flash's embedded font support to achieve a unique typeface. Going forwards, CSS @font-face will allow embedded fonts, covering this deficiency. Common layouts are doable within existing CSS; Canvas and SVG are available as last-resort options if your text needs demand elaborate transformations or filters.
TextField's input support is known to be buggy, especially for non-English input; browser forms are more reliable input editors, but less visually flexible. A "fancy-text" input is probably emulatable from within SVG or Canvas.
The new features of Text Layout Framework are impressive. It should fix some of the existing issues with TextField, and the implementation is open-source, which bodes well for future inclusion in a standard.
RTMP, RTMFP, and Protected Streaming
The Real Time Messaging Protocol is a proprietary protocol for streaming audio, video and data. It has three variations: plain TCP using port 1935, RTMPT, which encapsulates itself in an HTTP request to traverse restrictive firewalls, and RTMPS, which uses HTTPS. RTMP allows streaming of multiple data channels, and includes remote procedure call methods. Adobe has multiple server implementations available for the RTMP series, the latest of which is Stratus.
The Real Time Messaging Flow Protocol is a UDP-based version of RTMP with additional peer-to-peer functionality, allowing users to connect directly with microphone and webcam streaming.
Protected Streaming is Adobe's term for the DRM solution provided by the RTMP series; Flash Media Server is able to encrypt media on-the-fly to prevent a variety of data theft attacks.
There is no exact equivalent to any of this. Some of it can be emulated in some fashion, but not necessarily with the same performance characteristics owing to differences in protocol capabilities between a low-level TCP/UDP implementation and what can be done with HTTP and Web Sockets. The main power of RTMP is that it is designed specifically for the Flash platform and works directly on its API(see NetStream). The peer-to-peer features of RTMFP are wholly unique.
HTML5/JS is unlikely to ever gain a spec for DRM, both because of the political implications of the technology, and because past DRM solutions, including Adobe's, have a track record of being quickly broken. The "analog loophole" will remain a viable option for the foreseeable future, if nothing else.

Implementation Strength

There's a second set of considerations to address beyond the API, of course, and that's in the overall performance/reliability/security considerations that color the implementations of each platform. I'll admit to some guesswork, some bias, and handwavy estimation going on here, especially where I try to extrapolate.
  • Flash has taken the initative to speed itself up, starting with Flash 9 and the move to Actionscript 3. This language upgrade involved a new VM that could optimize against static type annotations and manipulate ByteArrays(raw byte data). Flash 10 has added Vector(typed arrays) and a "fast ByteArray", used by the Alchemy C->AVM2 compiler and haXe's Memory API. These speedups have enabled some dramatic new uses of Flash for the coders sophisticated enough to make use of them. Flash can also parallelize through Pixel Bender and the Shader class. This approach does have some demonstrated utility for general computation.
JS/HTML5 equivalents: JS is not as fast....yet. Web Workers look like an elegant near-term parallelization solution. JS5 has no real equivalent to AS3's annotated types or ByteArray, but the "ECMAScript Harmony" project aims to continue pursuing those language features and others that were left over from the ECMA4 process. Google's Native Client effort should also deserve a mention, since it also attacks low-level performance, but in a far more comprehensive way than just memory manipulation. And, of course, general-case JS performance continues to improve dramatically.
  • Flash also has a reasonably fast software renderer....at least, if you are running on Windows. (It is abysmal to useless everywhere else, in my experience.) The 3D support introduced in Flash 10 is not a real solution for 3D acceleration, but the 2D, at least, seems to be more mature than the existing implementations of Canvas, and it is much more comprehensive for immediate use-cases, especially in terms of effects and filters.
JS/HTML5 equivalents: Canvas has been proof-of-concepted multiple times over as an acceptable 2D graphics solution for typical existing browser apps, including games. (The JS emulations of the Game Boy and NES are proof of soft real-time bitmap manipulation ability, Another World JS shows off flat-poly rendering, and this particle demo makes hefty use of alpha-blended gradients.) Now that efforts are starting to consolidate on WebGL, which is a very promising standard, it is possible that JS will leapfrog past Flash for high-performance browser graphics. Adobe probably faces a major engineering challenge in reconciling 3D against their existing graphics use-cases, as this has been an oft-requested feature for years running. Regardless, the strong set of built-in graphics features, optimized filters and effects, and tool support remain compelling reasons to use Flash.
  • Flash being Windows-centric with respect to graphics brings up another point, which is that Flash has historically overpromised on what it can do across platforms; major differences in both performance and behavior across platforms have brought a lot of ire down upon the plugin over the years, and it is not especially known for spec-correctness or stability either(although, again, on Windows, at least, it is stable most of the time and backwards compatible with most content). The Flash security model is also rather byzantine, between the multiple-SWF-namespaces, the meta-policy system, and some odd restrictions on how different media types may be loaded or streamed(for example: Video can be loaded remotely, or embedded in the SWF, but cannot be loaded from bytes, while Sound can be loaded from all sources.), and several major exploits have been found in the plugin regardless.
JS/HTML5 equivalents: Browsers, as a group, have had a better track record of correct behavior, backwards compatibility, security, and stability. The addition of cross-domain access-control headers to HTTP through this draft spec should provide similar functionality to the Flash cross-domain security model, but with a less "hackish" approach to implementation.

Conclusion

Because Flash has been able to quickly implement some "low-hanging fruit" performance features, it will stay ahead of the game for the moment. But the indications are that Flash's codebase has grown quite creaky and inflexible, and unless Adobe can summon the resources to overhaul the code, support all the platforms properly, and continue pushing out new features, the browsers are likely to resolve their current issues and pull ahead for most use-cases in just another year or two; games and other media-intensive apps will lag behind, out of sheer ecosystem inertia, but the provisions to support them are mostly visible on the horizon. And it is worth remembering that there's a fundamental conceptual difference between the browser "document/resource" orientation and the Flash "display/SWF namespace" orientation; the Flash model simplifies distribution of "apps as content" like games because it can bundle the content into one file, and I don't see a spec out there that provides that equivalent ability to the browser. This isn't a deal-breaker, but it makes it harder to support a portal-style business model with interchangable programmatic content.

Personally, I am hedging my bet by using haXe. I am happily using Flash for current projects, but the bulk of my code will remain portable. As well, haXe is an excellent "language upgrade" to both JS and Actionscript.
Posted by James Hofmann at 12:55 PM Comments
Edited on: Friday, May 21, 2010 2:17 PM
Categories: Articles

Saturday, January 16, 2010

Suggest Nothing

Firefox's "Awesome Bar" is touted as a major feature. Besides entering URLs, it lets you browse to recent sites and enter incomplete data to reach often-used sites without explicitly adding bookmarks.

 

I decided to turn it off, and I think it was a good decision.

My reasoning: When I had it on, I would simply rely on the top five or six sites I had listed for "something to do" any time I was at the computer, bored, and didn't know what to do. But, of course, the Internet is not five or six sites. It's millions.

I bookmark things that are useful to my immediate work. "Fun sites" I have to remember the URL and manually enter now, or laboriously browse through my history to find. It encourages both restraint and curiosity, because it changes the results of effort: instead of typing in the same old URL, I could try punching something new into Google and see what comes up. And more often than not, that's a more productive and valuable option than the various online echo chambers that I would naturally gravitate to.

Posted by James Hofmann at 12:55 PM Comments
Categories: Articles

Thursday, January 07, 2010

Level Up!

I wrote the music for this game.

Play the game

Listen to the soundtrack

Author's blog

Posted by James Hofmann at 8:24 AM Comments
Categories: Projects

Wednesday, January 06, 2010

Deep Sea Descent

A submarine action game for Flash.

The game is released and playable here.

I recorded a development log here.

Posted by James Hofmann at 6:59 AM Comments
Edited on: Thursday, May 13, 2010 7:27 PM
Categories: Projects

Resourceful Game Development

I use the term "resourceful" to indicate my perpetual discontent with the status quo of how games are made. I'm always looking for ways to put them together more quickly, more reliably, and with better results.

I also have a tendency to get into the nitty-gritty details and internalize every aspect of the game-making process by doing it - hence, "resourceful" also describes my use of a broad array of skills, my unwillingness to be typecast within one field alone.

Posted by James Hofmann at 1:48 AM Comments
Edited on: Wednesday, January 06, 2010 1:49 AM
Categories: Articles