Monday, July 9, 2012

Develop with Attention to Details

As a software developer or a tester a critical asset is the ability to pay attention to small details. Regardless of what kind of project you're doing everything boils down to a collection of details that form your product. Most people love to brag about these details when showing off their work. Details like how their game can render the most realistic bloom effects of any game with no impact on framerate. But individual details aren't the whole story.

Attention to detail doesn't just mean being aware of every little nit-picky speck of your brilliant piece of artistry. Attention to detail means understanding how each detail relates to each other detail. Your program isn't a list of discrete bullet points. Your program is all of the interactions that the entire set of points taken as a whole.

You may remember me criticizing the design of testlink's XML RPC API a few blogs ago. For this example I'm going to use testlink again. This time I'm going after the user experience of creating a test plan.

The process of creating a test plan within testlink is meant to be made up of a specific sequence of steps:

  • Create any new test cases that are needed
  • Create the platforms the tests are to run on
  • Create the test plan
  • Assign the platforms to be tested to the test plan
  • Assign the test cases to be run to the test plan
  • You're done!

So, pretty straightforward. Here's what happens behind the curtains (minus a lot of irrelevant details, mainly a ton of housekeeping work with the table nodes_hierarchy):

  • Fill the database tables testcases, testsuites to create tree of test suites and cases
  • Fill the database table platforms
  • Fill the database table testplans
  • Fill a join table associating platforms with testplans
  • Fill a join table associating pairs of platforms and testcases with testplans

Still straightforward right? Except the UI of testlink doesn't require users to associate any platforms with a test plan before assigning test cases. This is reasonable since a lot of projects aren't multiplatform. Even if a project is multiplatform there's no obvious reason creating test cases first can't be done if mostly the same tests will run regardless of platform. Or at least based on the information presented by the UI.

This is what happens if test cases are associated first:

  • Fill the database tables testcases and testsuites
  • Fill the database table platforms
  • Fill the database table testplans
  • Fill a join table associating testcases with testplans
  • Fill a join table associating platforms with testplans

The problem here lies in the fact that the 2nd to last step does not associate test cases in the test plan with platforms since that information isn't available. In most cases the final step doesn't correct the error causing testlink to enter a messed up state that a regular user can't easily correct.

Now, in testlink's defence, there is an attempt to detect the problem condition but it requires the user to notice an easily ignored "critic" message and follow instructions provided on it. The user has to first add a single platform to the test plan, save, then add the others. Assuming the user follows the instructions they'll have their existing test cases paired up with one platform. All of the other platforms added to the test plan need to have their test cases flagged manually. For most real-world applications this is highly tedious.

My first change is to automatically associate test cases with any platforms added to the test plan. My assumption is that if you're targeting multiple platforms you want the majority of your features to work the same on most platforms with a few exceptions. Adding those exceptions would be a lot less tedious than adding everything.

Now there's a problem with my approach which isn't a problem in the original. What happens if someone makes a test plan with no platforms, runs it, then decides to port their software to multiple platforms, showing this by adding all the supported platforms to their test plan in one go?

Feel free to comment with what you think the logic error in my fix (there is one) is. Hint: the instructions provided when testlink detects the problem (add one platform which associates with existing test cases, then all others) won't run into the logic error in my approach.

Monday, June 11, 2012

Comments on Test Driven Development

It's always nice to spend a bit of time on nerd rage. I was considering a follow up to my meta-rant instead of this but I'll refrain from doing so. If anyone wishes to have a follow up on something specific feel free to leave a comment. But before doing so, yes I'm aware of the author's weak follow up article. Stating (paraphrasing) "the article was a joke, rebutting it shows you have no humor" is, in my opinion, a cop out. Either back up your statements or admit you made mistakes. On to the actual blog.

Test Driven Development is Cool

For those who are unaware test driven development (TDD for short) is a method for making software where you start by developing automated tests for your program then write your program to pass those tests. It's a process which I'm a big fan of. Since I've been using TDD for a while now I figured I could share a few comments from my experiences using TDD.

Test Driven Development Makes you Think

More specifically, TDD forces you to think about how the code you're writing will be used. This is especially useful when designing an API. A typical process begins with you designing an interface for whatever you're doing, then writing tests that use that interface. Remember my earlier article on web services? For a short summary; I discussed how you should try automate common work within an API to minimize the code required to do useful stuff with it. I used Testlink's XML RPC API as an example of a suboptimal API. It's not awful but using it results in a lot of code bloat and, as a result, poor performance.

In order to develop a good unit test you need to first think of how your API is going to be used. Each potential use for your API becomes a single test. It's very easy to come up with a few dozen tests for a relatively simple API. Doing this you'll see what parts of the API get re-used very quickly, i.e. boilerplate. And if you're developing a lot of tests I think you'll begin to see why I refer to such code as menial bullshit. And when your API makes you angry you'll begin to think of ways of making it easier to use.

Testing is Faster with TDD

Let's imagine you're making a game. Games have a huge variety of data that needs to be stored. Sure, the absolute quantity of data isn't all that big (relatively speaking, financial and analytics software have games beat by lightyears) but there is a lot of very different data. Some things such as sound samples, music, 3D models, 2D images and such have established formats others such as game levels, entities, AI code, saved games, recorded gameplay footage (for games that still do that, I miss old FPS games...) tend to vary from game to game. And all of that data needs code to handle loading it into the game and saving it from creation tools.

Using a conventional dev/test cycle would mean creating the code, integrating it into the game and tools and finally creating content using the tools before being able to do any effective testing of the code. And testing the resulting data means opening up the game and tools and manually using them to see that the data is correct. In-game testing in particular tends to require going through a lot of extra effort (i.e. starting the game, getting to a testing level, and setting up your test.) That's slow.

Using Test Driven methods means deciding what sort of data your file format will initially contain producing some mock sample then writing unit tests that use your game's file loader to load the file then verify the data they produce matches with what you expect. Each unit test works with a small amount of data to verify a specific part of your file loader works correctly. You can also easily create additional tests to check that different combinations of features in your file loader work correctly. Obviously there's the risk of combinatorial explosion but that's easy enough to avoid by limiting unit tests to covering features in isolation and obvious feature combinations. This will give you the most bang for your buck. Other tests can be added if bugs are discovered.

The speed advantage comes from eliminated testing overhead. When you need to test your code you simply run your unit tests. No need to run your asset creation tools, or the game or anything else. The only limit to the speed of your testing is the speed of your code. The best part, if you're skeptical about TDD, is you don't need to fully buy into TDD to do this. Just supplement your manual testing effort with unit tests. Even better, if you automate your product's build process then you can have your tests run automatically too by making your build tool run the tests right after a successful build finishes. Your entire dev team can then be notified about failing tests just like they would be for build breaks.

Test Driven Development has Problems

So far I've painted an extremely rosy picture of TDD. However, like all processes, it's not perfect. Far from it in fact. There are a good number of caveats about using TDD.

You Must Make Testable Code

Remember my comment on testing being made faster by TDD? This is only true if your code can easily be unit tested.

This is both good and bad. On one hand testable code tends to be very easy to work with since it doesn't have a lot of baggage that prevents it from being picked up and used. On the other hand, that baggage may be necessary for your code to perform optimally. Nine times out of ten however you're best off developing testable code. And if you think you think your case might just be that one you're probably wrong. Check first. This applies to all code regardless of whether you're making web applications or embedded software on a high performance real time OS

One tip: modularize. This means not only conventional modularization by keeping objects and procedures from being overly inter-dependent, but also moving parts of your project into libraries to make it easier to build tests without pulling in huge quantities of code. This pushes compile times downward for when you're testing and allows faster testing.

You Still need Conventional Manual Tests

Unit tests and other automated tests that are commonly produced by test driven development are great for verifying software interfaces and behavior. However, unless you're producing automation tools, you're not going to find anywhere near the full set of issues.

For example, you can't test that your software's workflow fits your users' expectations. Automated tests can't verify that a game is fun. Artistic merit is impossible to judge with software alone. The most bizarre interoperability issues typically only crop up during general use of your software and require manual testing. For a completely contrived example on a smartphone, when playing music on a media player, visiting a flash site on one browser tab and visiting an HTML5 site on another and using the GPS causes the phone to crash at random. But only for certain commuters in the big city during rush hour.

Unless your test developers are completely evil and have a lot of time and money you're not going to get these kinds of things happening in your automated test. Particularly if you follow conventional best practices for unit tests which tests stuff in isolation. The only way you're going to find these issues is if you have manual testing reflective of how your real users would use your product.

Test driven development works as an excellent complement to ad hoc manual testing. Without TDD you're unlikely to have the tester time available to do the kinds of heavy exploratory testing that would find issues like our phone crash during a morning commute and without skilled testers doing that sort of testing you're unlikely to get the critical information need to fix the issue.

Wednesday, May 30, 2012

The Worst Anti-Java Rant Ever Written

Well, okay. I exaggerate, since this is the Internet there is always something worse. But I'm calling it the worst ever since I'm a jerk. Still; this is the dumbest anti-Java rant I have ever read. Frankly it's so bad it makes me question my position of being a Java hater myself. But then I think about AWT, Swing and GregorianCalendar and I get better

Since I've already made it clear than I'm a jerk I'm going to look at the guy's points and take them apart. Java, or at least Sun/Oracle's Java, is bad. There's no question about that. But if you're going to tear Java a new one try to find points that can't be validly taken apart or dismissed out of hand by a true-believer... or a hater that's pissed off at being potentially associated with such dreck. Without further ado, let's get this trainwreck a-rollin'

1) Java has a compiler

Ruby does not. That's great! Fuck compilers and their false sense of security. Too often is bad code checked in or even deployed to production, simply because it compiled. No such luxury in the Ruby world.

Seriously. That is your starting point. You know, most people tend to lead off with something big and obviously wrong with the language. How about the stereotypical FactoryPatternStrategyVisitorDesignPatternFactory classes that give haters so much ammo yet every Java-head is supposedly head-over-heals in love with. Or how generics suck in Java and took way too fucking long to get implemented. Or at least mention how compilers slow down your code-test-commit cycle by inserting an extra step. Fuck no, that would require something resembling deductive reasoning.

Oh, and believe me. I have seen more than my fair share of terrible Python, PHP, Ruby and Perl code in my few years of coding professionally. Not having a compiler does nothing to make a bozo's code magically better. All it means is that they'll produce shit code that is a nightmare to read that by sheer luck passes your unit tests. If they exist in the first place and if they even bothered running them. They certainly don't bother compiling before committing often enough! Guess what? Having a compiler vs not having a compiler will make no difference if the problem exists between keyboard and chair.

You shouldn't be making your code harder to check for stupid errors. Especially if it's to an attempt make fools less foolish. There lies madness. Remember the maxim "Nothing is foolproof to a sufficiently talented fool." A better solution is to keep fools away from your project or rely on the human element of training your fools to be less foolish. Nothing is stopping you from having a quarantine branch in your project; Or having a list of restricted contributers.

Oh! Just for a bit of icing on the cake. Ruby can be compiled and often is (except in the default Ruby implementation.) Why can it be compiled? For the main reason compilers existed in the first fucking place. To convert human readable, but sub-optimal code into high-performance machine readable code. And what is one of the most popular things to compile ruby to? Fucking. Java. Bytecode.

2) Java framework authors are not application developers

Prime example: the JBoss guys, who are paid handsomely to work on framework code all day. Sure, they're exposed to real application development, but they don't do it themselves. As a result, none of their handiwork is extracted from actual working codebases. Which is a shame, because if it were extracted from actual working codebases then it might actually not suck. All Rails core and plugin contributors of significance are fulltime application developers, starting at the top with DHH himself and the Rails core team. Day in and day out we write applications in Ruby and extract the useful bits out for other Rails developers to make use of via gems and plugins.

This is about the closest our wonderful author gets to a potentially valid point. I can't make any comments on JBoss since I avoid Java like the plague but given this guy's track record I'm disinclined to give him the benefit of the doubt. But since I relish the opportunity to bash Java: let's look at WORA, a pillar of Java's language philosophy. Sounds wonderful on paper. Collapses like a house of cards as soon as you try to apply it to real hardware. Joel on Software can explain the cause. (article not related to WORA directly but I'm assuming you're smart enough to see the connection!)

Contrived example time! Let's go back in time to the heady days of the mid-late nineties when Java was all the rage. Let's imagine we're making a wonderful new GUI application with Java. So you get it working on your awesome top-of-the-line dev machine. Now it's time to test... and your user tells you that it dies. Why? Your user heard of this awesome thing called J2ME, Java on a cellphone. It's Java and Java is WORA so it should work. Right? Guess what, a shitty nineties era cellphone isn't going to handle a GUI application that is made for desktop.

Okay that's extreme to the point of silliness but the philosophy is Write Once Run Anywhere not Write Once Per Platform /trollface. Let's go with a more likely case. You're using some nice portable library but not every feature you're using in some library is supported on your users' hardware like it is on yours. Obviously you want to take advantage of the features when available. So what now? Hello special cases and hello code bloat. Or the alternative you're using the lowest common denominator in your code so your lunch is being eaten on high end hardware by people who didn't drink the WORA koolaid. Then your product dies because high end systems become low end systems within a year or less. But I digress. I'm here to bash someone else's anti-Java rant. Not write my own.

3) Most Java Programmers are Morons

And there goes any possible validity point 2 might have had. Oops.

So how does this detract from point 2? Well, let's imagine a world where most people are stupid. One solution is to have an omniscient council of vagueness dictate the process which uses the framework built from the lofty heights of their ivory tower. Obviously the whole thing fails horribly on encountering the nuances of real work. Exactly what point 2 says. So instead we have the masses build a framework of useful tools based on practical lessons learned in the trenches. Well look what point 3 says. The masses are idiots. So that won't work either. You just end up with a mess of unusable broken garbage. At least according to our buddy's assertions. So let's get the smart people together to make a framework from their ivory tower...

The obvious rebuttal is that the circular logic above actually bolsters point 2. Guess what, if you go that way you've got Argumentum ad Hominem It's the classic "You're stupid therefore your argument is false." Don't try that rebuttal. This whole point is also an argument by assertion Yes, most Java programmers are stupid. Guess what most programmers are stupid full stop. In fact most people are stupid.

That especially includes the author of this tripe for making the wonderful non-argument I've spent the last two paragraphs deconstructing.

Oh, and I spared you the meat of his argument since it amounts to "all the cool programmers are using stuff that isn't Java therefore Java programmers are stupid." I'll be attacking that one further down since it rapidly becomes a theme in our buddy's later points... And you wonder why I'm insulted this idiot is a representative of Java haters online.

4) Java is too Fragmented

Java has a gazillion open-source frameworks and they all suck ass. So what do Java teams do to cope? Cobble those suck-ass frameworks together into custom layered homebrews that are nothing more than exponential explosions of sheer, despicable suck-assiness.

In stark contrast, in the Ruby world, we only have Rails. All Rails projects are structured the same way and follow the same conventions. That's a good thing, since it means that Rails developers can move across projects with relative ease.

And the Rails fanboy reveals himself. What if I don't want to make a web application clever writer? What then? What the holy fuck then asshole? Java does have a lot of frameworks. Guess what? All open source languages have piles upon piles of frameworks, tools and random shit out there produced by the community. Good ones, like Rails, will be picked up by the community and become de facto standards. Let's see, how many authentication methods exist for Rails again? RESTful Authentication, AuthLogic, mod_auth_sspi, OpenID authentication and on and on. Fragmentation is a fact of life for Open Source. Don't like it? Join the thousands of developers working with Microsoft and Apple's tools instead. You might like it.

Oh, and let's not forget. Almost every single open source framework out there exists because some developer got annoyed with existing frameworks and made their own letting their experience guide them. Your precious Rails is yet another framework in the great morass that is the world of open source web application development frameworks. DHH saw a problem, wasn't happy with existing solutions, and made his own. And it's a damn good solution but he isn't exactly a dictator forcing the Ruby and Rails communities into the One True Methodology. The community embraced Rails of its own collective volition. It wasn't forced to do so.

5) Java is Too Slow

Ha. This is one of my favorite reasons, for the bloody irony of it. You see, Java isn't actually slow. Everyone reading this knows that it got plenty fast over the last five years or so. Nevertheless, 90% of the world that knows of Java thinks that it is slow, because of its association with crappy slow Java applets and crappy slow Java loading screens on mobile devices.

Ruby *is* slow, compared to Java, and yet it is fast enough. Amazing, isn't it.

Let's translate. "People think Java is slow even though it isn't; at least for well designed applications. So let's avoid using it because people will be prejudiced against applications listed as using Java." Guess what? You don't have to shove it in people's faces that you're using Java. Next!

6) Java doesn't have blocks and closures

It's a miracle. We finally have something that isn't a bare assertion and is a valid point. Functions as first class objects, anonymous functions and closures are extremely powerful tools for building useful algorithms with a minimal amount of code. Java isn't as expressive as alternatives such as C#, Ruby, Lisp and Python. This can lead to the stereotypical bloat of the pathologically bad Java application. However being less expressive than other languages doesn't automatically make a language bad. C for example is as good as it ever was for its purpose.

This is the kind of point you should tack on after all your hard-hitting points. The blub programmer isn't going to care about things they haven't experienced like closures. What they would care about are actual annoyances like how AWT/Swing applications are ugly crap in comparison to Qt, native or web-based alternatives. Or how the built in date/time libraries are a pain in the ass to use. In fact that's an ongoing theme of this essay so far. It's bare assertions followed by smug self-satisfaction at not using Java.

7) Java has Integrated Development Environments (IDEs)

Closely related to Reason #3 Most Java Programmers are morons. Everyone knows that the best programmers use Vim and Emacs. Then come the TextMate users. If you need to use an IDE then you suck, period.

I sincerely hope this point is a joke. This is something that massively pisses me off about certain Open Source advocates. Because tools might make life easier for a moron and lower the barrier to entry for programming newbs everyone must use the worst, most obsolete, tools possible. Not everyone does this. Our author's precious DHH (all disrespect aimed at the blog author, not DHH, nothing but mad props for him :) wasn't satisfied with the tools that existed and made something that makes web development easy and fun. I don't see the author bashing Rails despite the fact it makes development easier just like any other good tool.

No, a good developer doesn't need tools to make their life easier. But a good developer is also a lazy, easily annoyed, impatient, stubborn asshole. Guess what? I'd rather be solving interesting problems with my programs than dealing with breaks due to typos and other silly mistakes. An IDE with autocomplete and syntax checking built in lets me avoid that menial bullshit and move on with my life. Let's throw in a line debugger with watches and stack monitoring, code folding for faster reading, and shortcuts for kicking off your build tools, unit tests, program binaries etc. all accessible within your text editor and you've pretty much got an IDE.

How about another comparison? Would you say I Wanna Be The Guy is a better game than Super Mario Bros 3? It's certainly a harder game. But it crashes, the artwork is crappy and about half the deaths are bullshit surprise deaths that are unavoidable until you memorize the game. And it fucking crashes. Last I checked the consensus is that SMB3 is the main contender for best platformer evar and IWBTG is something that's for laughing at hapless Let's Players. Confession: I love playing through I Wanna Be The Guy. The game is a parody of the bullshit difficulty of many NES era games and modern romhacks. And it is glorious. Without the parody context it's not so great however. YMMV

8) Java has good debugging support

Java has great and powerful debugging (which is very necessary since most Java code sucks so much ass). Ruby has ridiculously pitiful debugging support, which means our code actually needs to be well-tested and readable.

See above. Unit tests, system tests, integration tests, static analysis *cough*includingcompilers*cough* and every other non-debugger tool under the fucking sun won't catch everything. You will have bugs. It's nice to have a useful tool for finding those obscure corner cases that the tests didn't catch. I have more important things to do with my time than tediously inserting trace code into my programs in some vain attempt to emulate what a proper debugger provides out of the fucking box. Next.
9) Java Makes a Lot of Money for Vendors

This is potentially the most subtle of all of the reasons on the list. Basically, the integrity of most anything having to do with Java is corrupted by the way that it is inextricably linked to a web of intrigue involving money, big vendors and bullshit enterprise politics and pandering. Ruby doesn't make major money for anyone except Pragmatic Dave.

Hoo boy; it's another random assertion pretending to be an argument.

This reminds me of an anti-Rails rant I read today. It's more interesting due to DHH's rebuttal than its own content but a relevant point went like this: something something shitty documentation something something selling books something.

Anything that gains popularity will make money for someone. Often many someones. Books, consulting, evangelizing, training and, of course, the resulting products all inject money into a language's or framework's ecosystem. I'm pretty sure O'Reilly, Twitter, Hulu, Yellow Pages, 37signals et al didn't use (or create, or write about) Rails for the purpose of losing money. Either way, anyone who has a stake in a particular framework, regardless of the reason, will want to influence it.

Peoples' desire to influence other people will mean politics. Last I checked most open source frameworks have some level of politics and politicking to deal with. Politics that relates to programmers' egos and personal beliefs in The Right Thing. Look at the flamewar over Javascript's implicit semicolons. And how many forks of various major projects were made specifically because someone didn't like some particular nuance? Funpidgin ring any bells? Last I checked none of the people involved were faceless corporate entities. Just stubborn egotistical asshole programmers. Hell, look at the most infamous anti-rails rant on the Internet. Most of the anger is directed specifically at the politics of the community. This sort of shit happens. Especially in open source. Get over it.

10) Java does not have DHH

In the words of my inimitable friend Zed Shaw, "If DHH ain't doing it, you don't fucking do it. (Seems every time some clever fellow gets into trouble it's because of that.)"

Who does Java have? Jimmy Gosling? Hahahahahahahaha...

Sigh. You just had to go there. You just had to go with the "my visionary is cooler than your visionary" argument. You just had to go with the most childish, insolent, smug, short-sighted, juvenile, peabrained, puerile, putrid, pointless, pissy, motherfucking worthless shitstain of an argument possible. Do you hear people advocating Python solely on the basis that it has Guido van Rossum (aka BDFL) at the helm? Not too often. People advocate it because of his vision, stupid. Why don't you speak of what DHH contributes to the community? How he is actually able to create a useful tool and eloquently defend his decisions for Rails against complaints. Like he does here. That is how you get people behind you. That is how you make sure everything created in your ecosystem closely follows your vision.

But noooooo. You just had to resort to the fucking mocking. Your point is presented stupidly. How about this? How about you try attacking Sun or Jimmy Gosling for specific missteps in how they've managed their community and caused Java to suffer versus how DHH succeeded? Maybe then I wouldn't have to call you a fucking douche. You fucking douche!

Closing Words

Well. Fuck. That was exhausting. And writing this bitchfest took a bit of effort too.

I appreciate the sentiment of the article in discouraging the use of Java. The sooner Java dies, the better. The poor quality of the article I've ranted about does nothing to diminish the shortcomings of Java or the superiority of any alternatives. I wish the article did more to highlight hard facts about what makes Java bad instead of sucking up to DHH and poorly advocating Rails.

In the words of Jon Stewart You're not helping

Tuesday, May 22, 2012

Making of an Arcade Frontend - Part 4

Previous entries:
Prologue
Part 1
Part 2
Part 3

Last part I talked about some boring math used to create a pretty rotating list of games. This time I'll be showing some more code. The goal today will be to have a smooth transition between game titles on the list.

So, here's what we're starting with. The code to position and draw the rotating games menu. No special effects and no transitions, the selected game is in the middle. Don't forget to read the comments since they cover most of the "clever" parts of the function.

# NOTE: These functions are members of a class.
# I've omitted most of it since it's not relevant to the example


def _selectorPos( self, i ):
    # Here's the math that was discussed in the previous blog!
    x = self.radius * math.sin( float( i ) * 3.14159 / float( len( self.selectors ) - 1 ) )
    y = (i - self.selectedIndex) * self.spacing
    return (x, y)

def Draw( self, screen ):
    # Draw the top half of the menu
    for i in range( self.selectedIndex ):
        pos = add(self.center, self._selectorPos( i ))
        # Rect is a tuple of vectors
        # The first is the top left, the second is the bottom right
        rect = (add(self.pos, neg(self.unselectedSize)), add(self.pos, self.unselectedSize))
        self.selectors[i].Draw( screen, rect )

    # Draw the bottom half of the menu
    # Reverse order so items closer to the center are drawn on top of ones further away
    for i in range( len( self.selectors ) - 1, self.selectedIndex, -1 ):
        pos = add(self.center, self._selectorPos( i ))
        rect = (add(self.pos, neg(self.unselectedSize)), add(self.pos, self.unselectedSize))
        self.selectors[i].Draw( screen, rect )

    # Draw the currently selected item, last so it's on top
    pos = add(self.center, self._selectorPos( selectedIndex ))
    rect = (add(pos, neg(selectedSize)), add(pos, selectedSize))
    self.selectors[selectedIndex].Draw( screen, rect )

Notice I've hidden some math away in functions. This makes the purpose of this code easier to discern since it's not buried in a ton of repetitive arithmetic. The functions add and neg are 2D vector addition and negation. Since Python provides tuples as a built in type I used them to represent vectors. This can be bad for performance because every time I do math on vectors a new vector gets created. That means lots of garbage objects for the garbage collector to clean up. Optimization is as easy as replacing tuples with a mutable type and would have no effect on this code since all the real work is hidden in functions. I haven't done so here because it hasn't been an issue.

So if we use this code to display a menu it will display a list of games in a nice circle with the selected game in the middle at one size, and everything else above and below it at a different size. Items further from the center are displayed behind ones closer. This allows items to overlap if I want and still look reasonably good.

Now, if you remember the skeleton I showed in Part 2, I had some code for responding to input. Now it's time to update it to allow the selected game to change. New stuff is in italics

# the main loop!
frameStart = time.clock()
time.sleep( 0.01 ) # XXX: don't want a frame time of 0 when starting
while True:
    frameTime = time.clock() - frameStart
    frameStart = time.clock()
        
    for event in pygame.event.get():
        if event.type == pygame.QUIT or (event.type == KEYDOWN and event.key == pygame.K_F12):
            sys.exit()
        elif event.type == KEYDOWN:
            if not selector.InTransition():
                if event.key == pygame.K_DOWN:
                    selector.Next()
                elif event.key == pygame.K_UP:
                    selector.Previous()
        
    selector.Update(frameTime)
    selector.Draw(screen)
    pygame.display.flip()
    screen.fill( (0,0,0) )

Nothing too surprising I hope! The only really special code here is right after the new KEYDOWN check. The checks simply make sure the person using the launcher can't change the selected game while the selection is in the process of changing. The code for selector.Next and selector.Previous is about the same. It sets a flag in the selector object to make it change selections. The work of changing selections happens in Update and Draw. Update maintains a timer which lasts for about 1/5th of a second. It also stops the timer and changes the selected game once the timer expires. Draw handles positioning everything based on the value of the timer. If no transition is happening the drawing code I showed you at the top is run. Otherwise some different code runs...

alpha = self.timer / self.transitionTime

# Draw the top half of the menu
for i in range( self.selectedIndex ):
    pos = add(self.centre, blend(self._selectorPos( i ), self._selectorPos( i - 1 ), alpha))
    rect = (add(pos, neg(self.unselectedSize)), add(pos, self.unselectedSize))
    self.selectors[i].Draw( screen, rect )

# Draw the bottom half of the menu
for i in range( len( self.selectors ) - 1, self.selectedIndex - 1, -1 ):
    pos = add(self.centre, blend(self._selectorPos( i ), self._selectorPos( i - 1 ), alpha))
    rect = (add(pos, neg(self.unselectedSize)), add(pos, self.unselectedSize))
    self.selectors[i].Draw( screen, rect )

# Draw the old selection
pos = add(self.centre, blend(self._selectorPos( self.selectedIndex ), self._selectorPos( self.selectedIndex - 1 ), alpha))
rect = (add(pos, neg(blend(self.selectedSize, self.unselectedSize, alpha))), add(pos, blend(self.selectedSize, self.unselectedSize, alpha)))
self.selectors[self.selectedIndex].Draw( screen, rect )

# Draw the new selection
pos = add(self.centre, blend(self._selectorPos( self.selectedIndex + 1 ), self._selectorPos( self.selectedIndex ), alpha))
rect = (add(pos, neg(blend(self.unselectedSize, self.selectedSize, alpha))), add(pos, blend(self.unselectedSize, self.selectedSize, alpha)))
self.selectors[self.selectedIndex + 1].Draw( screen, rect )

There's quite a bit of new stuff here. There are a bunch of calls to a new function "blend." What it does is create a new position that's "alpha" percent between two positions. 0% is at the first position, 100% is at the second position, 50% is right between the two. There are three variations on how blend is used.

blend(self._selectorPos( i ), self._selectorPos( i - 1 ), alpha)
This makes the items rotate upward. The top item goes offscreen and disappears, the item below the selection becomes the selected item and a new item slides onscreen from the bottom.
blend(self.selectedSize, self.unselectedSize, alpha)
blend(self.unselectedSize, self.selectedSize, alpha)
These make the old selection go from the size it has when selected to the size of everything else and the new selection go to its selected size.

Tuesday, May 15, 2012

A Mini-rant on Documentation

If you're releasing a non-trivial API... for example a YAML parser for .NET. Please remember to document the most commonly used functions so it's easy to understand how they relate. Whatever you do, don't write undocumentation.

What is undocumentation? Well, if you didn't follow the link, it's something that looks like documentation but is devoid of anything that makes it useful documentation. Like this:

// Default constructor for the Node object
Node::Node()
{
   // do stuff
}

This documentation says nothing that the code doesn't already say. Writing documentation sucks. I know. But in this case not writing documentation is an equally meaningful alternative. And it saves everyone time. Particularly me since I now know I have to search for code samples or troll message boards and Stack Overflow to get the information I want.

Rant over.

If you insist on taking the time writing documentation make sure whatever you write isn't stuff made obvious in your method signatures. To mangle DC Comics for a second; a constructor is. You don't need to tell me it's a constructor. Tell me what isn't shown in the code. Tell me when I might use it. Tell me how I can cause it to fail. Tell me why I'd need it in the first place. Every piece of your documentation should provide a hint about how you intend your functions to work together. Preferably, these hints should be about as subtle as a pile driver.

Ruby on Rails and the Standard Python Library are both generally good examples of documentation. The parts of Ruby itself that I have used were also generally well documented. For all its faults the parts of the Java library I have used were well documented. The issue there was more the godawful design of what I had to work with.

Programmers are lazy and have a low tolerance for unnecessary work. You know best how your API should be used. You should let your users know what you know. A nice side-effect is, usually, more, and happier, users.

As an aside. The YAML parser I mentioned above otherwise looks good. I might make another, less harsh, post about it earlier. I want to use it. But it's taking longer to grok than I'd like. The result was this rant.

Friday, March 23, 2012

A Look at Web Service API Design

Lately I've been spending some time working with the open source test tracking tool testlink For tracking manual testing efforts and linking tests to software requirements and other SDLC essentials it is a very nice tool. However its API leaves something to be desired. So today's topic is designing a usable API.

The purpose of the API is to allow automated testing to be tracked and reported in testlink much like manual tests are. In addition it could be used to provide a hook into an automated build system so testers are aware of new work asap. Testlink tracks test sets in two ways. First is test suites. These represent your entire pool of available tests. Second is test plans. Test plans represent some set of tests you need executed by your testers or your automation system and are taken from the test suites. Test plans are executed against builds of your software on one or more platforms (eg windows and Mac)

So with that background we can come up with some ideas for what we need in an API and compare with what testlink actually provides. Let's assume that you already have a working automated build and test system but need better reporting because there is too much data to work with without a tool to help. Since this system is already running and more or less fully automated it's pretty unlikely that anyone would be willing to manually add anything major to the database such as test case information and such.

Given that... Here's what I would expect a reasonable API to provide.
  • Create a test case within a suite which may be part of another suite. Also create the suites if they don't exist.
  • Create a test plan containing a list of pre-created test cases. Update as appropriate.
  • Assign results to tests in a test plan run against a build for a platform.
  • Create a build and associate it with a test plan (or several)

Not too much eh? The nice thing is that this hides a great deal of complexity which is handled manually in normal testing. Hiding complexity is always a major goal for a good API. Another advantage is that this concept keeps requests larger and less frequent. When dealing with distributed systems you pay a fixed time cost for every request made. That cost goes into negotiating connections, security, protocol headers and so on. So, fewer requests to a web API is usually faster.

Sadly testlink makes a very easy mistake in its API design. The developer chose to expose every simple step used in creating test plans and recording results except for a few cases where the API is more difficult to use than necessary. The list of actions look something like this

  • Create a single test suite optionally belonging to another (bad stuff happens if the suite already exists)
  • Create a test case belonging to a previously created test suite (ditto)
  • Create a test plan
  • Create a build
  • Create a platform
  • Assign a platform to a test plan
  • Assign a test case to a test plan
  • Record a result for a test case in a test plan run against a build for a platform
  • Yadda Yadda blah blah.

So. A user of this API needs to jump through the same hoops as they would when doing things manually. While this saves mental effort in designing the API you end up paying for it every time you have to write code to check that a suite (and the suites it's contained in) exists and create everything that's missing via a dozen or so function calls. Not fun.

Think of an API as a time investment. The more menial bullshit your API does for you the less you have to do when using it.

One last example. A test case in testlink has a number of properties such as its author, a description and the steps that are taken to carry out the test. When you use the testlink API you provide a key (a bunch of gibbrish) to get access. The key is unique to you. Now when calling an API to create a test case using your key the API ought to be smart enough to assume you are the author unless told otherwise. The version of testlink I'm using fails to make this leap. This means you need to modify the API (I did this, small win for Open Source) or have both a user name and their key to use the API for just this one function. Again if an API can reasonably do something for a user it should.

Tuesday, February 21, 2012

Making of an Arcade Frontend - Part 3

Last part of this series I talked about how I started coding up the arcade frontend based on translating the features I wanted into tasks the program has to do. One thing I want to do when starting any project is work on tasks that provide the most benefit for the least effort. The strategy I used in the previous part was to pick a task that was needed for a lot of features to work (finding information on games to launch.) The final result is a nice skeleton which I can build the launcher around.

Today I'm going to talk about a second method of getting a lot of visible bang for your programming buck. That is by finishing tasks for the most visible features in the program. In short, make the user interface before other stuff. The first method (finding common tasks and doing them first) is roughly the same as bottom up development for those into jargon. This method of building programs is normally known as top-down development.

If you don't get the names try to imagine a program being like a cake. Top-down means starting with the icing and decorations while bottom-up means starting with... well... with the bottom. Both methods have their gotchas. building from the bottom up tends to mean you have something unappetizing until you're all done your work. But, building from the top down means you have a hollow shell made of icing and fondant. It looks complete and appetizing but its missing everything that makes it a cake.

With that in mind I prefer to do both at once. This way of doing things doesn't translate very well into my cake analogy. The closest idea is to build a cake one slice at a time. What you get is kinda tasty, but obviously incomplete. You end up with something that can be released very quickly that gradually improves until you're done.

Anyway; enough about cake. Let's talk about the arcade frontend... I'm going to create a graphical menu to pick out a game to start. I drew inspiration mainly from the rotating song menu in Dance Dance Revolution. Playable games will show in a semicircle with the selected game in the middle at a larger size than the others. selecting a new game rotates the menu and you can rotate forever in either direction.


To get the right look requires a bit of math. placing the titles vertically is simple... sort of. Dividing the screen's height by the number of visible items will give you the amount of space each item can take. If you take that number and halve it you get the distance to the center of each space that can be used.

Now, I'm guessing a few people are asking why I need the center of the space where each item goes at all since PyGame draws images positioned at their top left. The reason is that the center of each item will stay the same no matter how large or small the item gets. It's very easy to calculate the top left of the image by subtracting half of the image's size from its center. It's not so easy to calculate the top left of the image relative to the top left of the  The image below shows this better than words can.
Another thing to note is that I'm using an odd number of games in the visible part of the menu. This way there's one "middle" game which is the selected game and an even number of other games around it. Having an even number of games would result in the selected game being off center which looks ugly.

Placing the titles horizontally requires a bit more math knowhow but not much. If you remember your trig class you might recall that the sine function looks like a smooth set of waves like this.


Source: http://images.yourdictionary.com/sine-curve

In programming the sine function usually uses a unit called radians. Radians are how mathheads measure angles. You can do some cool tricks with them once you get it. The important part is that half a circle (180 degrees) is equal to Pi (3.14159...) radians. The cool part is that sine between 0 and Pi radians looks exactly like half a circle. In fact the value of sine at any angle matches how far you are from the center of a circle vertically at that angle.

With that all that needs to be done is to multiply the item number by Pi then divide it by the number of items that are to be visible plus two, put that number into a sine function, then multiply the result by the radius of the circle. Why plus two? In order to support spinning between games an extra game is to appear offscreen and slide onto the screen when changing selection. If we don't take these two items into account games coming onscreen from the top or bottom will wobble to the left or right.

Here's the result of all that math

Not too bad eh?

Next entry I'll be showing some code and talking about how to handle transitions between titles. I'll also show you the code that this entry produced as well.

Thursday, January 12, 2012

PONIES! And random shite

Yes. I admit it. I'm a fan of My Little Pony: Friendship is Magic. After finding a mysterious new trend of pony image macros with a relatively modern art style I got curious. A brief bit of google-fu revealed the show so, out of curiosity, I watched the first episode... then the second, and third, and fourth... and, yeah.

So here's some random clips I find amusing.

http://www.youtube.com/watch?v=OPADMGqN1Uk&feature=related

http://www.youtube.com/watch?v=h7PGKcikaGY&feature=related

http://www.youtube.com/watch?v=hWD2Fb4Pneo&feature=related

http://www.youtube.com/watch?v=FbXh7ZipUuQ

http://www.youtube.com/watch?v=1A6NxMV4Lqo&feature=related

And some non-pony bits... just for fun

http://www.youtube.com/watch?v=RISJ--pvxmU&feature=related

http://www.youtube.com/watch?feature=endscreen&NR=1&v=jluv2HxFEqs

Tuesday, January 10, 2012

Making of an Arcade Frontend - Part 2

If you haven't read them yet check out the prolog and Part 1

I think it's been a sufficient ahem an excessive time since I've posted last...

During my Christmas vacation I managed to bash out the majority of the features I've wanted to support in my arcade frontend. I had a couple false starts before then. Frustrated, I went with the tried and true "just make the damn thing work" development methodology (aka hacking.)

Well, I didn't build it quite as haphazardly as that. The idea is to translate the project requirements into some minimal functionality that must be created for the project to be considered "working." For a small project like this it only takes about 10-30 minutes of effort. For larger projects it takes longer. Most of the time you'll find some features that are independent of each-other. To get the most bang for your buck your best bet is to start working on some feature that a lot of requirements depend on.

Huh? What?

I'll give an example. This is taken from the requirements list in Part 1 under each requirement is a number of functions that need to be implemented
  • Hide the regular Windows front-end.
    • Using pygame run in full screen mode
    • Leave full screen mode before starting a game, re-enter once the game exits
  • Allow the user to shut down the computer without exiting to Windows
    • Method for responding to user input
    • Method for confirming user action
    • Method for invoking windows shutdown
  • Allow an administrator to exit to windows
    • Method for responding to user input (key-mapped arcade controls)
    • Clean program shutdown
  • Allow rapid selection and launching of games using arcade controls (not keyboard and mouse)
    • Method for responding to user input (key-mapped arcade controls)
  • Support launching any game/program, not just MAME
    • Scan (something) to create a list of programs that are launchable
    • When prompted launch a program using information from the list
  • Display a preview of the selected game
    • Scan (something) to create a list of images associated with games
    • Method to load images as needed 
  • Display a list of games that can be played
    • Scan (something) to create the list of playable games
    • Method for distinguishing selected game from others
    • Method for displaying available games 
  • Display a marquee for the game... somewhere near the screenshot
    • Scan (something) to create a list of images associated with games
    • Method to load images as needed
  • Everything must have an animation
    • This means needing an endless update/draw loop for objects
    • Need a state machine to indicate whether some transition is occurring and what kind
  • Alter control-key mappings to support games without configurable controls 
    • Method to invoke IPAC-2 programmer with some known configuration
    • Scan (something) to create a list of control configs associated with games  
There are a couple things that pop out:
  • Method to load images as needed
  • Scan (something) to create a list of games and things associated with them
Of those scanning comes up the most and, more importantly, relates most directly to the purpose of the program which is starting games.

For my first crack at this I've decided that (something) will be a directory tree containing files called (game)-launcher.cfg which describe playable games. For the sake of organization, since there will likely be well over 100 files, the config files can be in any directory in the tree.

What do I want to put in the file:
  • The program to start
  • Extra information to pass to the program
  • Controller settings for the game
  • Where to find game's marquee, screenshot and other image files
Now, how do I format the file? I don't want to spend an undue amount of time writing a parser so I could use one of Python's built in parsers. But that still means I need code to convert that to an easily usable datastructure (let's just ignore JSON for now since it slipped my mind at the time) So... how about just making it a Python module. That reduces parsing to one line of code. The file itself simply contains a Python dict with a standardized name and standardized keys.

First the code to scan for config files:
def FindAllLaunchables( startDir ):
    outList = []
    dirList = os.listdir( startDir )
    for dir in dirList:
        checkDir = os.path.join( startDir, dir )
        try:
            if os.path.isdir( checkDir ):
                outList.extend( FindAllLaunchables( checkDir ) )
            elif os.path.isfile( checkDir ) and dir.lower().endswith("-launcher.cfg"):
                outList.append( checkDir )
        except WindowsError:
            pass
    
    return outList

That's it. The function recursively scans all directories under startDir and, if it finds a configuration file adds its location to an output list which the function returns.

This bit of code handles reading the configuration file.

def CreateLaunchers( configFiles ):
    launchers = []
    for launcherConfig in configFiles:
        moduleName = os.path.splitext( launcherConfig )[0].replace( os.path.sep, "_" ).replace( ".", "" ).replace( " ", "_" )
        
        moduleFile = open( launcherConfig )
        try:
            modulePath = os.path.split( launcherConfig )
            module = imp.load_module( moduleName, moduleFile, launcherConfig, ["cfg","rt",imp.PY_SOURCE] )
            launchers.append( config.Launcher( module.LauncherConfig ) )
        finally:
            moduleFile.close()
            del moduleFile
    return launchers

The meat here is the call to imp.load_module. The imp module exposes some of the guts of Python's import statement and is useful for importing arbitrary files as modules. Notice the config.Launcher object instantiation. The Launcher class will be used to carry out the work of starting up a game based on its configuration along with some other stuff.

And that's everything! To finish this initial step I stubbed in some code to start up fullscreen mode and to pick up keyboard input. That code is below and makes up the skeleton which the rest of the program will be built around.

pygame.init()

# load configuration
configFiles = FindAllLaunchables( search, skip )
launchers = CreateLaunchers( configFiles )

# startup sequence
screen = SetScreenMode()
pygame.key.set_repeat( 1000, 200 )
pygame.mixer.init()
things = []

# the main loop!
frameStart = time.clock()
time.sleep( 0.01 ) # XXX: don't want a frame time of 0 when starting
while True:
    frameTime = time.clock() - frameStart
    frameStart = time.clock()
        
    for event in pygame.event.get():
        if event.type == pygame.QUIT or (event.type == KEYDOWN and event.key == pygame.K_F12):
            sys.exit()
        
    for thing in things:
        thing.Update( frameTime )
        thing.Draw( screen )
    pygame.display.flip()
    screen.fill( (0,0,0) )

Whelp, that's all for part 2. I'll have more for you next time! (and since the project is working, next time should be sooner, not later) SetScreenMode isn't all that exciting so I've spared you its details. Notice that with this code we now have the following done.
  • Using pygame run in full screen mode
  • An endless loop to update/draw objects
  • Method for responding to user input (stub)
  • Scan (something) to create a list of games and things associated with them
Not bad for one blog-entry worth of work eh?

Friday, September 2, 2011

WOO!

Or more precicely Sandra and Woo

Oddly enough I found this comic through a banner ad posted on Something Awful's LP archive. I was reading through the epic that is Boatmurdered (no graphic violence, unless you count a white ASCII smiley turning into a red ASCII smiley as violent) I wasn't entirely sure what to expect but the ad interested me so I clicked. And have lost many hours reading through a highly approachable, yet surprisingly mature comic strip. Amusingly, the ad is still running now.

Initially it's something like Calvin and Hobbes... yet it's nothing like Calvin and Hobbes at the same time. The characters are all older (Sandra's 11, at least at first) and more mature. There's also more budding romance. In any case you should read it. The strip relies a great deal on characterization so some strips don't make much sense unless you know the characters but there's still plenty of strips which stand alone nicely.

Oh! And I almost forgot! There's a new Hawken trailer and more gameplay footage. I am itching to play this game so badly!

Friday, August 19, 2011

Another Gem

Posting this from work since I'm doing some boring data uploading crud.

If you ever find yourself doing this as a programmer/software engineer, please reconsider (your career choice)

From: http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96624/03_types.htm#29460
Note: Currently, VARCHAR is synonymous with VARCHAR2. However, in future releases of PL/SQL, to accommodate emerging SQL standards, VARCHAR might become a separate datatype with different comparison semantics. So, it is a good idea to use VARCHAR2 rather than VARCHAR.

Brilliant! Create a new type because maybe at some point you might want to change the behavior of an existing type at some unspecified time in a vaguely defined future. Apparently the guys at Oracle decided it made less sense to introduce a new type when the need arises (what sane people do) instead of adding a redundant type right away... just in case. Oh! And make the new type have the old behavior just to conveniently screw up backward compatibility if the original type does change. That's like making "Toy Story" the sequel to "Toy Story 2"... WTF

Tuesday, August 16, 2011

Do not use Java. Ever.

While browsing The Daily WTF I was led to this gem of a bug in Java. As if being bought out by Oracle wasn't enough.

I doubt the issue will ever be fixed since nobody in the OSS community seems to bother reading documentation for any APIs regardless of who produced them (based on rants from Linus and the above bug). Perhaps if they gave a shit about reading docs they'd give a shit about writing docs eh? But I digress...

Strike that... generalizations like that aren't fair since the OSS community is large and subject to Sturgeon's Law like any other. And subject to GIFT like any online community.

JAVA RANT TIME!


My experience with Java as an application development tool has been, frankly, appalling. AWT and Swing, when combined with NetBeans' visual editor tool, are easily the worst APIs I've ever had to work with.

A theme I've seen in my mercifully brief experience with Java is that it arbitrarily chooses to do things differently. Not necessarily because it's less verbose (Java code tends to be anything but verbose) or more flexible (where LISP supposedly cornered the market). Just different... in a manner that's pointless and stupid.

Imagine if you will that you're designing a data type to store dates. Some methods that might spring to mind would be GetDayOfMonth, GetDayOfWeek, GetMonth, GetYear, GetLengthOfMonth and so on. All fit common use cases for the printing of dates in various fashions used by humans. Using the functions wouldn't require consulting any documentation. So what does Java do? Mash all of that into one function! You say that description isn't all that helpful since it doesn't link to relevant information. Fuck you! Find it yourself! (it's here) Oh and let's not call the type for storing dates Date or anything like that. Let's call it GregorianCalendar, so that the most obvious common use cases are buttfucked right away.



Most software engineering programs include at least one course on how to make quality code. The fundamental rules of quality can be summed up as follows.

Make your program's actions and purpose blindingly obvious to the next idiot to see them.

Java's standard library fails even that relatively simple test. Ruby, Python, C#, C, Perl and who knows how many other languages manage to achieve this feat. This is stupid! The only other language which consistently pisses me off like Java is Perl. At least Perl is honest in being a pile of random hacks stacked haphazardly together to scratch some developer itches. Perl is a lazy tool for lazy developers. It fills its niche nicely though arguably Ruby and Python are better languages for the same niche and more besides.  
  

Don't use Java. Ever. If your environment is a JVM then try to use a better language that compiles to bytecode. You can find them, JRuby, Groovy, Jython, etc. If you can't do that then at least avoid using Sun's ass-tastic libraries... if Sun has a good library somewhere feel free to use that but my experience makes me doubt the existence of such a beast.

What's a better language? C#, Python, Ruby, C++ (despite its many flaws), Visual Basic (again despite its many flaws, I think this reflects nicely on how utterly godawful I think Java is) 

Sunday, July 31, 2011

Making of an Arcade Frontend - Part 1

Ah, time to take a break from work and dealing with ASP.NET web applications, continuous integration servers and all that fun (but boring to talk about) crap. Time, for The Making of an Arcade Frontend!

H'okay. So, like any good software project, my arcade frontend needs a plan. And any good plan starts with a set of goals. A bunch of things the frontend is required to do. In other words, software requirements. Woo! Exciting! Sounds like something out of a college software quality course eh? Well, at least a good software quality course would discuss requirements. After all, it's hard to tell whether your software is "right" or "good' if you don't even know what right or good are.

There are a few ways of going about making software requirements. You can write up a paragraph of what you want the program to do. Or you could make a checklist of features. Or you could draw a bunch of pictures. Or you could write a formal SRS document. The choice is yours.

I tend to favor brevity when coming up with goals for my software. It reduces the amount of effort I expend on the requirements stage dealing with contradictory requirements and other general issues. It also helps avoid falling into the trap of writing requirements as a set of instructions on how the program will work; instead of what the program needs to accomplish. If you do fall into the trap of writing a how-to for your program you'll regret it when you find that the design won't work with real code. Good requirements say nothing of how they get achieved. For a large project I tend to go with a short paragraph describing each requirement. A couple sentences does the trick quite nicely. Small projects only really need a set of bullet points. There's no hard and fast rules on what is or isn't descriptive enough for a given project. It really depends on the size of the projects and who is working on it. Practice makes perfect.

So, what are the requirements for my arcade frontend? Here they are.
  • Hide the regular Windows front-end. It should appear as soon as the computer becomes usable.
  • Allow the user to shut down the computer without exiting to Windows
  • Allow an administrator to exit to windows (e.g. to install more games)
  • Support launching any game/program, not just MAME
  • Allow rapid selection and launching of games using arcade controls (not keyboard and mouse)
  • Display a preview of the selected game
  • Display a list of games that can be played. Preferably in a manner that looks pretty (e.g. like how DDR displays its song list)
  • Display a marquee for the game... somewhere near the screenshot
  • Absolutely no hard transitions. Everything must have an animation to go with it
  • Alter control-key mappings to support games without configurable controls 
See, nothing all that complicated at all. So, now that I know what I want to do, I need to decide how to do it. That's for another article.

Friday, July 22, 2011

Making of an Arcade Frontend - Prolog

So, if anybody follows my wife's blog you'll have probably heard that I've been building a MAME cabinet. Now I'm not going to talk about the actual physical construction much. If you're interested in that I took plans for the TaitoRama cabinet from Project MAME as the base. After that I converted the measurements from Metric to Imperial so that I could build it using the tools I have. In the process I also altered the dimensions slightly, increasing the height of the cabinet to exactly 6 feet tall from at the peak.

The assembly is now done enough for me to start the fun part. Trying it out and tuning the UI.

The actual working part is a PC running Windows 7 which I put together for about 700 bucks including the monitor and OS. The overkill hardware means I can run stuff other than just MAME smoothly as long as it works well with a 6 button arcade control setup. (Street Fighter 4 is on my shopping list for this thing.) It works, it runs the games I want but... it's still a desktop PC. It doesn't look like an arcade cabinet, and certainly doesn't work with arcade controls.

I need a frontend to make the cabinet more snazzy. I need something to start up my games that works with the arcade controls, and I need to do something to make the PC look... well... less like a PC. Especially when booting. Every frigging machine out there has the same POST, Starting Windows, Login, Desktop crap; and I don't want to see that when turning on my arcade cabinet.

To do that, I have turned to the intertubes and found two pieces of the puzzle. The first is a simple registry key built into Windows 7. Turning it on enables support for a customized login/logout screen, you will only see it when the PC is turning off but it's a start.

The second piece is a more fun one. It's a program which allows anyone to create a customized animation for when you start up the computer replacing the usual glowy windows logo. It also lets you replace the captions "Starting Windows" and "(C) Microsoft Corporation" In my case I've changed the captions to "Main Screen Turn On" and some random nonsense. The animation is, well, a screen turning on revealing someone you might know. Much more fun.

I haven't found a method to replace the default ASUS POST screen (the image that first appears when the PC turns on) but it should be possible, the OEMs do it after all. However possible firmware hacking can wait, now is the time for getting my games started.

Now there are lots of arcade frontends out there. Many of them even support multiple emulators, which is good. But they all seem to be geared toward running emulators only. Even if they aren't I don't really care, I'm doing this for fun so I'm going to have fun making my own front-end. It will have my own (or my wife's) graphics, and custom made animations plus as much other pizazz as I wish to jam in there.

Also it will let me script in extra behind-the-scenes work for running any game I want. For example, if one game has a rigidly defined control scheme (say, Melty Blood) I can reconfigure the arcade controller's driver to work with that game. So, not only can I play awesomeness such as Contra, DoDonPachi, Donkey Kong and Metal Slug with MAME, I can also play I Wanna be The Guy, Cho Ren Sha 68k, and other non-emulated games.

More details to come.

Friday, April 22, 2011

The Importance of Profiling

Ah, profiling. A tool that I've neglected to use for far too long until forced to do so recently at work. No I don't mean that! No not that either!! Profiling is a tool which is used to examine how long each part of a given program executes to find out why it's slower than molasses in Antarctica.

A major tool that I support is a test automation framework that supports remotely exercising APIs under test via a scripting language. I had just finished the initial work of porting this system to support testing of some new software when I discovered a problem.

Under normal circumstances the program can run over one hundred commands per second depending on the time taken by the command itself. An early test however revealed that I was barely managing one or two commands per second. Something was wrong!

Worse, examining the code provided no obvious answers. There were no poorly made algorithms, no pointless sleeps, no redundant work, nothing. Embarrassingly, this was the first time I've actually used a profiling tool to solve a problem. All other times I've simply muddled around with the code until I found some obvious problem like the ones I mentioned. Whelp, no time like the present, right?

The tool I was using provided two ways to profile a program's internals. Both involve what's called instrumentation. What that means is the tool generates some extra code in the program for the purpose of measuring your code's behavior. The first profiling method, and by far the simplest, is to count the number of times every function is called. This is helpful in finding candidates for improvement or potential bugs that cause more calls to some code than necessary. The second measures the amount of time spent in each function in addition to the number of times it's called. This is better since it can tell you where your program is getting stuck longest.

In my case a function which waited for a command stood out as the long runner. Great! Except all it does is call a function to receive data. Digging through the function I found some informational prints, and a call to recv. Not much to go on. Prints are used in a lot of different places in the program and none of those calls took very long at all, so that's out. Time to put on my google Shinobi Shozoku and find out if there are situations that make recv slow.

The result? Yes! However it's not recv that's the problem. It's a little something called Nagle's Algorithm, which is part of the TCP/IP protocol stack. It's designed to reduce network traffic by attempting to combining multiple small packets and sending them at once. It does this by holding on to a small packet and waiting for a period of time before sending it, in case more data is coming. Since the tool was designed to minimize bandwidth and be very lightweight in design it would send encoded commands in the form of very small packets, typically a few dozen bytes being large for the tool. Disabling Nagle's Algorithm did the trick.

Without profiling I might have found the issue in question, but I would have wasted significantly more time either in trial and error. Or worse, not realizing I've made an error, and wasting hours trying to fix something that isn't the problem with negligible improvement.

Sunday, April 17, 2011

Component Based Architecture

This is a relatively old presentation now, but it's a useful one.
http://cmpmedia.vo.llnwd.net/o1/vault/gdccanada09/slides/marcinchadyGDCCanada.ppt

It describes some of the architecture of the game Prototype. It has a very nice description of what goes wrong with simple OO solutions for games when as the scale of a project grows.

Saturday, April 16, 2011

Looking Forward to this One

Well it's been... far too long since the last time I've posted here so I'm going to try to get back into the habit again.

Short story: I'm married, and have been since August 2010, work varies between satisfyingly challenging to insane, I have a pet cat named Doom, and I've barely had any time to do real hobby development work.

I'm going to keep things short so that I'm less likely to get overly lazy and stop posing for months at a time. I'm also not going to restrict my posts to anything in particular... beyond avoiding certain particulars of my job due to NDAs.

During work, I'll spend a smallish amount of time browsing the web. This helps to prevent me from going into mental vapor-lock and keeps me working faster than I would otherwise. I have a few sites I tend to go to that don't take much time to read, and relate just enough to what I'm doing that I don't switch out of the appropriate mindset for coding. One of these sites is the TIGsource blog. This is where I discovered a game that I'm very very excited to see. Hawken.

The game is a mech-sim like game with a pace more on the level of a classic multiplayer deathmatch. Either way, it's been far too long since I got a real fun mech game (years since I got Mechwarrior 4) and Hawken has a very nice feel based on the released gameplay footage. I also quite like its futuristic high tech shantytown setting. Hope the game turns out as awesome as it looks.

Monday, July 26, 2010

Three Projects... Four Projects... Five Projects!?!

Yes, well (conservatively) counting what I'm up to at RIM. The project I'm wrapping up is a particularly fun and rewarding one, creating a tool for providing detailed code coverage tracking for the various testing efforts within the OS Group. Sadly, the details aren't all that exciting. Mostly it's just processing gobs of similar data into an easily queried form. The majority of the work is in the logistics of collecting the data in a way that doesn't interfere with testing and manages to collect as much information is possible given the limitations of the testing environment. My other project(s) relate to some internal OS Group initiatives. I could tell you about them, but then I'd have to kill you ;)

So that's two...ish. Where's the other three? Well...

  1. Space Combat Sim
    Yup, that thing is still going. Adding bots, improving the graphics, cleaning the code up and generally learning as much about 3D networked games as possible.
  2. A shmup game developed from scratch for XNA on X-Box 360 and PC.
    Something simple for building a strong C# codebase that I can port to other projects. Goals here are making a programmable effects system and some decent GUI widgets.
  3. Another shmup, using FlatRedBall
    Why? Because screw you! That's why... Actually I figured I'd just start messing around with plugging tools together just since that's normally not the way I make games.

Actually, to go on a boring long monologue...

I have finished only a few game projects, mainly for school. That tends to be because I approach the subject by first building tools and such, then building the game using them. I end up having so much fun making the tools that the project devolves into adding new features and refining code that I lose focus on making the game. Then I get bored and start a new project.

Now, I'm a tools developer professionally I can finally spend all hours of the working day making all sorts of exciting tools for a moderately hardcore development environment. This means that I'm not getting quite the same buzz from making yet more tools at home. So... time to make some fugging games!

Later d00dz! I'll try to keep the interval to next post to less than a month this time.

Thursday, June 24, 2010

Some Inspiration

Lately I've been getting most of my coding jollies from my job as a tools developer at RIM. Mostly Python with a nice dose of C, SQL, and other stuff. Mainly fixing some reporting systems that go to external reports seen by management. Plus a dash of code janatorial work since nobody else seemed to be available/willing. After eight months doing solo work it's very nice to be working with a team again.

Anyway, that's not actually what I wanted to talk about. Today's just a shorty (I have a longer rant about myself coming later.) TIGSource recently posted a couple montages of a huge collection of free, indie games. I've played a few of them (Fraxy, Cave Story, Cho Ren Sha 68k, Prototype 2, Warning Forever, Clean Asia and one or two I can't recall... yea I'm a SHMUP fan) Holy hell there's some awesomeness.

Check it out!