Tuesday, December 23, 2008

From the cold snowy hill

A post before the end of 2008

Preface:
My mote-m experiment has effectively ended. Although it's still available in the store it has been superseded by team efforts from real artists looking to (and succeeding) at making it big on the app store. I wrote a postmortem about my experience about two months ago. I never published it because the iPhone App Store scene continues to change at such a rapid pace that anything written is immediately out-dated and irrelevant. In spite of that fact, I will share a few parts.

Introduction:
Let me say that these are my personal experiences and observations as an independent/first-time iTunes App Store game developer. I built Mote-M from the ground-up. I created the web site, wrote the code, created the art and answered everyone's kind emails. I consider Mote-M to be a success in it's original goals and a failure to achieve it's full potential. I might be wrong on any conclusions I make and apologise in advance for my poor grammar and inconsistent tense. You have been warned.

Development:
Mote Massacre, Mote-M for short, is a Tower Defense game in the style of the Desktop Tower Defense games. It started it's life in December of 2007 as a flash multiplayer game. When the iPhone SDK was announced the decision to port the game engine was made. After being approved by Apple in late-july (along with the rest of the non-special developers), I ported over the basic game and decided to launch the app as a fun toy-app for $0.99 in mid-August. The original goal was to build a fun game which would also pay for the developer registration. I really only expected maybe 20 people to buy the game. Since August I've watched the app store grow and evolve.

A Learning Experience:
Revelations I had as a complete n00b in the iTunes app store game business.

Quality of apps: The quality of apps and the relationship with an app's price and sales volume has been discussed elsewhere. It's still important to mention that with very low app prices a developer has to make money somewhere else or succeed in selling a very large volume.

Top sales lists DO matter: there are a set of passionate gamers who read the blogs and the forums and participate in the app store community but I'm willing to bet that the majority buy off the front page and the top paid apps lists. This is not surprising -- I probably wouldn't visit the forums and blogs if I weren't developing for the platform.

Rampant Piracy of Apps: The day you release your app for purchase is the same day anyone with a jailbroken phone can download your app for free. It's a fact of software -- you can't stop it, so don't try. The amount of time I spent trying to figure out the convoluted app DRM scheme could've been spent on developing a better app. To be fair the code signing stuff is pretty much a one time setup but from a goals standpoint it *just* fails.

The app store has huge potential: A developer can make a lot of money if they launch the app perfectly. Where perfectly in that sentence means: releasing an eye-catching, functional app which encourages impulse buys. Impulse buys fuel the app store right now. This may also be contributing to lower prices.

The Community:
This is one area where I was pleasantly surprised. The community of people who gathered around Mote-M are passionate and highly engaged. The e-mails I've received have been almost universally helpful and encouraging. Any developer not embracing their community is definitely losing valuable feedback.

Future Plans:
As I write this I have xcode open to a new super-secret non-game project for the mac. Once that project matures I'll return to the app store to see what sort of climate there is for indie game developers. Right now there seems to be a new flood of ports from existing games: SimCity (tm), TETRIS(r), Brothers In Arms(r), etc. Without users being able to demo apps they may stick to more well-known and bigger names instead of supporting software devs who create more original apps.



About gxjones.com:
Independent software developer Grant Jones started gxjones.com in late 2006. Grant grinds away creating another independent game with the experience he has gained from Mote Massacre and past applications he has written.

Saturday, October 11, 2008

Mote-M Base Source Code

Version v1.2 of Mote-M is complete so I took some time to bundle up the base 'framework' I used to create Mote-M. It's pretty unexciting but it takes care of the details which are necessary to setup an OpenGL ES rendering context on the iPhone.

Read further details here or just download it here (released under the BSD license).

Wednesday, September 10, 2008

Mote-M v1.2


My blog makes it look like I haven't done any thing for the past 2 months. This is simply untrue! I've been consumed with my Mote Massacre project which is currently available on the iTunes App store for $0.99.

Originally called 'Mote Massacre' I shortened the name to Mote-M because the icon on the iPod showed up as 'Mote...ascre' which doesn't sound quite right.
Mote-M is actually the evolution of the two-player tower defense death-match flash game I created back in December of 2007. Unfortunately I took down the server that was running the 2pTD flash game so it can't be played anymore; maybe someday it will come back -- or maybe Mote-M Multiplayer will be released?

The gxjones.com site has all the details on this game.

Thursday, July 10, 2008

ScatterBrain released


And now for something completely different...

ScatterBrain v1.0


Back in January I set out to create my own clone of a piece of software I thought was cool (a recurring theme I have). I call it ScatterBrain and it's a clone of the todo-list editor TaskPaper. Yes, I can hear the groans now, another todo-list program, yay!
It hasn't been in testing mode and it hasn't been in development mode either, it's just been sitting gathering dust for the past 4 months -- which is a waste. So I'm releasing it for free and without any sort of guarantee that it won't randomly crash or do anything else crazy.

Download

ScatterBrain v1.0 - OS X Leopard Only


If you do use it I'd love to hear from you @: grant -at- gxjones.com (Just know I cannot support this software unless I start charging for it. And if that's the case I recommend you go with the real thing: TaskPaper)

The Format:


It handles the typical taskpaper plaintext format:

Project:
- task

it also adds a group line which is identified by a '+' character and a section line which is identified by a '#':

#Some Section
+ A group

Clicking on the circle to the left of a task will mark is as "@done" as well as adding a @date tag with the current date.

Geeky details


Finally, if you absolutely need to change the color-scheme you can do it via tags within your text (I know that's uber geeky and not user friendly). Adding this to your ScatterBrain file results in project headers being black:

@pv_color_white(project-header-background-color,0.0,1.0)
@pv_color_white(project-header-gradient1-color,0.7,0.38)
@pv_color_white(project-header-gradient2-color,0.0,0.2)
@pv_color_white(project-color,1.0,0.75)


For reference, this is the default presentation context used:

@pv_color_rgb(group-color,0.0,0.5,0.0,1.0)
@pv_color_rgb(note-color,0,0,0,1.0)
@pv_color_white(background-color,1.0,1.0)
@pv_color_white(project-background-color,0.90,1.0)
@pv_color_white(project-header-background-color,0.85,1.0)
@pv_color_white(project-header-gradient1-color,0.86,0.65)
@pv_color_white(project-header-gradient2-color,0.66,0.3)
@pv_color_white(section-background-color,0.90,1.0)
@pv_font(project-font,user,24)
@pv_font(group-font,user,16)
@pv_color_white(project-color,0.25,1.0)



Development Status


I'd go back to it if there is interest. There were two killer features I was working on when I stopped development.

Known issues:


- large files will be fully reparsed and be very slow (so stick to smaller files); this was something I really wanted to address but never got around to it
- sometimes the formatting isn't updated
- formatting the background lags sometimes
- probably some memory leaks in there for good measure
- zero documentation - might be an issue for some people

Friday, July 4, 2008

FlashCanvas: 3 years too late?

So I guess I'm 3 years late to the canvas-emulation party:

  1. Manish Jethani mentions something about the canvas tag being used for a 3D game, John Dowdell from adobe responds in Nov. 2005

  2. Manish Jethani suggests a way to do a SWF-based Canvas on Dec 1st, 2005

  3. iecanvas from Emil A Eklund released December, 2005 (uses VML)

  4. excanvas from Google released March, 2006 (uses VML)

  5. AFLAX adds canvas emulation in March 2006


Overall, interest in this area seems to have died off - only recently with things like Processing.js and ContextFree.js has there been a renewed interested in backwards compatibility for the canvas tag.

side note: AFLAX uses the ExternalInterface just like FlashCanvas, so the performance observations would apply to AFLAX as well.

Thursday, July 3, 2008

FlashCanvas performance

Updated: see below.

The FlashCanvas experiment didn't really perform as well as I had hoped so I took a look to see where the slow down happens.
First, the speed of javascript execution was ruled out as the limiting factor. From the limited testing I did it is clear that javascript executes slower on internet explorer than ff or safari -- this is not news. Since flash is available on the platforms I can see they all perform roughly equivalent. This means that javascript execution is not the major performance bottleneck at this point because using a browsers native canvas element shows much better frame rates.

So this meant that the slowdown is occurring somewhere between the javascript call and the actual rendering to the flash MovieClip. I mocked up a dummy ping-pong page/flash file which simply calls a "ping" method from javascript into actionscript. The results revealed where the problem was:


note: JS2AS = JavaScript calling ActionScript; JS2AS2JS = Javascript calling ActionScript and ActionScript calling Javascript; os x and windows machines were physically different

Each call via the ExternalInterface is taking approximately 0.5 ms. Since the time it takes simply to call an actionscript method from javascript was now known I could then test to see if flash's rendering was taking up significant time: For the example1.htm page this means that it takes ~24 ms to render 20 individual lines. In Safari a call into actionscript is taking roughly 0.4 ms -- this is only the call time, it does not include the time to render anything. For example1.htm a single "particle" calls actionscript 3 times with the commands: [lineStyle,moveTo,lineTo]; each particle takes 1.2 ms in JS-to-AS calls; to take 1 second to render the frame ~833 particles need to be rendered. Changed the example code to render that many particles (and also time itself) results in:

(where time is in milliseconds)
So the time it takes for the javascript canvas wrapper, the javascript particle simulation and the actionscript code/line rendering is pretty much insignificant.

For comparison this is safari doing the same exact thing using it's native canvas element:

(where time is in milliseconds)

Next steps:

  • Investigate batching draw commands into an array to be passed only once into the flash renderer. Immediately this raises an issue about how the canvas API has been typically used: there is no explicit end of rendering or flush equivalent so the canvas-wrapper would never really know when drawing is finished. The most fine-grained control would be at the individual path level, which would result in nearly the same performance for something like the example1.htm file. Most graphics API have some sort of buffer flush either explicitly, like glFlush in opengl, or implicitly during a buffer swap.

  • Investigate other plugin technologies?




4-3-08 Update:
Batching commnads into an array does not eliminate the performance problem in ExternalInterface. FlashCanvas was changed to batch commands and then send them to flash with only one call via ExternalInterface. The result is only slightly faster (800 ms instead of 1 sec and a really slow 20 secs /frame in Internet Explorer 7). Since that part of flash is all closed I can't really take this any further -- my guess is that some sort of serialization/translation is taking all the time.

4-5-08 Update:
Try it at home: FlashCanvas 0.2. This includes the batched mode (which requires a call to context.fc_flush() when you want to send the commands to flash), see examples/example1_stress.htm to see how it works.

Tuesday, July 1, 2008

FlashCanvas


Download FlashCanvas 0.1
Released under the same Apache License as the exlorer canvas project.

What is FlashCanvas?


FlashCanvas is a canvas tag to flash bridge for browsers which do not support the canvas tag like Internet Explorer. FlashCanvas is an experiment to see if any performance improvement could be realized by using flash technology. The javascript code is a fork of the ExplorerCanvas project:
Firefox, Safari and Opera 9 support the canvas tag to allow 2D command-based drawing. ExplorerCanvas brings the same functionality to Internet Explorer. To use, web developers only need to include a single script tag in their existing web pages.


This FlashCanvas release only implements lines and fills. This is enough to support example1 and example2 from the ExplorerCanvas project.

FlashCanvas was put together in one day of hacking so it is pretty basic and has many bugs/quirks.

How does it work?


FlashCanvas is modeled after ExplorerCanvas which means it should be a drop-in module which provides canvas support. There are two main components combined together: the very basic FlashCanvas.swf flash file which compiles down to 688 bytes and the FlashCanvas.js wrapper/controller file. swfobject.js is used to embed flash into the page.

The FlashCanvas.js file implements a fake-canvas object and changes the existing canvas element into a a flash object (using swfobject.js). The javascript intercepts canvas commands and forwards them to the FlashCanvas.swf movie file using the ExternalInterface provided by the flash player. The flash movie clip then interprets the command and draws accordingly.

note: you must serve the files remotely. There exists a flash player bug which does not allow local connections to communication with actionscript from javascript using ExternalInterface even if permission is granted. (AS to JS does work with local connections however). A python script for running a SimpleHTTPServer instance is provided for testing purposes.


Why is ExplorerCanvas slow?


Although I'm not an expert on ExplorerCanvas, it is clearly not designed to do motion graphics. Almost everything ExplorerCanvas does is string manipulation to construct markup which is re-interpreted by Microsoft's Vector Markup Language. This method works sufficiently for static graphics but does not work well for motion graphics.

Does FlashCanvas provide better performance?


The short version: not really.
The longer version: All drawing commands are being forwarded from Javascript -> ExternalInterface (down into the browser) -> ActionScript -> Flash Drawing commands. This is a lot of overhead for drawing code. Doing something simple like a moveTo and lineTo would result in at a very minimum 8 separate levels of indirection.

FlashCanvas performance is discussed further here.

What other approaches could be taken?


Some other ideas:

  • Stop using broken browsers like internet explorer - We can dream...

  • A separate canvas plugin for internet explorer - this wouldn't be too difficult if the cairo graphics library were used as a starting point.

  • a more practical approach would be to abstract the canvas interface away by writing code targetted at the Processing language and then implement a processing flash interpreter (if one doesn't exist already)



How do I build FlashCanvas.swf?


The FlashCanvas.swf file is compiled using the MTASC and swfmill compilers.
Once those are installed run:
make

Tuesday, May 27, 2008

latest webkit build



Safari Version 3.1.1 (5525.18) vs. WebKit r34153

Both running the same UFWS development page which contains lots of canvas and javascript code (in a loop to animate).

Wednesday, May 21, 2008

Ep16


Episode #16 is release, getting closer to something resembling a game -- with an opponent and nifty spell graphics and all. Bumped up the update rate, which makes everything seem much smoother but also increase CPU load.
In a previous post I talked about anti-aliasing in firefox vs. safari. This turned out to be caused by the location the image was being drawn at was not an integer position. Which means the the pixels were being split across multiple pixels when rendered onto the canvas. The HTML5 specification does not really talk about this case and how it should be handled, maybe it should?

Monday, May 19, 2008

Ep15




Episode #15 is out, I completed the background on Friday, added a combat log on sat., on sunday I was rushed again to get something playable out. Players can now target things by clicking in the game and then perform actions via the buttons below the game. No spell animations yet and probably won't be until Friday. Once more of the framework is in place I'll have more time to finish update some actual gameplay with continuity between episodes, which is my ultimate goal. The flash version was nearing the point where it was strictly content development not tools and code development. CPU usage has jumped up almost double which is concerning will need to look into what is causing that.

Development shot showing the simplified collision map.

Friday, May 16, 2008

Ep14


Episode #14 introduces a newer - RPG style system that will eventually add player vs. computer combat. This means the player now has health and an available "energy" bar. The concept of failure has also been added via dying from low health points. This was the direction I have been planning to take the game.
The gameplay suffered again for this episode because I generally work on the background first and then work towards fitting the gameplay around the scene. In the end, because of the new additions, I simply ran out of time and had to push out whatever I had completed.

Wednesday, May 14, 2008

ufws canvas transition

My last flash version of UFWS (Episode #12) went up on Monday morning. The rest of Monday was spent transitioning all the actionscript code to javascript (and writing some notes down). Tuesday was spent finishing up and recoding some parts which basically meant cleaning up the original code a bit. The rest of the day was spent making the background and updating the three widget graphics used. I was a bit crunched for time to get some decent gameplay in unfortunately. Overall, though the transition was much smoother than I imagined; there are some things I still don't have figured out. Today Episode #13 is released and is now using the Canvas tag.

The rest of my notes:

  • There are some anti-aliasing differences between the Safari on OS X and Firefox on windows - The "game-over Congrats!" image has rendered text in a PNG displays on major blurrage in firefox for some reason, on OS X this text is crisp

  • no text rendering is a problem, will need to get creative when I want to display any signage (like popup menus I had in the previous flash episodes)

  • No native IE 7 canvas (or SVG) support continues to sadden me.

Monday, May 12, 2008

Canvas tag a Flash killer?

I'm mid-port of my Untitled FWS project to make use of the canvas tag. Here are some notes:

  • Since I'm cheap and haven't pirated Flash I use MTASC + swfmill to create my flash stuff which means my source is written in ActionScript version 2. Porting this code to javascript doesn't require a whole lot of changes.

  • Performance of the canvas tag isn't bad, considering the rendering loop is coded in an interpreted language. In my case I am creating an animated scene and the canvas tag is probably (don't know for sure) redrawing the whole thing every frame; Flash would limit redraws automagically based on what parts actually changed.

  • Firefox version 2.0.0.14 on OS X clearly has a very large memory leak dealing with the canvas' drawImage function that causes it to eventually crash after eating all available memory up. (This can be seen by simply setting an interval and continually drawing an image into a canvas element)Update:This appears to be just for OS X, the Windows version of Firefox 2.0.0.14 doesn't explode.

  • Firefox version 3 Beta 5 has plugged the leak and decreased CPU usage overall

  • Limited No text support in canvas elements in common browsers. however the HTML5 draft teases us with talk of rendering HTML and CSS into a canvas... THAT would be nice

  • No real IE support means this is basically not an option -- yes, there is an emulated canvas library from google but from the CAKE demo page it sounds like it doesn't work very well.

  • javascript intervals get called more regularly by Safari than their actionscript interval equivalents in my experience -- I think this is caused by some weird interaction between the flash plug-in and the safari browser

  • Blend modes are available and actually work without a huge performance penalty. this is better than current SVG blend mode support which relies on filters which aren't implemented (meaning there is only source-over fallback)

Saturday, April 19, 2008

visualizing edb's tag structure

This post deals with visualizing the internal storage format used by the elementaldb project.
I'm in the middle of rewriting the radix-tree storage engine in the elementaldb - while speed isn't a huge goal for the project, the newly rewritten proper crit-bit tree is performing inserts slower than the old version. So I thought it'd be interesting to use Graphviz to visualize the tag structure (and also the current radix tree) implementation. The tagm module was originally written for a mail client where messages could be tagged with a specific value. The generic requirements of the tag module were: it had to perform quick appends and it had to support a sort of hierarchical structure. The result is a linked-list implementation with nodes that can have an unlimited number of children. It's nothing really fancy but provides a convenient layer on which to write other data structures (b+tree, radix or anything else really).


This image shows the result of doing ten inserts of x = [0..9]. Each node is a tag value, in the current rtree implementation a tag node can potentially have a maximum of 256 children. These are sequentially searched (I know, I know) during a rtree put operation when a split branch point is reached. This means that storing binary data is very inefficient, hence the need to write a proper crit-bit implementation.


The image above shows the resulting structure when storing in a crit-bit structure. In this case a tag can have a maximum of 3 children: 0, 1, and data.

Wednesday, April 16, 2008

Untitled FWS


Untitled FWS is an episodic flash web strip that will be published every week on Monday, Wednesday and Friday.
My eventual idea is to actually have an entertaining story and goals to accomplish for each episode. So far the first published one on Monday contained only the very basic mechanics. The episode published today contains an actual goal and some objectives. For the next episodes I hope to continue this development trend.
The publishing schedule is very aggressive but it should force me to streamline the whole development process or fail miserably.

Maybe I'll give it a name soon too!

Saturday, April 12, 2008

Loveless


It's not very hard to see that Apple is the best at creating user interfaces. I've started using Amazon's MP3 Store and if you're a fan of DRM free music (and who isn't?) you should start using it too. The only problem is the interface to the store is simply awful. I've gotten so familiar with Apple's iTunes interface it's difficult to swallow a system where I can't see the most popular songs from an album or sort by most downloads or have any sort of interactive auto-complete search feature. When you go to check out for some reason Amazon's "One-Click" (tm) actually takes four clicks from the time I decide I want a song. After clicking four times for "one-click" the downloader pops-up to actually start the download process. The whole system needs to be put in the trash and Amazon's developer's should start over. The whole system feels very hackish and leaves a lot to be desired.
What can Amazon do? First, look at what Apple's done then try to achieve something similar but as a web solution. Retool the "MP3 Downloader" application to be a hidden plugin (similar to the Google gear's interface) where the web app. would communicate with the downloader portion via a javascript interface. This would make the whole interface seem more consistent (even though the plugin would still be required).
Apply lots of ajax magic to the page so that when I start typing "radi" I get "Radiohead" and a list of 5 other similar band and song names. Lists of songs should also be fast to load and NOT require the whole page to be (re)loaded. Make the song pagination system snappier so that browsing through songs feels snappier.
DRM-free music is worth the extra effort to go through the amazon system and as a new system goes it's not too bad but there is definitely quite a bit of room for improvement.

Thursday, April 3, 2008

php is teh funnays

So I'm squashing compiler warnings in my little project when I come across a warning when building in linux. It deals with pread/pwrite being implicitly defined. I check the man page, yes unistd is included but still the warning. So I google and find some PHP silliness:
Bug #32049 Implicit declaration of function pread - It's just a warning (ha!), note the date and files...
php4: files session handler broken on sparc - deals with the same files and almost 1 year earlier.

Warnings actually really do matter and they are normally pretty easy to fix. I know these were from a few years ago but the complete dismissive attitude of the bug response prompted me to post this.

Tuesday, April 1, 2008

2d line intersection

Playing around with line intersections again. There are two sites I found useful:
Intersection Point Of Two Lines
and N Tutorial's great site (I wish they had done more tutorials but they were probably busy doing N+).

To visualize it all I created a little cocoa app which displays two lines, the intersection point, a normal and a reflected ray from the intersection point:




Download Cocoa Project Source (requires Xcode dev tools): 2d_intersect.zip

Sunday, March 30, 2008

bug?

At least they got the correct units in there:

Saturday, March 22, 2008

the many ways we iterate dictionaries

It's interesting to see how each language reinvents a way to iterate a dictionary in an interpreted language (in no particular order):

Lua

for k,v in pairs(d) do
XXX(k,v)
end
Python

for k,v in d.iteritems():
XXX(k,v)

Ruby #1

d.each { |k,v| XXX(k,v) }
Ruby #2

d.each do |k,v|
XXX(k,v)
end
PHP

foreach ($d as $k => $v) {
XXX( $k, $v );
}
Javascript/ECMAScript/ActionScript

for( var k in d ) {
XXX( k, d[k] )
}



My point? No point.

Tuesday, March 18, 2008

elementaldb

I've put up my baby database engine I've been developing onto Google Code under the name elementaldb. elementaldb is a standalone network based document-oriented database engine which uses an SQL-like query language. It is released under the new BSD license. At this point it is really only an alpha release but I'd like to put it out for the community.

I have plans to publish more about the system architecture soon. To learn more check out the overview wiki.

Sunday, March 16, 2008

You forget so easy

ahh... must keep... blog alive...
I have no idea how regular (real) blog posters do it. Do they have any time to do actual work? Attempting to do one post a day and I run out of ideas after a week, while others can keep going for years! It really is impressive and I respect and enjoy their efforts.

Too busy to come up with a new post, I've been working on my new site redesign in between my new project (to be announced soon) and real pay the bills work (and my horrible WoW addiction which I can quit at any time... really). The new site will feature a homegrown discussion board system which will use the reCAPTCHA human verification system to let random human visitors leave comments without having to login or sign-up for yet another account.

The reCAPTCHA system really is pretty great. It shows two words and asks you to try to decipher them into a text-box, at which point my server sends your feeble attempts at optical character recognition to the recaptcha verification server. It all works relatively fast considering the load their servers must be under since they apparently are used by facebook, twitter, and stumbleupon according to wikipedia. Their API is simple and easy to understand although the diagram they use to convey how it works isn't so great. Still, I'm probably going to have user accounts because I personally don't want to keep entering these illegible words into a box before I post.

Friday, March 7, 2008

new XCode code-completion


I never figured out how the old-style xcode completion was supposed to work but I'm totally digging the new-style completion. It is more like the token field where something like "const char * key" is considered essentially one character. This makes replacing it with whatever you were going to put in there much easier. The update comes from the iPhone SDK which also includes some other things like llvm -- I don't remember seeing that as part of the leopard xcode install but it is definitely here now. I did a quick compile using: /Developer/usr/llvm-gcc-4.2/bin/llvm-gcc-4.2

Netflix Spotter

Here's a great new feature for netflix to add: A netflix user spotter who watches customers for movies they would most certainly hate and warn them before renting it. I don't think it'd be that hard to look at a user's past renting history and see that this movie is outside their normal movie realm. I imagine the notification would go something like this: "Hi Grant, I see you're trying to rent Across the Universe. Perhaps you didn't see that this is actually a musical that bastardizes the entire Beatles catalog into a lengthy, boring and poorly made movie. Would you still like to take the time to rent this?" To which I would respond: "No, I don't want to rent that anymore! Thanks, Netflix, for letting me know!"

Saturday, March 1, 2008

2/29 end of the week

Got some gxjones.com updates in development including discussion forms. My new pet project deals exclusively with the underlying back-end forum stuff... more news on that to come later. So updates to the site may be delayed, oh well -- it'll be worth it.

Of interest to me this week:
The Lemon parser Generator LALR parser generator used by SQLite
Pygments Python syntex highlighter... unfortunately I didn't have enough patience to get the output to play nice with this blog :(
ustr via anarchaia - agreed - this library still seems sort of heavy

Wednesday, February 27, 2008

2pTD - Development Part 3 (Dead Reckoner)


Continuing in the series describing how 2pTD was built:
My initial approach to unit movement was to send out complete individual unit paths. These were basically driving directions for the units by defining a set of waypoints. This worked for simple cases, however, units needed to start taking different directions based on newly placed towers on the field. The old "driving" directions didn't include these detours so they'd need to be retransmitted to the client. The result was it actually was using more bandwidth than a dead-reckoning system would. The image on the right shows the test application where the full path was being sent to the client. The lines show the path of the unit (the purple circles).


So what is dead reckoning?
Think of dead-reckoning as simply describing where a something has been in the past. It takes a while to grasp the concept of this delayed system but it is the key to most online environments. The idea is to describe retroactively where a unit has been and to simply replay a units movement slightly delayed. Game development sites have great resources dealing with this problem which can become quite involved if a robust system is required. For this particular project I went bare-bones minimum.

Basically, approximately every second for every unit the last position (1 second ago) and the current position of the unit is sent to the client. The client then linearly interpolates between the two points over a one second period. This works for most constant movement. It starts to get a little 'weird' when units start varying their speed, which can be seen when you place towers which change the speed of the unit. The result is the client shows more of an average of the units movement, when in reality the units movement may be more erratic.

Sunday, February 24, 2008

Itch Scratched

Matt Ball posts The Forgotten Delicious about his criticism of the delicious generation where apps are created with huge hype only to effectively stagnate and die.

He describes the typical programmer behavior of losing interest in a project once the "fun" part is done (scratching the "itch"). It happens to me, I'm sure it happens to most others as well. There are those programmers who find creating the code to be the enjoyable part. For them debugging, for example, just ends up being a chore and something to be avoided. Other things like documentation can also be categorized as unenjoyable but is often necessary.

From a business standpoint it could also be that the applications released weren't actually profitable and a new direction needed to be taken. The applications mentioned in the article are at the same time both incredibly niche and incredibly inexpensive.

In defense of the AppZapper creators, was there much that actually needed to be done? It's not as though the software offering was incomplete in functionality (I assume, I haven't actually tried AppZapper).

Saturday, February 23, 2008

JavaScript Core in Leopard (The Basics)

I just discovered the JavaScriptCore.framework which is new to Leopard. Creating a hello world or a similar very basic app is always the first step I take when try to learn some new programming API and the javascript framework was no exception for me. Here is an example of something entirely useless with no practical use: Defining a function using javascript which returns the sum of two numbers, then calling that javascript function from C through the JavaScriptCore.framework. Maybe I should've had it read the two numbers from stdin?

The getObjectProperty function was borrowed from another Apple sample. Remember you'll need to add the JavaScriptCore.framework to your application.

What happens in this example:

  • A javascript context is created and then the global object is obtained

  • The target javascript is converted from a NSString/CFStringRef to a JSStringRef

  • The javascript is evaluated which in this case defines the sum function.

  • The sum function is located in the global object and called with two arguments

  • The result of calling the function is converted to a number and then printed to stdout

  • javascript context is released



#import <JavaScriptCore/JavaScriptCore.h>

/* Convenience function for getting a property that is an object. */
static JSObjectRef getObjectProperty(JSContextRef ctx, JSObjectRef object, CFStringRef name)
{
JSStringRef nameJS = JSStringCreateWithCFString(name);
JSValueRef function = JSObjectGetProperty(ctx, object, nameJS, NULL);
JSStringRelease(nameJS);

if (!function || !JSValueIsObject(ctx, function))
return NULL;
return (JSObjectRef)function;
}
int main (int argc, const char * argv[])
{
JSGlobalContextRef g_context = JSGlobalContextCreate(NULL);
JSObjectRef jsGlobalObject = JSContextGetGlobalObject(g_context);
NSString *script = @"\
function sum(a,b) { return a+b; } \n\
";


JSStringRef scriptJS = JSStringCreateWithCFString((CFStringRef)script);
JSEvaluateScript(g_context, scriptJS, NULL, NULL, 0, NULL);
JSStringRelease(scriptJS);

JSObjectRef function = getObjectProperty(g_context, jsGlobalObject, CFSTR("sum"));
if(!function)
{
printf("no function called sum!\n");
}
else
{
JSValueRef arguments[] = { JSValueMakeNumber(g_context, 123.456 ), JSValueMakeNumber(g_context, 543.21 ) };
JSValueRef result = JSObjectCallAsFunction(g_context, function, NULL, 2, arguments, NULL);

printf("resulting number: %f", JSValueToNumber(g_context, result, NULL) );

}

JSGlobalContextRelease( g_context );
return 0;
}



Other resources:
2 JavaScriptCore samples from Apple (that I've found):
JSPong
JSInterpreter

Wednesday, February 20, 2008

MySQL for Python (MySQLdb)

Quick note about building the MySQL-Python module under OS X 10.5 w/ MySQL 5.0.51a:
When building there are some issues w/ the default setup so you need to change some files. The Red Elephants blog describes one approach, this way is more "proper" and makes less changes:

Step 1
install MySQL
Step 2
extract MySQL-python-1.2.2.tar.gz
Step 3
modify the file "site.cfg" uncomment the line starting with "#mysql_config" (line #13):
mysql_config = /usr/local/mysql/bin/mysql_config

Step 4
if you get errors about "error: duplicate ‘unsigned’" during compiling change the file _mysql.c at line 38 from:
#define uint unsigned int

to:
#include <sys/types.h>


Step 5
python setup.py build
sudo python setup.py install

A side note: defining uint explicitly like that isn't really best "practices" and causes problems. The mysql client library header will include sys/types.h anyway so we just include it a little bit earlier.

Monday, February 18, 2008

2pTD - Development Part 2 (A* Pathing)

Continuing in the series describing how 2pTD was built (Part 1):
When I set out to create this multiplayer game I knew the unit pathing system would be the most integral part of the whole system. Unit pathing is an algorithm which determines the path the unit will take from a source location to a destination. There are some great resources online for learning all about graph search algorithms. I chose the A* search algorithm for its simplicity.

There are two cases in the 2pTD game where pathing occurs:
1. When a tower is placed onto the field all units are checked to make sure that a path exists from where units currently are to where they are going.
2. When a new unit enters the field.

In retrospect the implementation of the system isn't exactly the greatest. Specifically, towers should take up a 2x2 area of the field instead of the 1x1 they currently do. This would make the paths of the units more interesting and would also greatly increase the placement options because the field size would be doubled.



Here is the pathing sandbox which was built for the purpose of developing the pathing algorithm and also to develop the networking system.

Friday, February 15, 2008

New Time Machine Icon in 10.5.2


Time Machine got its own status icon in the top menu bar in the new Leopard 10.5.2 update. Why is this icon always here? I would prefer it to only show up when it's doing a backup. At the very least get rid of the little analog clock in the middle of it, I sometimes try to read the time off it, or maybe set the time to when it last did a backup. I might be wrong but the time it shows is currently meaningless and confusing. At least I can disable the icon in the system preferences...
/steps-off-soapbox

Thursday, February 14, 2008

Usability and first impressions

So it's been a few hours after I submitted my 2pTD tower-d game to digg. Things I've learned so far:

  • 6 diggs after first submission, only ONE actual visit to the page (my guess is these are paid or volunteer moderators)

  • only 2 or 3 people actually played the game :(

  • because I did something stupid: I placed "New Game" above the "Single player" button -- the result is people get to the waiting for another player message and then leave (because no one else is playing!). Can't say I blame them!

  • those that did play were interested in apparently getting their score in the high scores gallery

  • python is a bit heavy even for this small use -- it never seems to release any memory. I chose to use one python process for all sessions because of the python startup time and resident memory size; I could startup individual processes for each session but would quickly run out of memory taking that approach (not to mention the startup time of python). What I'd really like is to be able to have an individual memory pool for each session but only have one python instance and just cleanup a sessions pool when completed. My implementation is probably to blame for any memory issues here.

  • Not that I expected it to be, but it wasn't a smash-hit... back to the drawing board.

  • If it did get lots of traffic the site could get killed by bandwidth usage. Weighing in at 1,883,094 bytes the SWF file is quite large. Then add in the bandwidth used by the actual game and it starts to become significant.

  • There is a general lack of interaction -- there should be chat capabilities or at the very least forums

NSData Base64 extension - revisited, again

Not exactly base-64 related but Apple does provide a limited set of crypto functions via a CommonCrypto API in 10.5+; start with the CCCryptor man pages. The advantage to this approach is the CommonCrypto routines are provided in the libSystem library not from OpenSSL (which reduces overall code size). A quick google search didn't find any frameworks or extensions built around this API (probably because it'd be trivial to implement).

Also semi-related, there is a Keychain framework which provides wrappers around the Common Data Security Architecture (CDSA) library in OS X.

Wednesday, February 13, 2008

NSData Base64 extension - revisited

Reading the cocoa-dev mailing list I saw some mention of a SSCrypto framework which provides a wrapper around OpenSSL. I just checked it out and compiled it but haven't put it to use yet. Licensed under a BSD-style license... If only I had seen this sooner. This wheel has been reinvented at least three times publicly, perhaps Apple should add something like this to NSData? :)

Tuesday, February 12, 2008

2pTD - Development Part 1

Here's my post to attempt to describe the technology behind my 2pTD game.
Basics:

  • One developer (Grant), MTASC + swfmill, 2 months to develop

  • Flash-based client communicates with servers using XML via XMLSocket connection.

  • dmtdsrv: Custom Python/C server utilizing libevent (base game engine)

  • 1 or more dmtdsrv servers acting as lobbies (where games start, high scores, current games)

  • 1 or more dmtdsrv servers acting as game session servers (where the actual game is simulated)

  • lighttpd web server

  • memcached which holds game and misc. state info


Details:
Once the flash client is loaded, they connect to the lobby which shows current games. When they select start single or multiple, players are assigned to a session ID, which is used to determine which session server they will be connecting to. Players are internally mapped to a session as well during the transition from the lobby to the game session -- this also prevents players from joining sessions which they weren't meant to be in. All communication is done via (not so compact) XML messages.

The client is intentionally as dumb as possible to avoid cheating and to allow the server to be the authority. All the tower specifics such as amount of damage and ranges are all determine server-side. This has the side-effect of making replays and real-time spectating of games possible without making massive changes to the flash client code. The flash client code was actually written completely in ActionScript using swfmill and MTASC to build.

Graphical resources were built using a combination of custom vector editors/animators and various graphics editors. Stay tuned for more info on these tools.

After every tower wave the game session state is sent to the memcache so it can be displayed in the lobby. Each session server is uniquely named and can handle many sessions. The system is designed to be able to handle high loads by starting many session daemons across many distributed servers -- although right now it's just 1 lobby and 1 game session.

Try playing 2pTD!

Part 2 will cover the unit pathing system, part 3 will cover the dead reckoning system.

Monday, February 11, 2008

TwirlVectorEdit

TwirlVectorEdit: The first step in creating a nice symmetric image that can be rotated (or neat effects can be applied to). You can download TwirlVectorEdit for your Mac running Leopard for free. It's a pretty specific tool (I don't even think of it as an application) so it is very rough around the edges. I'm almost positive illustrator does something like this but I don't own it so I had to make this. I used this to create a starting point for making rotating selection indicators (originally for the 2pTD game). I later ended up using the output of this program along with another custom tool to create animated "pulse" graphics which are currently use in the 2pTD game. The left pane contains the filled polygon you create with the mouse, the right pane shows the "twirled" resulting image. See the contained README for instructions on how to use it.

TwirlVectorEdit Application
TwirlVectorEdit Source (not much to it really!)


I used this tool as the starting point for making flash animations like these:

More to come on the tools I used to animate these.

Saturday, February 9, 2008

NSData Base64 extension

Encoding/decoding Base64 NSData seems to be a common problem that many Cocoa developers run into. I ended up writing my own category extension to the NSData -- but what I should have done is went to google and done a search for "NSData base64" where I would have found the exact code I was looking for.

Specifically: Dave Dribin's explaination of how to use the OpenSSL to do Base64 encoding/decoding. Incidentally using the OpenSSL library was the route I took as well -- yes, I am kicking myself for not taking the one second it takes to do a google search. I actually stumbled upon the base64 NSData Dave Dribin discusses at the beginning of his post and I was also put off by the lack of any licensing discussion.

On the other hand, I can justify reinventing the wheel because now the OpenSSL block I/O system isn't as mysterious as it once was. Only by actually implementing something with it can you really get how to use a library like this... and no, reading the documentation doesn't really help -- in fact, you'll probably get further reading the header files than the nearly non-existent online OpenSSL documentation. So with a grasp of the basics of the BIO system it's not such a far leap to add fancy encryption to NSData -- which is exactly what I had to do when I needed to encrypt and decrypt data.

Friday, January 18, 2008

2pTD - update 4

More updates, hooray! Added a third tab to the lobby called “High Scores” which is a neat display of past high scoring games. The bottom section shows a mini-preview and when clicked the field is shown as it would’ve been in game. The list is periodically updated (as of right now all games will go into the high score list). Still more improvements are in the works — things like sound and the ability to see the hit points of units as well as their resistance/speed values. The game as it stands right now is definitely fun so try it out now!

(copied from tumblr to blogger)

Monday, January 14, 2008

2pTD - update 3

2pTD updates: added single player which means you play against the computer (1pTD) — everything works the same way so it can be used to get a feel for the game. The computer AI itself is pretty basic at this point and sometimes it fails miserably against a real player. Also added a new class of towers: support towers and 3 new support towers. Support towers are short duration towers which provide benefits to other towers immediately surrounding them (right now it’s the 8 positions around the tower). The new towers are: resource reduction support tower, attack speed increase tower, and an attack speed decrease tower. These provide temporary buffs only a few seconds.

(copied from tumblr to blogger)