15. November 2011

Eclipse has this annoying habit of using the JRE instead of a JDK you have installed.  It isn’t immediately obvious what is happening until you attempt to build a project.  For example, I just move some PlayN source to a new laptop and when I try to compile I get:

[ERROR] Failed to execute goal on project tictactoe: Could not resolve dependencies for project com.gamefromscratch:tictactoe:pom:0.0.1-SNAPSHOT: Could not find artifact com.sun:tools:jar:1.6 at specified path C:\Program Files (x86)\Java\jre6\..\lib\tools.jar -> [Help 1]
[ERROR]

Which can be a bit of a head scratcher if you haven’t been bit by it before, but there error is exactly right, the JRE unlike the JDK doesn’t have everything installed, including the aforementioned tools.jar.  Fortunately the fix is quite simple.

In Eclipse, select the Window menu->Preferences.  Then select Java->Installed JRE’s.  Then click Add… select Standard VM then click Next.  In the JRE home, navigate to the folder you’ve installed the JDK to ( c:\Program Files\Java\jdk1.6.0_21\ in my case ).  It will now churn away for a while.  After a few seconds, it should look like this:

Now click Finish.

This will bring you back to the installed JRE’s window, unclick the JRE and click your newly added JDK, like this:

And voila!  you are now configured to properly use the JDK instead of the JRE in Eclipse.  So if you run into the error saying tools.jar is missing and you are using Eclipse, this is probably the problem.

If you launch Eclipse from the command line or via a shortcut, you can also set this value using the –vm command line setting, simply type:

eclipse.exe –vm c:\path\to\jdk\bin\javaw.exe

14. November 2011

Chapter 8 of the GFS beginner C++ tutorial, Pang! is now live and can be accessed here.

This chapter represents a bit of a break from the norm, in that it deals with code design more than it does actual SFML and game implementation.  I actually had a great deal of fun writing this chapter, but the end result is very little usable code.  There is a companion post to this one that illustrates much better use of SFML’s audio classes, that should be up shortly.  That said, I think you could learn a great  deal from this post, it may even alter the way you program!

Instead this post introduces the concept of design patterns and illustrates a way to de-couple  your code, so you don’t end up littered with global and manager classes.  It covers a concept that I have never seen covered by a game tutorial before, but then, there might be a good reason for that!

So give it a read and let me know what you think.  Would you like to see more posts like this, or would you like me to focus on more implementation specific aspects?

12. November 2011

The new update should make the install process even easier. The process still works the same, just now with less annoying warnings and work around required.  Also, the Java (target) has been split out as an individual sub-project, a move which makes lots of sense.  I would describe why, but frankly the original author Michael Bayne did a good job already.

Howdy everyone,

I just released PlayN 1.0.1 to Maven Central (and the mirroring to the
public servers is complete).

This release corrects a bunch of pesky errors relating to building
PlayN that crept into the 1.0 release in the eleventh hour.

It should now be possible to import the PlayN sample projects and to
create a new PlayN project using the Maven Archetype without
encountering a single error or mysterious weirdness in Eclipse. I
would have liked to be able to say "warning or error," but annoyingly
my Eclipse complains that certain XML files lack a DTD specification,
which seems excessively anal to me, but that's how they like to roll
over there at Eclipse HQ.

One other important change was introduced in this release. The PlayN
archetype now generates a separate "java" submodule which contains the
Java backend entry point file (FooGameJava) and which has a dependency
on playn-java. The core submodule now only depends on playn-core.

Prior to this change, the core submodule depended on playn-java (and
by transitivity playn-core) and the Java entry point was in the core
submodule. This eventually causes problems, because all of the other
submodules (html, android) depend on the core submodule, and if one
added some Java-only dependency to their code submodule so that they
could use it when testing with the Java backend, it would show up in
the html and android submodules and cause problems. Now the core
submodule can remain "pure" with only PlayN-safe dependencies, and if
to the java submodule where they won't cause problems with the other
submodules.

Because the Java entry point is in a separate project, it is now
necessary to test the Java backend via Maven in a different way.
Instead of "mvn compile exec:java" in the core submodule directory,
one now invokes "mvn test -Ptest-java" in the top-level project
directory. This is more consistent with the way the HTML backend
works, so that's nice. It's also unfortunately a little slower, and
when you're rapidly edit/compile/debugging, every millisecond counts.
The "ant run-java" target still works great in this new setup, and
remains very fast, so I recommend that command line users use that to
iteratively build and test their project. Eclipse users will now "Run
As -> Java Application" on the mygame-java project instead of the
mygame-core project, but otherwise everything is the same.

Due to current-working-directory related issues exacerbated by the
creation of the java submodule, I rewrote the Java asset manager to
directly from the file system (fragile). This means that you'll need
to make a change to your Java entry point. Where you probably had
something like:

platform.assetManager().setPathPrefix("src/main/java/playn/showcase/resourc es");

you should now use:

platform.assetManager().setPathPrefix("playn/showcase/resources");

As a fringe benefit, this was one of the main challenges preventing
the packaging of the Java backend up for use as a Java applet. Now
that this has been fixed, there are probably only a few niggling bits
that need fixing, and PlayN games can be deployed as Java applets by
anyone crazy enough to want to do so. :)

Also, for those of you using sound in your games, the Java backend
used to require that you maintain separate .wav versions of your sound
resources. The HTML backend used .mp3 versions of said resources. The
Java version has been updated so that it uses the .mp3 versions as
well, so you no longer need to maintain .wav versions of your sounds.
Sounds on the Android backend remain largely untested (meaning they're
probably broken), but when I get a chance, I'll make sure that they
also work properly with .mp3 files, so that things remain consistent
across platforms.

Between these and other small improvements to the archetype, it is
probably worth the small bit of trouble to regenerate your project
from the latest archetype, and move your sources and resources into
the new project, just to be sure that all the little fixes that have
Alternatively, you could generate a new project using the latest
archetype with specifications equivalent to your project and then diff
the files that were generated against those in your project and
migrate any fixes you find into your project. Whether one or the other
is easier will depend on how much you've customized your poms.

The flash submodule has been completely disabled in the latest
archetype. If the Flash backend is made functional again, it will be
reinstated.

The other key things to note is the removal of the Flash target ( which was apparently quite a ways from ready for prime time, and was breaking the build ).  Anyways, good job to the PlayN team.

9. November 2011

According to ZDNet Adobe just took Flash for mobile out to the pasture and put a bullet in it.

Our future work with Flash on mobile devices will be focused on enabling Flash developers to package native apps with Adobe AIR for all the major app stores. We will no longer adapt Flash Player for mobile devices to new browser, OS version or device configurations. Some of our source code licensees may opt to continue working on and releasing their own implementations. We will continue to support the current Android and PlayBook configurations with critical bug fixes and security updates.

I am no fan of Flash, but frankly HTML5 isn’t even close to be a valid replacement yet.  This move seems ill advised at best and downright stupid at worst.  I know hands down my Asus Transformer tablet gets far more usage than my iPad simply because it supports Flash.  If there was a valid rich media alternative to products like Flash and Silverlight, I would be all over it, but that technology sure as heck isn’t HTML5!

I don’t really have any stakes in this game at all, but I do think it was an ill advised play by Adobe.  So they are basically going to become a pure tools provider going forward?  This is a bit odd, as I’ve understood it, AIR was a bit of a flop?  Regardless, a move focusing more on AIR and away from Flash, is a move into being fully a development tool provider and out of being a platform provider.  One of the biggest sales bullets for desktop flash, it’s ubiquity, just went away.

9. November 2011

Along with many others, I don’t really recommend C++ as someone’s first language for various reasons.  Sometimes concrete examples aren’t easy to come by off the tip of your tongue, so I figured the next time I encountered one of those things that make C++ so beginner unfriendly, I would post it.  Not the obvious stuff like memory leaks, dealing with the linker or exceptionally cryptic template errors, but the more benign stuff that add up to frustrate new and experienced users.  If you are a veteran C++ coder, you will probably spot the problem in a second or two, but this is the kind of thing that will trip up a beginner completely and is a complete nightmare to solve.

Consider the following C++ header file:

#pragma once

#include "SFML/Audio.hpp"

class SoundFileCache
{
public:
SoundFileCache(void);
~SoundFileCache(void);

const sf::Sound& GetSound(std::string) const;
const sf::Music& GetSong(std::string);

private:
static std::map<std::string, sf::Sound> _sounds;
static std::map<std::string, sf::Music> _music;
};

class SoundNotFoundExeception : public std::runtime_error
{
public:
SoundNotFoundExeception(std::string const& msg):
std::runtime_error(msg)
{}
}

Pretty straight forward stuff right?  Two class declarations, nothing really funky going on.  Now consider the following implementation:

#include "StdAfx.h"
#include "SoundFileCache.h"

SoundFileCache::SoundFileCache(void) {}

SoundFileCache::~SoundFileCache(void) {}

const sf::Sound& SoundFileCache::GetSound(std::string soundName) const
{
std::map<std::string,sf::Sound>::iterator itr = _sounds.find(soundName);
if(itr == _sounds.end())
{
sf::SoundBuffer soundBuffer;
{
throw new SoundNotFoundExeception(
}

sf::Sound sound;
sound.SetBuffer(soundBuffer);
_sounds.insert(std::pair<std::string,sf::Sound>(soundName,soundBuffer));
}
else
{
return itr->second;
}
}

const sf::Music& SoundFileCache::GetSong(std::string soundName)
{
//stub
}

Again, pretty standard code, ignore the fact GetSound and GetSong don’t return values, they aren’t the issue here.

Now consider the error:

error C2533: 'SFMLSoundProvider::{ctor}' : constructors not allowed a return type

If you are new to the expression ctor, it basically just shorthand for constructor. For the record, it’s Visual Studio Express 2010 and if you double click that error, it brings you to this line:

SoundFileCache::SoundFileCache(void) {}

So… what’s the problem?  By the error, it is quite obvious that the constructor doesn’t in fact return a value, so the message is clearly not the problem.

What then is the problem?  I’ll show you after this brief message from our sponsors…

Welcome back… figured it out yet?  If not, I don’t blame you, the warning sure as hell didn’t help.  Here then is the offending code:

class SoundNotFoundExeception : public std::runtime_error
{
public:
SoundNotFoundExeception(std::string const& msg):
std::runtime_error(msg)
{}
} <-- Missing semicolon

So, forgetting a semi colon ( something you will do A LOT! ) results in a message that your constructor cannot return a value.  Now, once you’ve been coding C++ for a while this kind of stuff becomes pretty much second nature.  Getting nonsensical error messages?  Check your header for a missing include guard or semi colon become pretty much the norm.  But for a new developer, this is the beginning of a complete train wreck.

Think about if for a second, you just developed some of your first code, the error says you are returning something you aren’t, the compiler is pointing at your constructor and now you need to figure out just WTF is going on..  What do you do?  Many run off to a forum and post the error verbatim and hope for an answer ( which they will probably get, learning nothing in the process ). Hopefully you Google it using exact quotes, but even then you get forum answers like this where you have a bunch of other new developers fixating on the error message itself and leading the developer down a wild goose chase.  Fortunately a moderator stepped in and gave a proper explanation, but that doesn’t always happen.  Even worse, it is a legit error, you really can’t return from a ctor, so if you encounter it again in the future you may actually have a real problem but find yourself instead on a missing semi-colon hunt!

How would this work in Java, C#, Python or Ruby?  Well it wouldn’t, as no other modern language I can think of use header files any more.  For good reason too, they add a level of complexity for very little positive return.  It could be argued that separating interface from implementation is “a good thing”, but even that is munged up by the fact you can actually have you implementation in your header file.  Also don’t get me wrong, other languages have their faults too, just wait till you get forced to go on your first Java XML configured error hunt, you will be begging for C++ errors again!

This is just a classic example of the little things experienced developer forget the pain of experiencing in the first place!  As I said, once you’ve got a bit of experience this kind of stuff becomes second nature, but while you are learning this kind of error is absolutely horrific.  It’s little things like this that add up and make it so hard to recommend new developers start with C++.  When I say it isn’t pointers and memory management that make C++ difficult, I mean it.  It’s crap like this.