Sunday, September 13, 2015

Dev.Log - Dungeon 3D Game - Tools Part 2

I'm finally back to producing content for my pebble dungeon game.

As the sole programmer/artist/designer of this game, I tend to keep the work minimum so I can progress as fast as possible when I have time to allocate to the project.

The part 1 of the tool post mentioned about the human readable/editable level files. Editing those files worked well until I starting willing to put more complexity into my levels. 
I thought I should give some details about the tools I've developed to help with this.

Complexity = need for new tools


I like each of my level to be crafted to make them most enjoyable and challenging.
Each of them have a theme.
First one is the sewer level: quite fun to build, minimum texture set. I spent most of the time focusing on the layout.
The second one is the city level. this level is way more complex than the sewer one. The reason being that the city has various landmarks and is an "open sky" type of dungeon where buildings rise higher with more textures per grid cell.

After editing this level in a text editor, I started feeling the pain of the lack of "instant feedback" when designing this particular level.

As the beginning of the project, I started a simple level editor, that I eventually left unfinished to concentrate on more important things. 
At the time, I wasn't also quite happy on how the editor user experience was.

So I decided to explore new ways of editing levels... let me tell you this adventure :) 

2D level editor

What is simpler than a 3D level editor: a 2D one. 
The one I took on building ended up like this:




It didn't get really far...
While building it, I quickly realized the limitation of it. one of them is the non flat nature of my levels. 
Even by using the projected selected row at the bottom, it was light years away from being an efficient way of editing a level.
I quickly discarded it and put it in my virtual attic of software engineering things that didn't work but are to be kept for history records :)

Isometric level editor

Right after this, I felt strong that isometric would the answer to the 2D editor limitations. 
I found a isometric javascript library called sheetengine and started building my level editor.


This one went further in development. 
I really loved the style of it. Very neat and clean.
Building a level was rather fast and I could see the potential of it.
When I started using it for my most complex level, it shows that the lack of "free" camera was quite a problem. Especially in high-wall, narrow corridors.
This kind of sent me back to square one...

Back to full 3D

I finally decided to remove the dust on my full 3D level editor and give it a bit more love than I did before.
That is certainly what I should have done in the first place.



Unhappy with the user experience originally, I revamped the way tool selection was done.
From circular icon menus to normal top icon menus, adding shortcuts.
I also added a toggle between orbital camera and first person camera, so I can, at anytime, try it and see how the level looks like from the player point of view.

It has also a full undo/redo stack. That is a feature, I'm pretty happy to have develop for it, as this allow me to "make design mistake" and quickly come back from it and iterate on the design.

From a technical point of view, the level editor is built using Three.js running in a web browser. It loads and saves my human readable level files, so I'm still free to manual edit them if necessary.

As a necessity, I only develop the features that are really need when I need them. This makes the development process really focused and efficient.
I also got a long list of "nice to have" features, that will take me more effort to get to.

So far it serves its purpose very well and I've seen my productivity increased by a lot.

Conclusion

This experience shows that sometimes you have to "walk the path to know the path".
On the positive side, I have now a working level editor and I have learn something in the process.

I'll certainly post some screenshots of the game itself soon as I make good progress building the levels.
Stay tuned :)


Sunday, August 9, 2015

Dev.Log - Real Time Ray Tracer - Pebble Time version



After few awesome weeks visiting my home country France, I've had hard time to start doing anything productive on my computer.
The gorgeous summer doesn't really help much as well, as I spent most of my time at the Parkour Park.
Thanks to cloudy/rainy weather, today I finally managed to get something going.

I took my "old" real-time ray tracing app for Pebble and I converted it to work with the Pebble Time.
The conversion was quite straightforward. By using the SDK 3.0, I had to deal with some changes around the GBitmap related functions but nothing major.

The app now really take advantage of the color screen of the watch.
I've updated the few textures I made for the plane, and made sure each of them have a different color signature.
The colors are all computed internal in 24 bits (8 bit per RGB) and I apply a dithering process just before sending the pixel to the frame buffer. It works really well.

Here's a quick video of it:



The app is also available on the Pebble store:
https://apps.getpebble.com/en_US/application/52f8987720ab1e67030001a9

Monday, May 4, 2015

Dev.Log - Dungeon 3D Game - Pebble Time version


As I progress on the normal black and white version of my game, I'm also porting it over to a color version to get ready for when I will receive my Pebble Time.

I've made good progress. So far it runs in the emulator but looks really promising.

The emulator performance is quite bad and the application will certainly run much smoother on the device itself ( the same way the B&W version runs faster on the watch than in the emulator)

I'm really looking forward to receiving my Pebble Time to be able to upload it and tweak the application on the device itself. 

While waiting for this I've made a quick video of how the work in progress looks in the emulator:


I hope you will enjoy this. Feel free to leave a comment about it. 

Saturday, April 18, 2015

Dev.Log - Dungeon 3D Game - Tools Part 1


Recently, I have spent a lot of efforts trying to squeeze as much as possible in the tiny space of the Pebble Watch.
I now have a solid base that I can build content on.

To reach this point, I was only dealing with data in-lined directly in code as static arrays.
Convenient for prototyping, not so much for starting to produce interesting content....

This is what drive the need for tools. In the rest of article, I'm going through the various tools I have developed and used for this project.

Texture Tool - first generation

The first tool developed for this project was to generate textures as C static arrays.
I made a little C# application that takes a PNG file and convert it into a static array that I could paste into my code.

From a tech point of view, really nothing fancy or complicated but this saved a lot of effort importing and testing textures in game.

The tool loads a PNG in memory, goes through the pixels, convert them in grey scale and output the values in text file.

The grey scale conversion is quite simple and is done by weight-summing the RGB values:
grey = (0.21 * red) + (0.72 * green) + (0.07 * blue)
The weights are based on the human eye sensitivity to luminosity of each RGB channel.

So an image like this:



Would generates this code:

static uint8_t stone_texels[8*8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x80, 0x00, 0x80, 0xFF, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x40, 0x80, 0x40, 0x00, 0x40, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x80, 0xFF, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x40, 0x00, 0x80, 0x80, 0x40, 0x00, 0x40, 0x80,};

This already saved me quite a lot of time, especially when creating a texture for the "Beholder-like" monster ( please do not judge my pixel coder art :) )




For the time invested in writing the tool (an hour or so), the return on investment has been great. This allowed me to have decent textures to prototype with so that I could focus on developing the features.

But I reached a point where I need to produce a larger amount of content in a more data driven way.


Level Tool - first generation

For levels are also used static arrays first. But no tool to generate those. All hand-typed...

Works great but they are increasing the size of the executable. 
And most of the time, I don't need all this data in memory at the same time. 

So far, I had only one level. As soon as I implemented the next-level-load feature, I needed a way to keep only one level in memory and load it on-demand from the application resources.

This necessity forced me to go write a tool to generate those levels in a binary format compatible with the resource API.

First, I decided to have each of my level as a JSON file. Having human readable and editable format is an important point to me as it helps me to iterate on the source data without having to rely on an external tools/program to generate this file.

To convert from JSON to binary format, I picked up javascript. Why?
  • It parses JSON natively
  • It easy to write
  • There's a large set of available libraries for it
In an couple of hours (including a couple of trial and error cycles), I had my script converting my JSON levels in a binary format that I can add to my Pebble App resources.

(For the record, I do use NodeJS to execute my scripts)

I have now  a mini data "pipeline" that I can use to feed content to my application without affecting its size.

Texture Tool - second generation

With a tool for level, I needed now one to store textures in the application resources.
But ... why not using the SDK provided support for PNG images?

Well, I'm not using GBitmap. I'm using my own format. With my own format, I'm in control of the size, packing and performance... 

In a similar way to the level tool, the texture tool is made with JavaScript and run with NodeJS.

It takes a PNG image and extract the pixel and color information and transform it into my proprietary binary format ready for the application to process once loaded from the application resources.


Next steps


With this set of tools, I have a robust way to channel the content data in the application resources in an optimized way.

Tools are investment, you invest time in them, and you get returned time from using them.
(This can be measured as ROI, how many hours of work are you going to save by spending an hour writing a tool)

From the few hours I spent writing those tools, they certainly saved me my countless of hand editing, byte level tinkering headaches.

So what are the next steps now? 
Well, the level editing is still done in a JSON file. It's simple enough but if I add more features in the future that requires more complex level data, I may need to develop a more friendly "level editor".

on this note, and talking from experience, writing proper level editor can quickly become a time consuming task that take you away from the main feature development.

Conclusion

I hope you enjoyed this article as much as I enjoyed writing it :)

I'm curious about what kind of tools Pebble Watch Game makers are using. 
Please leave a comment to share your experience and give some feedback about it.


You can find the second part of this post here.

Wednesday, April 15, 2015

Dev.Log - Dungeon 3D Game - Source code & Bulk builds

I finally spent found some spare time this week to make some good progress on my Pebble Watch 3D dungeon game.

This article will be about how to keep your code base organized while getting the most of the compiler for the small amount of memory the watch provides.


Source code layout

I may not have mentioned  but, I'm using CloudPebble to develop on Pebble.
This is a fantastic development tool for few reasons:


  • First of all, it makes my code accessible from any device. Knowing that I'm coding on 3 different PC/Laptop and occasionally on a tablet, this makes my life a lot easier.
  • Secondly, it's platform independent. The above hardware list I'm using to code, features Windows, Ubuntu and Android operating systems. Cloud Pebble has no trouble there :)
  • It supports multiple source files projects
I know the last one may sound obvious for any dev IDE (even web-based) but a lot of Pebble Watch projects I've seen are still using one big monolithic file.

There's few reasons for that:
  • Editing preferences: you can find everything in one place without having to switch from one file to the other and every piece of code can be accessed by any other one.
  • Compiler friendly: reduced link time and the ability for the compiler to be able to globally optimize the final executable.
The second argument is, in my opinion, the most valid. Especially in a resource-constrained platform like the Pebble Watch.
And i measured it: with the compiler setup to optimizing for size, one big file results in a smaller executable than having the exact same code spread in multiple source files.

But ... I like organizing my code in multiple files (.h and .c):
  • First, because of my long API developer experience. I write libraries of functions that I can reuse in future programs so it makes each iterations faster.
  • Second, because I want to find quickly where the monsters related code is: in monsters.c :)
  • Third (related also to the API point), I want my header files to be the public side of each libraries and the .c file to have all the internal business hidden from outside.

There's a simple way to get the benefits of both worlds. It's used professionally on large projects (and particularly in professional video game development): bulk builds.


Bulk builds

The concept is rather simple:
  • Spread your source code in multiple source files
  • Exclude them from compiling
  • Have a "bulk.c" file that includes all the above source files and compile only this one.
CloudPebble doesn't give you the ability to exclude files from the build. To go around this you could use a different (non compilable) extension for your files. For example .inc files.
Since I already had all my .c files in place, I decided to use the pre-processor to help me. Each file is shaped this way:

#include "config.h"#ifdef BULK_BUILD

// source code 
#endif // BULK_BUILD

Then the bulk.c file looks like:


#include "config.h"#ifndef BULK_BUILD#define BULK_BUILD
#include<a.c>#include<a.c>// more includes
#endif // !BULK_BUILD

Now I can easily switch from bulk builds to non ones.
By default they are on. If I want to compile normally, I simply add #define BULK_BUILD in config.h file and now all the individual files are compiled separately.

This solution makes it easy to port any project to support bulk builds without having to deal with compiler settings.


Results

On my dungeon 3D game project this allow me to gain a fair amount of free space to add more features and data.
Here's the comparison on both generation of the watch ( using SDK 3.0 ).
  • Regular build
-------------------------------------------------------
APLITE APP MEMORY USAGE
Total footprint in RAM: 24016 bytes / 24KB
Free RAM available (heap): 560 bytes
-------------------------------------------------------
BASALT APP MEMORY USAGE
Total footprint in RAM: 43572 bytes / 64KB
Free RAM available (heap): 21964 bytes
-------------------------------------------------------
  • Bulk builds
-------------------------------------------------------
APLITE APP MEMORY USAGE
Total footprint in RAM: 23672 bytes / 24KB
Free RAM available (heap): 904 bytes
-------------------------------------------------------
BASALT APP MEMORY USAGE
Total footprint in RAM: 42916 bytes / 64KB
Free RAM available (heap): 22620 bytes
------------------------------------------------------
If we look at the size of the executable, the bulk build version is only a few percent smaller than the regular build. 
This may not seem significant, but in that case this translates to 344 and 656 bytes of extra space that can be used to add more code or content. 
And believe me, once you reach the limit of the device, every byte counts.

On this note, I will certainly talk more about how I manage to squeeze all the features of my dungeon game in the tiny memory of the Pebble Watch.
There was a great article from David Drake on this subject related to his game:
http://davidcdrake.com/2015/03/27/pebblequest-25kb-of-awesome/


Conclusion


Developing for the Pebble Watch is a very challenging but extremely fun experience. There's many roads that are just waiting to be explored which makes it exciting. 
You need to experiment, invent and think out of the box to define what you've designed to finally see it coming to live on the device.

I'll try to up the pace of my posts. Let me know if this article was useful or if even share your own experience with this device.

Wednesday, March 25, 2015

Pebble Watch - Dev - Tesseract, ray-tracing and more...

When I got my Pebble Watch about a year ago, the first think that came to my mind, as a software engineer, was to develop applications for it.

But as a game software engineer, my ultimate goal was to extract the best out this hardware. 

When you look at the specs, it's like being back to the old-school days: 

  • limited color depth ( very limited to 1 bit :) )
  • limited memory (24k per program - almost)
  • limited CPU power and features
  • limited input system
  • C based programming
Perfect set up to challenge myself :)

Step 1 : Tesseract

First idea was to do something that nobody did before: Real-time 3D.
After a couple of hours of coding, I got my wireframe rotating tesseract ( 4D cube projected in 3D then projected on the 2D screen ) running at 30 fps on my watch:



This was certainly fun to do but this was lacking the most important part. Pushing the hardware to its limit and see what could be achieved by doing so.

Step 2: Real-time Ray tracing

The old-school aspect of this task reminded me of the Amiga times and the checker sphere.
Then the idea of making a real-time ray-tracer came to me. 
I started simple with a sphere and a light and slowly added a plane, then reflections and shadows ( note that you can see the reflection of the sphere shadow in the sphere reflection :) )
One major piece of the code was the dithering to accommodate the 1 bit deep display.
After adding the ability to change the texture of  the ground plane and ability to rotate the camera around the sphere it looked like this:

This is where i started reaching some limits of the Pebble.
The math heavy ray-tracing code was fast enough to display a picture after few seconds, but that was far from real-time.

The first optimization step was to optimize the code to take advantage of some specifics of the scene.
The obvious one was to convert the rather general ray-plane intersection to a more optimized ray-horizontalPlane version. 
Then i used a directional only light to save some cycles too.
Once this was done the speed wasn't yet enough to call it real-time.

I started using using faster math tricks: Fixed point math, fast sqrt for example.
 As this was not yet enough, I spent quite a lot of time trying to optimize the code that generates the initial ray from the camera to pre-compute as much stuff as possible and keep the x and y inner loops operation as fast as possible.

The code was now running nicely but not yet fast enough... I had to think at something else.

I was fill-rate bound. the cost of computation was directly linked to the number of pixels to render. The final solution was quite simple.
By rendering a quarter of the pixels per frame so that all pixels get updated over four frames, the performance was good enough to rotate around the sphere in an close to real-time fashion.
This also produced a nice trailing/ghost effect that added to the coolness of the achievement.

The resulting program ending up being about a thousand line of C code including comments and blank lines.

The app is on the Pebble app store if you want to try it for yourself:
https://apps.getpebble.com/applications/52f8987720ab1e67030001a9

This was good experience to learn and also build some solid code library that I could use for other performance demanding application.

I'm now looking to see how I will be able to port this to the new Pebble color.

Step 3: Game 

 After the ray-tracer, i wanted to go back to my roots: a game.
I started a tunnel avoidance type of game but quickly wanted something cooler.
I was a big fan of the old-school dungeon crawlers (Dungeon master, Ultima Underworld ...).
This was enough for me to get enough motivation to write one.

The game is still in development for both version of the Pebble. It has been so far the most challenging app i've develop for this device.
I'm going to dedicate several posts to talk about its development in details. So stay tuned. 
In the meantime, here's a video of it at a earlier stage:






Dev.Log - Dungeon 3D Game - Tools Part 2

I'm finally back to producing content for my pebble dungeon game. As the sole programmer/artist/designer of this game, I tend to kee...