Friday, 2 December 2011

The Silliness of the Lambs - DEMO 2

I have added the missing features to The Silliness of the Lambs and I have improved some aspects of the game based on the feedback I received from different sources, so I am releasing a second (and hopefully last) demo. Thanks again for everyone who tried the previous demo and provided feedback :) I have digested the suggestions and chose the most important ones to be included in the game.


New features:
  • Sound effects
  • Improved UI graphics (might need seed some more improvement...)
  • Gameplay improvements (e.g. the sheep don't get stuck in the corners)
  • Some minor bugixes
Since the graphics hasn't changed much no screenshots this time.

Sunday, 20 November 2011

The Silliness of the Lambs - DEMO

I have finished the demo for the Android version of The Silliness of the Lambs. You are free to download it, all feedback is welcomed. It contains six levels, and it is fully (or hopefully) playable.

To install the APK file you have to copy it to your device (or download it right there, it's only half MB) and after enabling Unknown Sources it is ready for installation.


It features updated graphics and new levels. I have implemented a level selecting screen, font rendering, and lots of small things to make it a complete game.

After finishing it (making a pile of levels, fixing possible bugs, implementing sound playback and adding sounds and music) I plan to release it on the Android market. Hopefully I can do it soon :)

Title Screen

Sample level

It's cold in here

Another level

Thursday, 3 November 2011

The Silliness of the Lambs - Level Editor

In the web based version of the game the levels were tile-maps and some additional objects (dog, sheep, bush...). Every level's data was inlined in the Processing source, the tile-maps were stored as arrays and the objects were added to the level instances. I designed the levels on paper, then based on the drawings I created the maps in a text editor and calculated the positions for every object - it was quite tedious.

In the Android version I use an image for the background, and objects for everything else. I did not want to create the levels manually, so I quickly put together a simple level editor. I have finished it in one day and I think this time will come back soon when I'll start producing the levels for the game. Since I develop the game in Java I chose it as the language for implementing the editor. I recalled my memories of creating GUIs in Swing, designed it on paper and then manually coded it (I prefer creating simple user interfaces manually rather than using an editor). When most of the widgets were in place I implemented the event handlers and listeners, the editor was functioning. Creating new levels is now a piece of cake :)

Using it is quite simple. After clicking the "New" button you can choose the background image from a file open dialog, and it is displayed in the editor. The logical dimensions of the level can be set in the text-boxes on the left. The dog, sheep and bushes can be added to the level by selecting them from the "palette" and clicking on the image. Walls (and generally every blocking areas) can be added by selecting the "Wall" tool and drawing a rectangle. Setting the fold is similar. This follows the logic of the game, since objects that could move have a circle shape, and blocking objects are represented by axis aligned boxes. The level can be saved as an XML file by clicking the "Save" button (surprisingly).

Screenshots (as you can see it's not a WYSIWYG editor):

Initial window

After loading the background picture

Adding the dog (black circle)

Adding a few sheep (grey circles)

Some bushes... (green circles)

Setting the fold walls (red rectangles)

Setting the fold area (blue rectangle) 

In-game screenshot of the level

Thursday, 27 October 2011

Do Androids Dream of Electric Sheep?

Soon they will. I am porting (or rather rewriting) The Silliness of the Lambs to Android. The game doesn't need much processing power, the gameplay is quite casual, and it's control mechanics is ideal for touchscreen devices, so the idea to make a smartphone version came quite naturally. It is possible to play the original on a phone in the browser, but it's too slow, and I wanted to get into Android programming anyway.

So I went to, learned the basics of Android development, installed JDK + Eclipse + Android SDK, and started to discover the platform and tried to build up the basics for the game. I was surprised to find that developing for Android is as easy as stomping on kittens. My pessimist self expected that I would have to build the Java project, then manually convert it to an Android package, then somehow transfer it to my phone where I can finally run it. Instead of this I just have to click on the Run button, lean back in my chair, and all of the tasks is done automagically. If my phone is connected to the dev computer through USB then the program is run on it, otherwise the emulator is started and my program is run inside it. On a second thought this is what I really expect of a development environment.

After discovering the possibilities I decided to use OpenGL ES for rendering. I have made a simple program which created an OpenGL display and drew a flat shaded triangle, and then extended it step-by-step, added handling of touch events, controlling fps, implemented texture loading and drawing of textured rectangles. At this point I had a basic engine with the functions I needed, so I could start porting the game source. Since Processing is quite similar to Java it did not seem to be too hard, though it wasn't easy. Java needs lots of "decoration" (public final static abstract...), classes go to separate files, the libraries have different functions, etc.

During the porting/rewriting I could restructure the code, so it is organized better now. I have redesigned some aspects of the implementation of the game, e.g.  instead of a tiled background (which determined both the graphical appearance of the level and the physical representation) I use one big background image (graphical appearance) and the physical objects (e.g. walls) are now stored independently. This modification speeded up both rendering and collision detection. The levels are not inlined in the code anymore but loaded at runtime from xml resources.

So now I have a (gameplay-wise) mostly functional version for Android. This means that I am ready with the 90% of the project, now I just have to finish the remaining 90%. I have to implement font rendering, create a menu or level selecting screen, create levels and other contents, and I also plan to add sound effects and maybe music. After it's finished I would like to release it on Android market. I intend to release a demo soon so that you can try it if you are interested.

Some images as usual (please note that some parts of the graphics are just placeholders :)

In the emulator:

On my phone:

P.S. I have watched Blade Runner to have some right to use this title :) I will also read the book.

Saturday, 3 September 2011

The Silliness of the Lambs

As I've promised I'm presenting my new game: The Silliness of the Lambs. It's a simple browser based 2D game with a top-down perspective. You control a tireless shepherd dog and your task is to baffle the not-so-smart sheep into the fold.

The game is implemented in Processing.js. The development took 2 weeks, with all the planning, designing, programming, producing the artwork, editing the levels and testing. It was all done by me, and I'm proud of the result. The graphics is authentic programmer art, so don't judge too strictly :) I plan to write some articles of the technologies used in the game.

Some screenshots:

You can play it in your browser.

The source is available for download:

Tuesday, 30 August 2011

My new shirt

After the summer holiday and some unfinished projects I am back with new articles. This one will touch a lighter topic than the previous ones: there will be less programming, and a bit more art :) But don't be afraid, the next article will be about a game I've made and which needs only some polishing now.

My girlfriend has bought some textile paint recently, six different colors in little buckets. It aroused my creative self, it made me want to do something with it - especially when I saw how beautiful images she painted on the clothes she was making. So I decided I would use that textile paint to make a nice shirt for myself.

The paint was given, I needed a light colored shirt to paint on, and a "good motive" that I would gladly wear. I found an old plain white shirt in my wardrobe, it was perfect for my needs. I like the style of the clothes that Cyberdog makes, so I browsed their site, found this design, and knew that I wanted to copy it:

I started to convert this image to include only the drawing. First I cut out the interesting part:

As you can see luckily the relief of the model girl did not distort the image considerably. My plan was to print this image to paper, then put it under the shirt, and follow the lines with my brush to get the best result. But before that I wanted to clear the background of the image to white. On the first hand it saves tint when printing, and on the other hand the image picture would be clearer under the textile. The white shirt is not fully transparent obviously, so I wanted to get rid of every misleading noise.

I was trying to somehow convert the grey-scale background to white, and leave the black shapes untouched. Converting to 2 color black-and-white was not a good solution, because the antialiased forms became too sharp, pixelized. I tried everything I could think of in Gimp, Photoshop, IrfanView, but I couldn't find a function or plugin that would do what I needed. Googling did not help either. I really did not want to clean it up by hand. At that point I thought that if I can not find a tool to solve my problem then I'll make one - I'm a programmer after all :)

So at first I collected my expectations concerning the new tool:
  • convert the grey background to white
  • leave the black shapes untouched
  • keep most of the edges antialiased
  • leave non-grey colours untouched (this was important because I was planning to convert other images which were coloured)

The hard thing is to decide if a grey pixel is part of the background or it is part of an antialiased edge. I used a threshold value to decide the problem: if the pixel is grey, and it's darker than the threshold then keep it's original color, otherwise make it white. I used an other threshold parameter to decide if a pixel is grey or it's another color: if the difference between the RGB components of the pixel was lower than the threshold, it was considered grey and dealt with as described previously, otherwise it was considered to be another color. Maybe there is a plugin/program which does roughly this and I just could not find it - I would be glad to hear about it.

The implementation is a short Python script. I used PySFML for loading, saving images and accessing their pixels. It is a bit overkill for this purpose, but I was already familiar with this library, it was easy to use, and it was already installed on my machine so I could start scripting immediately. I think the code will be easy to understand after the explanation:

from sfml import sf greyness = 20 lightness = 500 def convert(pixel): r = pixel.r g = pixel.g b = pixel.b if abs(r-g) + abs(r-b) + abs(g-b) < greyness and r+g+b > lightness : return sf.Color(255,255,255) else: return pixel img = sf.Image() img.LoadFromFile( 'input.png' ) w = img.GetWidth() h = img.GetHeight() for j in range(h): for i in range(w): pixel = img.GetPixel(i,j) img.SetPixel(i,j, convert(pixel)) img.SaveToFile( 'output.png' )

Here is the result of using the script on the previous image:

It's not "perfect", there are many grey pixels littered around in the background, but I was satisfied with the result, it's much better than the original after all. My expectations were more-or less accomplished, most of the background was converted to white, it was now economical to print and did not contain much distracting parts.

I printed the image in A4 size, realized it was too small, so printed it again on two A4 pages. I glued them together and onto a wooden panel. I put the whole stuff into the shirt and then smoothed and pinned the shirt onto it. The first A4 sized copy was good for reference. I covered a part of the floor with newspaper as a workplace, gathered the black paint, the brush, some test-cloth and a cushion for my knees - everything was ready to paint :)

I took some photos as I progressed:

I worked in two turns on two days, the whole process took about five hours. The paint was quite thick so I could only paint short dashes. When I finished painting I was tired as hell from kneeling on the ground for hours. My mind was tired too, since I had to concentrate hard to paint all those minute details as exactly as possible. But at the same time I was extremely satisfied and proud of my work, I haven't felt similarly for a long time. When I started I didn't really believe I could make it. It was not finished yet (it needed ironing to fix the paint and I planned to cut the sleeves off), but I was through the hardest part.

Here is an image of the final product:

Ordering a shirt from Cyberdog would have been much less work. So was all this hard work worth it? Absolutely. I had much fun during the whole process; now I can enjoy the fruits of my work; and I have a nice shirt I can proudly wear, and tell everyone who asks about it that I made it myself with my two hands :)

This happens when fashion meets programming. I hope that this little multidisciplinar excursion was not too boring. As I have already said, next time I'll be back with a more hardcore topic.

P.S. I hope it's not a copyright infringement that I used the picture from Cyberdog.

Sunday, 8 May 2011

Random name generation continued

In the previous post about random name generation (which can be found here) I have mentioned an improvement of the described method, and now I have it implemented.

I have modified the original implementation, so that it uses the last two letters for choosing the new letter. I also had to modify the first phase of the algorithm which makes the statistical representation of the "language", now it calculates the probabilities that a letter in a word follows two previous letters.

The names generated with this modified method are more similar to the original sample names, and it happens more often, that it is one of the samples - though it can be helped by using more samples. The length of the generated names is also more close to the average length of the samples, so I have removed the part that generates a new name until the length is neither too short nor too long.

The source code is available as before, and you can try it with the previous sample names for comparison:

Generated name:

Thursday, 5 May 2011

Random name generation

Procedural content generation is usually used for making maps, terrains, plants, etc., but names can also be generated procedurally.

Back in university I studied language technology among others, and during this course we were taught an interesting method for generating random words based on the statistical characteristics of a given language. These words looked similar to the real words of the language at first sight, but they did not necessarily belong to the language.

This method consists of two phases. In the first phase we make a statistical representation of the words of the language. For this we need a sample set of words. We have to iterate through every word in the set, and calculate the probability that a letter in a word follows another letter. For example if we have only the word 'abacac' in the set, then the probabilities are:
  • a word starts with letter 'a' with probability 1
  • letter 'a' is followed by 'b' with prob. 1/3 and by 'c' with prob. 2/3
  • letter 'b' is followed by 'a' with probability 1
  • letter 'c' is followed by 'a' with probability 1/2, and ends the world with probability 1/2

In the second phase we can generate words based on the probabilities. First we choose a starting letter, and then we repeatedly choose a letter that can follow the previous letter until we choose to end the word (if possible). Staying with the previous example:
  • we have to chose 'a' as the first letter
  • the second letter can be 'b' with prob. 1/3 and by 'c' with prob. 2/3; if we throw a dice we choose 'b' if the number is 1 or 2, and 'c' otherwise; let's say we got 4, so our word so far is 'ac'
  • 'c' can be followed by 'a' or end the word; 1 to 3 on the dice means we choose 'a', 4 to 6 means the word ends; let's say the number is 2, thus our word becomes 'aca'
  • we have to choose a letter that follows 'a' again, let's say we threw 6, so our word is 'acac' now
  • now a successor to 'c' is needed again, suppose our number is 5, so we are finished, our final word is 'acac'

This example does not show the power of this method, it's just to demonstrate the algorithm. With a large set of words much better results can be achieved.

The method can be simply used to generate names, this can be really useful for games. For example we know lots of elven names, and with this algorithm we can generate similar random names that we can give to NPCs or help the player choose a name. It can also be used for names of cities, animal races, etc.

Since sometimes the names can be too short or very long based on the samples, my implementation generates a new name until a name is found which is neither too short nor too long.

An improvement of this method might choose a letter based not on the last generated character, but on the last 2, 3, ...N characters. This way the words are more similar to the original words, but more samples are needed to achieve good results.

I have implemented this method in Javascript, so that it can be embedded into the blog. The source code is available for download.

You can also try it: enter the sample names into the textbox separated by spaces, and click 'Generate new name' to (surprisingly) generate a new name.

Generated name:

Saturday, 30 April 2011

Simple procedural heightmap generation

There are already several methods for procedural terrain generation (perlin noise, fractals, diamond-square algorithm, etc.). All of them has it's advantages, disadvantages, I do not want to judge or compare them, I just want to describe yet another method I came up with. I think it's main advantage is it's simplicity, it is very easy to implement, yet produces interesting terrains.

The algorithm starts with a flat heightmap, i.e. every cell of the map has a height of 0. Then in a number of iterations it modifies the heightmap, creating the final terrain. In every iteration step a line is generated which crosses the map region, this is achieved by randomly choosing two defining points in the map area. Then the height of every cell of the map on one side of the line is increased by a given value (practically by 1). That is, we repeatedly cut the map into two halves randomly, and raise the level of one of them.

After several iterations the heightmap has enough variation. The height values are between 0 and the number of iterations. After finding the minimum and maximum values we can interpolate the height values into any range we want. The number of iterations required to get a good looking terrain depends on the size of the map, larger maps usually require more iterations.

Advantages of this algorithm:
  • simplicity
  • works for any map size
  • scalable (the quality of the terrain can be controlled with the number of iterations)
  • high computational cost ( for an W*H sized map and N lines it is O(W*H*N) )
  • not "infinite" like perlin noise
An online demo is available here, it is implemented in processing.js. It generates a 100*100 map with 256 iterations. Since it runs in the browser the calculation speed is quite slow, so be patient.
The source code is also available: download.

A 256x256 map generated with 1024 lines

Tuesday, 26 April 2011

Light propagation with CA

I plan to make a 2d rpg. I have looked at several different variations of calculating field of view (this used to be a good summary, but seems to be unavailable at the moment), but I did not really like any of them. Somehow they seemed to be too sharp, too "digital" - something is either visible or not.

I wanted a fov calculation that gave more natural results, and I thought that simulating light propagation would be a good candidate. Since the game world would be a 2d grid, the idea of using a cellular automaton to calculate light propagation came to my mind, and I started experimenting with it.

After a few ours of planning and coding, I got the results that satisfied my need:

How does it work? Every cell in the grid has two attributes. The first attribute is transparency: if a cell is transparent, light can propagate through it, otherwise it can only receive light. This value represents wether the cell in the game world is blocking the light, it is not updated by the automaton.

The second attribute is the strength of the light in that cell. In my implementation it is a floating point value between 0.0 and 1.0. This value is updated during every iteration, the new value is the average of the cell and the neighbouring cells. If the cell is blockling the light, it's value is not included in the averaging, so that they do not light other cells, even thought they can receive light.

I have used 4 neighbours in my implementation. The drawback of this is that the corners are in shadow. This could be easily solved by using 8 neighbours, but that increases the computational costs. Another improvement could be using RGB colours instead of the simple light strength, this way more interesting effects could be achieved.

Strictly speaking this might not count as a calculation of field of view, but it achieves a similar effect. I think this method could give a good atmosphere to a game, especially to games with stealth / horror elements. (Imagine walking down a corridor, when suddenly your torch goes out, and everything becomes totally dark... and then you hear a noise...)

I have implemented this method in processing.js, it is available here, you can experiment with it in the browser. The mouse cursor is the source of the light. In the beginning every cell is a wall, blocking the light. You can 'carve' empty cells into the grid by holding the left mouse button, or build back the walls with the right mouse button. The source code is available here.