October 14, 2008

PPE 2: Java Project Skeleton

GameOfLifeServer

I've been following the progression of the tool AppFuse for some time now but haven't had a chance to use it. This seems like a prime time (cue learning curve for first new technology). While there are many Java frameworks I could use, I've found the Spring Framework to be rock solid and know that it covers everything I could want to do with this simple application. Spring has also created Spring Web MVC to support the front-end pieces. I think it offers a cleaner solution than Struts. AppFuse supports Spring Web MVC based projects so that should make this straight forward.

Alas AppFuse requires Maven (cue learning curve for second new technology) which I don't currently have installed. Back to the command line for that. I already have Java installed so that AppFuse requirement is there and I'll start off with the HSQLDB profile since my MySQL server runs on a different machine and I don't want to mess with configuration just yet.

# 3rd party Java projects I store in a standard directory
cd /Applications/Java
# downloaded from one of the available mirrors
tar -zvxf ~/Storage/apache-maven-2.0.9-bin.tar.gz
setenv MAVEN_HOME /Applications/Java/apache-maven-2.0.9
setenv PATH "${PATH}:${MAVEN_HOME}/bin"

The latter two lines I'll be adding to my shell so that they get picked up next time I launch a terminal window. If you hadn't noticed those commands are in tcsh. I like it better than bash as my terminal shell (since I never made the switch to zsh which I hear is even better) but any scripting I do is in bash.

Now to let AppFuse do its magic.

cd ~/source/trunk/danielr/projects/PPE/
# tried to run the AppFuse Maven command line but got an error, see below
svn delete GameOfLifeServer
svn commit -m "Remove server directory since AppFuse complains if it already exists"
# now I can run it
mvn archetype:create -DarchetypeGroupId=org.appfuse.archetypes -DarchetypeArtifactId=appfuse-basic-spring -DremoteRepositories=http://static.appfuse.org/releases -DarchetypeVersion=2.0.2 -DgroupId=com.neophi.gol -DartifactId=GameOfLifeServer
# checking this into subversion as recommended
svn add GameOfLifeServer/
svn commit -m "Initial AppFuse generated project"
# now to play with the project
cd GameOfLifeServer/
# since I don't want to deal with MySQL properties right now
mvn -Phsqldb
mvn -Phsqldb jetty:run-war

Man those Maven targets are downloading a lot of stuff. That makes sense since I've never used Maven before so have nothing in my local repository. Overall as I've been playing with AppFuse the documentation on their site has been good enough that I can muddle through it. Now to pull it into the IDE.

# create Eclipse project files
mvn eclipse:eclipse

After launching Eclipse I added a Java Classpath Variable called M2_REPO pointing at "/Users/danielr/.m2/repository". I tried to use Maven to add it but it didn't work. Turns out it might have worked but had issues trying to use "~" when specifying the location of my Eclipse workspace directory. Next I imported the project located at "~/source/trunk/danielr/projects/PPE/GameOfLifeServer/". It imported and compiled with the expected errors. I think that means it's time to commit to subversion again.

# don't check in the directory Maven creates its files in
svn propset svn:ignore target .
# add the Eclipse created files
svn add .classpath .project .settings/
svn commit -m "Added ignores and Eclipse project files"

And with that, I'm calling it quits for today.

Closing Thoughts

For a snapshot of the project in process grab PPE-2.tar.gz.

For the history of this project see Programming Project Experiment (PPE).

Tags: gameoflife java ppe

October 14, 2008

PPE 1: Flex Project Skeleton

The most tedious part of any project I find is getting the skeleton setup. Thankfully Flex Builder's project wizards make this easier. I'll be creating two Flex projects, one called GameOfLife, which will hold the UI application, and one called GameOfLifeTest, which will hold the testing code. Additionally I'll create a Java project called GameOfLifeServer which will hold the back-end code. Both the production and test code will reside in the same Java project since you can easily mix them in Eclipse's Java mode, unlike with Flex. These will all be sibling projects in a top level directory.

Command Line

First a little command line mucking to get the directories setup:

cd source/trunk/danielr/projects/
mkdir PPE
mkdir PPE/GameOfLife
mkdir PPE/GameOfLifeTest
mkdir PPE/GameOfLifeServer

GameOfLife

Run through the Eclipse new Flex Project Wizard using the directory above as the project root and accepting all the defaults.

Now onto the associated test project.

GameOfLifeTest

Run through the Eclipse new Flex Project Wizard using the directory above as the project root and accepting all the defaults.

To GameOfLifeTest I need to add the testing library I'm going to use. For this project I'm planning on sticking with FlexUnit. An alternative that I considered was fluint. Like some of my other decisions I'm sticking with what I know works well and I don't see anything with fluint that I'll be needing that FlexUnit doesn't already cover. After downloading the current release I drop it into the libs folder of the recently created project.

Next I need to put in the FlexUnit test runner scaffolding. Makes me wonder how hard it would be to extend Flex Builder to add a "Create new FlexUnit Project Wizard". In this case I'm just going to cut and paste the code from the recipe I wrote that is up on the Adobe Cookbook. Lastly I want to setup how the test project is going to reference the code from the main project. Since Flex Builder can't efficiently handle compiling multiple projects at once (i.e. a SWC library project and the application that it depends on) I'm setting this up as a source path reference. Be warned that such a setup has it's own set of problems.

Since I'm the only developer on the project I'm doing the quick and dirty "source path" add folder option. Eclipse will store a hard coded path in the project file which means that anyone else importing the project will get an error unless they also happen to store the folder at "/Users/danielr/source/trunk/danielr/projects/PPE/GameOfLife/src". The simple fix is once the project is imported, go to the project properties and update the source path folder reference.

To finish this skeleton code I want to make sure I can create and test something that exists in the referenced source path. At this point I only have the main application, but that's good enough to verify things are working with some trivial test. Note I'm break from the traditional test naming scheme since I'm going to delete this test once I have some real code to work on.

package com.neophi.gol
{
    import flexunit.framework.TestCase;

    import mx.core.Application;

    public class ApplicationTest extends TestCase
    {
        public function testApplication():void
        {
            var gol:GameOfLife = new GameOfLife();
            assertTrue(gol is Application);
        }
    }
}

Next I need to include it in the test suite that gets run. A quick edit to GameOfLifeTest.mxml will do the trick:

private function createTestSuite():TestSuite
{
    var testSuite:TestSuite = new TestSuite();
    testSuite.addTestSuite(ApplicationTest);
    return testSuite;
}

Sweet. That compiles and runs and passes! Next up a small stub of the main application.

GameOfLife

Not much to do here but make sure it compiles and runs. For that I'm just going to stick in a simple label.

<mx:Label text="Game Of Life" horizontalCenter="0" verticalCenter="0"/>

That was easy enough. That is also now compiling and running. For the paranoid, you could run the test suite project again to make sure everything is still working. Remember to refresh the test project otherwise Eclipse might not pick up the fact that we changed a file in a referenced source path. Have I mentioned that source paths are buggy? Now to create a skeleton back-end. Looks like I'll work on that tomorrow as it's later than I thought.

For a snapshot of the project in process grab PPE-1.tar.gz.

Closing Thoughts

The format I used for this post is working well so I'm going to continue using it, not that you can tell all of the thought process behind it. What I've been trying is before I do something I've been writing the step down and then performing it to make sure what I thought I was going to do actually worked. Given how bad I am with tenses when writing most of the time, these posts will probably be worse in that regard so fair warning on that front. As a tongue-in-cheek expression call this approach blog first development, which some might say is a BFD.

For the history of this project see Programming Project Experiment (PPE).

Tags: flex gameoflife ppe

September 22, 2008

Pixel Bender and Conway's Game of Life

When I started reading about Pixel Bender and realized at its core it was a cellular automaton engine I immediately thought of Conway's Game of Life. I started looking into how to use Pixel Bender to render generations in the game of life.

Given that pixel bender is boundless (i.e. defined over an infinite plane of discrete pixel coordinates) I had to introduce the notion of a border pixel to make handling edge cases easier. Since most of the area in a generation is dead I decided to use white for a pixel that is dead (easier on the eyes) and black for a pixel that was alive. My initial attempt at the algorithm ran into a bug with the kernel export for Flash Player feature. After some rewriting I had a working pixel bender kernel that implemented the logic (albeit unoptimized):

<languageVersion : 1.0;>
// $Id: GameOfLife.pbk 57 2008-09-16 02:55:33Z danielr $
kernel GameOfLife
<   namespace : "Daniel Rinehart";
vendor : "NeoPhi.com";
version : 1;
description : "Conway's Game of Life";
>
{
    input image4 src;
    output pixel4 dst;

    void
    evaluatePixel()
    {
        pixel4 border = pixel4(1.0, 0.0, 0.0, 1.0);
        pixel4 dead = pixel4(1.0, 1.0, 1.0, 1.0);
        pixel4 alive = pixel4(0.0, 0.0, 0.0, 1.0);

        pixel4 me = sampleNearest(src, outCoord());

        // default to no change in pixel
        dst = me;

        // I would like to write "all(equal(border, me))" but that's buggy in Flash
        if (!((border.r == me.r) && (border.g == me.g) && (border.b == me.b)))
        {
            int aliveNeighborCount = 0;
            float2 offset = float2(pixelSize(src).x, pixelSize(src).y);

            // Find out how many of my neighbors are alive
            // left
            pixel4 test = sampleNearest(src, outCoord() + (offset * float2(-1.0, 0.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // upper left
            test = sampleNearest(src, outCoord() + (offset * float2(-1.0, -1.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // up
            test = sampleNearest(src, outCoord() + (offset * float2(0.0, -1.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // upper right
            test = sampleNearest(src, outCoord() + (offset * float2(1.0, -1.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // right
            test = sampleNearest(src, outCoord() + (offset * float2(1.0, 0.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // lower right
            test = sampleNearest(src, outCoord() + (offset * float2(1.0, 1.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // down
            test = sampleNearest(src, outCoord() + (offset * float2(0.0, 1.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }
            // lower left
            test = sampleNearest(src, outCoord() + (offset * float2(-1.0, 1.0)));
            if ((alive.r == test.r) && (alive.g == test.g) && (alive.b == test.b))
            {
                aliveNeighborCount++;
            }

            // As per: http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
            // 1. Any live cell with fewer than two live neighbours dies, as if by loneliness.
            // 2. Any live cell with more than three live neighbours dies, as if by overcrowding.
            // 3. Any live cell with two or three live neighbours lives, unchanged, to the next generation.
            if (((alive.r == me.r) && (alive.g == me.g) && (alive.b == me.b)) && ((aliveNeighborCount < 2) || (aliveNeighborCount > 3)))
            {
                dst = dead;
            }
            // 4. Any dead cell with exactly three live neighbours comes to life.
            if (((dead.r == me.r) && (dead.g == me.g) && (dead.b == me.b)) && (aliveNeighborCount == 3))
            {
                dst = alive;
            }
        }
    }
}

Now with a working filter I used some of the recent posts by Mike Chambers on how to embed a pixel bender kernel into MXML. However, since I wasn't using it as a filter and wanted more control over the flow I leveraged the ShaderJob class.

var shader:Shader = new Shader(new gameOfLife() as ByteArray);
shader.data.src.input = current;
var result:BitmapData = new BitmapData(current.width, current.height);
var shaderJob:ShaderJob = new ShaderJob(shader, result, current.width, current.height);
shaderJob.addEventListener(ShaderEvent.COMPLETE, handleShaderDone);
shaderJob.start();

Slap a minimal UI around it and you have (click to launch, view-source enabled, Flash Player 10 required):

Tags: flex gameoflife pixelbender