> Rabbit Escape (a bit like Lemmings) v0.1 released for Linux, Windows and Mac

February 10th, 2015

Today I am releasing the first version of my new game, Rabbit Escape.

It’s an arcade puzzle game inspired by Lemmings and Pingus, but intended to be simpler and easier to control on a mobile device.

Your task is to guide a party of rabbits from the entrance to the exit by dropping tokens in front of them that give them special abilities such as building bridges or climbing walls.

Here’s what it looks like:

Rabbit Escape

An Android version will be coming soon, but for now I’m releasing the desktop version for Linux, Windows and Mac.

There are 60 levels, and I’m hoping people will be sending me lots more soon!

I plan to write a level editor, but for now you can create your own levels by editing text files.

The game is Free Software under GPL v2, and the graphics, levels etc. are released under the non-commercial Creative Commons BY-NC-SA licence. The choice of a non-commercial license for these parts is intended to prevent people copying the game wholesale onto an app store and making money from it. If you want to use it under a different license, please contact me.

I plan to charge the minimum price on the Android store, and offer the desktop version for free (providing an opportunity for donations).

Please try it out and let me know how you get on. It’s a bit rough around the edges, but the game mechanics work, and it seems like it might be fun.

If you’d like to contribute, I’d be very excited! You can find the code at github.com/andybalaam/rabbit-escape.

> Snake in Groovy

February 5th, 2015

I’m starting a series where I write the game Snake in lots of programming languages.

I almost always use writing Snake as my way in to understand a new language, so I’ll share my thoughts about each language as I go.

Slides: Snake in Groovy

If you want to, you can Support me on Patreon.

> Programmatic equivalents of web.xml sections for Tomcat

February 5th, 2015

Most documentation for J2EE configuration is based on having a web.xml file, but I want to configure my Tomcat programmatically. Here are some of the things I have found out.

Please use the comments below to correct what I got wrong, and mention equivalents for other parts of web.xml.

Getting started

<web-app ...

in code becomes something like:

import org.apache.catalina.Context;
import org.apache.catalina.startup.Tomcat;
...
Tomcat tomcat = new Tomcat();
Context context = m_tomcat.addContext( "", "WebContent" );

Adding a Servlet

<web-app ...
    <servlet>
        ...
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.example.MyServlet</servlet-class>
        ...
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/foo/*</url-pattern>
    </servlet-mapping>

in code becomes something like:

...
Class servletClass = MyServlet.class;
// MyServlet extends javax.servlet.http.HttpServlet 
String servletName = servletClass.getSimpleName(); // Or something else if you like
Tomcat.addServlet( context, servletName, servletClass.getName() );
context.addServletMapping( "/foo/*", servletName );

Adding a filter

<web-app ...
    <filter>
        <filter-name>MyFilter</filter-name>
        <filter-class>com.example.MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MyFilter</filter-name>
        <url-pattern>/bar/*</url-pattern>
    </filter-mapping>

in code becomes something like:

...
import org.apache.catalina.deploy.FilterDef;
import org.apache.catalina.deploy.FilterMap;
...
Class filterClass = MyFilter.class;
// MyFilter implements javax.servlet.Filter
String filterName = filterClass.getSimpleName(); // Or something else if you like
FilterDef def = new FilterDef();
def.setFilterName( filterName );
context.addFilterDef( def );
FilterMap map = new FilterMap();
map.setFilterName( filterName );
map.addURLPattern( "/bar/*" );
context.addFilterMap( filterMap );

Adding a Listener

<web-app ...
    <listener>
    	<listener-class>com.example.MyContextListener</listener-class>
    </listener>

in code becomes something like:

...
context.addApplicationListener( MyContextListener.class.getName() );
// MyContextListener implements javax.servlet.ServletContextListener

This is for a ServletContextListener: it may be similar for other listeners, but I’m not sure.

> JAX-RS (using Apache CXF) in embedded Tomcat example

January 13th, 2015

I had serious trouble today firing up an embedded Tomcat server that serves up REST resources using JAX-RS via Apache CXF.

Here’s minimal example, hopefully saving you the same trouble:

src/HelloJaxRs.java:

import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;

public class HelloJaxRs
{
    public static void main( String[] args ) throws Exception
    {
        Tomcat tomcat = new Tomcat();
        Context context = tomcat.addContext( "/", "" );

        Wrapper servlet = context.createWrapper();
        servlet.setName( "jaxrs" );
        servlet.setServletClass(
            "org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet" );

        servlet.addInitParameter(
            "jaxrs.serviceClasses",
            Hello.class.getName()
        );

        servlet.setLoadOnStartup( 1 );
        context.addChild( servlet );
        context.addServletMapping( "/rest/*", "jaxrs" );

        tomcat.start();
        tomcat.getServer().await();
    }
}

src/Hello.java:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path( "/hello/{name}" )
public class Hello
{
    @GET
    public String getThing( @PathParam( "name" ) String name )
    {
        return "Hello, " + name;
    }
}

build.xml:


<?xml version="1.0" encoding="UTF-8"?>
<project default="run">

    <target name="run" depends="compile">
        <mkdir dir="bin/tomcat.8080/webapps"/>
        <java
            classname="HelloJaxRs"
            fork="true"
            failonerror="true"
            dir="bin"
        >
            <classpath>
                <pathelement location="bin/"/>
                <fileset dir="lib"><include name="**/*.jar"/></fileset>
            </classpath>
        </java>
    </target>

    <target name="compile">
        <mkdir dir="bin"/>
        <javac srcdir="src" destdir="bin">
            <classpath>
                <fileset dir="lib"><include name="**/*.jar"/></fileset>
            </classpath>
            <compilerarg value="-Werror"/>
        </javac>
    </target>

</project>

To download the dependencies (or you can do something clever with Maven):

$ mkdir lib
$ cd lib
$ wget http://www.webhostingjams.com/mirror/apache/tomcat/tomcat-7/v7.0.57/bin/apache-tomcat-7.0.57.tar.gz
$ tar -xzf apache-tomcat-7.0.57.tar.gz
$ wget http://www.apache.org/dyn/closer.cgi?path=/cxf/3.0.3/apache-cxf-3.0.3.tar.gz
$ tar -xzf apache-cxf-3.0.3.tar.gz
$ cd ..

To run Tomcat:

$ ant

Then, in another terminal, you can see it’s working:

$ curl http://localhost:8080/rest/hello/andy
Hello, andy

> Vim persistent buffer list combined with saved sessions

January 8th, 2015

I like to use several saved Vim sessions to remember what files I was working on in a particular project.

I also like to have a list of buffers I have open on the left-hand side of the screen that is always visible and up-to-date.

Sometimes, the existence of a generated buffer like the list of buffers can confuse the session restore code, but I have found a way to make this work nicely using the Buffergator plugin and the built-in mksession command.

Here are the relevant snippets from my .vimrc.

I am a beginner: please comment if you see bugs or possible improvements.

" Prerequisites: install the Buffergator plugin


" Save session on exit, excluding problematic stuff like options

set sessionoptions=blank,buffers,curdir,tabpages,resize,winpos,winsize
au VimLeavePre * if v:this_session != '' | exec "mks! " . v:this_session | endif


" Open Buffergator when you press F5

nnoremap <F5> :BuffergatorOpen<CR>


" Various Buffergator options to make it persistent,
" and displayed how I like

let g:buffergator_autodismiss_on_select = 0
let g:buffergator_display_regime = "bufname"
let g:buffergator_sort_regime    = "filepath"
let g:buffergator_autoupdate = 1


" Suppress the error message about the Buffergator buffer
" when you restore a session

function! OpenBuffergatorIfItsBufferExists()
    if bufnr("[[buffergator-buffers]]") > ''
        BuffergatorOpen
        normal o
    endif
endfunction

autocmd VimEnter * call OpenBuffergatorIfItsBufferExists()

Now when I start vim with vim -S path/to/session.vim the session is restored and saved when I exit, with a persistent buffer list on the left, and no errors during the session restore.