Bit’s Blitz – Puzzle Game

Bit's Blitz - Puzzle Game

Bit’s Blitz – Puzzle Game

In the third year of my Computer Science BSc (2013) as part of the Commercial Games Development module, we were placed into groups and tasked to produce a computer themed game designed for children. Each of the group members had to produce a game design document, one of which would be chosen for the group to develop. My group consisted of me, Aaron Ridge, Michael Killingbeck, Andrew Woodrow, Joshua Twigg and Alex Lynch.

The group decided to go with my game design which was inspired by the classic puzzle game Chip’s Challenge, with the idea being to reimagine it and modernise the graphics.

Game synopsis:
 “‘Bit’s Blitz’ is a fun 2D puzzle game following the escapades of its protagonist ‘Bit’. The game takes place across a series of levels increasing gradually in difficulty, gradually introducing new game-play elements. The player controls ‘Bit’ around a grid, constrained by a series of maze-like blocks and hazards. ‘Bit’ must successfully collect all the computer components that are scattered around the level and then repair his computer to proceed to the next level.”

Details:
Developed using C# and the XNA framework for the PC platform (Windows XP+).

 

The nice thing about this game design was that we could focus on the puzzle aspect of the game, time and imagination permitting, due to the simple overhead on technical implementation. The tile-based game engine was written from scratch using XNA, utilising XML data structures to store level data and a custom made loader. A cool and free little program called Tiled was used to ‘paint’ the level layout and export it into our XML format. I’d strongly recommend this to any considering 2D tile-based games for constructing levels, having said that, it’s a nice programming exercise to develop your own editor if you get the chance.

All gameplay aspects including animations and particle systems were programmed for the game, using no other libraries except XNA. I designed the game framework based on the State Design Pattern which worked out really well and continue to use it for game development.

With the use of XML and Tiled it allowed us to churn out level designs at an alarming rate and the final product has over 20 levels! Not bad considering the 2 week development time. When giving the presentation of the game, we literally only had time to demonstrate about 5 of the best levels, odd considering level variety tends to be in short supply for prototypes.

Sound effects were added (free assets) however I’ve removed these from the video and added music since honestly, they weren’t brilliant! The above gameplay video demonstrates various levels (played by me). I could barely remember most of the levels so it’s pretty much a blind play-through with some genuine mistakes.

For the project we all chipped in and the group worked well together. The game was never released or published anywhere, though if anyone is interested I could stick the executable on here for download.

CUDA Ray Tracer – Dissertation Project

Featured

After on and off work for a year, and many thousand words later, my final year BSc dissertation project and report was completed. Can a ray tracer ever be truly ‘complete’? This post a brief description and summary of my project.

A download to my full dissertation report can be found below and as well as a few renderings from my prototypes:

Report:

1293 Downloads

Prototype Renderings:

The project from a personal point of view was an important one. It was a period where I gained heightened interest in graphics programming, gaining an understanding of the principles of computer graphics, the mathematics involved and also the creative satisfaction that comes from it. When creating realistic virtual graphics from essentially nothing but code, maths and a display, on the face of it, it’s very easy to gloss over the ‘magic’ of it all, especially when you understand the complexity of how we actually perceive the Universe and the shortcuts that must be taken for computers to accurately mimic the natural phenomena of our brain’s visual perception.

 

CUDA Ray Tracer - Dissertation Project

CUDA Ray Tracer – Dissertation Project

 

A Bit of Biology and Philosophy:

The modern computer when you think of it, is really just a primitive extension of our own bodies, simple enough that we can manipulate, manage and understand it, with much greater control and predictability then our biology. They allow us to achieve things we could not otherwise do and many of the components inside a computer carry out very similar roles to organs found within us. Of course we can think of the CPU as a brain, but what else? Going into more detail, the GPU could be seen as a specialised part of the brain engineered to handle visual computation, just as our brain has it’s own visual cortex. A virtual camera in a rendering program replicates the capabilities of part of our eye, defining an aperture or lens through which to calculate rays of light, and like-wise, an ‘image plane’ positioned in front of the camera, carries out essentially the same functionality as our retina, but using pixels to make up the visual image of what we see.

When you understand the detailed steps required to render something in 3D, you realise that we are essential trying to recreate our own little simplified universe, it’s a pretty profound concept that when taken much further, manifests itself in popular science fiction such as the Matrix. After all, is mathematics not simply the ‘code’ of our Universe? It’s perhaps not as silly as it may sound, when you get down to the fundamentals of game developers creating virtual worlds, graphics programming being an essential component, and looking just how real and immersive these worlds are starting to become.

So What Is Ray Tracing?

Ray Tracing

Of all popular rendering techniques, it’s ray tracing that perhaps stands out the most in respect to my previous comments above. We all know roughly how and why we see, where light rays shine from a light source such as our Sun, they travel millions of miles to get to us and out of all the infinite number of rays, the tiniest percentage may find it’s way directly into our eye. This could be from directly looking at the Sun (not recommended!), and also from scattered or reflected light that has hit a surface, finding it’s way on a collision course with our eye.
This is fundamentally close to how ray tracing works, but with important differences. If a computer had to calculate the trajectory of all possible rays been fired out from a light source, this would be impossible with modern hardware, there are just too many potential rays, of which, only an infinitesimally small amount would ever find there way into the camera (eye) of the scene, and it’s only these rays we are interested in anyway. Instead, and referred to as ‘Backwards Ray Tracing’, light is fired from the camera (eye) into the scene and then traced backwards as it is reflected, refracted or simply absorbed by whatever material it hits. We then only have to fire a ray from the camera for each pixel in the image, which is still potentially a considerable number of rays (1920×1080 = 2073600 primary rays) and that’s without counting all the secondary rays as light scatters throughout the scene, but at least this reduced number is quite feasible.

Still, it is ray tracing’s close semblance to how light interacts with us in the real world that makes it a very elegant and simple algorithm for rendering images, allowing for what is known as ‘physically based rendering’, where light is simulated to create realistic looking scenes with mathematically accurate shadows, caustics and more advanced features such as ‘global illumination’, something that other faster and more common rendering techniques like rasterization (pipeline-based) cannot do.

Illumination and Shading:

Phong Shading

Phong shading

The ultimate main job of firing the rays into a scene in the first place is to determine what colour the pixel in our image should be. This is found by looking at what a ray hits when fired into a 3D scene. Put simply, if it hits a red sphere, the pixel is set to red. We can define the material information for every object in the scene in similar fashion to how we know in the real world that a matt yellow box reflects light. Technically, the box is yellow because it reflects yellow light, and is matt (not shiny) because it has a microscopically uneven surface (diffuse) that scatters the light more evenly away from the surface. Compare this to light hitting a smooth (specular) surface, most of the light would bounce off the surface in the same direction and appear shiny to our eyes. Clearly, for computer graphics, we are not likely to program a surface material literally in such microscopic detail as to define if it is rough or smooth, but we can cheat using a popular and effective local illumination model such as Phong, essentially using the ‘normal’ of a surface, the directions of our light source and camera and some vector math to put it all together and calculate the colour of the surface based on it’s material and angle, creating a smooth shaded object rather than a ‘flat’ colour.

Intersections, Distance Functions and Ray Marching:

Implicit Functions

So we know why we need to fire the rays, but how do know a ray has hit a surface? There’s a few different ways this can be done, all down to the complexity of the geometry you’re trying to render. Ray intersections with simple shape such as planes or spheres can be calculated precisely using linear and quadratic equations respectively. Additionally, for complex explicit 3D models made from triangle mesh, linear algebra and vector math can also be used to compute the intersections.

Another technique, has been gaining popularity in recent years, despite been around quite some time in academic circles. Rendering complex implicit geometry using ‘distance functions’ with nothing but a pixel shader on your GPU as shown on websites like Shadertoy have popularised a subset of ray tracing called ‘ray marching’, requiring no 3D mesh models, vertices or even textures to produce startlingly realistic real-time 3D renderings. It is in fact, the very freedom from mesh constraints that is apparent when you observe the complex, organic and smooth ray marched geometry possible using the technique. Ray marching allows you to do things you simply cannot do using explicit mesh, such as blending surfaces seamlessly together, akin to sticking two lumps of clay together to form a more complicated object. Endless repetition of objects throughout a scene at little extra cost using simple modulus maths is another nifty trick allowing for infinite scenes. By manipulating the surface positions along cast rays, you can effectively transform your objects, twist, contort and even animate; it’s all good stuff.

The Dissertation Project:

My development project was comprised of two parts, a prototype phase to create a ray tracer using GPGPU techniques and a hefty report detailing the theory, implementation and outcomes. For those unfamiliar, General-purpose computing on graphics processing units (GPGPU) is a area of programming aimed at using the specialised hardware found in GPU’s to perform arithmetic tasks normally carried out by the CPU, and is widely used in supercomputing. Though the CPU hardware is singularly much more powerful than the processors in a GPU; GPU’s make up for it in sheer numbers, meaning they excel and outperform CPU’s when computing simple highly parallel tasks. Ray tracing, is one such highly parallel candidate that is well suited to GPGPU techniques and for my dissertation I was tasked to use NVIDIA’s GPGPU framework called CUDA to create an offline ray tracer, done from scratch using no existing graphics API. Offline rendering means not real-time, and is clearly unsuitable for games, yet is commonly used in 3D graphics industry for big budget animations like those by Pixar and DreamWorks, with each frame individually rendered to ultra high quality, sometimes over a period in excess of 24 hours for a single frame.

In the end I produced four different ray tracing prototypes for comparison, incorporating previously mentioned techniques. Prototype 1, running purely on a CPU single thread using simple implicit intersections of spheres and planes. Prototype 2, the same but implemented using a single CUDA kernel and running purely on the GPU across millions of threads. Prototype 3, a CPU ray marcher using distance functions to render more complex implicit geometry. Prototype 4, the same as 3, but implemented using CUDA. My aim for the project was to assess GPGPU performance and the rendering qualities of the ray marching technique, the findings of which can be found in the report.

I knew when I picked this project that I was not taking an easy topic by any stretch, and a great thing I can take away from this is the extensive research experience and planning needed to simultaneously implement many different difficult concepts I had no prior knowledge about, yet still managed to produce a cohesive project, and fully working prototypes, achieving an 88% mark for my efforts, which I am very pleased with. As expected, with heinsight there are things that I would do differently if repeated, but nothing too major, and really, it’s all part of the learning process.

Ray tracing, ray marching, GPGPU, CUDA, distance functions and implicit geometry were all concepts I had to pickup and learn. I bought some books, but in the end, research on the internet in the form of tutorials, blogs, academic papers and lectures proved more beneficial. Sometimes, it takes a certain kind of way to present the information for your brain to ‘click’ with certain principles, and all of us are different. The Internet is a treasure trove in this regard, if you spend the time, you can usually eventually find some explanation that will suit your grey matter, failing that, re-reading it a million times can sometimes help!

Future Plans:

On the back of this, I will be continuing this subject into my masters degree and will likely be pursuing this further during my masters dissertation. I am already busy at work on a real-time implicit render with UI functionality running in DirectX 11 (A couple of early screenshots above). Additionally, I’d love to get a chance to contribute to a research paper on the subject, but we’ll see.

I plan to make some easy to follow tutorials on implementing ray tracing and ray marching at some point for this website, when I get the chance. Hopefully, they could  help out other students or anyone else wanting to learn the aforementioned topics. I know first hand and from friends, that at times it can be frustrating since although there is theory out there, there is comparatively very little information on actual implementation details for the subject, when compared to say pipeline-based rendering.

OpenGL Cross-platform PC/PSP Game Coursework

Last semester as part of the Advanced Graphics module of my CS degree at Hull University, we were tasked with a group project to produce a cross-platform OpenGL mini-game for the PC and Sony PSP based on a specification. The game premise was to move around a 3D ‘maze’ consisting of four rooms and connecting corridors, avoiding a patrolling AI that would shoot you if within its line of sight. The objective was to collect 3 keys to activate a portal to escape and beat the game.

The groups were selected at complete random with 4 members. As per usual, group coursework assignments are particularly difficult due to the extra concerns of motivating members and assigning work and by year 3 of University, you get a good idea on the best way of operating within them to secure good grades. I went in with the mindset of doing as much work as possible after we assigned tasks. Hopefully each would carry out their allocated work, if not, I’d just go ahead and do it, no fuss. Luckily one chap in my group was a friend and he did an excellent job coding the AI, mini-map and sound while I worked on coding the geometry, camera, lighting and player functionality etc.

1

Mini-maze model

Static environment lighting

Static environment lighting

Cross-Platform Limitations:

Having worked with OpenGL and shaders last year for my 3D ‘The Column‘ project, it was some-what limiting when I realised that the PSP didn’t support them and that fragment-based lighting was a no go. With one requirement of the game being a torchlight effect that illuminated the geometry, this would therefore mean that for PSP compatibility, vertex-based lighting would need to be implemented and that meant tessellation of primitives to prevent the lighting looking very blocky and…well very 90’s. Luckily the PSP did atleast have support for VBO (Vertex Buffer Objects) which meant effectively each tessellated model could loaded onto the graphics card only once to improve performance.

Unified Code

An interesting aspect of this project was the required consideration for a consolidated code-base that where possible allowed shared functionality for both the PC and PSP platforms i.e limiting how much platform specific code was used. This was essential since the game would be a single C++ Solution for both platforms.

I designed the code structure based around principles Darren McKie (the course lecturer) described, and produced the following class diagram that reflects the final structure:

Unified Cross-platform Class Diagram

Unified Cross-platform Class Diagram

The majority of game code resides in ‘Common Code’ classes that are instantiated by each particular platform ‘Game’ object. Certain code such as API rendering calls were kept platform specific but made use of the common classes where necessary. A particular nice way of ensuring the correct platform specific object was instantiated was carried out using ‘#Ifdef’, ‘#ifndef’ preprocessor statements and handled by a ‘ResourceManager’ class.

As mentioned earlier, per-vertex lighting had to be implemented due to PSP compatibility. A primitive with a low number of vertices would thus result in very blocky lighting. To prevent this I created a tessellation function that subdivided each primitives vertices into many more triangles. I played around with the tessellation depth to find how many iterations of subdivision could be achieved before inducing lag and was very happy with the lighting result considering there is no fragment shader; a given for today’s modern pipelined-based rendering.

Active Portal

Active Portal

The PSP implementation proved more tricky due to getting to grips with the PSP SDK and having access to very little documentation, however the game was successfully implemented onto a PSP device and ran with decent performance after compressing the textures down and removing geometry tessellation to allow for the PSP’s limited memory capacity.

The game was written in C++ and  the following libraries and software were used:

  • GXBase OpenGL API
  • Sony PSP SDK
  • OpenAL
  • Visual Studio 2012
  • Paint .Net

C++ word wrap for console output – Tutorial

I’ve been tinkering in C++ and decided to start making an old fashioned “text adventure” game as a nice little project to grasp the language.

As I started writing the game it quickly became clear that formatting all the strings manually with “new line” characters (n) to get the text to not breakup mid-sentence in the console was going to be hassle. I fancied a challenge and rather than grabbing some pre-written code from the web (how not to learn anything) I decided to work on an algorithm and make my own function that can deal with any string size and wrap the text neatly to the console.

I thought I’d make this little tutorial for anyone who wants to use it in their program but also wants to understand how the code works.

Here’s the function:

Note: Functionality has been gradually added, the updates further down detail the changes. I’ve included a Visual Studio code solution zip with the latest code at the bottom of this page.

void OutputText(std::string s)
{
	for (unsigned int i = 1; i <= s.length() ; i++) 
	{ 
		if ((i % BUFFER_SIZE) == 0) 
		{ 
			int spaceCount = 0; 
			if (s[(i-1)] != ‘ ‘) 
			{ 
				for (int j = (i-1); j > -1 ; j–)
				{
					if (s[j] == ‘ ‘)
					{
						s.insert(j, spaceCount, ‘ ‘);
						break;
					}
					else spaceCount++;
				}
			}
		}
	}

	std::cout << s << std::endl;
 }

Although the function is written here in C++, the algorithm can easily be applied to C# and other languages with just a few syntax changes. I was in two minds whether to go a route of splitting a string at the end of the line and then adding a newline character on the end, then “glueing” the strings together and repeating for each line, or whether to do it the way I did it which was by finding the last character on each line and then looping back through the line until it gets to a space and simply inserting “whitespace” on the end.

I’ll go through exactly what the function is doing:

for (unsigned int i = 1; i <= s.length() ; i++)

Here we are preparing to loop through each character in the string to find where we want the line breaks.

 if ((i % BUFFER_SIZE) == 0)

This bit of modulo arithmetic checks the current loop iteration value to see if it is a multiple of the console window buffer width (80 default) and thus the character in the strings length that would be at the end of a line. By checking if it’s a multiple it allows us to apply this function to any size string. You’ll need to define BUFFER_SIZE in your program or simply replace it with the number value you want i.e 80.

BUFFER_SIZE could easily be changed via a variable and set to whatever buffer width your console window is using (see bottom of this article on how to get the current console buffer width value).

int spaceCount = 0;

I initialise this variable for later use to keep track of the number of characters the loop has backtracked through in the string to find a space. (We’ll need to insert this number of whitespace into the string).

if (s[(i-1)] != ' ')

Here we are establishing whether the character at the end of the line is already a space. If it is, we don’t need to do anything and it’ll skip to the next loop iteration. Note “(i-1)” here, we do this because “i” is looking at the string based on it’s length with the lowest possible length obviously being 1. However when it comes to looking at the character array of the string “s”, arrays in C languages start at 0, thus we need to subtract 1 from the total length of the string to balance it. I could have adjusted the “for” loop to start at 0 instead and end at (s.length()-1) however this would have meant adjusting the modulo statement and personally it made more sense to me this way.

for (int j = (i-1); j > -1 ; j–)

Once we have the character at the end of a line in “i” and know it’s not already a space, we loop backwards from this position in the string until we find a space i.e the end of a word.

if (s[j] == ' ')
{
	s.insert(j, spaceCount, ' ');
	break;
}
else spaceCount++;

As stated above, we check if each character we loop through is a space (‘ ‘). If it is then we have found the end of the last whole word on the line that fits and thus where we need to insert whitespace. We know how many spaces to insert because each time a character is checked and isn’t a space, we increment the “spaceCount” variable so we know how many spaces to insert to fill the line to the end.

std::cout << s << std::endl;

We then output the newly word wrapped string to the console!

It’s great for text adventures or any program that outputs large strings since you can just call this function with any size string (within memory limits!) and it’ll do the rest. I tried to keep the solution as neat and minimal as I could.

Update (14/08/2012): Retrieving the console buffer width value

I thought I’d add in addition a way to get the console buffer width from the console each time text is output. This allows users to change the console window size and the text will wrap to it on the next output.

void OutputText(std::string s)
{
	int bufferWidth = GetBufferWidth();

	for (unsigned int i = 1; i <= s.length() ; i++)
	{
		if ((i % bufferWidth) == 0)
		{
			int spaceCount = 0;

			if (s[(i-1)] != ‘ ‘)
			{
				for (int j = (i-1); j > -1 ; j–)
				{
					if (s[j] == ‘ ‘)
					{
						s.insert(j, spaceCount, ‘ ‘);
						break;
					}
					else spaceCount++;
				}
			}
		}
	}

	// Output string to console
	std::cout << s << std::endl;
}

As you see here I have added at the top a function call “GetBufferWidth()”. This will return an integer with a value of the currently set console buffer width and store it in the bufferWidth variable that the OutputText function uses.

The code for GetBufferWidth is here:

int GetBufferWidth()
{
	CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
	int bufferWidth, result;

	result = GetConsoleScreenBufferInfo(GetStdHandle( STD_OUTPUT_HANDLE ),&bufferInfo);

	if(result)
	{
		bufferWidth = bufferInfo.dwSize.X;
	}

	return bufferWidth;
}

It’s a relatively simple function that makes use of the CONSOLE_SCREEN_BUFFER_INFO class. You will need the ensure you have “#include” for windows.h specifically for the “wincon.h” child library containing the console services.

“dwsize.X” gives us the max number of available character “columns” in the window (by default 80), Note* “dwsize.Y” isn’t needed here but would give us the max number of available character lines for the window so by default it would return a value of 300 since that’s the default limit for console output (it would not give us the value of lines within the visible portion of the window).

Update (20/10/2012): Wrapping string text with newline characters (paragraphs)

I recently had a comment mentioning the problem with using this algorithm with paragraphed text. I had already come across this issue and had added some additional code to allow it to work with strings with “n” (newline) characters in. I’ve been meaning to do a blog post update with it for quite a while. I appreciate comments from people because it means people are using the code I’ve put on here and gives me an incentive to update this post so thanks.

Below is the full modified code. As can be seen from line 11, I have added a new block of code to check for any “n” characters (you could extract this into a separate function for neatness). If a “n” is found it inserts spaces into the string before the “n” character filling to the end of the line and jumps the loop iteration to the first character on the next line. I’ve also added a new char declaration on line 7.

By adding whitespace before the “n” character and thus moving it right to the end of the line, we are effectively countering all that extra space that the console window needs to generate when it hits a newline character. This would completely mess up our algorithms positioning in the console window if it wasn’t at the end of the line.

void OutputText(std::string s)
{
	int bufferWidth = GetBufferWidth();

	for (unsigned int i = 1; i <= s.length() ; i++)
	{
		char c = s[i-1];

		int spaceCount = 0;

		// Add whitespace if newline detected.
		if (c == ‘n’)
		{
			int charNumOnLine = ((i) % bufferWidth);
			spaceCount = bufferWidth – charNumOnLine;
			s.insert((i-1), (spaceCount), ‘ ‘);
			i+=(spaceCount);
			continue;
		}

		if ((i % bufferWidth) == 0)
		{
			if (c != ‘ ‘)
			{
				for (int j = (i-1); j > -1 ; j–)
				{
					if (s[j] == ‘ ‘)
					{
						s.insert(j, spaceCount, ‘ ‘);
						break;
					}
					else spaceCount++;
				}
			}
		}
	}

	// Output string to console
	std::cout << s << std::endl;
 }

In detail:

if (c == 'n')
{
	int charNumOnLine = ((i) % bufferWidth);

Here if the current character in the string array is a “n” then it enters the new block. It then declares a new temporary variable for use later that contains the characters position within the line (defined by the width of your console window).

spaceCount = bufferWidth - charNumOnLine;

Next we calculate the number of spaces we will need to insert into the string from the “n” characters position to move it to the end of the line. We do this by finding the difference between the position of the current character in the line and the last position on the line.

s.insert((i-1), (spaceCount), ' ');

We then insert just before the “n” character the calculated number of spaces.

i+=(spaceCount);
continue;
}

Then we increment the current loop iteration by the number of spaces we just added which should set the loop index to the first character on the next line and “continue;” which will take us straight to execute the next loop iteration, repeating the process and checking every subsequent character for any more line breaks. If it doesn’t find one, it carries on as normal.

Here’s a screenshot of it in action with double “/n/n” line breaks inserted randomly into the string:

 

Download link for latest version of code (Visual Studio Solution):

1026 Downloads