Ways to deploy a Java Game

When you develop Java games for PC, you have different ways to deploy them. We want to talk a bit about some of them.

Downloadable

The user has to download the game to run it on his machine, probably it comes with an installer to install the game before he can play it.

Pros

  • The game can be played offline when it has no online requirements.
  • User knows where the game is installed and sometimes decides where he wants to install it. They also can uninstall the game.
  • It is the only way to deploy a game in portals like Steam, Altitude Game is an example of that.

Cons

  • Users have to download a patch each time there is a new version. As a developer, you can implement something to download patches and apply them.
  • As a developer, you have to implement an installer. Also, you have to make different installers for each platform, an example of that is Revenge of the Titans (ROTT) from Puppy Games.
  • You have to create patches and deploy new files to be downloaded each time you have a new version of the game after a bug fix or new feature. Else, you force people to download large files each time you have an updated version.
  • Java Runtime Environment (JRE) must be installed or you have to embed JRE with your game. In the second case, your game file becomes bigger, for larger games that is not a problem but for small games embedded JRE could be, for example, 300% of the game size (at today, JRE weight is about 20MB). Even though there could be a JRE installed, being able to execute your program directly depends on a good configuration of the JRE within the OS. To solve that, developers usually generate a native wrapper that detects where the installed JRE is, and if it is not installed prompts the user to download one, or reports the error to the user.

Applets

Java Applets works inside the browser, as well as other web technologies like Flash and Unity. Users only have to open a page with a Java Applet inside and it is loaded by the web browser. Minecraft is an example of a successful Java Applet Game (it has other deployment options as well).

Pros

  • Users only have to follow a link to play the game. No game install is required.
  • Users are always playing the latest game version, because it is being downloaded from the server.
  • As other web technologies, you can add information or even ads to your applet page without having to put that inside the game.
  • Java Applets are as powerful as a Java Desktop application.
  • New Generation Java Applets accepts Java Networking Launching Protocol (JNLP) files (more info on next blog posts).
  • Pack200 and GZip compression support to reduce jar download sizes (only using plugin2).

Cons

  • JRE must be installed on the client machine. However, nowadays you can assume the required plugin is installed on most of the client machines.
  • You need a web server to deploy your game jars or you have to use a games portal like GameJolt or Games4j.
  • Dependning on the Java Applet technology you are using (plugin2, etc), firefox can freeze when the applet is loading, or could not work on Mac OS (more information on next blog posts).
  • As a developer, you need to sign your jars with a certificate if you want to have full access (to do extra stuff like writing a configuration file on user's home folder).
  • If you ask for full access, a security dialog box is displayed. It tends to scare users, if you have a valid certificate then it is a bit less scary.

Web Start

Java Web Start is some kind of mixing between the last two. As developer you use a JNLP file to describe which resources must be downloaded. Users only have to click on a JNLP link and then the game is opened automatically by Java Web Start.

Pros

  • Users only have to follow a link to play the game. No game install is required.
  • Automatically downloads the latest version of your game from the server each time the user wants to play a game.
  • It has a cache for downloaded resources, so if you only update one jar then it is the only one downloaded by the user's machine the next time the user opens the game.
  • As a developer you can specify to run the game offline.
  • It has a clean way to specify your game's resources using the JNLP file.
  • Pack200 and GZip compression support to reduce jar download sizes.

Cons

  • Some browsers are not configured correctly (for example, Google Chrome) and they don't open the JNLP automatically using Java Webstart, they just download the file.
  • Same thing with certificates and signing as the Java Applet.
  • As a developer you need a web server to put all your game's resources, we don't know any portal which accepts JNLP games yet.
  • Java Webstart Cache and Log files are difficult to find on user's machine.

Getdown

Getdown is a custom solution made by Three Rings in order to replace Java Web Start technology due to its limitations, as it is explained on Getdown's project Wiki. We lack experience and information about this solution, so the pros/cons section could be a bit empty.

Pros

  • Open source, that means you know what is happening, and you can collaborate, something impossible with Java Web Start.
  • Working examples of mmo games like Sprial Knights from Three Rigns and Tribal Trouble 2 from Oddlabs.

Cons

  • It is custom made. That means, as a developer you have to be aware that if something goes wrong you may have no support (note the conditional). But can't say it is really a cons because with Java Web Start you don't have any support at all from Oracle's team.

References

  1. Altitude Game - http://altitudegame.com/
  2. GameJolt - http://gamejolt.com/
  3. Games4j - http://games4j.com
  4. Getdown - http://code.google.com/p/getdown/
  5. Java Plug-In Technology - http://www.oracle.com/technetwork/java/index-jsp-141438.html
  6. Minecraft - http://www.minecraft.net/
  7. Oddlabs - http://oddlabs.com/
  8. Pack200 - http://download.oracle.com/javase/1.5.0/docs/guide/deployment/deployment-guide/pack200.html
  9. Puppy Games - http://www.puppygames.net/
  10. Revenge of the Titans - http://www.puppygames.net/revenge-of-the-titans/
  11. Sprial Knights - http://spiralknights.com/
  12. Steam - http://store.steampowered.com/
  13. Three Rings - http://www.threerings.net
  14. LWJGL Wiki - http://www.lwjgl.org/wiki/index.php?title=General_FAQ#Distributing_LWJGL_Applications

UPDATE: added link to LWJGL wiki page about how to distribute LWJGL Java Applications (most of them applies for Java Applications in general)

VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)

Games as Applets 2

Talking with kappaOne, one of the LWJGL developers, he pointed us that our applet solution has one problem. When js is disabled or it has failed to load, then the applet tag is not written, then the game is not loaded.

In order to fix this problem, we adopted part of his solution. He always creates the applet tag for the game and then hides it using js. If for some reason js fails, then the applet starts automatically.

The new html needed looks like this:

Html:

  
<div id="applet" class="applet" align="center">
	<applet id="gameApplet" width="800" height="600" code="com.gemserk.games.appletverifier.AppletVerifier" archive="http://www.gemserk.com/appletverifier-0.0.1-SNAPSHOT.jar">
		<param name="jnlp_href" value="http://www.gemserk.com/prototipos/zombierockers-webstart-release/launch-applet.jnlp" >
	</applet>
</div>

And this is the modified js with a merge between his solution and ours:

Javascript:

  
var width="800";
var height="600";
var jnlp_href="http://www.gemserk.com/prototipos/zombierockers-webstart-release/launch-applet.jnlp";
var screenshotUrl="http://blog.gemserk.com/wp-content/uploads/2010/12/zombierockers-screenshot01.jpg";
var appletTag;

var requiredVersion = '1.6.0_10+'
var attributes = { code:'com.gemserk.games.appletverifier.AppletVerifier',  width:width, height:height} ; 
var parameters = {jnlp_href: jnlp_href}; 

hideApplet(); 

function hideApplet(){
	var appletbox=document.getElementById('applet');
		appletTag = appletbox.innerHTML;

	if (navigator.appName == 'Microsoft Internet Explorer') {
		var params = "";
		var p = appletbox.getElementsByTagName("PARAM");
		for(var i=0; i < p.length; i++) {
			params += p[i].outerHTML;
		}
		appletTag = appletTag.replace("</APPLET>", params+"</APPLET>");
	}

	var isRequiredVersion = deployJava.versionCheck(requiredVersion);
	var text = ""
	var callback = ""

	if (isRequiredVersion) {
		text = "Click to play"
		callback = "showApplet()"
	} else {
		text = "You don't have java plugin enabled, click to install"
		callback = "installJava(\'" + requiredVersion + "\')"
	}

	// adds the screenshot inside the applet div
	var screenshotDivHtml = "<div id=\"screenshot\" class=\"play\" onclick=\""+callback+"\" style=\"width:"+width+"px; height:"+height+"px;\">";
	screenshotDivHtml += "<span>"+text+"</span>";
	screenshotDivHtml += "<img id=\"screenshotImage\" src=\""+screenshotUrl+"\" alt=\""+text+"\" width=\""+width+"px\" height=\""+height+"px\">"+"</img>";
	screenshotDivHtml += "</div>";

	appletbox.innerHTML=screenshotDivHtml;
}

function showApplet(){
	var appletbox=document.getElementById('applet');
	appletbox.innerHTML = appletTag;
}

function installJava(version) { 
	deployJava.installJRE(version);
}

You can see a working example here.

Thats all.

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)

Games as Applets

As you may know, we are publishing our games in two formats, Applets and Webstart. Applets works in a similar fashion as a Unity or Flash applications does, you open the web page and the game loads inside it. Webstart applications starts as a desktop application, outside the browser.

In this post we will explain how we deal with Java Applets. One thing we didn't like about applets is that they starts as soon as you visit the page, sometimes you want to visit a game page only to see some information or read comments, etc.

We created a workaround for that, it consists in showing a game's screenshot with a text "click to play" and whenever a player clicks on it, the game is started.

Implementation

Our solution consist in a css with the styles to show the screenshot with the text and a javascript with the logic to change the screenshot with the Java Applet.

First we have styles to show the text over the screenshot and highlight it whenever the user moves the mouse over it.

Style:

  
.play {
	display:block;
	position:relative;
	-moz-opacity:0.80;
	opacity:0.80;
}

.play span {
	-moz-opacity:0.60;
	opacity:0.60;
	display:block;
	position:absolute;
	top:225px;
	z-index:100;
	width:100%;
	color: white;
	font-size: 80px;
	text-align: center;
}

.play:hover span {
	-moz-opacity:1;
	opacity:1;
	display:block;
	position:absolute;
	top:225px;
	z-index:100;
	width:100%;
	color: white;
	text-align: center;
}

Then, we have some javascript to create the screenshot div dynamically, and to replace it with the applet tag when the user clicks on it, or send the user to install the needed version of Java if he hasn't installed yet.

Javascript:

  
	var requiredVersion = '1.6.0_10+'
	var width = "640"
	var height = "480"
	var screenshotUrl = "floatingislands03.jpg"

	var url = "launch-applet.jnlp";
	var attributes = { code:'org.newdawn.slick.AppletGameContainer',  width:width, height:height} ; 
	var parameters = {jnlp_href: url}; 

	var isRequiredVersion = deployJava.versionCheck(requiredVersion);
	var text = ""
	var callback = ""

	if (isRequiredVersion) {
		text = "Click to play"
		callback = "startGame()"
	} else {
		text = "Click to install Java"
		callback = "installJava()"
	}

	var screenshotDivHtml = "
"; screenshotDivHtml += ""+text+""; screenshotDivHtml += "\""+text+"\""+""; screenshotDivHtml += "
"; var appletElement = document.getElementById('applet'); appletElement.innerHTML += screenshotDivHtml; function startGame() { var screenshotElement = document.getElementById('screenshot'); var appletElement = document.getElementById('applet'); appletElement.removeChild(screenshotElement); var oldwrite = document.write; var newHtml = ''; document.write = function (str) { newHtml += str; } deployJava.writeAppletTag(attributes, parameters); document.write = oldwrite; var realAppletElement = document.getElementById('realApplet') realAppletElement.innerHTML = newHtml } function installJava() { deployJava.installJRE(requiredVersion); }

Also, we will need to add two divs to the html to make the javascript to work.

Html:

  

That's all, if you want to take a look at a working example, click here.

VN:F [1.9.22_1171]
Rating: 5.0/5 (2 votes cast)

Android development

We have been wanting to try the Android platform for some time and just recently bought an HTC Desire phone (It rocks, not so much the multitouch implementation).

Right now we are:

  • Investigating the platform, going through the API and Best Practices, to see what kind of games we can do, and how easy it is.
  • Decoupling our engine from some libraries like Slick2d and Groovy in order to test if we can reuse it for Android development.

One huge issue with Android right now is that the market has support for selling apps from a little list of countries. Of course Uruguay which is where we are from is not one of those. So we have to see if we can make things that can be supported with ads, donations, other markets (not the main android market), or some other solution.

We will be making some update when we have more knlowledge about this interesting platform.

VN:F [1.9.22_1171]
Rating: 4.0/5 (1 vote cast)

New way to show our games

As the title says, we have changed the way we were showing the games.

Now, we have a page for each game showing a screenshot, the game's description and links to play it as an applet or via webstart. This is the page where we would add any content about the game like videos, faq, reviews, comments, etc.

One objective of this change was to make applets more friendly letting you see information about the game before interrupting you with the applet loading and also a friendlier message when you don't have the correct version of the java plugin for your browser.

If you click on the play as applet link, a new page is displayed showing an image of the game and the game's instructions, you can load the applet by clicking on the image.

Hope you like the change.

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)

First attempt at Highscores for games

We are doing our first attempt at implementing online highscores for our games.

Our Score structure right now is:

Score { 
  id : String   - The unique identifier
  name : String - The name of the player 
  points : long - The value of the score
  timestamp : date - The time when the score was submitted
  tags : Set[String] - A set of tags of the score
  data : Map         - Extra data of the score
}

The tags are used to classify the scores by different criteria, for example, the difficulty, the level, etc.

Data is a map of simple values used to add extra information of the score, like bombs left when the user died or enemies killed of each type, etc.

The idea is to have an online application for the highscores of all the games. All comunication is performed using a gameKey which is unique for each game and allow us to separate the scores by game.

Our current API consist of a submit method and a query method and it is based in HTTP and JSON.

 submit(gamekey : String, name : String, tags : Set[String], 
    points : long, data : JSONString) : String

This method allows us to submit a new score and returns the generated id for it. The extra data attached to the score is specified by a JSON string. The timestamp is generated at the moment the score is stored.

 scores(gamekey, tags, limit, ascending) : List[Score]

This method allows us to query for scores of a game by using:

  • tags : returned scores must have every tag in tags
  • limit : returned quantity must be less than limit
  • ascending : if true scores are returned ordered by points ascending

Our first implementation will be based in google app engine but is not online yet, and Jylonwars will be the first game using it.

There are some features we are thinking about:

  • Security: the submitted scores should be encrypted and validated (we know it is not totally safe but it would prevent casual tampering)
  • Online scores board

Also, we are thinking about making the server project opensource.

VN:F [1.9.22_1171]
Rating: 4.0/5 (1 vote cast)