New Gameplay Video

Hi folks,

we are very proud to show our new gameplay video. The video is from Tim (321Spiele). Many thanks to Tim for is awesome video.

The new main features of this release are:

– Tutorial / Quest System
– Extended UI (questbook, event notification)
– AI Improvements / Stable
– People need to sleep
– new 3D objects (trees)
– new minimap
– eventsystem

Internally we had more than 100 tickets in this version with several improvements and preparation for further releases. But now we are on a good way to release much quicker than before and build more feature and more content. So stay tuned!

 

Time to Market – Reduce your build time with Ant and Ivy

Hi folks,

in the last days we prepared our non official release candidate 0.4.0. During this release, we optimized our dependency management and the release process to a fully automated process. I would like to share my experiences with you and show some example how to move from a manual process to a fully automated process. This article consists of two parts. The first part describes dependency management with Apache Ivy and the second part describes the build process with Apache Ant.

Dependency Management

Tool: Apache Ivy

Today, almost all Java based software has a lot of dependencies to other software packages in special versions. To manage all these dependencies by hand is really hard, especially if you have a distributed team and everybody has to manage the dependencies by himself. It is quite hard to keep everyone up to date with the same version of each package. In order to get rid of this you should use a tool which automatically manages your dependencies. After a short google you should find a bunch of tools with different pros and cons. Since we want to keep it simple, we decided to use Apache Ivy.

Let’s start

Since we are using Eclipse as IDE it is really easy to install Ivy. To install Ivy, click “Help -> Install New Software” and enter the url http://www.apache.org/dist/ant/ivyde/updatesite

At the moment we have the following dependencies (high level) in Drohtin:

  • JMonkey Engine (incl. some of their dependencies)
  • Nifty GUI
  • commons-io
  • Google Guava
  • Reflections
  • Javassist

Since JMonkey Engine and Nifty GUI are not in the normal maven repository we need to add their repositories to our ivy configuration. So we start with the main ivy configuration ivysettings.xml:

<ivysettings>
      <settings defaultResolver="default"/>
      <resolvers>
        <ibiblio name="public" m2compatible="true"/>
        <ibiblio name="jme3" m2compatible="true" root="http://updates.jmonkeyengine.org/maven"/>
        <ibiblio name="nifty" m2compatible="true" root="http://nifty-gui.sourceforge.net/nifty-maven-repo"/>
        <chain name="default" returnFirst="true">
            <resolver ref="public"/>
            <resolver ref="jme3"/>
            <resolver ref="nifty"/>
        </chain>
    </resolvers>
</ivysettings>

So what does this mean? In line 2 we are saying that Ivy should use the “default” resolver to resolve all dependencies. The lines 7 – 11 define which resolvers are included in the default resolver. These are public, jme3 and nifty which are defined in line 4 -6. Since jme3 and nifty are not default, we have to provide the root to these repositories.

Make sure that your Ivy eclipse plugin is using this new settings file. You can easily add this file, click “Windows -> Preferences -> Ivy -> Settings -> Ivy settings path”.

Now we have to tell ivy which dependencies our specific project has. Go to your project and create a new file with the name ivy.xml (either create it in top level of your project folder or in a new folder). The initial file looks like this:

<ivy-module version="2.0">
     <info organisation="de.drohtin" module="Drohtin" revision="0.4"/>
</ivy-module>

Now you have to add the dependency management to your project. In Eclispe right click your project and navigate to “Build Path -> Add Libraries -> IvyDE Managed Dependencies” and choose your created ivy.xml file.

The configuration above just defines your own project without any dependencies. This is fine if your project starts from scratch. As soon as you are starting to use libraries you have to add the dependencies in your ivy.xml file.

<dependency org="com.jme3" name="jme3-core" rev="3.0.10"/>

The following example shows the current ivy.xml file of Drohtin.

<ivy-module version="2.0">
    <info         organisation="de.drohtin"         module="Drohtin"         revision="0.5">
    </info>
    
    <dependencies>   
        <!-- JME3 Dependencies -->
        <dependency org="com.jme3" name="jme3-desktop" rev="3.1.0-SNAPSHOT" changing="true"/>
        <dependency org="com.jme3" name="jme3-niftygui" rev="3.1.0-SNAPSHOT" changing="true"/>
        <dependency org="com.jme3" name="jme3-blender" rev="3.1.0-SNAPSHOT" changing="true"/>
        <dependency org="com.jme3" name="jme3-jogg" rev="3.1.0-SNAPSHOT" changing="true"/>
        <dependency org="com.jme3" name="jme3-lwjgl" rev="3.1.0-SNAPSHOT" changing="true"/>
        <dependency org="com.jme3" name="jme3-effects" rev="3.1.0-SNAPSHOT" changing="true"/>
        <dependency org="com.jme3" name="jme3-core" rev="3.1.0-SNAPSHOT" changing="true"/>
        <dependency org="com.jme3" name="jme3-plugins" rev="3.1.0-SNAPSHOT" changing="true"/>
        <dependency org="org.lwjgl.lwjgl" name="lwjgl" rev="2.9.1"/>
        <dependency org="com.jme3-lib" name="oggd" rev="1.0.0"/>
        <dependency org="com.jme3-lib" name="lwjgl-natives" rev="2.9.0"/>
        
        <!-- Nifty Dependencies -->
        <dependency org="lessvoid" name="nifty" rev="1.4.1"/>
        <dependency org="lessvoid" name="nifty-default-controls" rev="1.4.1"/>
        <dependency org="lessvoid" name="nifty-style-black" rev="1.4.1"/>
        <dependency org="org.bushe" name="eventbus" rev="1.4"/>
        <dependency org="org.jglfont" name="jglfont-core" rev="1.4"/>

        <!-- Other Dependencies -->
        <dependency org="org.ogce" name="xpp3" rev="1.1.6"/>    
        <dependency org="java3d" name="vecmath" rev="1.3.1" />
        <dependency org="commons-io" name="commons-io" rev="2.4"/>
        <dependency org="org.javassist" name="javassist" rev="3.20.0-GA"/>
        <dependency org="org.reflections" name="reflections" rev="0.9.10"/>
        <dependency org="com.google.guava" name="guava" rev="18.0"/>
    </dependencies>
</ivy-module>

As you may notice we are using just the jme3 libraries that we really need. We are also using the 3.1 Snapshot version. You may also wonder what the “changing” attribute is doing. So in general Ivy build a local cache with all dependencies you need for all projects on your local computer. This improves the performance of Ivy and it works just fine if a specific revision of the library is not changing (that means the .jar file of version x stays the same). So if Ivy downloads version x and store it in the local in the cache, it will use this file all the time you are requesting version x (instead of downloading the file again). At the moment the revision of 3.1.0-SNAPSHOT stays the same but the .jar file is changing (without increasing the revision number). The changing flag forces Ivy to check the online repository all the time and download the file if necessary. This reduces the performance of Ivy.

So your Ivy dependency management is up and running and you can add each library you need. If a library becomes an update you just have to adjust the revision of your dependency and Ivy will automatically remove the old file and download the new one.

Build Management

Tool: Apache Ant

As a developer, you usually start your game from the IDE. The IDE takes care of all dependencies, resources and compiles your Java code. You just have to click the “start” button. At some point you may want to give your game to a friend to check it out or you want to publish the game. How do you export anything? Do you have a long list of things to do in order to make your game runable outside the IDE? How long does it take to export your game manually? And by the way – isn’t it boring to do the same export over and over again? Maybe it is time to automate your build process. There are also many tools, each has its own strengths and weaknesses. We choose Ant as our build tool, because it is easy to use and has an integration with Ivy.

Let’s start

Since we are using Eclipse as IDE, Ant is already integrated – Awesome!

Ant uses a build.xml file to store the tasks that should be executed for your build. You can define targets in that file which are necessary for your build process. You can define a target for each process in your build process. This allows us to structure the whole build process and divide it into small understandable task. So let’s start with a simple build file (create a build.xml in the top level of your project folder):

<project name="Drohtin" default="relase-all" basedir=".">
     <property file="${basedir}/build.properties" />
     <target name="release-all" description="Releases Drohtin" />
</project>

In the first line we define the project name and the default target to execute. The second line imports the build.properties file for this build process (later more about this file) and the third line defines the target “release-all”. If you execute this build file nothing will happen, because the “release-all” target has no task inside. The build.properties file is a key-value file and contains some variables for the build process.

Now we want to extend our build.xml that something happens. We start with a new target to set up some folder where we want to store the compiled classes.

<project name="Drohtin" default="relase-all" basedir=".">
     <property file="${basedir}/build.properties" />

     <target name="init" description="Creates necessary folder structure">
        <mkdir dir="${build.dir}" />
        <mkdir dir="${build.dir}/classes" />

        <ivy:settings file="${ivy.settings.file}" />
        <ivy:resolve file="${ivy.file}" />
        <ivy:cachepath pathid="lib.prod" conf="master" />
        <ivy:cachefileset setid="lib.prod.fileset" conf="master" />
        <ivy:retrieve /> 
              
     </target>

     <target name="release-all" depends="init" description="Releases Drohtin" />
</project> 

The target “release-all” depends on the target “init”. That means the target init will be executed before the target “release-all”. This allows us to structure the build process quiet good. Let’s have a closer look at the target “init”. At first we create two new directories (${build.dir} is a variable from the build.properties file; our value is “${basedir}/build”). We are using these directories to store artifacts of the build process (e.g. class files).  At second we set the Ivy settings (path to ivysettings.xml) and resolve the dependencies of your project (path to ivy.xml). The command ivy:retrieve store all dependencies in a lib folder in your project.

So far so good. Now we extend the build file to compile our code.

<project name="Drohtin" default="relase-all" basedir=".">
     <property file="${basedir}/build.properties" />

     <target name="init" description="Creates necessary folder structure">
        <mkdir dir="${build.dir}" />
        <mkdir dir="${build.dir}/classes" />

        <ivy:settings file="${ivy.settings.file}" />
        <ivy:resolve file="${ivy.file}" />
        <ivy:cachepath pathid="lib.prod" conf="master" />
        <ivy:cachefileset setid="lib.prod.fileset" conf="master" />
        <ivy:retrieve /> 
              
     </target>
     
     <target name="determine-classpath" >
        <path id="classpath">
            <fileset dir="${build.classes}/"/>
            <fileset dir="${lib.dir}/">
                <include name="*.jar" />
                <exclude name="*sources.jar"/>
                <exclude name="*javadoc.jar"/>
            </fileset>
        </path>
    </target>
     
     <target name="compile-drohtin" depends="init, determine-classpath">
        <javac includeAntRuntime="no" srcdir="${src.dir}" destdir="${build.dir}/classes" classpathref="classpath" source="1.8" target="1.8"/>        
    </target>

     <target name="release-all" depends="compile-drohtin" description="Releases Drohtin" />
</project>

We created two new targets and changed the dependency of the task “release-all”. The first new target is “determine-classpath”. This target defines our Java classpath. The classpath contains the directory ${build.classes} (incl. all files in that directory) and the directory ${lib.dir} (our value is ${basedir}/lib). The result is, that all our classes and our Ivy dependencies are in the classpath. The second new target is “compile-drohtin”. This target compiles our source code by using the javac command. It compiles all files in the srcdir and stores them into the destdir. It is also using the classpath we define in the target “determine-classpath”. If you execute your build file you should get a new directory /build/classes with all compiled classes of your code.

Okay, just some more things to do. Here is the final version of the build file:

<project name="Drohtin" default="relase-all" basedir=".">
     <property file="${basedir}/build.properties" />

     <target name="init" description="Creates necessary folder structure">
        <mkdir dir="${build.dir}" />
        <mkdir dir="${build.dir}/classes" />

        <ivy:settings file="${ivy.settings.file}" />
        <ivy:resolve file="${ivy.file}" />
        <ivy:cachepath pathid="lib.prod" conf="master" />
        <ivy:cachefileset setid="lib.prod.fileset" conf="master" />
        <ivy:retrieve /> 
              
     </target>
     
     <target name="determine-classpath" >
        <path id="classpath">
            <fileset dir="${build.classes}/"/>
            <fileset dir="${lib.dir}/">
                <include name="*.jar" />
                <exclude name="*sources.jar"/>
                <exclude name="*javadoc.jar"/>
            </fileset>
        </path>
        <pathconvert property="classpath.name" pathsep=" ">
            <path refid="classpath" />
            <mapper>
                <chainedmapper>
                    <flattenmapper />
                    <globmapper from="*.jar" to="lib/*.jar" />
                </chainedmapper>
            </mapper>
        </pathconvert>
    </target>
     
     <target name="compile-drohtin" depends="init, determine-classpath">
        <javac includeAntRuntime="no" srcdir="${src.dir}" destdir="${build.dir}/classes" classpathref="classpath" source="1.8" target="1.8"/>        
    </target>
    
    <target name="copy-data">
        <mkdir dir="${build.release}/data" />
        <copy todir="${build.release}/data">
            <fileset dir="${data.dir}" />
        </copy>
        <copy file="${basedir}/logging.properties" tofile="${build.release}/logging.properties"/>
    </target>
    
    <target name="copy-dependencies">
        <mkdir dir="${build.release}/lib" />
        <copy todir="${build.release}/lib">
            <fileset dir="${lib.dir}" includes="**/*.jar" excludes="**/*sources.jar, **/*javadoc.jar" />
        </copy>
    </target>
    
    <target name="release-drohtin" depends="compile-drohtin, copy-dependencies, copy-data">
        <echo message="classpath.name : ${classpath.name} " />
        
        <jar destfile="${build.release}/${dist.jar.name}-${project.version}.jar">
            <manifest>
                <attribute name="Main-Class" value="${main-class}" />
                <attribute name="Class-Path" value="${classpath.name}" />
            </manifest>
            <fileset dir="${build.classes}" includes="**/*.class" />
            <fileset dir="${basedir}/ressources"/>
        </jar>
                        
        <delete dir="${lib.dir}" />
        
        <echo message="Project ${dist.jar.name} released with version ${project.version}" />
    </target>
    
    <target name="clean-all" description="Delete data from former build.">
        <delete dir="${build.classes}"></delete>
        <delete dir="${build.release}"></delete>
    </target>

    <target name="release-all" depends="clean-all, release-drohtin" description="Releases Drohtin" />
</project>

First have a look at the two targets “copy-dependencies” and “copy-data”. These targets just copy all our Ivy dependencies and our data folder (in the data folder are all game assets like graphics or sounds) to the release directory. You may note that the libraries are copied to a /lib directory (we are doing this to have a clear structure). Since we changed the classpath of our libraries we extended the target “determine-classpath” with a conversion of the classpath. Finally the target “release-drohtin” builds the jar file by using the compiled class files. The manifest for this jar file contains the main class and our adapted classpath. After you executed your build process you will have a /build/release directory with your executable jar file, all dependencies and all data your game needs.

That’s all for now. I hope you enjoyed reading and it helps you a little bit with your dependency management and your build process. Questions and comments are very welcome.

Additional Information/Resources

Here is also the content of our build.properties file:

dist.jar.name = Drohtin
main-class = de.drohtin.DrohtinGS
src.dir=${basedir}/src
lib.dir=${basedir}/lib
data.dir=${basedir}/Data
build.dir=${basedir}/build
build.classes=${build.dir}/classes
build.release=${build.dir}/release
ivy.file = ${basedir}/ivy/ivy.xml
ivy.settings.file = ${basedir}/../ivysettings/ivysetting.xml

And our project structure and the locations of the mentioned files:

Project Structure

Project Structure

Game Message Menu

Hi folks,

after a while of silence we are happy to return with some new features we are currently working on. So we integrated a new event bus system in our game. This allows us to post and consume event all over the game. Let’s make an example:

  1. A new building becomes ready
  2. As soon as the building is ready, it fires a BuildingReadyEvent
  3. Event is consumed by the UI and notice the player that the building is ready

This brings me to the main topic of this post – the Game Message Menu. We create a new part of the menu where game messages appears. It is located in the upper left corner of the screen and is a list of item. The following screenshots shows the Game Message Menu with four item (at the moment all picture are equal but this will change):

Game Message Menu

Game Message Menu

The Game Message Menu is configurable. That means it is possible to choose which kind of events are interesting and which not. So everyone can adjust this menu for his own preferences.

As soon as an event happen in the game a new item shows up at the top of the list. If the max amount of items is reached the oldest item at the bottom of the list will be removed. That means the list always shows the top X events.

You can also click on an item to remove it. Depending on the item an additional action happen. For example if you click on an BuildingReadyEvent item, the camera will move to this building. Another example is a QuestEvent. As soon as you click on such an item the quest-menu opens.

So the new Game Message Menu is very helpful to get all important information from you village and the surrounding world.

I hope you like this new feature. Feel free to comment.

P.S. If you want to know more about the event bus and an example feel free to ask and I will provide an example.

New Ingame Menu

Hi folks,

we finally updated our ingame gui. We tried some new styles and finally we find a good one. The menu itself is not ready, but we want to show the current status of the development.

Menu_Overview

At the moment we have the 3 parts “top menu”, “build menu” and “unit menu” in our gui. Lets have a look in detail:

Top Menu

The top menu shows the current amount of the basic resources in the village you are looking at. It is possible to change the displayed resources and adapt it to your needs. Furthermore the top menu shows the resources available in this area of the map. With this information you can find a good spot for your village.

Top_Menu

Build Menu

The build menu shows all buildings. Each level of your village has a set of buildings. As soon as you reach the next level of the village you are able to build a new set of buildings. As you can see, we are planing 4 level. Each level will have 10 until 15 different buildings. That means the final game will have approximately 50 different buildings.

Build_Menu

Unit Menu

The unit menu has 3 parts. The first part includes the name of the unit (in this case the name of the building), a picture and the health of the unit. The second part contains unit specific information. In this case it contains the resource in this building (1 bole, 1 firewood). The third part of the unit menu contains buttons to interact with the unit. In this case it is a button to force that a carrier collect the resources stored in the building.

Unit_Menu

Outlook

We are planing to add a mini map and some kind of information strip with important information for the player.

We hope you like the new style of the gui. So feel free to comment and share your ideas with us.
Please do not forget to support us on Greenlight.

The Benefits of Tents

Hi folks,

today I would like to share our intention to create tents in Drohtin. At the very beginning of the game you will start with a bunch of people being somewhere in the wilderness. The resources in your storage are tight and you have to find a nice place to found your first village. In this early stage of the game it is very difficult to find the right place for each building and you probably want to move one or the other building to another spot. Since your resources (time and material) are very tight you can not build each building several times until you find the right spot.

In middle Ages tents are usually used for temporarily military camps, because tents are very flexible and cheap. Flexibility and a low price are exactly the requirements we want to cover. That`s why we decided to use tents for the first level of a village. So let`s have a look at the details and compare tents with normal buildings (houses) which are available in the next level of the village.

Construction Cost/Time

The construction cost of tents are very low. In general the construction cost of a tent is less than half of the construction cost of a normal building. Also the construction time is much shorter than the construction time of a building. That means tents are very cheep and fast to build.
The common resources to build a tent are Bole and Tent (Resource Overview).

Removal

You can remove each building in Drohtin. If you remove a building the worker can recycle some of the resource of the construction costs. The recycle rate depending on the type of building. A tent is 100% recyclable, that means you get all construction cost back. The recycle rate of a building is much lower (probably around 50% of the construction costs).

Replacement

All buildings are replaceable. The replacement of a tent is very fast and cost no resource. Some worker will remove the tent from the old spot, use exactly the same resource and rebuild it on the new spot. The replacement of a normal building takes much more time and additional resources.

Productivity/Capacity

Some of the tents are production buildings like the Woodcutter or the Stonecutter, other are storages like the Headquarter. The general size of a tent is small and that means there is less space available. Depending of the type of tent the small size has different effects. For example the storages of the Headquarter, the Woodcutter and the Stonecutter are smaller. Additionally the maximum amount of worker in the Woodcutter/Stonecutter tent is just 1 (in normal buildings are two or more workers). That means the productivity of a tent is much lower than of a normal building (at least 50%).

 Resistance

Since the construction costs (time and resources) are low and the used resources (Bole and Tent) are not very solid tent are not very robust against damage. Compare to a normal building, it is very easy to destroy a tent. It is also possible to steal a tent. Some enemy builders can remove one of your unguarded tent and capture the construction resources of this tent.

I hope you gain insight into the idea of tents. Feel free to comment. We are always open for ideas to force the difference between tents and normal buildings even more.