Friday, July 26, 2013

Helpful Java Libraries: Notes from my IndyJUG presentation

INTRODUCTION



Yesterday, I gave a presentation at the meeting of the . The presentation, "Serious Game Development in Java," gave some background about how I transitioned from game hobbyist to serious game development researcher, and I talked about my two successful Java-based serious games: and .




A portion of the attendees at the IndyJUG meeting



Usually when I talk about these projects, I am describing the environment, my experience working with multidisciplinary undergraduate teams, or design and evaluation processes. Given that this crowd was primarily professional Java programmers, I decided to take a different tack, and I talked about the software architecture and what I learned by building these games. In particular, I talked about some of the libraries we incorporated into the game. Several attendees asked me if I could share more information about the libraries and why I chose them, so I decided to write this follow-up.



MORGAN'S RAID



Morgan's Raid was written using , which had been my go-to library for Java game development. However, the original developer and maintainer, , has moved on from the project, and it seems to be struggling now. Kevin did a good job keeping the libraries in sync with the native libraries of , and with him off the project, I would not recommend starting new projects in Slick2D. Kevin has moved on to , which looks like an interesting project, although I prefer , as described in the next section.



Here is a brief description of the other libraries we used in Morgan's Raid. For brevity, I'm not including their transitive dependencies, but note that managing transitive dependencies on this project is precisely why I was blown away by , as described in the next section.



* : robust handling of command-line arguments, which we used to easily modify runtime behavior, e.g. fullscreen vs. windowed mode

* : robust handling of application configuration, such as animation speed, default volume, etc.

* : mocking library for test-driven development

* : broad and robust library that simplifies Java development, making particular use of the , , andclasses.

* : all the time calculations are handled with this fantastic library, and if you're doing any time-based logic, you should be using it too.

* : parser for , which we used to describe the cinematic scenes in the game

* : though not a library, we used this for continuous integration



I have several posts on this blog about the design and development of Morgan's Raid. If you're new, here are some of the most descriptive:EQUATIONS SQUARED



When I began work on this project, I knew I wanted to develop an HTML5+Javascript solution with the least possible amount of pain. I evaluated several possibilities and settled on . This amazing library allows cross-compilation of the same codebase to desktop Java, HTML5+Javascript (via ), Android, and iOS (and Flash, kind of, but its support has not been great).

PlayN relies upon to manage dependencies and project configuration. It took me some time to make sense out of how it was working, but now it's hard to imagine going back to manual dependency management. In Morgan's Raid, for example, when I wanted to add a new library, I had to manually download the binaries, and all the binaries of its transitive dependencies, put them into my project's lib folder, configure the build path, configure native libraries if necessary, and then hope that all the different libraries would work together. To upgrade any library to a new release, which happened to some of our core libraries during development, I had to repeat this process by hand. By contrast, to add, say, to Equations Squared, I just added this to my pom file:



org.mockito

mockito-all

1.9.0

test



That last bit, the scope, is really fascinating: it says that the project should use Mockito only when running unit tests. Scopes aren't needed for most of the libraries I use, but this example shows how simple a process it is to specify them. Also, need to update to a new release? Just update that version tag and Maven takes care of the rest.



Speaking of Mockito, it has become my favorite mock object library for Java. The API design is elegant and allows for readable code with minimal boilerplate. Here's a sample unit test--the same one I showed in my IndyJUG presentation--that demonstrates Mockito. By way of explanation, this code builds a token list containing "-" and "1", parses it into the expression "-1", then creates a visitor object and hands it to the expression. The expected behavior is that the visitor visits two nodes in the parse tree: the unary negation and the value 1. Note that mock and verify are static calls to the Mockito library.



public void testVisitorHitsNegationAndInteger() {

tokens = ImmutableList.of(

SymbolToken.MINUS,

IntegerToken.create(1));

Expression e = parseTokens();

Expression.Visitor visitor = mock(Expression.Visitor.class);

e.accept(visitor);

verify(visitor).visit(UnaryOperation.NEGATE);

verify(visitor).visit(1);



Equations Squared uses the , , and libraries from . Pythagoras is a collection of geometry utilities that is well described . React brings functional reactive idioms and the slots/signals idiom to Java, and that merits a small example. My GameView class exposes a signal with a method like this:



public SignalView onGameOver() {...}



Any agent in the system that needs to know when the game end condition is met can connect a slot that is notified when the signal is emitted, for example:



game.onGameOver().connect(new UnitSlot() {

public void onEmit() {

displayListOfBadgesAndDemerits();



Signals can have type parameters as well, though here I am using the simplest form. React also provides convenient value objects that emit signals when values change:



Value v = Value.create();

v.connect(new ValueView.Listener() {

public void onChange(Integer newValue, Integer oldValue) {

// Handle change here.



As you can see, what I'm doing is using React to provide convenient, quick, efficient reification of the . No extra boilerplate required here, no fat interfaces and adapter classes: just hook up slots and signals and get going.



Where PlayN provides a low-level API for game development, provides many of the niceties one needs to get games up and running, such as handling screen transitions, layer animations, and UI widgets. One of the reasons I love TriplePlay (and PlayN) is that the designer takes care to support programming idioms. This is a direction I have been taking much of my own development as well. Consider this example from Equations Squared that handles popup notifications:



tweenTranslation(popup.layer())



The code reads exactly as one would explain the animation sequence. When source code is as short and expressive as it needs to be to convey an idea, that's a good program. Working with some of the fluent styling API in TriplePlay takes a little getting used to, especially if one comes from a push-button background as in Swing. However, I really felt like my own ability to express myself fluently in Java increased after learning to use TriplePlay.



For more on Equations Squared, check out .



ACKNOWLEDGEMENTS



I want to thank for inviting me to present, and to all the IndyJUG community for their warm welcome. The event was graciously hosted by , and I could tell by their amazing facilities that they are a company who takes their work seriously and respects their employees. Check out this centrally-located kitchen!



The E-gineering Kitchen



I also want to recognize the valuable contributions of the , , andfor their support of open source software development, as well as the significant contributions ofto Slick2D and to the whole PlayN ecosystem.
Full Post

No comments:

Post a Comment