Friday, 10 March 2017

GDC 2017

A couple of days ago I returned from sunny San Francisco where I was attending GDC 2017. I'm at a loss for words to describe how amazing the whole event was. It is absolutely mind blowing to meet so many people from the industry, to share ideas and just to nerd out. Talks were super interesting but as everyone knows, the evenings are the heart of the whole event.

During the first day, on the Narrative Summit I also delivered a talk about Quests and Non-linear Narratives in Horizon: Zero Dawn (full talk is freely available in the GDC Vault, presentation slides are already available at the Guerrilla Games website). Where I talked about the Quest System I built and designed for Horizon: Zero Dawn, our process in creating it and our approach to non-linear narratives. It's sort of a Engineer's Approach to Game Narrative :P

I never talked at such a important event before so I was pretty scared and breathless. However it would seem it all went quite well, the I reception I got was amazing. The fact that the game was critically well received undoubtedly helped as well (currently 89 on Metacritic!). Afterwards I was answering questions for an hour, so I missed the following talk (sorry Amy!).

One of the coolest things that happened to me during the conference was meeting Jeff Howard. Who had his own talk: Force and Fire: Making Your Game More Metal (also available on the GDC Vault, but account is needed for access). He wrote an amazing book about quests in video games (Quests: Design, Theory, and History in Games and Narratives), which I used to create my talk and even quoted at the very beginning. The meeting was unexpected to say the least :D



Apparently some of the game press also found the talk worthwhile, which blows my mind even more:
 My friends at Guerrilla Games also gave talks on other topics:

Friday, 29 July 2016

libGDX and Editor update

Over the past year I've made some significant changes to the Zaria framework and the Zone Editor. Polish, improvements but also I slimmed down it a bit.

Zaria has been working for a very long time on top of jMonkey Engine 3.0. As amazing as that engine is it proved a bit troublesome at times. Quite a bit of my game projects hit significant delays, because functions that would be expected to just work, would not. All 3d projects hit problems with physics, stable rendering of shadows or general performance. All of these can be worked out of course, but my ambition was never to write a game engine, it was to create a framework for quick development of cRPGs (along with such games).

Given all that I decided to take a step back and more conservatively look at what can be done. It would seem that for the time being scaling down and developing a 2d game was a good way to go.

jME3 is great 3d engine, but is not particularly good for 2d projects. I decided to look at the other big Java game engine/framework - libGDX which had very good 2d support (as well as some other really cool features like HTML5 support).

Switching the backend is never simple. So it took a while to decouple Zaria from jME3. The benefit of that is that Zaria and the Zone Editor is now agnostic in regards to backends. It can be used for any Java game engine and all specific code is now put in separate libraries. It also made development for Android simpler as I abstracted all desktop specific code as well.

There are many things still to do. Fixing jME3 support to work with the new abstracted logic (I've been working exclusively with libGDX for now), adding a plugin architecture to the editor, so custom, engine specific editors could be added easily, while still making the core editor engine agnostic, adding netbeans/eclipse plugins for common Zaria actions and types, improving documentation and howtos. However this drastic change was good for the whole project. Made me think what it is actually supposed to be doing and how to implement it in a clean way.

Along the way I managed add two new features to the editor that I really like. One is suggestion support to the script editor, to make scripting even easier:


Now when scripting Ctrl+Space will show a dropdown with all possible functions that can be used at the given moment (pretty much like any IDE).

Another thing is I added support for Value and Function types. These can be used by different definitions provide a value (like how far the fireball can go in regards to character magic stat). However because thet are definitions by themselves, they are easy to tweak from the editor. Plus the CurveFunction got its own custom editor (strongly inspired by the libGDX Particle Editor):


You can add points which will define the function, zoom in and zoom out. Currently three types of functions are supported: Linear Interpolated, Spline Interpolated and Polynomial.

And yes I did (finally!) change the color scheme to dark.

I'm continuing to work on the project. New cool things are coming.

Tuesday, 10 March 2015

Escaping the vacuum

Unless you're an astro-engineer it doesn't make sense to build stuff in a vacuum. Tools, whatever they may be, have to be tested and proved in action. And the best way to test a game editor and framework... is to make a game :D

So I started working on small hex based project, using Zaria.


The game itself is progressing slowly but steadily. I'm able to iterate relatively quickly and it's very easy to make systems data driven. Overall, not bad, although a lot can be still improved. The effect on the framework and the editor has already been very, very positive. I found a million bugs, identified a million more of annoyances, and one by one I'm getting rid of them.

The biggest problem I have right now is the way objects are identified. Currently the user needs to input a unique string for every object definition. It makes sense for objects that are being used explicitly later on, but the majority are not. What I want to do is to switch to a system, where only some objects have an user generated ID, but all will have an automatically generated UUID (using http://docs.oracle.com/javase/7/docs/api/java/util/UUID.html), which will be used internally by all systems to identify definitions.

Saturday, 23 August 2014

More Editors!


The Zone Editor was made so that any kind of game data could be edited in a single coherent way. However very often specific elements benefit from having custom editors. The map editor is good example of that - it is much easier to create a map using a 3d view than in text or graph format.

Some time ago I added an additional editor for Entity Instances and now the time has come to add more:


Editing particle effect emitters.

Editor for materials. Works for all MaterialDefinitions.


Viewer for geometries.

I made a small framework for this type of editors, so adding a new one is as simple as implementing a function that creates a spatial from a object definition.

Sunday, 6 July 2014

Simplifying scripting

Using scripting languages in game development has been common for years. And for good reason - most of them are easy to learn, and the lack of compilation decreases iteration time. Right now pretty much every major game engine has a scripting layer. Zaria too. It uses slightly modified JavaScript running on top of Rhino.

During my previous game projects I also used a variety of scripting languages: UnrealScript, NWScript, Lua etc. While working with them I found one thing really annoying - in most cases without browsing through a wiki or looking through documentation I had no idea what the available API was. Going through various web pages, or even printed documentation made it difficult to get back into coding. It's easy to loose focus and more difficult to get it back again.

With compiled languages it's easier. Their strict structure makes it simpler to implement various code completion and suggestion tools, which in turn makes exploring the available APIs quicker.

What Aurora (and Electron) toolset had, was a searchable, drag'n'drop list of all available script functions right next to the editing area - extremely useful stuff. I really missed such a feature when working with Unreal Engine 3 on Blade Lords.


In order to not repeat past mistakes and learn from good examples I decided to implement a similar feature in the Zone Editor.


A searchable palette on the right lets the user drag any available function right into the script. Functions are grouped by category, which can be defined by whoever creates the script function. Tooltips also provide some basic information on what the function does. Also to make it even more easy, other scripts can be dragged from the file view into the editing area, which will result in a properly resolved import.

On the code side adding a new script function is really easy. Just create public static method and add the @ScriptFunction annotation. The editor will parse this data and show the function in the palette.

There are other features I can imagine that could further enhance script writing, but for now I think this already makes stuff much clearer and simpler.

Thursday, 3 July 2014

Adding lights to entities

I implemented static lightmap support some time ago with nice results. However moving stuff did not yet have a lighting solution.

I wanted to have something in which the data for lighting would be common for static and dynamic objects. What I what I came up with is to save the light data (position, color, power, radius) that is used to generate lightmaps and use it also to create localized lights for entities.

By localized I mean that each entity creates its own set of lights, which affect only it. This allows for attaching quite a lot of them, as the lights will affect only a small amount of geometry and gives a lot opportunity for LOD optimizations. The only down-side is that this method will not support shadow casting. However, in the end, this is not that big of a drawback, as such an amount of dynamic shadows would kill the framerate anyway.

I created a component for that, so making an entity dynamically lit, is now trivial. The first test can be seen here:


The map from which this video was taken:

The scene had 8 lights and with 7 entities the fps was around 2700. So far not bad.

Saturday, 21 June 2014

Multiple files from a single wizard in NetBeans

I've been fighting with NetBeans modules recently. I wanted to add templates for common class types used in Zaria. Half of them, in order to be useful, go in pairs: Object + ObjectDefinition.

To make the process as easy as possible, I wanted to be able to crate both files using a single dialog or wizard. Meaning: If I choose to create a new EntityComponent then both NewEntityComponent.java and NewEntityComponentDefinition.java get created with all boilerplate code in place.

I managed to do that. However, either because of bugs or weird design decisions, it is far from straightforward.

Ok. So how to do it?


First have a look at https://platform.netbeans.org/tutorials/nbm-filetemplates.html

It shows how to create a new module that will generate a new file from a template. It is a good beginning and in theory should be all you need.

The annotation @TemplateRegistration in the field content can take multiple files. Spec says that the default New File wizard should then create both files using the input templates.

However the reality is different:
  • Only the first file is created. To fix this you need to create your own custom wizard.
  • If you want to generate java classes from templates, you need to call the template file xxx.java.template Otherwise the module will not compile.
 

How to create your custom wizard?


Although it shows more than needed here, a good initial tutorial can be found at https://platform.netbeans.org/tutorials/nbm-wizard.html

In the New Wizard dialog choose New File instead of Custom. This will remove some of the complications and will make the wizard automatically work with New File menu in NetBeans.

Annotate your wizard as in the first tutorial:
   @TemplateRegistration(  
     folder = "Zaria",  
     iconBase="eu/cherrytree/zaria/modules/filetemplates/zaria_file.png",  
     displayName = "#EntityController_displayName",  
     content = {"EntityController.java.template" , "EntityControllerDefinition.java.template"},  
     description="EntityControllerDescription.html",  
     scriptEngine = "freemarker")  

   @NbBundle.Messages("EntityController_displayName=Entity Controller")  


And the whole trick is in the instantiate() method in your WizardIterator:
    
     private FileObject getDefinition(FileObject fileObject)  
     {  
         for(int i = 0 ; i < fileObject.getParent().getChildren().length ; i++)  
         {  
             FileObject obj = fileObject.getParent().getChildren()[i];  
               
             if(obj.getName().equals(fileObject.getName() + "Definition"))  
                 return obj;  
         }  
           
         return null;  
     }  
       
     @Override  
     public Set<?> instantiate() throws IOException  
     {  
         // Prepare the arguments for passing to the FreeMarker template.  
         String name = (String) wizard.getProperty(GameObjectVisualPanel.nameProperty);  
         Map<String, Object> args = new HashMap<String, Object>();  
         args.put("name", name);  
   
         //Get the first template.  
         FileObject firstTemplate = Templates.getTemplate(wizard);  
           
         // Find the second template.  
         FileObject secondTemplate = getDefinition(firstTemplate);  
                   
         DataObject dTemplate1 = DataObject.find(firstTemplate);  
         DataObject dTemplate2 = DataObject.find(secondTemplate);          
   
         // Force usage of the script engine.  
         secondTemplate.setAttribute("javax.script.ScriptEngine", firstTemplate.getAttribute("javax.script.ScriptEngine"));  
   
         // Get the package.  
         FileObject dir = (FileObject) wizard.getProperty(GameObjectVisualPanel.pathProperty);  
         DataFolder df = DataFolder.findFolder(dir);  
   
         // Set the names of the file:  
         String targetName1 = name;  
         String targetName2 = name + "Definition";  
   
         // Define the templates from the above, passing the package, the file name, and the map of strings to the template:  
         dTemplate1.createFromTemplate(df, targetName1, args);  
         dTemplate2.createFromTemplate(df, targetName2, args);  
   
         // End.  
         return Collections.EMPTY_SET;  
     }  


It would seem that there are two issues:
  • The second file in the TemplateRegistration is quirky. It would seem that the templates are always put one after another. There no are guarantees when it comes to ordering of FileObjects in regads to templates. Therefore you will need your own trick to associate them with each other. In my case name is sufficient.
  • The script engine is only assigned to the first file. Therefore you have to copy the ScriptEngine attribute from the first template to the others.
With these two tricks everything seems to be working fine :)


BTW. If you need to get the currently selected source directory, use:
         Project project = Templates.getProject(wizard);  
         Sources sources = ProjectUtils.getSources(project);  
         SourceGroup sourceGroup = sources.getSourceGroups("java")[0];  
               
         FileObject src_root = sourceGroup.getRootFolder(); 

I've been testing this in jMonkey Engine SDK 3.0 which is modified version of NetBeans 7.x. Maybe NetBeans 8.x does not have this issues. However the Internet suggests that as of June 2014 people are still having problems.