Quantcast
Channel: GameDev.net
Viewing all 17825 articles
Browse latest View live

Design Patterns: Singleton Basics

$
0
0
Design Patterns are among the bread and butter of the good developer's cookbook. Basically, any serious job interview you will have as a Junior to Mid-level programmer, will have a question on Design Patterns in it. They are very important in many regards and essential in others. But no other is quite as controversial as the Singleton Design Pattern.

Very rarely have I seen a project that has no implementation of this whatsoever. In this article, I will explain the importance of using this Design Pattern and how to implement it.

Singleton


So what is really the Singleton? Well, it is a Design Pattern that allows us to restrict the class that implements it to have just one instance of itself at all times. In plain terms this means that if we implement Singleton on a class, it will always have just one instance. That's it. That instance will be accessible throughout your code but you will no longer be able to create new instances of the class.

Why should we use it?


There are many reasons. Here is a short list of some “why we should do it” stuff:
  • You will have one singular encapsulation module for the logic of your class that will serve in a way that you can do easy dynamic changes without changing the scope of your programming logic.
  • You can manage a single resource clearly through your code.
  • As the Singleton Design Pattern implements the lazy instantiation, it allows us to get and use it's encapsulated logic as it is needed at runtime.

When do we need Singleton


An implementation of Singleton is needed on classes that would represent something that you use in one form and consistently throughout your project. That would be per say your in-game's scoreboard that monitors your current point count. It's something that you would need during your gameplay experience to increment your score. However, you would need it at the end of your level to calculate your high-score. In that regard, implementing Singleton to your scoreboard class would be perfect. You increment your score and it is stored in the single scoreboard object that you have. When the time comes for us to calculate your in-game high score, we simply access this object and see what you've accumulated.

Another classic case would be to store and access the rules of a board game. Normally, if you are developing a regular board game, your rules should be the same all together. There is absolutely no reason for you to create a new object every time and for every game you play. There is no point to have this both from a performance standpoint and from data loss perspective.

But why use Singleton and not a class with static methods?


Singleton is not a replacement for a class with static methods. It's a totally different thing. It's also used in different cases.

You would use a class with static methods in situations where you do not need an instance at all. Normally, the static methods are going to be used to do operations with objects that are outside of the class. Generally, the static methods should be implemented in a more generic way as well. They are probably going to be used by multiple logic segments with different parameters altogether. With Singleton, you have a class that should work like a normal one. That's it. Like in the examples above, it's not merely a class containing some methods that are going to be used as tools later on. It is going to contain programming logic on its own.

So to talk in examples – you will need Singleton in your board game’s rules and in your in-game scoreboard. You would need a static class if you plan to dynamically instantiate reusable UI elements that serve only temporary purpose and are not a part of your core interface.


Singleton Implementations


Here we will take a look at a real implementation of Singleton in Java.

Java class implementing Singleton:

public class Scoreboard {

	public int currentScore; //we will use this for the score later on
	private static Scoreboard singleton = null; //this we will need for the implementation
	
	protected Scoreboard(){
		//nothing here really. At least for this example.
	}

	public static Scoreboard instance(){
		//this is the method that we are going to use to return the one instance of this class.
		if(singleton == null){
			singleton = new Scoreboard();
		}
		
		return singleton;
	}

}

Now to use this implementation in another class in order for you to see how it's actually going to happen.

public class HelloScoreboard{
	public static void main(String[] args){
		Scoreboard.instance().currentScore = 10; //here we call and set currentScore
		System.out.println(Scoreboard.instance().currentScore.toString());
	}
}

As seen in the example above, we have the Singleton class Scoreboard. It has its instance() method. Through this method we will get the one instance of this class. Any calls we want to make to the class have to be done through this method. Now, if we take a look at the currentScore variable, we will see that in the main method of HelloScoreboard we are setting it to the value of 10. From this point on, every time we refer to this variable, its value is going to be 10, at least until we change it for some reason. Again, its value can be changed wherever we please.


Singleton Issues


There are some major issues with the Singleton Design Pattern to look out for. If not implemented correctly and in turn, not handled correctly, you may be getting more issues then you would wish.

Multithreading


This is quite possibly one of the biggest issues out there. The problem here is something like this - let's say that you have two threads that for some reason are calling our Singleton object. Since they are two separate threads, we would get a logical paradox - two instances of the Singleton object. That's just not what we want at all. What we want is to have one instance that encapsulates a singular resource and functionality. By having the multithread issue, we completely make the point of the Singleton useless.

How can we fix this problem ?

Well, generally this is not a problem that can be truly "fixed". It can merely be "mended". We can do that by synchronising/locking the Singleton object.

Here is a Java implementation for this:

public class Scoreboard {

	public int currentScore; //we will use this for the score later on
	private static Scoreboard singleton = null; //this we will need for the implementation
	
	protected Scoreboard(){
		//nothing here really. At least for this example.
	}

	public static Scoreboard instance(){
		//this is the method that we are going to use to return the one instance of this class.
		if(singleton == null){
            synchronized(Scoreboard.class) {
                if(singleton == null){
					singleton = new Scoreboard();
                }
            }
		}
		
		return singleton;
	}

}

So this is what basically is happening here - on entry, the first thread will check if the singleton instance is null. If it is, then we go to the synchronized lock. When the other thread enters, the creation of the instance is locked. At this point we have another failsafe as well. If/when the second thread manages to get past the lock, when the first thread is done, we have a new check. At this point we block out the issue with the multiple instances.

Unit Testing


This is another major Singleton issue. That's because we would need to test the Singleton instance with every single class that uses it in one way or another. That's just not the idea of the Unit Tests. We want to test just one thing - not one thing and the Singleton. That makes two things and it also makes a corrupt test. Another thing to note here is the fact that the Singleton object has a "state" of a sort. At any time you change something, you change the Singleton's values and thus - it's current state. That makes it near impossible to track the states and the test data in a massive test case.

Again, as with the Multithreading issue, here we cannot fix the problem and make it go away. However, there is a workaround that can be used to make things a little bit easier. What can be done is this - for the tests, we can implement an overloaded version of the instance() method that would go with our needs. This is best seen by an example, so let's get into it.

We will change up the Scoreboard class and add some additional logic to it - we will have a public double time that would be used for the time we've spent while we accumulate the score. We will also create a class that is going to call both the current score and the time. We are going to call this class EventAtScore and it is going to initiate an event when the player has reached a specific score at a specific time. That will be also the class that we are going to perform the tests on.

First off, here is the Scoreboard class:

public class Scoreboard {

	public int currentScore; //we will use this for the score later on
    public double time;
	private static Scoreboard singleton = null; //this we will need for the implementation
	
	protected Scoreboard(){
		//nothing here really. At least for this example.
	}

	public static Scoreboard instance(){
		//this is the method that we are going to use to return the one instance of this class.
		if(singleton == null){
            synchronized(Scoreboard.class) {
                if(singleton == null){
					singleton = new Scoreboard();
                }
            }
		}
		
		return singleton;
	}
    
    public static Scoreboard instance(int score, int theTime){
		//this is the method that we are going to use to return the one instance of this class.
        //this is the overloaded method that we are going to use for the tests.
		if(singleton == null){
            synchronized(Scoreboard.class) {
                if(singleton == null){
					singleton = new Scoreboard();
                    singleton.currentScore = score;
                    singleton.time = theTime;
                }
            }
		}
		
		return singleton;
	}

}

Ok, so now let's go to the EventAtScore class. This would be it's normal construction.


public class EventAtScore{

    public String eventMessage = "";
    
    public EventAtScore(String defaultMessage){
    	this.eventMessage = defaultMessage;    
    }
    
    public void displayEventMessage(){
    
        Scoreboard theBoard = Scoreboard.instance();
        
        if(theBoard.currentScore == 100 && theBoard.time == 60){
        	System.out.println(eventMessage);   
        }
    }
}


And this is what we would have if we wanted to make a specific test.


public class EventAtScore{

    public String eventMessage = "";
    
    public EventAtScore(String defaultMessage){
    	this.eventMessage = defaultMessage;    
    }
    
    public void displayEventMessage(){
    
        //Here we use the overloaded version of the instance() method
        Scoreboard theBoard = Scoreboard.instance(100, 60);
        
        if(theBoard.currentScore == 100 && theBoard.time == 60){
        	System.out.println(eventMessage);   
        }
    }
}


As seen above, here we are able to produce values in the instance on it's initialization. That suits our needs for testing, at least to some point.

There are more flexible and better ways to perform such a test, however I simply wanted to make a point with this. If you are interested in how this can be done properly, you can read up on the following materials:


Debugging and Solving Issues


Since the Singleton can be called at any one point in your code, this makes it really hard to track when your instance got it's values/logics messed up beyond expectations.

The resolution here should really be to be careful why, when and where you call your Singleton object but mostly - you need to watch out if your implementation of this pattern is really needed. If you are making too many calls to the Singleton object, you might want to consider another approach.

The Singleton "knows" Too Much


Some times, the deviation of the Sinleton pattern from the traditional OOP understanding is making it an issue of what kind of things it can manipulate. We should not put calculations or any process that has a major role in our code. That's to say that if you have some basic and driving logic, you should by all means NOT include any parts of it inside the Singleton implementation.

Dependency Issues


This is a real blocker as well. When we use the Singleton Design Pattern, we take the risk of making the code too dependent on the object's state/values/logic. Let's say we expect the Singleton object to behave in a certain fashion. We base our logic on that behavior and we think that things are going to go smooth. And it does. Everything is going ok and you are happy that your code works as expected. Well, that's up until you totally forget what you've done with this. And then you decide to make some minor changes here and there. Now, your Singleton object does not behave the way you thought it would. Not only that, now you are totally not in controll of what's happening.

Singleton Implementation in Other Languages


Java is a fairly clear language to port from, however it would be good to take a look at other implementations and how things go there as well.

Singleton in C++


This would be the basic Scoreboard Singleton example from above, only done in C++.

#include <iostream>

using namespace std;

// This is the Scoreboard
class Scoreboard {

    public:
        static Scoreboard* singleton;//The Singleton Instance
    	int currentScore;
    	double time;

    public:
        static Scoreboard* Instance();

    private:
        Scoreboard();

};

Scoreboard* Scoreboard::singleton = NULL;

Scoreboard::Scoreboard()
{
    
}

Scoreboard* Scoreboard::Instance()
{
    if ( singleton == NULL ) {
    	singleton = new Scoreboard();
    }

    return singleton;
}

Singleton in C#


This would be the basic Scoreboard Singleton example from above, only done in C#.

using System;

public class Scoreboard
{
   private static Scoreboard singleton;
    
   public int currentScore;
   public double time;

   private Scoreboard(){
   
   }

   public static Scoreboard Instance
   {
      get 
      {
         if (singleton == null)
         {
            singleton = new Scoreboard();
         }
         return singleton;
      }
   }
}

Interesting Points


I chose Java for most of the examples in the previous chapters because I find it to be really easily portable to other programming languages. If you are doing work with C++ or C# you should have no problem in porting this code. The concepts are basically all the same.

Things You Can Look Up


Here are some online materials that I've fount useful on the Singleton subject:


Conclusion


Using Design Patterns in your code is really something from which you can benefit a lot. Singleton is quite possibly the most common of them all along side with the Factory Design Pattern.

Knowing how to implement Singleton can serve you really well.

Article Update Log


14 May 2013: The article was written.
16 May 2013: Added "Things to Look Out For" in the article.
23 May 2013: Refactored the article. Added a couple of issues with the Singleton.
24 May 2013: Added materials to the article.
24 May 2013: Added more code to the Testing section of the article. Added more materials.
24 May 2013: Added basic Singleton implementations for C++ and C#.

For a Career in Gaming, are Game Design Degrees Worth It?

$
0
0
Many students and parents believe that if they are interested in a career in gaming, then the best thing for them to pursue is a degree in "Game Design", "Game Programming", or "Game Art and Animation". There is no shortage of schools nowadays offering these programs, and you see advertisements everywhere online. It seems to make sense, right? If you want to do games, then why not go ahead and have the word "game" in your major? It seems like you'd be a shoe-in for any job opportunity.

While a few of these programs can lead to a successful career in gaming, in my career advising with parents and students I actually recommend against them, at least at first.

Why would I not recommend seeking game degrees? There are a few reasons. First is the flexibility. If you are interested in programming and think you'd like to work in the games industry, then that's great. Engineers are in high demand and you will likely find it easy to land yourself a fun, high paying job. However, my first suggestion is always to try and get into a top-tier computer science program and major more generally in "computer science", not "game programming". With a computer science degree you have an enormous amount of flexibility with your career. Computer science majors can get you not only into any game company, but almost any technology company as well. Not only EA, Activision, and Zynga will be recruiting you, but also Facebook, Amazon, Google, Apple, IBM, and a slew of others.

The key here is that you never know what the future may hold. If, for instance, you begin your career in gaming and then develop different interests, then you have the option of moving somewhere else in technology. But if you majored in "game programming", then you are locked in against your will, there isn't much you can do. So as a career advisor I can't recommend degrees that specialize in games as a first choice.

The second reason is the level of depth and expertise. You would think that majors that are focused on games would be in higher demand within the games industry than more general majors, but this actually isn't true. If you look at the new hires at the top game companies, then they typically have majors in Computer Science, Art and Animation, or Business/Finance, without the word "game" attached to any of them. One of the reasons for this is that the games industry is so dynamic, the rules change every year as we move from platform to platform, opening up new audiences and players. Thus, if you are taught specifically how to use Adobe Flash and Unity in school, then you may not be as much help when the next thing comes along. But if you know how to do art of all kinds or coding of all kinds, then you will be useful for decades to come.

Finally, students with game-specific majors, even if they are hired at top companies, often end up in "Associate" positions to start their career in gaming, instead of a higher paid position right off the bat. This is because of the reason above, the skills learned in a game degree are narrow, and so companies need to see these new hires prove themselves before moving them into a more general role that may require skills outside of what they learned. But a computer science or art and animation degree doesn't have these problems.

An Option, But Not the First


As I've said, these are all my first recommendations. However if other top tier schools in art or computer science are not an option for you, then a strong game degree can help you start your career in gaming and make your start. But it's important to realize the ways in which it may be affecting your future.

Best of luck!

This blog post is reprinted from The Game Prodigy, a site for students and parents interested in careers in games.

Article Update Log


No updates so far.

Photo credit: Lou FCD

Spring RTS Engineering Internals

$
0
0
Spring is a free open source RTS game engine originally created by Stefan Johansson and Robin Westberg, members of the Swedish Yankspankers game clan. Originally intended to bring the gameplay experience of Total Annihilation into three dimensions, the engine has since evolved to support a plethora of more modern and more flexible features, including built-in high-level extensibility through a Lua scripting interface.

Any developer who wants to contribute to Spring RTS or any other open source project needs to understand the existing code, and for that he can read the documentation, explore forums, read comments from code or read the code itself.

Another way is to use tools and query the code base. Like SQL for a relational database, CppDepend provides the CQLinq language to request the code and help to understand C/C++ within. It’s also free for open source projects.

In this article we will analyze Spring RTS with CppDepend to discover some internal design choices.

Paradigm used


C++ is not just an object-oriented language. As Bjarne Stroustrup points out, “C++ is a multi-paradigmed language.” It supports many different styles of programs, or paradigms, and object-oriented programming is only one of these. Some of the others are procedural programming and generic programming.

Procedural Paradigm


Global functions

Let’s search for all global functions inside the Spring engine:

from m in Methods where m.IsGlobal && !m.IsThirdParty select m

Attached Image: spring22.png

5092 functions are global, which represents around 20% of all the Spring methods. But what’s interesting is that these functions are grouped by namespaces which makes the code modular and easy to understand.

Structures

In a procedural program, modules interact by reading and writing a state that is stored in shared data structures. Let’s search for all data structures defined by Spring:

from t in Types where t.IsStructure && t.Methods.Count()==0
select t

Attached Image: spring27.png

Static functions

In general, it’s better to declare a function as static unless you have a specific need to call it from another source file.

from m in Methods where m.IsGlobal && m.IsStatic

Attached Image: spring26.png

Functions candidate to be static

from m in Methods where m.IsGlobal && !m.IsStatic && !m.IsThirdParty
&& m.MethodsCallingMe.Where(a=>a.SourceDecls.FirstOrDefault()!=null && a.SourceDecls.FirstOrDefault().SourceFile.FilePathString!=m.SourceDecls.FirstOrDefault().SourceFile.FilePathString).Count()==0
select m

Attached Image: spring29.png

Object Oriented paradigm


The object-oriented paradigm makes extensive use of virtual functions and polymorphism, let’s search for virtual methods.

from m in Methods where m.IsVirtual select m

Attached Image: spring2.png

And to have a better idea of existing virtual methods, we can use the Metric View.

In the Metric View, the code base is represented through a Treemap. Treemapping is a method for displaying tree-structured data by using nested rectangles. The tree structure used in a CppDepend treemap is the usual code hierarchy:
  • Projects contains namespaces.
  • Namespaces contains types.
  • Types contain methods and fields.
The treemap view provides a useful way to represent the result of a CQLinq request, so we can visually see the types concerned by the request.

Attached Image: spring3.png

As we can observe, virtual methods are not widely used.

Abstract classes

Low coupling is desirable because a change in one area of an application will require less changes throughout the entire application. In the long run, this could alleviate a lot of time, effort, and cost associated with modifying and adding new features to an application. Using abstract classes can improve the low coupling; let’s search for all abstract classes:

from t in Types where t.IsAbstract select t

Attached Image: spring4.png

Inheritence

In object-oriented programming (OOP), inheritance is a way to establish Is-a relationship between objects. It is often confused as a way to reuse the existing code which is not a good practice because inheritance for implementation reuse leads to Tight Coupling. Re-usability of code is achieved through composition (Composition over inheritance). Let’s search for all classes having at least one base class:

from t in Types where t.BaseClasses.Count()>0 select t

The Metric view shows us that many classes are concerned, and inheritance is mainly used.

Attached Image: spring16.png

Generic Programming

C++ provides unique abilities to express the ideas of Generic Programming through templates. Templates provide a form of parametric polymorphism that allows the expression of generic algorithms and data structures. The instantiation mechanism of C++ templates insures that when a generic algorithm or data structure is used, a fully-optimized and specialized version will be created and tailored for that particular use, allowing generic algorithms to be as efficient as their non-generic counterparts.

In the C++ world two schools are very popular: Object Oriented Programming and Generic Programming, each approach has their advocates, this article explains the tension between them. Let’s search if Spring uses templates:

from t in Types where t.IsGeneric && !t.IsThirdParty select t

Attached Image: spring6.png

Spring RTS uses template classes, especially for containers and utility classes. We can also search for generic methods:

from m in Methods where m.IsGeneric && !m.IsThirdParty select m

Attached Image: spring7.png

Only some methods are templated.

Spring RTS startup


To understand what happens when the RTS engine starts, let’s begin with the dependency graph concerning some methods invoked by the entry point WinMain.

Attached Image: spring9.png

When the engine starts it searches for the existing cores to exploit all the processing machine power, and after that delegates the initialization to the SpringApp class. Let’s search what happens when the Initialize method is invoked.

from m in Methods where m.IsUsedBy ("SpringApp.Initialize()") && !m.IsThirdParty
select new { m }

Attached Image: spring10.png

This method initializes all the other classes with which it collaborates like LuaOpenGL, CMyMath and CGlobalRendering, and after it invokes the startup method. And here’s the dependency graph of the startup method.

Attached Image: spring11.png

External frameworks used


When developing a product, it’s preferable to not reinvent the wheel and reuse proven and mature frameworks. Let’s search for external types used by Spring.

from t in Types where t.IsUsedBy ("rts")
select new { t }

Attached Image: spring25.png

Spring RTS uses mainly boost, this library is aimed at a wide range of C++ users and application domains. They range from general-purpose libraries like the smart pointer library, to operating system abstractions like Boost FileSystem, to libraries primarily aimed at other library developers and advanced C++ users, like the template metaprogramming (MPL) and domain-specific language (DSL) creation (Proto).

For example concerning network communication Spring uses the boost.asio library, which provides developers with a consistent asynchronous model using a modern C++ approach.

Conclusion


For any developer using the Spring RTS, or any new code base, it’s better to know sometimes how it works internally, for which the better approach is to go inside the code source. In this case we have found that the Spring RTS code is very simple to understand and evolve.

Game Programming: Snake

$
0
0

Introduction


What is Snake?


Quoting Wikipedia:

Snake is a casual video game that originated during the late 1970s in arcades and has maintained popularity since then, becoming something of a classic. After it became the standard pre-loaded game on Nokia mobile phones in 1998, Snake found a massive audience.


Who is this article for?


In order to get the most out of this article, you should be familiar with the C++ programming language, and have written and successfully compiled a few programs (or games) on your own.


What will I learn?


If I do my job right, you should learn how to develop a Snake clone game. We are going to talk about the basics first, that is, getting something on the screen. Then we will cover gathering input from the player and making things move. Next we will go through the architecture of the game, and finally we will take each step one by one and by the end you should have a solid understanding of how to sit down and write your very own Snake game from scratch.


What do I need?


I will be using a Windows machine, however you may use a Linux or a Mac computer because we are using a cross-platform library so that our game can target as many platforms as possible without changing the code. That said, here is a list of things to bring with you.

  • C++ compiler (I will be using the Mingw C++ compiler provided with the Code::Blocks IDE)
  • SDL version 1.2.15 which may be obtained here.
  • Pen and Paper (or the digital equivalent) for taking notes.

Compiler Setup


First things first.


The first thing we need to do is download and setup our compiler (Remember, we are using Mingw through the Code::Blocks IDE here) to use SDL. Head on over to the SDL download page and download SDL-devel-1.2.15-mingw32.tar.gz then extract the contents to your computer.


You should have a folder called SDL-1.2.15 containing a bunch of files. I like to keep my computer tidy, and I create a root folder called “CLibs” in which I install all my libraries that I will use with the C and C++ programming languages. I would recommend that you do the same in order to avoid confusion later on.


We will only need the include, lib, and bin folders from the SDL-1.2.15 folder. Go ahead and copy those folders into C:\CLibs\SDL-1.2.15\ and then we can move on over to configuring Code::Blocks so that it is able to find the SDL library files it needs.


Start up Code::Blocks and click on the Settings menu, then click on the Compiler and Debugger... menu item. In the window that opens, choose the Search directories tab, and under the Compiler sub-tab, you need to click on the Add button and browse for the C:\CLibs\SDL-1.2.15\include folder and click the OK button to add the folder to the compiler search directory paths. Now click on the Linker sub-tab and repeat the process for the C:\CLibs\SDL-1.2.15\lib folder. Click on the OK button and you are finished with telling Code::Blocks where the SDL files are located.


Testing the install.


We are going to write a very small program to test that Code::Blocks is correctly configured to use SDL.


Step 1.


Select File -> New -> Project from the menu in Code::Blocks, and then select Empty project from the templates and click on the Go button.


Step 2.


If you see “Welcome to the new empty project wizard!” just click on the Next button. Otherwise, if you see “Please select the folder where you want the new project to be created as well as its title.” then type in a name for your project. In this case, we are testing SDL, so type in the name SDLTest into the Project title field and then click the Next button, and the Finish button on the next screen.


Step 3.


Select File -> New -> Empty file from the menu and click Yes when asked “Do you want to add this new file in the active project (has to be saved first)?” and enter sdltest-main.cpp as the file name, and save the file to the SDLTest folder created along with your new project. When asked to select the targets, just click the OK button.


Step 4.


Finally we get to write a little code. Enter each line exactly as you see it. I will not explain this test code, because all we are looking for is a yay or nay about SDL being configured correctly, and this article’s purpose is not to go over basic code.


#include <SDL/SDL.h>
int main(int argc, char* argv[])
{
    if (SDL_Init(SDL_INIT_EVERYTHING) < 0) 
    {
        return -1;
    }
   
    SDL_Quit();
    return 0;
}

Step 5.


Last thing, we need to specify the SDL libraries so we can compile the project. Right-click on the SDLTest item in the Projects panel and select Build options... then select the Linker settings tab. Under the Other linker options box, type in the following items each on their own line.

  • -lmingw32
  • -lSDLmain
  • -lSDL

Take note that each line begins with minus sign then a lowercase letter L.
    
Step 6.


Well, I know I said last thing in the previous step, but this really is the last thing. Build the project and Run the project. Select Build -> Build from the menu and as long as there are no errors, select Build -> Run from the menu. If you have any errors, go back to Step 1 and read through and make sure you have done everything as specified. If you continue to have trouble, then contact me with the full error you are having, and I will see if I can help you get things sorted out.


You should get a black console window appear and it should say


Process returned 0 (0x0)   execution time : 0.201 s
Press any key to continue.


If this is not the case, then something went wrong. If you see the text like above, then you are ready to proceed further into this article.


All systems are go.


Okay great, SDL is installed, Code::Blocks is configured, you know how to get an SDL project created and compiled, we’re good to move on to something a little more exciting. We are going to take a small step away from the code and have a look at some pretty pictures to help you understand what we are going to be doing over the next few sections of the article.


Attached Image: GenericGameLoop.png


This is called the game-loop. Every single game has something like this inside of it. From Pong to Halo to Farmville to World of Warcraft. (Disclaimer: These games and their names are copyright and/or trademarks of their respective owners.) Every Single Game Has A Game Loop of some kind. This fun little loop is what keeps the game going. If nothing ever looped, the game would start, and then they would just about immediately end. That would be really boring. So let’s see what exactly is going on here. First we do a little housekeeping, like handling events and what-not, next we update the game world, finally we render the game world, and the whole thing repeats until something tells it not to.


Now, there are hundreds if not thousands of articles and books out there that will explain this in at least a hundred different ways in more detail. I’m not going to add to that total with this article. Instead I am going to jump ahead right into our next project which is called Big Blue Box (Disclaimer: I did not check to see if Big Blue Box is trademarked or copyrighted to anyone. If it is, sorry for using your name.) in which our job as a programmer is to make a big blue box appear on the screen. Fun? Nah... but we have to start somewhere before we can get to the fun stuff.


SDL Basics


Beginnings of Big Blue Box


Just like the SDLTest project, create a new project and configure the linker settings so the project will compile, and also throw in a .cpp file into the mix so we have somewhere to write our code. I’m calling my project BigBlueBox and the source file bigbluebox-main.cpp you can do the same, or change the name. Your choice.


Okay, first we need some include statements and then we need to define some constants for our little program.


#include <iostream>
#include <SDL/SDL.h>

static const unsigned WINDOW_WIDTH = 800;
static const unsigned WINDOW_HEIGHT = 600;
static const unsigned BOX_WIDTH = 256;
static const unsigned BOX_HEIGHT = 256;

Everything should be self-explanatory. Our window will be 800x600 and the box will be 256x256. Simple enough. We need iostream because we will be using the cerr error output stream for error reporting and naturally we need SDL.h because we are writing a program which uses SDL. Next, we write the main code.


int main(int argc, char* argv[])
{
    return 0;
}

This should be pretty much stuck in your brain if you have had any programming experience with C and C++. The rest of our program’s code will fall between the starting brace of the function and the return zero line.


I usually declare my variables when they are used, however in this particular project I will declare all the variables I will use at the top of the function just so that you can refer to a single location to see the datatype of a variable being used.


We are going to need a pointer to an SDL Surface, to represent our primary drawing surface and our program’s window. We need an SDL Event object for our event handling. We need an SDL Rect object to define our box’s position and dimensions. We need a couple unsigned integers for our box color and the color to make the background, and finally we need a boolean variable for keeping track of our game loop. Let’s see the variable declarations now.


SDL_Surface* displaysurface = NULL;
SDL_Event sdlevent;
SDL_Rect boxrect;
unsigned boxcolor;
unsigned backgroundcolor;
bool running;

The next thing we need to do is initialize SDL. This is accomplished with the SDL_Init function. Then we need to set the video mode to create our program’s window. This is accomplished with the SDL_SetVideoMode function. We then set the window caption text to something relevant to our program. This is accomplished with the SDL_WM_SetCaption function. If we don’t do this, the caption will be “SDL_app”. Let’s have a look at the code for all of this now.


if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
    std::cerr << "SDL_Init Failed: " 
              << SDL_GetError() << std::endl;
    return -1;
}

displaysurface = SDL_SetVideoMode(
    WINDOW_WIDTH, WINDOW_HEIGHT, 32, 
    SDL_HWSURFACE | SDL_DOUBLEBUF);
if (displaysurface == NULL)
{
    std::cerr << "SDL_SetVideoMode Failed: " 
              << SDL_GetError() << std::endl;
    return -1;
}

SDL_WM_SetCaption("Big Blue Box", NULL);

Next we are going to set up our box to be the right size using our constants we defined at the start of our code, and then we will position our box in the center of the screen.


Note:  
Tip: To center an object on the screen, first subtract the object’s size from the size of the screen and then you divide the difference by two.


boxrect.w = BOX_WIDTH;
boxrect.h = BOX_HEIGHT;

boxrect.x = (WINDOW_WIDTH - boxrect.w) / 2;
boxrect.y = (WINDOW_HEIGHT - boxrect.h) / 2;

Now we are going to set up our color variables. We want obviously a blue box. And I want a black background, so we are going to use the SDL_MapRGB function to get the right color values. Lastly, we set our running boolean to true.


backgroundcolor = SDL_MapRGB(displaysurface->format, 0, 0, 0);
boxcolor = SDL_MapRGB(displaysurface->format, 0, 0, 255);
running = true;

We finally arrive at the game loop. Our game loop will be very simple, since our program is not really a game, we don’t have much to do here. We just need to handle a couple events and then draw our screen.


while(running)
{
    // handle events
    // render game
}

The most complex part of this will be handling the events, and honestly, this is not really that difficult. We need to handle the SDL_QUIT event, which is sent when the user tries to close the window. If we don’t handle this event, well the window would refuse to close and your user will be pretty irritated with you.


Note:  
Tip: ALWAYS remember to handle the SDL_QUIT event or your users will be very unhappy with you and your game.


Handling the event is pretty simple really. We just need to tell our game loop to stop looping, in our case, we just set our running boolean variable to false. Easy peasy. We would also like to be able to close our game by pressing the ESC key on the keyboard. To accomplish this feat, we need to handle the SDL_KEYDOWN event and check for the SDLK_ESCAPE key, and same as the SDL_QUIT handler, tell our game loop to stop looping. That wraps up the event handling we need to do here.


Now, that we know what events we have to handle, we need to know how to actually find out what events are being fired off. To do this, we need to call the SDL_PollEvent function inside a loop so that we can handle all events that get queued up when our game is running. Let’s have a look at the code for our event handling. Remember that this code falls within our game loop.


while(SDL_PollEvent(&sdlevent))
{
    switch(sdlevent.type)
    {
        case SDL_QUIT:
        {
            running = false;
        } break;

        case SDL_KEYDOWN:
        {
            if (sdlevent.key.keysym.sym == SDLK_ESCAPE)
            {
                running = false;
            }
        } break;
    }
}

Great, now the only thing left to wrap up our game loop is the rendering of our game screen. We will use the SDL_FillRect function to color our background, and to draw our box on the screen. After everything gets drawn, we need to call the SDL_Flip function in order to make our rendering visible on the screen because we are using double buffering (and we definitely want to be using double buffering). And lastly in order to keep our CPU happy, we will call the SDL_Delay function to give a few time slices back to the system.


SDL_FillRect(displaysurface, NULL, backgroundcolor);
SDL_FillRect(displaysurface, &boxrect, boxcolor);
SDL_Flip(displaysurface);
SDL_Delay(20);

Our game loop is done. The rest of the code that follows should be outside the game loop’s closing brace. In order to wrap up the game code, we need to clean up after ourselves. Because our game is very simple and we don’t allocate anything other than the display surface, we can clean up by calling the SDL_Quit function.


SDL_Quit();

And we are done! Now go ahead and build and run the project. You should see a big blue box on a black screen. Press the ESC key on your keyboard and the window should close.


Attached Image: BigBlueBox-Screenshot.png


Moving Boxes.


Our next little project will build on the BigBlueBox project and we will add the ability to move our box around the screen using the arrow keys. We are going to need to add a couple additional variables to the top of our main function. We need an SDL_Rect to define the boundaries in which we can move our box, and an unsigned integer that defines the speed at which the box is able to move.


SDL_Rect boxbounds;
unsigned boxspeed = 6;

Now after we set the running boolean to true, before we start the game loop, we need to set up our bounding box rect. There are four variables in an SDL_Rect which we are going to use to specify the left, top, right, and bottom edges of a bounding box in which our box will be able to move. We subtract the size of our box from the size of our window to get the limits of the upper-left corner of our box.


boxbounds.x = 0;
boxbounds.y = 0;
boxbounds.w = WINDOW_WIDTH - boxrect.w;
boxbounds.h = WINDOW_HEIGHT - boxrect.h;

We now are going to check if any of the arrow keys are being pressed, and if they are being pressed, move our box by adding or subtracting the box speed. We also need to ensure the box does not move outside out bounding box we have defined. But first, we have to have a way to read directly the current state of the keyboard. We are able to accomplish this task with the SDL_GetKeyState function. The code should be added to the game loop after the event handling loop and before the code that handles the rendering.


unsigned char* keys = SDL_GetKeyState(NULL);

if (keys[SDLK_UP])
{
    boxrect.y -= boxspeed;
    if (boxrect.y < boxbounds.y)
    {
        boxrect.y = boxbounds.y;
    }
}
else if (keys[SDLK_DOWN])
{
    boxrect.y += boxspeed;
    if (boxrect.y > boxbounds.h)
    {
        boxrect.y = boxbounds.h;
    }
}

Now that takes care of the UP and DOWN movement, so let’s take care of the LEFT and RIGHT next.


if (keys[SDLK_LEFT])
{
    boxrect.x -= boxspeed;
    if (boxrect.x < boxbounds.x)
    {
        boxrect.x = boxbounds.x;
    }
}
else if (keys[SDLK_RIGHT])
{
    boxrect.x += boxspeed;
    if (boxrect.x > boxbounds.w)
    {
        boxrect.x = boxbounds.w;
    }
}

And that is all we are going to need to do. You should be able to build and run the project as before, and this time you can move the box around the screen using the arrow keys, and the box should not move beyond the edges of the screen. We have now covered enough of the basics that you should have enough knowledge of using SDL at this point to start writing your Snake game. So I’m done here.





...just kidding. Well, just about the last part. I’m not done here. I still have to teach you about programming Snake, since that is what this article is really about. This has all just been a crash-course introduction to get your appetite whetted. Now, before we can code our Snake game, we have to talk about how we are going to engineer our game code.


A Look At Snake


I am going to use a very simple design for our little Snake game. For brevity and to help keep the focus on the core subject, I will not be implementing sound, I will not be using any external bitmaps, I will not implement scoring or text output, and I will not implement any sort of game state management or anything that would otherwise further complicate the program. This article is not about how to go about creating a polished, retail-ready game. It is about how to program a Snake game, and that is all I am going to do here.


For our game, we need two objects. The Snake, and a “Collectable Coin” which causes the Snake to grow in length. The rules are simple as well. If the Snake collides with the edge of the screen or itself, then the Snake will die. The player uses the Arrow keys to control the Snake in any of the four directions; Up, Down, Left, and Right. The Snake cannot be made to move in the opposite direction of it’s movement, as that would cause the snake to bite itself instantly causing death. We will use simple filled rectangles to represent the various visuals of the game.


The code will consist of three classes and the main() function which houses the sample init and game loop code you have seen in the BigBlueBox project. The body of the Snake will be composed of multiple pieces, referred to as segments which will be held in a deque, or double-ended queue which can be found in the C++ STL. You can read more about deques here.


In order to make the Snake move, we will prepend a segment positioned in the location where the Snake is going to move, and if the Snake is moving into a location where there is no “Collectable Coin”, the tail end of the Snake is chopped off. Using a deque makes this process straightforward through the push_front and pop_back methods. In order to cause the Snake to grow in length, we do not chop off the tail if we collide with a “Collectable Coin”.


The game screen is divided into a number of “Cells”. A single segment and the “Collectable Coin” are both sized the same as a single Cell. The Snake begins in the center of the screen. This should be enough information for us to start writing the code for our little Snake game.


Building Snake


Finally, we get to have some fun programming. In order for us to begin, we will need to include a few header files, and then define our constants. We will need iostream for using cerr for our error reporting, deque to contain our Snake Segments, and of course SDL.h to access the SDL library functionality which powers our game.


We have our window dimensions, the four directions the Snake can move, and some constants to define the scale of the game world, and lastly the starting location and length of the Snake are defined as constants as well.


#include <iostream>
#include <deque>
#include <SDL/SDL.h>
static const unsigned WINDOW_WIDTH = 800;
static const unsigned WINDOW_HEIGHT = 600;
static const unsigned GO_UP = 0;
static const unsigned GO_DOWN = 1;
static const unsigned GO_LEFT = 2;
static const unsigned GO_RIGHT = 3;
static const unsigned CELL_SIZE = 20;
static const unsigned CELL_WIDTH = WINDOW_WIDTH / CELL_SIZE;
static const unsigned CELL_HEIGHT = WINDOW_HEIGHT / CELL_SIZE;
static const unsigned START_X = CELL_WIDTH / 2;
static const unsigned START_Y = CELL_HEIGHT / 2;
static const unsigned START_LENGTH = 3;

The first class in our little game is nothing more than a data structure that keeps track of the position of each segment of the snake.


class SnakeSegment
{
    public:
    unsigned x;
    unsigned y;

    SnakeSegment(unsigned x, unsigned y)
    {
        this->x = x;
        this->y = y;
    }
};

Next up we have the Coin class which keeps track of the position of the coin. The same data as the SnakeSegment, however I wanted to have two distinct classes. The only notable difference between the SnakeSegment class and the Coin class is a method which randomly sets the position of the “Collectable Coin”.


class Coin
{
    public:
    unsigned x;
    unsigned y;

    Coin()
    {
        Respawn();
    }

    void Respawn()
    {
        x = 1 + rand() % (CELL_WIDTH - 2);
        y = 1 + rand() % (CELL_HEIGHT - 2);
    }
};

The third class of our game is where the majority of the work is located, and is also inevitably the most complex. The Snake class is a composite of the previous classes along with a few members necessary to implement the desired mechanics. We need to keep track of the direction the Snake is moving, we need a timing mechanism to keep from calling our collision detection code every frame, and a few colors. I also reuse a single SDL_Rect object for all the rendering to minimize the allocations and deallocations per-frame. We need methods to restart the game, update the game, render the game, determine if the game is over, and handle player input and collisions with the walls, the “Collectable Coin” and the snake itself.


class Snake
{
    private:
    std::deque<SnakeSegment> segments;
    Coin coin;
    bool dead;
    unsigned direction;
    unsigned time, timeout;
    unsigned headcolor, segmentcolor, coincolor;
    SDL_Rect renderrect;
    public:
    Snake(unsigned headcolor, unsigned segmentcolor, 
          unsigned coincolor);
    ~Snake();
    void Restart();
    void Update();
    void Render(SDL_Surface* dest);
    inline bool IsDead() { return dead; }

    private:
    
    void UpdateInputControls();
    void RenderSnake(SDL_Surface* dest);
    void RenderCoin(SDL_Surface* dest);
    void AddSegment(unsigned x, unsigned y);
    void MoveSnake();
    bool CheckForWallCollision();
    bool CheckForSelfCollision();
    bool CheckForCoinCollision();
};

Before I get into the code that implements the Snake class methods, I want to show you the main function and how the Snake class is used to create the gameplay flow. You have already seen most of the code in the BigBlueBox project, however there are a few small changes in the code arrangement. The layout is still the same: Init, Game Loop (Handle Events, Update, Render), Cleanup.


In the Init section of the main function, the following code should be written. If it is not immediately obvious, the background color is dark green, the head of the snake is red, the body of the snake is bright green, and the coin is yellow.


if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
	std::cerr << "SDL_Init Failed: " 
               << SDL_GetError() << std::endl;
	return -1;
}

SDL_Surface* displaysurface = SDL_SetVideoMode(
    WINDOW_WIDTH, WINDOW_HEIGHT, 32, 
    SDL_HWSURFACE | SDL_DOUBLEBUF);
if (displaysurface == NULL)
{
	std::cerr << "SDL_SetVideoMode Failed: " 
               << SDL_GetError() << std::endl;
	return -1;
}

SDL_WM_SetCaption("Snake", NULL);

unsigned backgroundcolor = SDL_MapRGB(
    displaysurface->format, 0, 64, 0);
unsigned snakeheadcolor = SDL_MapRGB(
    displaysurface->format, 255, 0, 0);
unsigned snakebodycolor = SDL_MapRGB(
    displaysurface->format, 0, 255, 0);
unsigned coincolor = SDL_MapRGB(
    displaysurface->format, 255, 255, 0);

Snake snake(snakeheadcolor, snakebodycolor, coincolor);

SDL_Event sdlevent;
bool running = true;

In the SDL_KEYDOWN section of the event handling code of the Game Loop, after the code that handles SDLK_ESCAPE, the following code needs to be added to allow the player to restart the game after dying by pressing the ENTER (RETURN) key.


else if (sdlevent.key.keysym.sym == SDLK_RETURN)
{
    if (snake.IsDead())
    {
        snake.Restart();
    }
}

Simply call the Update method of the snake for the Update section of the Game Loop, and call the Render method in the Render section. That wraps up the code for the main function. Next we will take a look at the method implementations of the Snake class.


Constructing the Snake


First up is the class constructor. Most of the construction process has been delegated to the Restart method, to avoid code duplication. The constructor consists of setting the colors and then calling the Restart function to finish the construction.


Snake::Snake(unsigned headcolor, unsigned segmentcolor, 
             unsigned coincolor)
{
    this->headcolor = headcolor;
    this->segmentcolor = segmentcolor;
    this->coincolor = coincolor;
    Restart();
}

Destructing the Snake


The class destructor just needs to clear out the deque since we do not have any dynamic memory allocations which need to be freed.


Snake::~Snake()
{
    segments.clear();
}

Restarting the Snake


As mentioned before, the construction of the Snake has been delegated to the Restart method to avoid code duplication. When the Snake is restarted, the deque is cleared out, then the starting snake segments are added to the deque. The direction of movement is reset as well as the dead flag and the timing mechanism.


void Snake::Restart()
{
    segments.clear();
    for (unsigned i = 0; i < START_LENGTH; i++)
    {
        AddSegment(START_X - i, START_Y);
    }
    direction = GO_RIGHT;
    time = 0;
    timeout = 6;
    dead = false;
}

Adding Snake Segments


We add segments to the tail of the starting Snake by pushing to the back of the deque. This only occurs when building the initial Snake body in the Restart method.


void Snake::AddSegment(unsigned x, unsigned y)
{
    SnakeSegment segment(x, y);
    segments.push_back(segment);
}

Updating the Snake


If the Snake is dead, we do not continue the update. First we update the input controls, then update the timing mechanism. If the time has not timed out, we do not continue the update. If the time has timed out, we check for collisions and finally move the snake.


void Snake::Update()
{
    if (dead) { return; }

    UpdateInputControls();

    time++;
    if (time < timeout)
    {
        return;
    }

    time = 0;

    if (CheckForWallCollision() || CheckForSelfCollision())
    {
        dead = true;
        return;
    }

    if (CheckForCoinCollision())
    {
        coin.Respawn();
    }
    else
    {
        segments.pop_back();
    }

    MoveSnake();
}

Controlling the Snake


We do not want the Snake to be able to reverse its direction of movement, so our movement code is a little more than just if key pressed, then move. But nothing too difficult.


void Snake::UpdateInputControls()
{
    unsigned char* keys = SDL_GetKeyState(NULL);

    if (keys[SDLK_UP] && direction != GO_DOWN)
    {
        direction = GO_UP;
    }
    else if (keys[SDLK_DOWN] && direction != GO_UP)
    {
        direction = GO_DOWN;
    }
    else if (keys[SDLK_LEFT] && direction != GO_RIGHT)
    {
        direction = GO_LEFT;
    }
    else if (keys[SDLK_RIGHT] && direction != GO_LEFT)
    {
        direction = GO_RIGHT;
    }
}

When the Snake hits the Wall


Checking for collision between the head of the Snake and a “Wall” is a straightforward process of testing if the head of the Snake has reached any of the four edges of the game world.


bool Snake::CheckForWallCollision()
{
    unsigned headx = segments[0].x;
    unsigned heady = segments[0].y;

    return (
            (headx == 0) ||
            (heady == 0) ||
            (headx == CELL_WIDTH) ||
            (heady == CELL_HEIGHT));
}

Watch Out For Your Tail


If the Snake’s head touches another segment of the Snake body, it dies from the poison. Just loop through the deque starting at the segment after the head and if the head is in the same location as the iterated segment, you have a collision.


bool Snake::CheckForSelfCollision()
{
    unsigned headx = segments[0].x;
    unsigned heady = segments[0].y;

    for (unsigned i = 1; i < segments.size(); i++)
    {
        if (segments[i].x == headx && segments[i].y == heady)
        {
            return true;
        }
    }
    return false;
}

Collecting Coins


This is the easiest collision check of them all. If the head touches the coin, you collect the coin. Pretty easy stuff after all the code we have written so far.


bool Snake::CheckForCoinCollision()
{
    return (segments[0].x == coin.x && segments[0].y == coin.y);
}

Moving the Snake


In order to make the Snake appear to move, we push a new head segment to the front of the deque. Since the Update method takes care of popping the back end segment off of the deque, this gives the illusion that the segments are following the head segment, which looks like the Snake moves as an intelligent entity.


void Snake::MoveSnake()
{
    static const int movex[] = { 0, 0, -1, 1 };
    static const int movey[] = { -1, 1, 0, 0 };

    unsigned x = segments[0].x + movex[direction];
    unsigned y = segments[0].y + movey[direction];

    SnakeSegment nextsegment(x, y);

    segments.push_front(nextsegment);
}

Drawing the Snake


If the Snake is dead, we do not continue the rendering process. Coins are rendered first, then the Snake itself. Since all visuals are the same size rectangle, we are able to reuse a single SDL_Rect structure and simply update the x and y values for each component to be rendered in the correct location. Every x and y value needs to be multiplied by the size of a single “Cell” in the game world, so that the on-screen positions line up correctly.


void Snake::Render(SDL_Surface* dest)
{
    if (dead) { return; }

    renderrect.w = CELL_SIZE;
    renderrect.h = CELL_SIZE;

    RenderCoin(dest);
    RenderSnake(dest);
}

void Snake::RenderCoin(SDL_Surface* dest)
{
    renderrect.x = coin.x * CELL_SIZE;
    renderrect.y = coin.y * CELL_SIZE;
    SDL_FillRect(dest, &renderrect, coincolor);
}

void Snake::RenderSnake(SDL_Surface* dest)
{
    renderrect.x = segments[0].x * CELL_SIZE;
    renderrect.y = segments[0].y * CELL_SIZE;
    SDL_FillRect(dest, &renderrect, headcolor);

    for (unsigned i = 1; i < segments.size(); i++)
    {
        renderrect.x = segments[i].x * CELL_SIZE;
        renderrect.y = segments[i].y * CELL_SIZE;
        SDL_FillRect(dest, &renderrect, segmentcolor);
    }
}

The End is Here


Attached Image: Snake-Screenshot.png


With that, our little Snake game is complete. Go ahead of build and run the project and you should get a dark green screen with a red & green snake that you can control using the arrow keys to collect yellow coins that randomly appear after you collect each one. If you bite yourself or hit a wall, you die, and nothing will be drawn but the dark green screen. Pressing the Enter key will restart the game, and pressing ESC will quit the game.


If you have any problems with the project, or would like to discuss the project. Feel free to contact me. My email address is ccpsceo@gmail.com. Please include “Programming Snake” in your subject when emailing me. You may also contact me via Skype by adding the user bbastudios and when asking for me to add you, include that you have read this Programming Snake article


Thank you for reading. I hope you have enjoyed this as much as I have.


Sincerely,
Richard Marks
Senior Technical Director
Bang Bang Attack Studios
www.bangbangattackstudios.com

Crafting a Maze Game

$
0
0
In this article we are going to perform some basic Game Design for a simple five stages maze crawler. Let's start with the obvious question – what is this maze crawler game going to be and how are we going to go on to develop it?

The goal in the game is going to be to get from point A to point B in order for you to finish the level. Along the way you are going to meet all sorts of weird traps that are going to try to stop you from fulfilling your goal. Another thing to note is that a good maze crawler does not repeat itself too much. That's to say that we should switch the player's starting and finishing point on a random basis. We are going to discuss all of these concepts further down the article.

Main Concept


Let's start right here. Nothing can truly be achieved if you do not have a good planning base. Firstly, we need to define the exact objective of the game. We've already determined that we should be able to get from point A to point B to complete the game, however that alone is just not very appealing. Let's say that our player is spawned at a certain point in the maze. From that point you would need to find a teleport in order to escape the current location you are in.

Now … in the current article we are talking about a very very small game, mostly due to the fact that this is all aimed towards beginners. We are going to design 5 such levels. However, the lack of quantity should never be a reason for neglecting the replay value. This is one of the most important elements of a good game and in turn – good Game Design. If you have good replay value, you have a good game (at least in the general number of cases). So how are we going to make this small game have any replay value at all? Well … to start off, we are going to have different locations for the player and the teleporter inside the maze level itself. The number of random locations is not going to be too big in this example in order to avoid confusion but we'll get to that shortly. What I want to say here is that along the lines of this article we are going to implement other (more) elements that increase replay value in a vastly different way then having a random spawn position.

Now, before we can get to actually do something more serious, I'm going to put in here the basic schema of the maze so we can take a look at what it's supposed to look like. Further chapters are going to deal with corridor design and other stuff along these lines. This schema is going to be that of the very first level.


Attached Image: Level 1.png


As you can see in the picture, we have four entrances and a couple of “endless loops” within this maze. Hardly a challenge, yet we are going to turn it into one. As this article progresses we are going to add random spawn points, traps and many more features. We are also going to go over designing such a level and making it harder and harder in terms of logistics.

Random Spawning points


Now, let's take a look at a modified version of the first level of the maze crawler that we talked about in the previous section.


Attached Image: Level 1-2.png


As you can see, in the image we have the four entrance points. They are going to serve not only as a beginning location but also they are going to be our teleporter points. And this is how things are going to go – in this design we should have only one entrance point and only one teleport. On each of the four locations we are going to place a game object as a marker. If you are using Unity3D for example, I would suggest using a small cube and from there removing its mesh. Each marker is going to have an id from 1 to 4. From this point on, firstly we are going to instantiate the entry point in one of the four locations by generating a random number in the 1 - 4 range. Then we will cache the id. After that we will instantiate the teleporter. This is going to be done in the same way as the start location, except for the fact that we are going to check the random id. If it is the same as the cached, we will get another random id. And of course there are far better technical solutions then this but they are all in the technical field and we are not going to overload the article with such things.

So this is how we generate the random starting point and the teleporter. Now time to do something more interesting.

Enter the Traps


What's a good maze without some traps to make your life miserable? In our simple maze, we are going to define three types of traps – hidden pits on the floor, arrows shooting out of the walls and stalactites falling from the ceiling. Now, let's take a look at some trap placement in the following picture.


Attached Image: Level 1-3.png


As you can see here, we have the pits placed on turns or on corridor entry, the arrows are placed in long corridors along with the falling ceiling. You can evade the traps on the floor by jumping and the arrows and stalactites can be evaded through running. However this doesn't seem too hard, does it? The player will eventually learn where you've placed your traps and thus – your maze no longer poses a threat to the in-game character. From that point on you lose your replay value. We have to fix that. We will do that by implementing something that we are actually familiar with.

Random trap placement. Yes, you heard me – random trap placement. We will do this in a similar way as the entry point and the teleporter. However, a note to the technical guys – here we have a big array of elements to spawn. A more sophisticated exclusion mechanism is in order. On a side note as well, here you are going to have to be careful where you place your traps inside the corridor. You don't want to get in a situation where the maze becomes too hard or damned near impossible to finish. But we'll get to that later on when we talk about corridor building.

Good, now we have the randomized traps. However is that really enough? No, it isn't. Let's add a new feature to the mix.

The All-mighty Timer


Let's make things intense. A countdown timer. Not just a countdown timer but a best time as well. So how do we do this? Well, the timer has to have enough time to just find the teleporter at a regular gaming pace. However, the less time you spend in finding the teleporter, the more you would move up in high score. If you can't find the teleport in time, well, you kick the bucket and get a nice “Game Over” message.

Now, a reasonable question would be how to choose your time? What exactly should your regular gaming pace be? Well, this is something that you are going to have to find out for yourself – by playing your own maze. A lot. A tip I can give you here is some reverse engineering. Before actually implementing the countdown timer, do a timer that counts up the time you need to complete the maze. After tracking your time, both normal paced and best time, you can calculate what you are going to have to put in your final product.

Corridors and Corridor Loops


Now … an interesting question would be how to position your corridors and how to structure the maze itself. The first thing is, you have to make the corridors intersect with each other in such a way that it would confuse the player. You have to make him doubt if he's been through this path before or not. With the traps and the countdown, the player really doesn't have all that much time to think about what's going on. That's your chance to confuse him even further. A good thing to do here is to create a loop through the corridors with at least two similarly positioned exits. If you can manage to link at least one of the exiting corridors to the same loop again, then your players are in for a treat.

This really is up to you and your creativity. You can do whatever you like with this.

Difficulty Increase


And last but not least, we have a 5 level maze, yet we've only discussed how to make the first one. So … how can we make things even harder? Well, here is a short list of some of the things you can do here:
  • For level 2 we should do something simple. Remaster the corridors and add more traps.
  • For level 3 we should add two more entry/teleport points. Remaster the corridors and add more traps.
  • For level 4 we should remaster the corridors and add a lot more traps. We should decrease the countdown time as well, however it shouldn't be drastic.
  • For level 5 we can try to only remaster the corridors and trap positions, yet decrease the countdown timer … a lot. This should be made really hard.
This is just an example. It's really up to your creative ideas at this point.

Interesting Points


This is a basic overview of what a maze crawler game should look like, at least in my opinion. There are a lot of things you can do here and many stuff you can blend in.

Be creative.

Conclusion


The Game Design of a Maze Crawler game is something that bends itself to simple rules and a lot of logistics.

Experimenting is key to a successful desgn.

Article Update Log


15 May 2013: Initial release

Untangling Licensing and Copyright in Game Art

$
0
0
First off, I am definitely not a lawyer.  So please do not take any of this information as legal advice.

However, I am a producer at Heavy Cat Studios, and I have a fair amount of experience in merchandising, licensing, intellectual property management and production.  Our studio has variously developed or co-developed graphics, writing, voices, sound and animation for 31 game projects under a variety of different licensing terms, and we've had the opportunity to evaluate those projects from concept to distribution.

If you do need legal advice, it really isn't as expensive to hire an intellectual property attorney as you might think.  An intellectual property attorney will be able to advise you on the specifics of copyright, trademark and patent law and how those different categories of intellectual property can affect your game project.  Even an hour-long consultation with a good IP attorney is worth the cost, even if you are only looking for general advice on the best way to manage development.  

Believe it or not, all three major categories of intellectual property can and do affect your game project, even if you haven't given them a great deal of consideration or filed any paperwork yet.  Despite the (often correct) protests of many programmers, software can be patented.  Software is copyrighted the moment it hits your computer's RAM or hard drive, and if you have a title for your game, it is a candidate for a trademark.  

It is also not just your intellectual property you have to be concerned about.  Your game project must be managed so it doesn't infringe on some other company's patent, or violate another company's trademark or copyright either.   Fortunately, the finer points of intellectual property law are unlikely to have any major effect on the average indie game project unless you appropriate someone else's source code or artwork without permission.  Even that is completely unnecessary in a world where there are six open source alternatives available for whatever you might need.

So let's talk some basics.  

Copyright


The last major overhaul of copyright law in the United States took place in 1976.  That legislation made a number of changes that affect every creative project.  It also made a lot of things much easier for authors, programmers and musicians, among others.

First, and most important, everything you create is copyrighted the moment it is "fixed in a tangible medium."  That means if you save a file to disk, write on a pad of paper, record a sound or perform a dance routine on video, that qualifies as a "work" which is now copyrighted.  You now have certain exclusive rights in that work, such as the right to make copies and the right to distribute those copies.

An exclusive right is one that only you can exercise.  If someone else wants to exercise those rights, you have to give them permission or they are "infringing" on your copyright.

Now most people believe that a copyright must be "registered" with the government in order to be effective.  That's partially true.  Copyright vests the moment any copyrightable work is fixed in a tangible medium (yes, that means that grocery list you wrote on the back of a Taco Shack coupon is copyrighted).  However, in order for you to file suit and recover damages, that copyright must be registered.  

Registering a copyright is an extraordinarily simple process.  For a small fee, you file a form with the Librarian of Congress along with two copies of your work.  The Library of Congress will then send you a certificate.  You now have a registered copyright.  If you so choose, you can now file suit and recover damages including statutory damages (essentially a 'fine') from anyone who infringes on your registered copyright.

But what if it's you and three of your best buddies working on a game together?  Who owns the copyrights?  Well, this is where the fun begins.

If you so choose, you can grant permission for another person or company to exercise your exclusive rights under copyright law.  This is called a "license."  In most cases when three people (Yes, girls and women make games too. Look up Roberta Williams if you don't believe me) are working on a game, they are tacitly granting permission for everyone else to make use of their work during development.  But once the game is done, the ownership issue can get very murky legally.

Technically if three people have contributed source code to a project, for example, there are three people with exclusive rights in portions of that work.  Any one of them could prohibit distribution of their work and bring the project to a halt.  They would be completely within their rights to do so.  The way to avoid problems like this is to make use of one of the provisions of copyright law to assign the copyright to a single entity.  Then it is that entity which owns the rights to the entire work.  This is known in the industry as "securing" rights.

Depending on how serious you are about your game, it might be worth your time to look into setting up a company to "own" the copyrights to your game.  That can bypass a lot of the difficulty and make provision for each of the people who work on the game to own a share of the company itself instead of one game.  The specifics of this are outside the scope of this article but it is something your IP attorney might be able to help you with.

Under the Copyright Act of 1976, there is a category of copyright assignment called a "Work Made for Hire."  This is a provision of copyright law where if an employer hires an employee or contractor to produce a copyrightable work, the employer gets the copyright once it is produced. Technically, the copyright vests in the employer instead of the employee the moment it is "fixed in a tangible medium".

Work for Hire only applies to certain kinds of works, so it is important that you do your homework ahead of time.  If a work doesn't qualify, calling it a Work for Hire may not secure any rights.  In such a case, the copyright may "revert" to the original author (employee or contractor) and give the employer no rights.

In cases where a Work for Hire isn't practical, an author can "assign" their copyright to another party.  This is essentially selling the right, or transferring title to the right.  Assignment of a copyright is subject to certain legal restrictions.  Generally it can only be done with a written contract.  

It is vitally important that a group of people working on a project make provision to assign the copyrights (through either process) to some entity, whether it is a company or the manager of the project.  This prevents all kinds of potential hang-ups and obstacles later, especially if that project starts earning any significant revenue.

Copyright and Game Art


The moment pencil touches paper (or stylus touches Wacom, or mouse clicks in Photoshop), the art is copyrighted.  That copyright vests with the artist and stays with the artist unless there is an agreement between the game developer and the artist for assignment or license of those rights.  

Artists who are knowledgeable about copyright law often grant licenses to developers to make use of their work.  This is something we offer at Heavy Cat Studios through our distribution company Palace in the Sky Productions.  The least expensive option is for a developer to commission art under a commercial license.  They can then make use of that art in their game project and even sell the game at retail.  However, our studio retains the copyright.

Some developers want full rights to their work.  For those clients, we offer to assign the copyright in the works we produce for an additional fee.  

If you are a game developer this is something you must be cognizant of before you start commissioning artwork from any third party, especially a studio.  You should prepare a written agreement (this is an excellent time to bring in an IP attorney) and make sure the artist or studio signs it before they begin work.

A verbal agreement isn't enough.  Your artist owns the copyright to the art they produce regardless of any agreements you made ahead of time unless those agreements are in writing and they are appropriate for the rights you want to exercise.  This is crucially important.  Failure to secure rights in the art for your game can sink your entire project.

Once you start the process of securing your rights, also be aware that copyright law can vary depending on the part of the world you are operating in.  By and large, you will need to obtain worldwide rights to any work you want to make available on the web, since national borders do not prevent a work from being transmitted from one place to the next.  Copyright licenses can be divided in any way a rights holder chooses.  This means they can say "you can copy my work, but not in Canada."  Make sure you have rights for every territory you plan to sell your work in.  

International copyright law is largely governed by a treaty called the "Berne Convention."  The specifics of this treaty are outside the scope of this article, but suffice to say that any country that is a signatory to this convention will have strong protection for copyright holders.  You will need to secure rights in all of these territories in order to avoid running into possible problems in other countries.  The easiest method, of course, is to obtain worldwide rights to any copyrighted work you need to include in your game.

In most cases, art for a game qualifies under the "Works made for Hire" rules as contributions to an "audiovisual work."  Again, consult with an IP attorney on the particulars.  If a work doesn't qualify, you can always have your artist assign their rights in the work.  

Trademark


A trademark is a word, icon or visual representation that uniquely identifies your company or product in the marketplace.  Game art can most definitely be trademarked.  The most obvious candidates for trademark protection are your game and company logos.

There are two kinds of trademarks.  One is often referred to as a "common law" trademark.  It is used to secure protection for a mark in commerce while registration is pending.  It is identified by the "TM" next to the mark.  This means the word, icon or visual representation is a trademark, and that trademark protects that mark, but that is has not yet been registered.

A registered trademark is one that has been filed with the United States government.  It is identified by the "circle R" ® symbol.  Only a registered trademark can use the registered trademark symbol.  

Filing a trademark registration is a project that absolutely requires the assistance of a qualified attorney.  Attempting to do this on your own without significant study and care can be both expensive and time-consuming and there is no guarantee of success.  The Patent and Trademark Office can and often will reject applications with even trivial errors or omissions.  Better to get help with this one.  

Trademark in Game Art


We know a logo is often the best candidate for a trademark.  However, in some cases, your character art can qualify as a trademark.  The most recognizable trademarked character is Mickey Mouse.  Disney Corporation is uniquely identified by the "mouse ears" motif and by the character itself, so that character can qualify for protection under both copyright and trademark law.

Trademark law is written to prevent the buying public from confusing one company with another.  It prevents one company from using the good will and reputation of some other company to sell its own products.  This is unfair competition because the first company may not have earned such a reputation with customers who trust the trademark.  Essentially using another company's trademark is tantamount to impersonating them in the marketplace.

Once you have trademarked your game logo, for example, if some other developer uses a logo that is too similar to yours, you have the right to stop them because that other developer could confuse your audience and customers into thinking they are somehow affiliated with you.  You might not want that, so trademark law gives you a way to stop them from inviting the public to draw the wrong conclusion.  

While you are securing rights, be sure to consider registering a trademark for your game's logo and for your iconic characters if you so choose.  It is a valuable way to protect the quality and reputation of your product in a competitive market.

Patent


You probably think I'm not going to come up with a way to apply patent law to games, but you might be surprised at how easy it is to stumble into patent problems without even thinking about it.  

For most projects, copyright is more than enough protection.  Preventing some third party from taking your game, slapping a new logo on it and selling it is the key protection in copyright law.  

But copyright only protects your specific expression.  Patent law protects the method or process embodied in that expression.  It is somewhat more abstract than copyright law.

Many programmers object on a number of bases to the idea of a software patent.  In some cases, there may be a consensus there is only one right way to do something in software, and if that is patented, that means any programmer who doesn't have the patent must violate someone else's rights in order to write their program, even if it is original work that doesn't infringe on the other programmer's copyright.  

Patent and Game Art


Leaving aside for the time being the controversy over whether software should be patented, just be aware that computer games and games in general are not immune from patent law.  The board game "Mouse Trap" for example, was a candidate for a patent, since the little plastic Rube-Goldberg machine that dropped the cage on the mouse was a working mechanism with a commercial application.  

Mouse Trap is a tremendous example of just how far intellectual property law can stretch when applied to a game project.  Theroetically, that colorful plastic trap mechanism qualifies under all three major categories of intellectual property:  The pieces themselves can be copyrighted as unique sculptures.  The entire trap mechanism can qualify as a separate unique sculpture distinct from its pieces.  The entire mechanism could qualify as a unique symbol of the company that markets the game, making it a candidate for trademark protection and, since it is a working mechanism with a commercial purpose, it could also qualify for a patent.

That's a lot of rights for one game, but that level of protection could be considered appropriate given the iconic nature of the game for the Ideal Toy Company.  It likely took a lot of work to get that game to work as well as it did, so it was also advisable the authors of the game do what is necessary to protect their invention.

Patents can be licensed or assigned just like any other intellectual property.  If you own a patent, you have a series of exclusive rights just like a copyright or trademark holder. However, a patent has a short term.  It also requires the assistance of a qualified attorney to file.  Patents are very technical and specific.  

For most game developers, patents are not going to be a major concern unless you find yourself up against a litigant who claims you violated their patent.  The overwhelming majority of game software is very similar from a technical standpoint, so the likelihood of a patent claim, while possible, is still fairly remote.

Free Software


Any 21st century discussion of intellectual property would not be complete without covering the world of free software and open source software.  

Be aware that free software and open source software are not "un-copyrighted" works.  Those works are still covered by and protected by copyright.  In fact, the copyrights in those works are what gives their authors the legal authority to enforce licenses like the GNU General Public License.

The only works that are not covered by copyright law are those that are placed in the public domain by their authors.  Public domain software is free for the taking.  You can do anything you want with public domain works.  

Publically licensed works, such as those under the GNU General Public License and its equivalents should be considered copyrighted software with a permanent license attached.  That license gives you stable, permanent permission to exercise certain rights of the copyright holder under certain conditions, but that permission is contigent on you fulfilling those conditions.  Remember that permission can be withdrawn as well as granted, and that if permission is withdrawn, your right to exercise the copyright holder's exclusive rights is also withdrawn.  The same is true of works you might find in the Creative Commons.  

Very often, with a little work, you can assemble a great majority of what a game project needs from publically licensed sources and supplement the rest with commercial works.  This can often reduce costs in areas where even with significant expenditures, you will not exceed the quality of what you can obtain for low cost or no cost anyway.  

Free Art


There are a number of stock art services available.  For most game purposes, these sources can be hit or miss with regard to quality or technical limitations.  Art is subjective.  It is evaluated on style as much as utility, and graphics that are cobbled together from numerous sources often look like they were cobbled together from numerous sources.

Some kinds of art, however, can look presentable, even attractive if they are assembled from multiple sources.  Many of the projects we do at Heavy Cat Studios make use of pixel art, and our Indie Game Art Store features pixel art for RPG and sidescroller-style games.  Because of its style, pixel art is a bit more forgiving when it comes to looking like it all fits together.  Two different styles of illustrated art, on the other hand, might not look quite as attractive.

Conclusion


The key to the intellectual property side of indie game development is to be aware of the details and to make sure you have your bases covered.  The best example of the hazards you face if you don't do your due diligence is the Spider-Man property.

For decades, the Spider-Man movie rights languished at Marvel because there were up to ten different companies with various rights to make a film.  Since these licensees could not agree on how to make a movie, it just didn't happen.

The reason is if one of them went off and started production, any of the others could have used their license to say "this producer is exercising the legal exclusive rights I obtained from Marvel to make this film" and thereby stop production.  They were all within their rights to say no.  Trust me when I tell you getting ten people to agree in Hollywood is like trying to get a unanimous vote in Congress.  It ain't happening, no matter how much money you have.  Ronald O. Perelman was a multi-billionaire when he owned Marvel Entertainment.  He didn't make much progress on Spider-Man movies either.

It took nearly 40 years for Spider-Man to escape from the rights mess.

Marvel filed for bankruptcy in the late 1990s.  During that case, the company managed to unravel all the licenses.  That's why we got to see a Spider-Man film series starting in the early 2000s.  All the copyrights and licenses reverted to Marvel after the company emerged from bankruptcy.  Because they now had their exclusive rights back, they could then proceed to make their film.  They exercised their right to make a "derivative work" under copyright law.

If you are an indie game developer, my advice to you is very simple.  Unless you want your game to be tied up in a copyright dispute for 40 years, protect and manage your rights.  It will make your project that much more valuable and have a much better chance of success.

Copyright © 2013 Palace in the Sky Productions LLC


Article Update Log


16 May 2013: Initial release

Case Study: Bomberman Mechanics in an Entity-Component-System

$
0
0
The Bomberman series of games are simple games with an interesting set of mechanics. Having used an ECS framework in a few projects, I thought it would be useful to see how we can implement these mechanics using this pattern.

I won't go into a detailed introduction of ECS here. For a great primer on the topic, have a look at Understanding Component-Entity-Systems.

I also provide a working game that contains the bulk of the PvP core mechanics, and look at what value ECS provided us (and where there is room for improvement). The game leverages ECS in lots of other ways, but for the purpose of this article I will only discuss the core game mechanics.

For the purposes of clarity and language-independence, code samples in the article will be a sort of pseudo-code. For the full C# implementation, see the sample itself.

Also, I use bold capitalized names to refer to components. So a Bomb refers to the official component, while if I mention a bomb I'm just talking about the concept or the entity that represents the concept.

Let's get to work


Before designing any system, it's necessary to understand the scope of the problem you're trying to solve. This means listing out all the interactions between various game objects. From there, we can figure out the right abstractions to use. Of course, knowing all the interactions is impossible if your game is under development - or even if you're trying to make a clone - because there will be things you missed at first. One of the advantages of ECS is that it lends itself to making changes as needed while affecting a minimum of other code.

A rough summary of the PvP Bomberman gameplay is as follows. Players plant bombs that destroy other players and disintegrate blocks. Disintegrated blocks leave behind various powerups that augment the destructive power of your bombs, or affect player speed. Players complete to see who is the last to survive as a clock counts down to total destruction.

Without further ado, let's look into the basic bomb mechanics Bomberman and come up with a design we can implement using the ECS pattern.

Explosions


Attached Image: Impacts123.jpg
Explosion showing behavior with (1) hard blocks, (2) soft blocks, and (3) empty space


When a bomb explodes, the explosion shoots out in various directions. The following things can happen:
  • "Hard blocks" block the path of the explosion
  • "Soft blocks" block the path of the explosion (usually), and are destroyed; they randomly reveal a powerup
  • Un-triggered bombs will detonate
  • Any players hit by the explosion will die


Attached Image: ChainReaction.jpg
One bomb's explosion can trigger another bomb


It seems there are two concepts here: how a particular object reacts to the explosion (dies, triggers, disintegrates), and how a particular object affects the path of the explosion (blocks it, or doesn't).

We can create an ExplosionImpact component to describe this. There are only a few ways an object can affect the path of the explosion, but many ways it can then react. It's doesn't make sense to describe the myriad ways an object can react to an explosion in a component, so we'll leave that up to a custom message handler on each object. So ExplosionImpact might look like this:

enum ExplosionBarrier
{
    None = 0,
    Soft = 1,
    Hard = 2,
}
class ExplosionImpact : Component
{
    ExplosionBarrier Barrier;
}

That's pretty simple. Next, let's look at the innate properties of an explosion. This basically depends on the type of the bomb. But it's useful to distinguish bombs vs explosions, since bombs have additional properties like a countdown timer and an owner.

Explosions can:
  • propagate any or all of 8 directions
  • sometimes propagate through soft blocks (pass-through bombs, which have blue explosions)
  • different propagation ranges (or an infinite range)
  • sometimes propagate through hard blocks!


Attached Image: InfiniteRange.jpg
Power Bomb or Full Fire gives bombs infinite range


There are two obvious ways to model an explosion. You could have a single entity for an explosion, or an entity for each piece of the explosion as it propagates out (Bomberman is grid-based, so the latter is feasible). Given that an explosion can propagate unevenly depending on what it hits (as previously discussed), it would be somewhat tricky to represent with a single entity. It seems then, that one entity per explosion square would be reasonable. Note: this may make it seem tricky to render a cohesive image of an explosion to the screen, but you'd actually have a similar problem if your explosion was a single entity. A single entity would still need a complicated way to describe the shape of the overall explosion.


Attached Image: SquareBomb.jpg
Dangerous Bombs explode in a square instead of a line


So let's take a stab at an Explosion component:

class Explosion : Component
{
    bool IsPassThrough;         // Does it pass through soft blocks?
    bool IsHardPassThrough;     // Does it pass through hard blocks?
    int Range;                  // How much further will it propagate?
    PropagationDirection PropagationDirection;
    float Countdown;            // How long does it last?
    float PropagationCountdown; // How long does it take to propagate to the next square?
}

enum PropagationDirection
{
    None        = 0x00000000,
    Left        = 0x00000001,
    UpperLeft   = 0x00000002,
    Up          = 0x00000004,
    UpperRight  = 0x00000008,
    Right       = 0x00000010,
    BottomRight = 0x00000020,
    Bottom      = 0x00000040,
    BottomLeft  = 0x00000080,
    NESW        = Left | Up | Right | Bottom,
    All         = 0x000000ff,
}

Of course, since we're using ECS, things like position and the explosion image are handled by other components.

I've added two more fields to the Explosion component that bear some mentioning: Countdown represents how long an explosion lasts. It's not an instant in time - it lasts a short duration, during which a player can die if they walk into it. I also added a PropagationCountdown. In Bomberman, from what I can tell, explosions propagate instantaneously. For no particular reason, I've decided differently.

So how does this all tie together? In an ECS, systems provide the logic to manipulate the components. So we'll have an ExplosionSystem that operates over the Explosion components. You can look at the sample project for the entire code, but let's briefly outline some of the logic it contains. First of all, it's responsible for propagating explosions. So for each Explosion component:
  • Update Countdown and PropagationCountdown
  • If Countdown reaches zero, delete the entity
  • Get any entities underneath the explosion, and send them a message telling them they are in an explosion
  • If PropagationCountdown reaches zero, create new child explosion entities in the desired directions (see below)
ExplosionSystem also contains the propagation logic. It needs to look for any entities underneath it with an ExplosionImpact component. Then it compares the ExplosionImpact's ExplosionBarrier with properties of the current Explosion (IsHardPassThrough, etc...) and decides if it can propagate and in what directions. Any new Explosions have one less Range, of course.

Powerups


Next, we'll trace the path from collecting powerups to the player dropping bombs. I've used a subset of 12 of the typical Bomberman powerups (I've left out the ones that let you kick, punch and pick up bombs - I didn't have time to implement them for this article, but it could be a good follow-up). As before, let's look at our scenarios - what the powerups can do - and come up with a design.
  • Bomb-Up: Increase by one the number of simultaneous bombs the player can place
  • Fire-Up: Increase the blast radius (propagation range) of the bombs' explosions
  • Speed-Up: Increase player speed
  • (the above three also have "Down" versions)
  • Full-Fire: Bombs have infinite range (except when combined with Dangerous-Bomb)
  • Dangerous Bomb: Blast expands in a square, and goes through hard blocks
  • Pass-Through Bomb: Blast propagates through soft blocks
  • Remote Bomb: Bombs only detonate when you trigger them
  • Land Mine Bomb: Your first bomb only detonates when someone walks over it
  • Power Bomb: Your first bomb has infinite range (like Full-Fire but only for the first bomb)


Attached Image: PowerUps.jpg
Various powerups that have been revealed under disintegrated soft blocks


You'll see that while most powerups affect the kinds of bombs you place, they can also affect other things like player speed. So powerups are different concepts than bombs. Furthermore, powerups are not exclusive, they combine. So if you have a couple of Fire-Ups with a Dangerous Bomb, you get a bomb that explodes in a bigger square.


Attached Image: PassThrough.jpg
Pass-Through bombs propagate through soft blocks.


So essentially the player has a set of attributes that indicate what kinds of bombs they can place. The powerups modify those attributes. Let's take a stab at what a PlayerInfo component would look like. Keep in mind, this won't contain information like position, current speed or texture. That information exists in other components attached to the player entity. The PlayerInfo component, on the other hand, contains information that is specific to the player entities in the game.

class PlayerInfo : Component
{
    int PlayerNumber;	// Some way to identify the player - this could also be a player name string
    float MaxSpeed;
    int PermittedSimultaneousBombs;
    bool FirstBombInfinite;
    bool FirstBombLandMine;
    bool CanRemoteTrigger;
    bool AreBombsPassThrough;
    bool AreBombsHardPassThrough;
    int BombRange;
    PropagationDirection BombPropagationDirection;
}

When a player drops a bomb, we look at its PlayerInfo component to see what kind of bomb we should drop. The logic to do so is a bit complicated. There are lots of conditionals: for instance, Land Mine bombs look different than Dangerous Bombs that explode in all directions. So when you have a Land Mine that's also a Dangerous Bomb, what texture is used? Also, Power Bombs powerups give us infinite BombRange, but we don't want an infinite range when the bomb propagates in all directions (or else everything on the board will be destroyed).

So there can be some fairly complex logic here. The complexity arises from the nature of the Bomberman rules though, and not from any problem with code. It exists as one isolated piece of code. You can make changes to the logic without breaking other code.

We also need to consider how many bombs the player currently has active (undetonated): we need to cap how many they place, and also apply some unique attributes to the first bomb they place. Instead of storing a player's current undetonated bomb count, we can just calculate how many there are by enumerating through all Bomb components in the world. This avoids needing to cache an UndetonatedBombs value in the PlayerInfo component. This can reduce the risk of bugs caused by this getting out of sync, and avoids cluttering the PlayerInfo component with information that happens to be needed by our bomb-dropping logic.

With that in mind, let's take a look at the final piece of our puzzle: the bombs.

class Bomb : Component
{
    float FuseCountdown;  // Set to float.Max if the player can remotely trigger bombs.
    int OwnerId;		  // Identifies the player entity that owns the bomb. Lets us count
    					  // how many undetonated bombs a player has on-screen
    int Range;
    bool IsPassThrough;
    bool IsHardPassThrough;
    PropagationDirection PropagationDirection;
}

Then we'll have a BombSystem that is responsible for updating the FuseCountdown for all Bombs. When a Bomb's countdown reaches zero, it deletes the owning entity and creates an new explosion entity.

In my ECS implementation, systems can also handle messages. The BombSystem handles two messages: one sent by the ExplosionSystem to entities underneath an explosion (which will trigger the bomb so we can have chain reactions), and one sent by the player's input handler which is used for remotely triggering bombs (for remote control bombs).

One thing you'll notice is that the Explosion, Bomb and Player components share a lot in common: range, propagation direction, IsPassThrough, IsHardPassThrough. Does this suggest that they should actually all be the same component? Not at all. The logic that operates over those three types of components is very different, so it makes sense to separate them. We could create a BombState component that contains the similar data. So an explosion entity would contain both an Explosion component and a BombState component. However, this just adds extra infrastructure for no reason - there is no system that would operate only over BombState components.

The solution I've chosen is just to have a BombState struct (not a full on Component), and Explosion, Bomb and PlayerInfo have this inside them. For instance, Bomb looks like:

struct BombState
{
    bool IsPassThrough;
    bool IsHardPassThrough;
    int Range;
    PropagationDirection PropagationDirection;
}

class Bomb : Component
{
    float FuseCountdown;  // Set to float.Max if the player can remotely trigger bombs.
    int OwnerId;          // Identifies the player entity that owns the bomb. Lets us count
                          // how many undetonated bombs a player has on-screen
    BombState State;
}

One more note on players and bombs. When a bomb is created, it inherits the abilities of its player at the time it is placed (Range, etc...) instead of referencing the player abilities. I believe the actual Bomberman logic might be different: if you acquire a Fire-Up powerup, it affects already-placed bombs. At any rate, it was an explicit decision I made that I was felt was important to note.  


Attached Image: Killed.jpg
A soft block is no protection against a Pass-Through bomb (spiked)


Let's finally talk about the powerups themselves. What do they look like? I have a very simple PowerUp component:

class PowerUp : Component
{
    PowerUpType Type;
    int SoundId;          // The sound to play when this is picked up
}

PowerUpType is just an enum of the different kinds of powerups. PowerUpSystem, which operates over PowerUp components and controls picking them up, just has a large switch statement that manipulates the PlayerInfo component of the entity that picked it up. Oh the horror!

I did consider having different message handlers attached to each powerup prefab which contained the custom logic for that particular powerup. That is the most extensible and flexible system. We wouldn't even need a PowerUp component or PowerUpSystem. We'd simply define a "a player is colliding with me" message which would be fired and picked up by the custom powerup-specific message handler. This really seemed like over-architecting to me though, so I went with a simpler quicker-to-implement choice.

Here's a little snippet of the switch statement where we assign the player capabilities based on the powerup:

    case PowerUpType.BombDown:
		player.PermittedSimultaneousBombs = Math.Max(1, player.PermittedSimultaneousBombs - 1);
    	break;
    
    case PowerUpType.DangerousBomb:
    	player.BombState.PropagationDirection = PropagationDirection.All;
    	player.BombState.IsHardPassThrough = true;
    	break;

Prefabs


My ECS allows you to construct entity templates, or prefabs. These assign a name to a template (e.g. "BombUpPowerUp"), and associate with it a bunch of Components and their values. We can tell our EntityManager to instantiate a "BombUpPowerUp", and it will create an Entity with all the right Components.


Attached Image: Prefabs.jpg
Visual representation of various prefabs


I think it would be useful to list some of the prefabs I use for the Bomberman clone. I won't go into details on the values used in each; I'll simply list which Components each type of entity uses, with some comments where useful. You can look at the source code for more details. These are just examples of prefabs - e.g. in the actual game there are multiple types of Brick (SoftBrick, HardBrick) with different values in their components.

"Player"
    Placement
    Aspect
    Physics
    InputMap           // controls what inputs control the player (Spacebar, game pad button, etc...)
    InputHandlers      // and how the player reacts to those inputs (DropBomb, MoveUp)
    ExplosionImpact
    MessageHandler
    PlayerInfo

"Brick"
    Placement
    Aspect
    Physics
    ExplosionImpact
    MessageHandler     // to which we attach behavior to spawn powerups when a brick is destroyed

"Bomb"
    Placement
    Aspect
    Physics
    ExplosionImpact
    MessageHandler
    ScriptContainer    // we attach a script that makes the bomb "wobble" 
    Bomb

"Explosion"
    Placement
    Aspect
    Explosion
    FrameAnimation     // this one lets us animation the explosion image

"PowerUp"
    Placement
    Aspect
    ExplosionImpact
    ScriptContainer
    PowerUp

Interesting Points


An ECS also gives you great flexibility at creating new types of entities. It makes it easy to say "hey, what if I combine this with that?". This can be good for brainstorming new kinds of mechanics. What if you could take control of a bomb? (Add InputMap to a bomb entity). What if explosions could cause other players to slow down? (Add PowerUp to an explosion entity). What if explosions were solid? (Add Physics to an explosion entity). What if a player could defect an explosion back towards someone? (A little bit of logic to add, but still pretty trivial).

You'll find that it is very easy to experiment and add new code without breaking other things. The dependencies between components are (hopefully) clear and minimal. Each pieces of code operates on the absolute minimum it needs to know.

Of course, I also faced some problems in this little project.

I decided to use the Farseer Physics library to handle collision detection between the player and other objects. The game is grid-based, but the player can move on a much more granular level. So that was an easy way to get that behavior without having to do much work. However, a lot of the gameplay is grid-based (bombs can only be dropped at integer locations, for instance). So I also have my own very simple grid collision detection (which lets you query: "what entities are in this grid square?"). Sometimes these two methods came into conflict. This problem isn't anything specific to ECS though. In fact, ECS ecnourages my usage of Farseer Physics to be entirely limited to my CollisionSystem (which operates over Physics components). So it would be very easy to swap out the physics library with another and not have it affect any other code. The Physics component itself has no dependency on Farseer.

Another problem I faced is that there is a tendency to make certain problems fit into the ECS way of thinking. One example is the state needed for the overall game: the time remaining, the size of the board, and other global state. I ended up creating a GameState component and an accompanying GameStateSystem. GameStateSystem is responsible for displaying the time remaining, and determining who won the game. It seems a bit awkward to cram it into the ECS framework - it only ever makes sense for there to be one GameState object. It does have some benefits though, as it makes it easier to implement a save game mechanic. My Components are required to support serialization. So I can serialize all entities to a stream, and then deserialize them and end up exactly back where I was.

One decision that I often faced was: "Do I make a new Component type for this, or just attach a script for custom behavior?" Sometimes it is a fairly arbitrary decision as to whether a piece of logic merits its own Component and System or not. A Component and System can feel a bit heavyweight, so it is definitely essential to have the ability to attach custom behavior to entities. This can make it harder to grok the whole system though.

I currently have 3 ways of attaching custom behavior to an entity: input handlers, message handlers and scripts. Scripts are executed every update cycle. Input and message handlers are invoked in response to input actions or sending messages. I was trying out a new input handler methodology for this project. It worked well (but it might make sense to combine it with message handling). I was using the keyboard to control the player. When it came time to implement gamepad support, it took all of five minutes. I was inspired by this article.


Attached Image: Diagram.jpg
A powerup entity (generic container) is defined by its components: Placement, Aspect, ExplosionImpact, ScriptContainer and PowerUp. ScriptContainer allows attaching scripts for custom behavior. In this case, a wiggle script is responsible for wiggling the powerup around.


Scripts often need to store state. For instance, a script that makes a powerup wiggle, or a bomb entity wobble (by changing the Size property in its Aspect component) needs to know the minimum and maximum sizes, and what point we are in the wobble progression. I could make scripts full-fledged classes with state, and instantiate a new one each each entity that needs it. However, this causes problems with serialization (each script would need to know how to serialize itself). So in my current implementation, scripts are simply callback functions. The state they need is stored in a generic property bag in the Scripts component (the Scripts component simply stores a list of ids that are mapped to a specific callback function). This makes the C# script code a little cumbersome, as each get and set of a variable is a method call on the property bag. At some point, I plan to support a very simple custom scripting language with syntactic sugar to hide the ugliness. But I haven't done that yet.

Conclusion


Theory is nice, but I hope this article helped with showing a practical implementation of some mechanics with ECS.

The sample project attached is implemented in XNA 4.0. In addition to the mechanics described in this article, it shows some other things which might be interesting:
  • How I handle animating the components like explosions
  • The input mapping system I briefly described above
  • How I handle querying objects at a particular grid location
  • How little things like the bomb wobble or land mine rise/fall is done
I didn't have time to implement AI players in the sample, but there are 3 human-controllable characters. Two of them use the keyboard: (arrow keys, space bar and enter) and (WASD, Q and E). The third uses the gamepad, if you have that. It should be possible to implement a mouse-controlled player without too much work.


Attached Image: DeathBlocks.jpg
When time runs out, death blocks appear...


The sample features 12 full-functioning powerups (some of the more powerful ones appear too frequently though), random soft blocks, and the "death blocks" that start appearing when time is running out. Of course, a lot of polish is missing: the graphics are ugly, there is no death animation or player walking animation. But the main focus is on the gameplay mechanics.

Article Update Log


24 May 2013: Initial draft

From Python to Android

$
0
0
I have published this article to my blog before, but because it is not so frequently visited and I did not find much advice for this subject I am writing the same article down here to share with everyone.

This article is about porting a game written in python with pygame to Android. To do so we will use the pygame subset for Android, which can be obtained here. The pygame subset for android has ported a subset of the pygame architecture to the Android architecture. Hence it allows us to easily program games in python and port them to an Android application. This article will explain how to do so by using the breakout game, programmed by myself and obtainable here: Attached File  break0ut.zip   39.08K   11 downloads

In the end we will have a breakout game on our Android device which can be controlled by swipe gestures or by tilting the android device itself.

If you want to rebuild what we will build during this article you will need the following programs:
  • A Java Development Kit e.g. via Oracle or OpenJDK
  • Python 2.7 and pygame obtainable here and here
  • Device Drivers for your Android device, if you are using Windows and a little help for Linux here
  • pygame subset for Android (PGS4A), obtainable here
These programs are more or less needed if you want to run the breakout game itself and then later port it to your Android device. If you plan to skip this part and simply run the game on your local PC, the pygame library is not needed. The whole porting and programming is just one more click apart.

Setting everything up


The first three parts just need to be installed, either via a package management system if you are using Linux or by downloading and installing them if you are using Windows. PGS4A just needs to be extracted in a folder of your choice. As far as my project setup is concerned this looks like the following and can be viewed on github:

./pgs4a/ directly containg all PGS4A stuff
./pgs4a/breakout/ containing all the python source code and our main.py
./pgs4a/breakout/data/ containing all images and so on for our game

This structure needs to be like this because PGS4A will only work this way. Now mostly everything is set up, except PGS4A - we will start with this. First you should test if everything is up and running for PGS4A by running:

cd pgs4a
./android.py test


This should return green text stating All systems go! This basically means that we met all prerequesits. After this we need to install the corresponding Android SDK which can be done by executing

./android.py installsdk

This should start the installation of the needed Android SDK. During this installation you are asked to accept the TOS of the Android SDK and if you would like to create an application signing key, which is needed if you want to publish your application on the Play store. You should answer both questions with yes. The key is needed later on for some signing purposes and the installation process. But be warned if you want to sell the application in the Play store you will need to recreate a key, because the key created during this process uses no password. If you have finished successfully you will be rewarded with It looks like you're ready to start packaging games.

Important: At this point you must make sure that you actually installed an SDK! You may get an error or a warning that the filter android-8 is not accepted. If you received such an error you need to manually install the Android 8 sdk. This can be done by running

./android-sdk/tools/android


    Attached Image: androidSDKManager.png


Now the Android SDK manager should come up. You may need to update Tools before you actually see the same content as in the window above from there you can now install the Android API 8, which is needed to port pygame to Android. This will install the required API manually, which is needed because PGS4A has long not been updated. After this we are nearly ready to start porting our breakout pygame to Android.

Adding Android to breakout


In this part we are going to actually add the android device stuff to our game. For this purpose I would recommend you read through and download the source code. Now you should be capable of running the code within your python environment and be able to play the breakout game. If not make sure you have done everything right regarding the setup of your python and pygame.

All modifications, and we do not have much modifications, are performed in the main.py, which includes the main function of our game. The modification includes importing the Android stack of PGS4A, initializing the Android stack, map Android-specific keys and adding some Android-specific stuff. Afterwards we should be capable of playing without further modifications to our game.

Importing the Android package should be done below our standard imports in the main file. Hence we need to change the header with the imports to something which looks like this:

import pygame, sys, os, random
from pygame.locals import * 
from breakout.data.Ball import Ball
from breakout.data.Bar import Bar
from breakout.data.Block import Block

# Import the android module. If we can't import it, set it to None - this
# lets us test it, and check to see if we want android-specific behavior.
try:
    import android
except ImportError:
    android = None

Now we have imported the Android-specific commands and are able to ask if we can access them or not via the android variable. The next step would be to initialize the Android environment and map some keys, we do this after we initialized pygame and set some parameters:

def main():
        """this function is called when the program starts.
				it initializes everything it needs, then runs in
				a loop until the function returns."""
# Initialize Everything
        width = 800
        height = 600
        pygame.init()
        screen = pygame.display.set_mode((width, height))
        pygame.display.set_caption('break0ut')
        pygame.mouse.set_visible(0)

        background = pygame.Surface(screen.get_size())
        background = background.convert()
        background.fill((0, 0, 0))

        # Map the back button to the escape key.
        if android:
                android.init()
                android.map_key(android.KEYCODE_BACK, pygame.K_ESCAPE)

At the bottom of the above code we checked if the Android package was loaded, if this is the case we initialize the android subsystem and map the back key of our Android device to the Escape key. So if we wanted to add a menu to our application which is normally called with the Escape key this would open the menu. In this particular example of breakout the Escape key will exit the game.

Next we have to react to some Android-specific stuff, which is needed in each game. The game may be put into a pause mode, e.g. when the application is switched or the user tries to go back to the home screen. To react to this kind of behavior we have to add the specific code to our game loop:

# main game loop
        while 1:
                clock.tick(60)

                # Android-specific:
                if android:
                        if android.check_pause():
                                android.wait_for_resume()

This would wait for a resume of our application if our game application was set in the pause mode. Due to the checks for the android variable we are capable of playing the same game on the PC as well as on our Android device. If you want to start the PC version simply run the main.py and you are ready to go. With these last additions to our main source code, we are now capable of porting our breakout game to an Android Application and develop on the PC using our standard setup.

The porting process


Now we have reached the point were we want to put everything we have created so far to our Android device. To do so we need to configure our setup, which is easily done running the following command:

./android.py configure breakout

Make sure that the breakout folder exists before you execute the command otherwise you will get some errors. After you have executed this command you will be asked several questions including the name of the application and the package. As far as the package is concerned make sure not to use any special characters including -, _ and so on, otherwise you will get errors later in the process. As far as the rest of the questions are concerned I have stuck to the default answers. After you have finished you should be able to see a file called .android.json in the breakout folder, which should look like this:

{"layout": "internal", "orientation": "landscape", "package": "net.sc.breakout", "include_pil": false, "name": "breakout", "icon_name": "breakout", "version": "0.1", "permissions": ["INTERNET", "VIBRATE"], "include_sqlite": false, "numeric_version": "1"}

The next and last step before we can play our game on our Android device is the compilation and the installation of the apk on our phone. Both is handled by the following command line:

./android.py build breakout release install

Before you execute the command make sure you have created an assets folder. If you have not the execution will fail and you are not capable of compiling the application. I guess the creator of the PGS4A forgot or did not implement stuff to create folders. Also as I mentioned before PGS4A is an old application and therefore may not work very well.

If you have done everything correctly you should be able to play the game on your android device or the emulator you have connected or started. It should look very similar to the picture below. You should now be capable of porting any game created with pygame to android.


    Attached Image: breakoutOnAndroid.png


Simple but Effective Collisions Part 1: Radial Collision Handling

$
0
0
The illusion of smooth collision detection is paramount to a realistic gaming experience. Imagine if you were playing a horror game and you suddenly slipped through the dungeon walls, or you were driving a vehicle through a forest, only to crash into a tree with no effect or feedback. The facade of realism would instantly be broken. The horror game's environment would no longer be immersive, and driving your vehicle would simply feel like moving a camera through a world you cannot touch or feel.

Of course, you probably already knew that. Anyhow, the purpose of this article is to present the first of two methods for modelling collisions in your own games. I'm hoping to release another article detailing the second method in the near future. The method described in this article, which I call 'radial' collision handling, can be used to model objects which can be enclosed by bounding cylinders. It is ideal for objects such as trees and poles, and can even be used to simulate collisions with small rectangular objects.

I call the second method 'nodal' collision handling, and it can be used to provide bounding regions for a series of connected walls in any arrangement. It could be used to model the interior of a house or hut, or the walls of a maze. It will hopefully be discussed in a future article.

I created these methods (or rather implemented them, as it's likely they've been used before) with two aims. First off, each method should allow me to detect collisions, which is an obvious requirement of collision detection! Second, each method should handle collisions in such a way as to 'slide' the player/object around the obstacle rather than bringing them to an awkward halt as soon as they touch it.

Radial collision handling


The Concept


As mentioned, this system allows you to handle collisions with objects which can be enclosed by bounding cylinders. These cylinders can be defined by two numbers, or rather, a vector and a float - one containing a location, and the other containing a radius. Let's imagine we have a simple scenario with a triangle of trees placed on a simple flat plane:


Attached Image: articleImage2.png


The player can move the camera around in a first person view, and is able to walk among the trees. We will use the 'radial' collision detection method to prevent the camera from passing through the trees. When the player attempts to walk through a tree, the algorithm will slide them smoothly around it, as seen in pretty much all current first person games. This process involves two steps, which are repeated every frame:

  1. If the camera has entered a tree's bounding cylinder, register a collision.
  2. Calculate a new location for the camera which puts it back outside the bounding cylinder.

So, how do we do this in practice?

The Implementation


We'll start out by defining the location of each tree using an array of 2D vectors. We only need 2D vectors because the trees are not going to affect our motion in the up-down direction. If you wanted to use this algorithm for objects on 3D terrain rather than a 2D plane, it should work just as well with the same vector format because it's not possible for a walking person to collide with a tree from above or below, only from the side. Because of this, we only need to worry about the positions of the trees in the x-z plane, whether we have a flat terrain or not. As mentioned, we will use DirectX syntax and functions from here on in:

//The array contains 3 vectors - one for each tree:
D3DXVECTOR2 v_treePositions[3] = {D3DXVECTOR2(0, 1), D3DXVECTOR2(1, 0), D3DXVECTOR2(-1, 0)};

We will also define a variable to describe the radius of each tree trunk. We will assume they're all the same radius, but if you wanted to personalise each one, you could define an array of numbers, or add a third component to the vectors describing tree locations.

//Each tree is 1m in radius:
float f_treeRadius = 1.0f;

...and while we're at it, we will define a vector to hold the location of our first-person camera as it changes from frame to frame:

//This is a global vector holding the camera's location. It starts at the centre of the world (0, 0, 0):
D3DXVECTOR3 v_camPos(0, 0, 0);

OK, now each tree has an entry in our program, and we know where our player's camera is from frame to frame. All that remains is to put this information to use! We will define a function which will be called every frame. This function will loop through the tree locations, comparing each one to the location of the camera for that frame. If it registers a collision (i.e. if the camera's location is closer to one of the trees than is permitted by the bounding radius), then we will push the camera back outside the bounding radius. The effect is cumulative, meaning that each tree makes its own contribution to the overall position change. This way, the algorithm also works for closely bound groups of trees where the camera could be in contact with more than one at once.

Let's go through the function line by line:

D3DXVECTOR2 handle_Collisions_Radial()
{
	D3DXVECTOR2 v_deltaPos = D3DXVECTOR2(0, 0);

	for (int i = 0; i < 3, i++)
	{	
		D3DXVECTOR2 v_vectorToCentre(v_camPos.x - v_treePositions[i].x, v_camPos.z - v_treePositions[i].z);

		if (D3DXVec2Length(&v_vectorToCentre) < f_treeRadius)
		{	
			v_deltaPos += ((f_treeRadius / D3DXVec2Length(&v_vectorToCentre)) - 1) * v_vectorToCentre;
		}
	}

return v_deltaPos;
}

First, we notice that the function returns a D3DXVECTOR2. This corresponds to the amount by which the camera needs to move to put it outside of the bounding cylinders of all the trees. It returns a D3DXVECTOR2 because the trees only affect the location of the camera in the x-z plane.

Second, we create an inline vector called v_deltaPos which will be filled with the overall change in position required to put the camera outside the bounding radii of all the trees. This is the vector which the function will eventually return.

Next, we enter a loop which will iterate through all the trees. Since we have three trees, we will have three iterations.

Third, we create a temporary vector called v_vectorToCentre. This contains a directional vector between the location of the camera and the location of tree [i] in the x-z plane.

Fourth, we compare the length of this vector to the bounding radius. Note that the +y direction is up.

Fifth and finally, if the camera is indeed within the bounding radius of the current tree, we will add on just enough of v_vectorToCentre to put it back outside the tree trunk.

Once the loop is complete, we return the resulting position change.

The process is fairly intuitive until the final step. This diagram explains the maths behind it a little clearer:


Attached Image: articleImage1.png


As you can see, the location of the camera has moved within the bounding radius of tree [i]. In order to put the camera back outside of the bounding radius while simultaneously making it slide smoothly around the edge, we need to add a certain amount of the vector v_vectorToCentre to the camera's position until it is once again outside the bounding radius, such that:

Attached Image: CodeCogsEqn1.gif

In this equation, |v_vectorToCentre| denotes the length of the vector between the camera position and the tree's centre. It is calculated using the D3DXVec2Length() function. We are looking for the value of k - that is, the linear multiple of v_vectorToCentre which we should add to our camera position in order to put it back outside the bounding radius. In order to find the value of k, we can first divide through by |v_vectorToCentre|. This gives us:

Attached Image: CodeCogsEqn2.gif

This can easily be rearranged to get:

Attached Image: CodeCogsEqn3.gif

We have now calculated our value of k. All that remains is to add this linear multiple of v_vectorToCentre to our overall change in location (v_deltaPos). If you review the fifth step in the function, you can see that this is exactly what is happening. If called every frame, this function will calculate a collision contribution for each tree in the loop. Once this contribution is acquired, it should be added to the camera position vector as follows:

//Call the function to assess collisions:
D3DXVECTOR2 v_camPosCollisionDelta = handle_Collisions_Radial();

//Since this function returns a D3DXVECTOR2 and our camera position is a D3DXVECTOR3, we
//will need to create a dummy D3DXVECTOR3 with no y-component to add to v_camPos:
D3DXVECTOR3 v_camPosCollisionDelta3D(v_camPosCollisionDelta.x, 0, v_camPosCollisionDelta.y);

//Finally, we will move the camera according to our collison delta vector:
v_camPos += v_camPosCollisionDelta3D;

//Now that we have our new camera position, we can continue to render the frame as normal...

Conclusion


That's it! You may be surprised at how well this simple method works. The effect is quite satisfying, and it certainly added an extra professional depth to my exploits in the first-person camera world. Of course, this method could be used to handle collisions involving objects other than a first-person camera, and subjects other than trees. This is also a bare-bones version of the algorithm, and it could easily be adapted to handle collisions in 2D games as well as collisions between circles and spheres and their environment (throughout, we assumed that the first person camera was a simple point rather than an object with dimensions).

I intend to write another article describing another collision method which can be used to simulate walls and interiors/exteriors of buildings and things like hedges and maze walls. Until then, thanks for reading!

Article Update Log


19 May 2013: Initial release

Conjuring a Compelling World

$
0
0
Many types of games rely heavily on a well-crafted world, be it imaginary or partially based on reality. Some obviously will need richer environments than others; classic role-playing games are much more narrative-driven than, say, sports or shooter titles.

In any case, designing your game's world can be a critical part of crafting a valuable and entertaining experience for your players. There are a number of things to keep in mind when setting out on this journey. If you keep the following tricks in mind during the process, the results should speak for themselves.

Take More Than A Day


As the old saying goes, Rome was not sketched on a napkin in a bar. Or something like that. Anyways, the point here is that good design takes a lot of time, effort, and refinement. The first step to creating a great experience is to be prepared to invest a good deal of work.

The all-important corollary to this is that your first version is probably not worth keeping completely as-is. Get feedback, sleep on it, and iterate. Many of the best stories took endless tweaking and even complete rewriting before they became the classics we think of now.

Originality is Dead


There's a dirty secret to the creative process: very few ideas are truly new. Virtually everything is derivative in some way or another. This isn't as much of a problem as it may sound like; putting a fresh spin on something is often all it takes to invent a really compelling idea.

Clever world-crafters will use this to their advantage. Instead of striving to fabricate a completely new experience, work on adding your own flavor to something that people will already find familiar. This is powerful because it gives you a common ground with your players right off the bat. That commonality can be a highly effective hook for getting someone into the experience to begin with. Dropping into a completely alien setting can be stimulating for some types of player, but most will be overwhelmed and confused. Give your players just enough familiarity to know what to try, and they'll be encouraged to explore on their own.

Go With What Grabs You


The most surefire way to create a boring experience is to not care. Creating a world is an immense and involved task; to do it well requires a degree of passion and fixation. Even if your personal "hook" is just a phrase or mental image, start with a seed that you find compelling.

It's worth keeping in mind that not everyone will find the same things equally enticing; knowing your audience can be immensely valuable in crafting a world that appeals to them. However, you need a concept that is personally important to you.

Having a key idea or even sensation you want to convey will take you far. You probably only need a few words to express this in most cases, but handled well, it can become a thread woven deeply into the fabric of an entire universe. Players will sense your personal attachment to that thread and will tend to be intrigued themselves.

Retelling personal experiences can be a great way to accomplish this, but don't feel constrained to actual facts. Dress up the story in the way you wish it had turned out, or raise the stakes. If you saved the day by showing up to the family barbeque with the ketchup everyone else forgot, turn that into a grand adventure with a runaway nuclear reactor and the emergency shutdown codes that nobody else could find.

The flip side of this is that sometimes you need to be less attached to an idea; if something grabs you but nobody else seems to care, it may be time to make the difficult decision to leave that idea behind and pursue something else. Even the best creators struggle with this; the difference between extremely good storytellers and tabloid article authors is that the good world-crafters are willing to let go of stupid ideas.

Learn From the Masters


Developing your skills as a world-builder will follow the pattern of any other discipline. Studying the work of other creators will be vital to honing your own abilities.

Draw insipiration from things you've read, watched, played, or even lived through. Think about what kinds of feelings are evoked by your favorite stories and worlds. Think about what sorts of emotional reactions you want to instill in your players.

Remember what your favorite experiences and worlds feel like, and think critically about how they may have accomplished that ambiance.

Use Every Art Form Available


Games - and especially video games - have the fascinating advantage of being multimedia products. The word is rather beaten to death in today's society, but it's worth going back to the literal definition: games span many different mediums, from visual art to audio to music and maybe even physical feedback.

Never underestimate the potential of this when crafting your own worlds. A game's visual style, audio style, musical style, and so on can all be used to great effect when applied in concert. Know how to leverage the various stimuli you have at your disposal, and use them to help underscore the emotional impact you want your world to have.

Know When to Break Expectations


A powerful way to create emotional tension and memorable moments is to break expectations. When players think they know how something will turn out, and the tables suddenly turn on them, the resulting moment of shock can be a powerful tool for instilling certain impressions. Just be sure you know what reaction you want to go for; arbitrarily breaking expectations is just plain confusing. Using shock as a tool to reinforce impressions must be done judiciously and carefully.

Feed Imagination; Generate Curiosity


There is a classic rule from improv comedy that applies to developing your worlds: never say "no." In other words, try not to purposefully close off possibilities. Leave things open for imagination and curiosity as much as possible, unless you need to resolve a major plot point - but even then, open questions can be powerfully compelling.

Imagination-feeders can be as simple as strange symbols in obscure locations, or as massive as giant spaceships appearing in the night sky. The extent and scope will depend a lot on the world you want to make, but the principles are timeless.

Purpose, Interest, Resistance, Resolution


The final cornerstone of crafting a compelling world is a storytelling pattern as old as stories themselves. The general idea has been studied and documented for centuries, but it bears repeating with a minor twist in the context of creating game worlds.

Put simply, players must be taken through four stages of dramatic progression, beginning with purpose. Purpose gives players a reason to be in the world and a goal to accomplish.

Once the player's purpose is established, and usually hot on the heels of that moment, it is time to create interest. Give the player some motivation beyond simply "get this random thing done." Another way to think of this is that interest is the context in which purpose plays out.

Of course, dramatic tension cannot exist without resistance. There must be some person, force, internal conflict, or other general reason why the purpose is difficult to achieve. The nature of resistance is usually bound up heavily in the interest.

Finally, once the player overcomes the resistance and accomplishes the purpose, they should feel a sense of resolution - that something was indeed changed, perhaps for the better (or maybe not!) in the course of exploring the game world.

The trick to all this lies in layering and staggering the stages of the cycle. An overarching story line may set up the four phases on a grand scale, while a single "mission" or "chapter" does so on a slightly smaller scale, and then a single battle or adventure within the game may provide a third and most-succinct incarnation of the pattern. Virtually all game stories follow this structure to some degree.

Putting It All Together


Find something that interests you personally, and build around it; be prepared to invest a lot of time getting it right and fleshing out the details, and never lose sight of the possibility that you may need to start over. Along the way, use examples from other experiences you've found compelling to help inspire and shape your own world. Never close off possibilities if you don't absolutely have to, and feed the imagination of your players - even if they imagine things you never thought of yourself; or maybe especially if they do.

Last but not least, know how to structure the dramatic cycle of your world, and don't be afraid to break expectations to underscore your points and create lasting memorable moments.

Once you've created a universe, you're officially qualified to make an apple pie from scratch. Best of luck!

APE: Author, Publisher, Entrepreneur

$
0
0

Author's Summary


In 2011 the publisher of one of my books, Enchantment, could not fill an order for 500 ebook copies of the book. Because of this experience, I self-published my next book, What the Plus!, and learned first-hand that self-publishing is a complex, confusing, and idiosyncratic process. As Steve Jobs said, "There must be a better way."

With Shawn Welch, a tech wizard, I wrote APE to help people take control of their writing careers. APE's thesis is powerful yet simple: filling the roles of Author, Publisher and Entrepreneur yields results that rival traditional publishing. We call this "artisanal publishing"--that is, when writers who love their craft control the publishing process and produce high-quality books.

APE is 300 pages of step-by-step, tactical advice and practical inspiration. If you want a hype-filled, get-rich-quick book, you should look elsewhere. On the other hand, if you want a comprehensive and realistic guide to self-publishing, APE is the answer.


Attached Image: 51+ISsTRGxL.jpg
    Click the image to view this book on Amazon


GDNet Staff Review


Much like the argument that the phrase "gay marriage" is becoming obsolete in favor of simply "marriage", the old terms "vanity-publishing" and "self-publishing" are becoming less distinguishable from simply "publishing". While paper-publishers who publish paper books that end up on the New York Times Bestseller List and live on the shelves at your local bookstore are not going anywhere soon, the prestige of being recognized by a "big publisher" is no longer much of a thing. Self-publishing is no longer the home of crackpots and D-list celebrity memoirs. Self-publishing is...publishing!

APE: Author, Publisher, Entrepreneur-How to Publish a Book by Guy Kawasaki is the latest and best book I've thus-far found about how to write, format, and sell that book that is inside you and is dying to escape. It starts with the conceptual material that you will find in just about every "how to write a book" book, but it does it without the obligatory "how to impress the publishing house" chapter. But that's not necessarily a rosy path. If you have the writing skills of a chimp but somehow manage to finagle Random House into publishing your novel on paper, you can bet that it will go through enough passes of editing that it will be literate by the time it hits the shelf. Not so with electronic publishing. APE does cover both the challenges of writing and multi-pass editing in addition to all the technical bits required to get your words into an internet bookstore.

The technical aspects of the book are quite specific and useful, and they use the book itself and the author's previous e-book What The Plus! as a test-bed for all of their experiments. After all, a 300+ page MS Word document is a pretty good way to test the depth of the various software tools that can convert your work into the formats preferred by online stores.

Despite the author's notable work with Apple, the book is quite free of brand evangelizing. He's clearly just finding the best tools to get the job done.

My main worry about a book of this type is that it will become dated and the references to particular pieces of software or services will become curiosities over time. And addressing this, Mr. Kawasaki is using himself as an example of how electronic publishing can keep a work current in the face of rapidly changing technology. The book itself has undergone several updates since first appearing in the e-bookstores. It is one of the chief advantages of electronic publishing compared to paper, and it is an advantage the author is leveraging.

APE: Author, Publisher, Entrepreneur-How to Publish a Book is a work in which the author has done all the experimentation required to get a book written and formatted and uploaded and published and monetized and successful. If you have a book inside you that wants out, this book will help you get there.

Games as Art and Why You Shouldn't Care

$
0
0
“The chess pieces are the block alphabet which shapes thoughts; and these thoughts, although making a visual design on the chess-board, express their beauty abstractly, like a poem… I have come to the personal conclusion that while all artists are not chess players, all chess players are artists.” -Marcel Duchamp


When you ask anyone who has ever loved a game what their favorite game is, you never really know what to expect, but you can bet that game made their list for a reason. Maybe they loved it because it was artsy, but maybe they loved it because it told an fantastic story. Maybe they liked the character progression, or maybe the dialog made them laugh. Maybe it was that game that allowed them to share an intimate bond with another person, or maybe they fell in love with exploring a new universe. Maybe they just like killing time on their farm.

The point is, all of these experiences can be intensely meaningful to the person on the other side of the screen, board, stick and can, etc. – regardless of whether or not someone thinks it qualifies as art. In other words, my response to the question, “Is a game art?” is an earnest “Who cares, did you get something out of it?”

It’s my opinion that our job as game developers is to create meaningful experiences – to entertain. In some form or another, that’s why most of the developers I’ve met or worked with got into the industry in the first place. For me, games were one of the few subjects that my father and I really connected on, from Backgammon and Chess to Legend of Zelda and Quake Thunderwalker CTF, and that’s always been one of the main influencing factors in deciding that I wanted to make them. I love games and the experiences I’ve had with them and I want to create more of that.

We know that games have brought people together since at least the very beginning of recorded history and, given what we know about human nature, we can easily assume that they’ve been doing so since the dawn of man. In that context, the thought that anyone would seek to validate games by labeling them as art seems not only unnecessary, but detrimental – it distracts from the essence of what makes games so powerful. Games don’t need to be art to be significant because they are already tantamount to the human experience. I’m not saying there’s no room for certain games to be art or to not be art, but to let that define our craft would be to miss the point entirely.

Can a game be art? Hell, a game can strengthen families, it can build friendships, it can introduce lovers, it can change the way you see the world around you, it can teach you things you didn’t know about yourself. Games do all of these things and so much more every day all over the world on an immeasurable scale, as games always have.

I really want to drive that point home: games have always had the power to affect droves of people in a meaningful way. A set of rules can do that. That’s just a property of games. Stack up the sheer number of prides humbled by a game of Go or restless minds calmed by a few rounds of Solitaire and they easily outrank, by at least an order of magnitude, the reach of even the most famous works of art that history has to offer. By that measure, being art must be the least significant thing a game could ever do.

At this point you might be thinking, “…but if we concede that it doesn’t really matter whether or not games are art, doesn’t that mean we’d also be forfeiting all the potential cultural, legal, and financial privileges enjoyed by traditional artistic media?” Well, yes and no.

I would argue that as part of a global society in which games have long been more or less universally accepted, our efforts would be better spent talking about why games are so incredibly valuable and worthwhile by their own merits, rather than falling into the centuries-old trap of trying to get everyone to agree on what the hell makes something art.

When I hear people talk about certain specific games as being works of art, myself included, they typically mean that the game is an exceptionally good game based on criteria used to judge whether or not games are good, not that it’s exceptionally good at being some other sort of thing that’s maybe art but probably isn’t a game. In that sense, you have one group of people saying simply that that yes, some games are incredibly good games, and another group sort of butting in to argue that no, there are no games that are paintings.

To the point, the question should be, “If games are so important, why aren’t they offered the same recognition and consideration as art?” That’s a question that, sadly, I don’t have an answer to.

Maybe it’s because play comes to us so naturally that we’ve learned to associate it with childish behavior. Maybe it’s the nature of play being so deeply hard-wired into our genes that causes us to take it for granted and devalue the beauty in the architecture of a brilliantly engaging set of rules.

Whatever the reason, games typically aren’t regarded with the dignity they deserve. If they were, we might be in the throes of a heated debate over whether or not carving a sculpture or performing a dance could truly be considered a game. Wouldn’t that be something…


GameDev.net Soapbox logo design by Mark "Prinz Eugn" Simpson

Tips for Working With an Art Studio

$
0
0
In 2012 I had the pleasure to work with Meta3D Studios in developing artwork for my mobile game Hamster Chase, and I'd like to share some tips on getting the most out of working with an art studio.

Before Approaching a Studio


Before you make first contact, try to have as many of the following on-hand as possible:
  • A partial game design document. Have something to give the studio that at least tells them what your game is about, and how big (or small) it is with respect to story, characters, enemies, and content. It's fine to explain your game in a few sentences over e-mail, but they need a good idea of how much work to expect based on your vision of the game.
  • A list of needed assets (works of art). Don't just include the game characters, weapons, items and level textures; you may also need a user interface, menu art, an icon, a splash screen, box art, banners, art for your website...and the list goes on. The more you think of ahead of time, the better...but if you forget something really important, let your main contact at the studio know ASAP.
  • Visuals and sketches. It's OK if you have a bunch of MS Paint mockups and scribbles on scanned documents; the art studio needs at least a basic idea of what you have in mind for everything.
  • Reference images or videos. Sketches tell a studio what you need, but references help them understand the finer details. There is no shame in taking screenshots or videos from other games; just don't ask them to copy from them verbatim. If you can do it, making a video of a textureless demo of your game can be helpful, too.
  • A budget. Know how much you would like to spend, and know what your hard limit is on spending. Depending on how much art you need, you could get a quote from a studio for fifty or for five thousand dollars (That may as well be several million dollars for you younger Indies).
  • Realistic expectations. You may not be the studio's only client, so don't be offended if they don't reply to your e-mails every five minutes. If they give you a quote, and you think "Wow, that's way more than I expected to spend!" then at least put it in perspective. The studio needs to make its livelihood, taxes must be paid, and dinners put on tables. It takes time and resources to create art. Even if it's an animated cartoon hamster, consider that every frame was created after hours of work, and a bit of trial and error. A professional is just that because they make the difficult look easy.
  • A deadline. Let the studio know up front whether you're fighting a deadline, or just developing your game at a casual pace. It's a courtesy to both the studio and its other clients who really need their games out the door in two months.
  • Experience playing similar games. This is a challenge for me because I feel like if I play other games, I'll subconsciously steal their game play ideas, and seeing such well polished games makes me shy away from trying to compete. Really, the opposite attitude should prevail: You can learn an awful lot about how to make your game great by playing other games in the same genre, and even find ways to make it better!
If you have no idea how you want your game to look, then study the portfolios of various art studios. If you're still not sure, let the studio know what kind of game you're making, and they can share additional examples with you. If you're still not sure, then you're not ready yet. Please don't ask a studio to devote their time to be your art consultant free of charge.

Getting Started With the Studio


Lets say you've found your dream studio, they're happy to have you as a client, and that you've agreed on a payment plan. Make sure you get the following things established:
  • A way to share assets. Usually the studio provides you with this. I like Basecamp because all the assets were neatly organized, and the interface was easy to use. Dropbox is handy, too.
  • A tentative timeline. A simple "it will probably take x hours total" or "we may have it done in y-z weeks" will suffice. Nobody can know exactly how long a project will take before it's done.
  • A direct line to your primary contact at the studio. If something comes up that requires special or sensitive attention, you don't need to bullhorn it to the whole studio.
  • Someone on your team who is the primary contact for the studio for the same reason.
  • Availability. Don't sign up with a studio, and then not reply to their messages for a day or two at a time. You will leave a terrible first impression, and they'll think you're not serious about the project. Be especially proactive in communicating with the studio at the beginning of the project. Let them know when you're generally reachable, and find out the same from them.

Working With the studio


Here are things to keep in mind throughout the process of working with any studio:
  • Communication: The project only moves forward as fast and effectively as your messages do. Keep a flow of communication going. If someone is going to be out of the loop for a while, let the studio know. For example, Meta3D studios delivered a ton of assets to me late one week. It was going to take me the whole weekend to update my game with it, and I had a busy week ahead at my full time job. I told them I needed time to catch up, and I'd let them know as soon as I was done. Knowing that, they could safely budget more time toward other projects that week.
  • Flexibility: Chances are the studio you work with has more experience than you do with art development, so think about any constructive advice they give you. If they tell you they can't do something, it's because they can't do it. In those cases, work with them to find another way to make the assets work. Neither you nor the studio will know exactly how an asset will look until it's done.
  • Sudden project changes: If you realize you forgot to ask the studio for something important, let your main point of contact know immediately. Asking for new assets affects their schedule and how much you're paying them. So does deciding that you don't want other assets after all (and you're still paying for the time they already invested). It's OK if you make a significant change to the project once; but if it becomes a habit, then your team had better stop and figure things out real fast.
  • Know your product: I found myself waffling around some basic game play design decisions far into the project. I didn't even have a design for the game's main UI until near the end of the contract. If I had spent more time playing other games similar to mine in look and feel, I would have learned a lot, and had been more prepared to work with the studio. That would have enabled Meta3D Studios to make more Hamster Puzzler content in less time.
  • Playable demos: I use Unity3D to develop games, and the web deployment made it easy for me to show off the assets from within the game to the studio. There's no substitute for collaborating and reviewing a work in progress than for the developer to produce intermediate builds for everybody!
  • Patience: In this generation of game development, it seems like every day a new game comes out with amazing art that was completely developed by one person or a small team over a few months. Don't let this lead you to believe that art studios can do better than that in a fraction of the time. Custom art takes time and resources to develop; and for all you know, those developers may have used pre-existing assets. When you see a polished work of art, you don't always see the sketches and rough drafts that came before it.

In a nutshell


Respect the people you work with. You're not just working together to build assets, you're also building a business relationship. If you're unhappy with how things are going in general, take it up with your main contact in private. If the contract is finished with both sides happy, the developer gets quality art in their game along with the possibility of discounts on future projects. The studio gets another referral, and another star to add to their portfolio.

But enough reading, it's time to get out there and make your imagination come to the screen!

Revisions


23 May 2013: Initial release

The Shaming of Pac-Man: A Remake of the Classic From the 80's With A Beginner Friendly Class Framework

$
0
0

In this long titled article, I will address two things:

Firstly, I will present my Pac-Man remake that I prepared for the themed article contest of May. Following a brief technical overview and highlight of some code items of extra interest I will adress the part that was most fun to me: The storyline I added to the game.

Secondly, I will present in a semi-detailed overview the class structure that I used to make the game. This section is intended for beginner game programmers that may be a bit confused as to how to piece together their knowledge about animations and game loops and drawing to the screen into a finished, small, solid, game.


My Pac-Man remake


To start off with: The finished game is available at www.mrbenterprises.eu/PacMan . It is based on JavaScript/HTML5. I would recommend you try it with Chrome on Debian or Windows if you can't get it to run, since those are combinations I have successfully run the game on.

Apart from the new story and the cut scenes and the space trucker persona I decided to give Pac-Man, the gameplay is a subset of the original Pac-Man described in detail in the excellent Pac-Man dossier by Jamey Pittman. Due to time running out I had to cut some aspects – in my version the ghosts only have the chase state, there are no power-ups (and thus no ghosts can “die”) and the spawning mechanism of the ghosts is a bit different. I also had to cut several cool things that I had in mind (teleport animation and ship energy core graphics, for example... sad!).

What is identical though is the AI of the ghosts (minus a bug that was apparently part of the original), the ghosts and pacman graphics, and the tileset should be more or less identical as well.


Some cool technical details


While there are lots of things to mention, there are three things I felt particularly good about.

  1. I sort of really nailed MVC for the GameObjects. And letting the container class inherit the model class and pass itself to the view and controller was such a convenience.
  2. The base for the graphics is not data in any image format, but arrays holding the pixel on/off info. So one could say that the game has vector graphics, scalable to any size. The graphics scale is set at the start of the game and distributed to every entity. I included a configuration option for people to try out different settings in case of tiny/large screens.
  3. The ghosts are exactly the same except for their color, obviously, and their target tile acquiring component which is set at instantiation by the GhostFactory. It felt really good getting down a sort of component-based approach to the design in such a neat way.

The (added) story line


For me, the most fun in making games is the world and story creation, and hopefully leaving the gamer in a state of emotionally exhausted awe* at the epic end screen. As such I felt that just making a Pac-Man clone with reproduced gameplay mechanics would be bland. Early on I tried to come up with a different take on the whole thing, and decided on making Pac-Man an irritating, immoral douchebag space trucker, whose interest in his fellow xenomorph is decided on the basis of the profit he can make off of looting the unfortunate alien in question.

* Who can hold back a tear of grief when in the win scene the stars drift slowly by, underlining the feeling of sadness and doom of the remnants of the ghost species.

Further, the usual Pac-Man map is, of course, a spaceship, and the ghosts are members of an alien species whose home world is dying. Their millenia-old search for a better life is put to hard test when Pac-Man enters the scene.

All in all, I thought it could all be a nice lesson on the dire consequences of non-sustainable living and wasting others' resources.


My Beginner-Friendly Game Dev Class Framework


In this section I present the system of classes I used to make my Pac-Man game. The text is aimed at beginners who could use a focusing point for their first somewhat bigger (relative to previous projects) game.


Our goal


We want an ordered system that is easy to understand and that will enable easily going from, say, the loading screen to the title screen. We also want to be able to handle user input and draw to the screen, animate objects and route user input correctly.

In addition, of course (?), we want a diversity of things moving on the screen. We want a VampireSnail that eerily stalks its prey in the dark of the midnight hours, but also a FriendlySnail that cares for the well being of the player and offers health potions at opportune time. Or maybe a... HockeyPlayer, or something, if you're into the weirder kind of stuff.


Our way: The system


What I made to be able to have all of the above, is a system that is made up of four classes: The Game, the Scenehandler, the Scene, and the GameObject classes. Let's look at these classes in detail and take note of their functionality.

Note:  I describe the classes part in words, and part in a made-up computer language. So bear in mind that you might have to do some detective work to translate the different code bits into your own language of choice. In fact, you should view the code samples as sketchy code showing the important aspects of the class rather than the precise implementation.


The classes


The Game class

The Game class is the top level class and, chronologically speaking, would be the first thing we create in the code. Ideally we want the whole game to work automagically just by the simple line


Game g = new Game();

Possibly with the addition of

g.start();

The Game class is responsible for:

  1. Creating a Scenehandler
  2. Creating the first Scene in the game
  3. Adding the first Scene to the SceneHandler
  4. Entering a game loop or somehow setting up a piece of code to be called repeatedly

And, for each loop in the while loop:


  1. Getting input and distributing to the SceneHandler
  2. Calling update on the SceneHandler

So, in code the Game class could look something like the following.

Class Game()
{
	SceneHandler theSceneHandler = new SceneHandler();
	firstScene = new TheFirstSceneConstructor(theSceneHandler);
	theSceneHandler.addScene(firstScene);
	while(true)
	{
		input = getUserInputInSomeWay();
		sceneHandler.handleInput(input);
		sceneHandler.update();
		sleepSomeNumberOfMilliSeconds();
	}
}

What are the important bits to notice here?

First, the Game has a SceneHandler. It creates the first scene and gives it to the SceneHandler, but does not keep a reference to the first Scene. In this way, the Game does not have to know about later Scenes. It's okay for the Game class to know only about the first Scene, because as you will see below, a Scene can link itself to the next Scene, without the involvement of the Game class.

Secondly, as mentioned, the Game sets up a game loop and tells the SceneHandler about updates and input.

That was not so much, was it? Let's go on to the SceneHandler to further clarify the workings of the system.


The SceneHandler class

In short, the SceneHandler manages a list of Scenes, and has a number of comvenience functions added to it. Let's have a look at the code:


class SceneHandler()
{
	Array myScenes;

	function addScene(scene)
	{
		myScenes.add(scene); //push
	}

	function removeLastScene()
	{
		myScenes.removeLastAdded(); //pop
	}

	function update()
	{
		myScenes.getLastElement().update();
	}

	function handleInput(input)
	{
		myScenes.getLastElement().handleInput(input);
	}
}

As you can see, the main (and sort of only) point of the SceneHandler is that it has an array of Scenes. It also has functions to add a Scene to the last position of the array, and a function to remove the lastly added Scene.

An important thing to notice, though, is that the SceneHandler's update and handleInput functions call the corresponding functions on the last Scene added. So, the last Scene in the array has a certain role. It is the current Scene. We could even have added an extra property to the SceneHandler class called currentScene to emphasise this (and made sure that it was always the same as the last element in the array).

So using this setup, it means that only the current Scene gets input from the user and is notified of another cycle in the game loop.

With this simple class digested, we walk on to the Scenes themselves, where we start filling things with content.


The Scene class

The important points of the Scene are:


  1. To create and store objects (GameObjects)
  2. To tell the stored objects when its time to update and draw themselves
  3. To pass user input to the objects
  4. Enable searching for an object from outside the class
  5. To store a reference to the SceneHandler and make that, too, available to the objects.

In more words, we could also say that a Scene has an array of GameObjects. And when the Scene is created, it will fill its array of GameObjects with different objects, depending on what part of the game the Scene corresponds to (Options menu, title screen or main game screen, etc.). A very important aspect here, is that each GameObject will be given a reference to the Scene. This enables the objects to search for, remove and add new objects to the Scene! (by calling getObjects and manipulating the array).

Since the objects are given a reference to the Scene, and can ask the Scene for its SceneHandler, the objects can also change the current scene! So if, in the main game scene, your CollisionDetection object notices that TheHero is at the same tile as TheMonsterThatEatsHeroes, it easily switches to the more appropriate GameOverScene.

As game cycles pass, the Scene tells its objects when it's time to draw themselves to the screen and when it's time to update themselves. i.e, in the Scene update function,  it loops over its objects and calls the update and draw functions of the objects. First the update function on all objects, and then the draw function of all objects. In the same manner, user input notifications are passed on from upper classes to the objects.

Let's look at some code, to hopefully straighten out remaining question marks.


class Scene(sceneHandler)
{
	SceneHandler theSceneHandler = sceneHandler;
	ArrayLikeClass myObjects;

	// Create cool objects and put in myObjects here

	GameObject theExampleObject = new ExampleObject(this);
	this.addObject(theExampleObject );

	function update()
	{
		foreach(object in myObjects)
		{
			object.update()
		}

		foreach(object in myObjects)
		{
			object.draw()
		}
	}

	function getObjects()
	{
		return	myObjects;
	}

	function getScenehandler()
	{
		return theSceneHandler;
	}

	function handleInput(input)
	{
		foreach(object in myObjects)
		{
			object.handleInput(input)
		}
	}

}

The GameObject class

The GameObjects are the Dragons, StrangeObelisks, Pencils, or whatever interesting things you want to have in your game. A GameObjects may even be an abstract thing like a Text or a GameOverTrigger.

There are some things the system demands that all GameObjects have in common:

The object needs to have functions for drawing and updating itself. It need not actually do something in those functions (although I guess most objects would), but it should have the functions so that they can be called. The drawing method for drawing itself to the screen, obviously, and the update method for AI considerations.

Another important thing, which is needed for the system to be as flexible as we want it to be, is that a specific object can be identified by having a tag (or an id if you will). The good thing about a tag is that it allows us to search for a particular object in a collection of several objects.

The reason that we want to search for a particular object is that one specific object might want to know something about another specific object. The WickedWolf, for example, would be interested in calling getPosition() on the object with the “LittleRedRidingHood” tag.

In essence, the tag functionality allows our objects to be interactive and reactive towards each other. Objects may take decisions or pathfind or cease to exists, etc, based on the status of other objects.

And as noted, since the gameObject has access to its parent Scene, it can remove or add objects, and also change the current Scene of the game completely through the Scenehandler.


class GameObject(scene)
{
	theScene = scene;
	myTag = 'someTagAppropriateToTheGameObject';

	// other variables that this object needs 

	function update()
	{
		// do something cool ? AI! Check for game over, search for sheep to eat, 
	}
	function draw()
	{
		// draw something that represents the view of this object (at this moment)
	}
	function handleInput()
	{
		// change something (or not) in the object depending on the input 
	}
}

Now, it's important to realize, and you've already done that of course, that the line saying “other variables that this object needs” contains a possible ton of different things depending on what you want the object to do. Maybe you want to have objects to have a position (yes). Then you have to add that upon construction, and change the position in the update function, and draw the object at different places depending on position in the draw function.


Summing up


I hope that some recognition of a usable pattern has formed in the reader's brain. Should my noob pedagogy have left questions lingering behind - feel free to contact me on my twitter, @NiklasBjornberg

Some final considerations


MVC pattern


Should you glance into the code of my Pac-Man project, you will find that the GameObjects are divided into even smaller classes too – namely Models, Views and Controllers. That is because I follow the Model-View-Controller pattern for the GameObjects. I find this a very powerful pattern, because it helps me to keep the code and data for the behavior (the controller part) of an object away from the code and data for drawing (the view part) an object and the model data. So all in all it helps to make things a lot less messy and facilitates changing parts without affecting other parts.


Diverse requirements among GameObjects


As you might have noted and pondered upon, in my system I propose that things like a GameOverTrigger or CollisionDetection be GameObjects and stored in the Scenes object array. This may pose some problems. For example, one object (WickedWolf comes to mind again) might want to examine the position of all the other objects. But this would mean, in the context of most languages and usual implementations, that all the objects in the object list has to implement a getPosition function, for example. In the generic problem statement, the expectations of one object affects all the other objects and forces them to have an interface that is possibly counterintuitive to their nature.


How do we solve this? Here are some ways, in order of level of genius:


  1. Introduce separate lists for each kind of objects.
  2. We really make all objects have an interface that answers to the demand of all the others. This might be okay in a small project with very similar GameObjects.
  3. Based upon tag, you select only the objects you are interested in and that should, by the tag value, live up to your expectations.
  4. Instead of just getting the property or calling the function you want, you make sure it is there first. Either by a language supported way or using some sort of component based approach (see last month's article winner! Seems really interesting.)

I would suggest the solution in item 4. But I guess that all except item 1 could be argued for.


Article Update Log


30 May 2013: Hello world!

Build-Order Optimization in StarCraft

$
0
0
David Churchill and Michael Buro
University of Alberta
Computing Science Department
Edmonton, Alberta, Canada

Abstract


In recent years, real-time strategy (RTS) games have gained interest in the AI research community for their multitude of challenging subproblems — such as collaborative pathfinding, effective resource allocation and unit targeting, to name a few. In this paper we consider the build order problem in RTS games in which we need to find concurrent action sequences that, constrained by unit dependencies and resource availability, create a certain number of units and structures in the shortest possible time span. We present abstractions and heuristics that speed up the search for approximative solutions considerably in the game of StarCraft, and show the efficacy of our method by comparing its real-time performance with that of professional StarCraft players.

Attached File  aiide11-bo.pdf   166.7K   8 downloads


References


Branquinho, A., and Lopes, C. 2010. Planning for resource production in real-time strategy games based on partial order planning, search and learning. In Systems Man and Cybernetics (SMC), 2010 IEEE International Conference on, 4205–4211.IEEE.

Buro, M., and Kovarsky, A. 2007. Concurrent action selection with shared fluents. In AAAI Vancouver, Canada.

BWAPI. 2011. BWAPI: An API for interacting with StarCraft: Broodwar. http://code.google.com/p/bwapi/.

Chan, H.; Fern, A.; Ray, S.; Wilson, N.; and Ventura, C. 2007a. Extending online planning for resource production in real-time strategy games with search.

Chan, H.; Fern, A.; Ray, S.; Wilson, N.; and Ventura, C. 2007b. Online planning for resource production in real-time strategy games. In Proceedings of the International Conference on Automated Planning and Scheduling, Providence, Rhode Island.

Iba, G. 1989. A heuristic approach to the discovery of macro-operators. Machine Learning 3(4):285–317.

Kovarsky, A., and Buro, M. 2006. A first look at buildorder optimization in real-time strategy games. In Proceedings of the GameOn Conference, 18–22. Citeseer.

ORTS. 2010. ORTS - A Free Software RTS Game Engine. http://skatgame.net/mburo/orts/.

Stolle, M., and Precup, D. 2002. Learning options in reinforcement learning. Abstraction, Reformulation, and Approximation 212–223.

Smarter Steering: Using Context for Direction

$
0
0

Smarter Steering


I should begin this by giving credit where credit is due. The idea for contextual steering described herein is lifted heavily from work by Andrew Fray as described in his excellent GDC 2013 AI Summit lecture. For the most part the ideas and hard work are based on his lecture, although I've added a few twists of my own. (As a bonus, the above lecture includes a great introduction to steering systems in general, which is a solid starting point if you're not already familiar with the concepts.)

Now that that's taken care of, let's get started!

The Problem With Local Steering


Local steering is a powerful model and highly worth exploring for almost any game that requires freeform movement in an environment. Unfortunately, one of the biggest difficulties with getting good results from local steering systems lies in its context-free nature. Each steering force that is implemented needs redundant logic for obstacle/collision avoidance, for instance. As the number of forces increases and the complexity of logic scales up, it can be cumbersome to create clean code that is both efficient and does not needlessly repeat complex calculations.

Generally, good implementations of steering become a layered, twisted maze of caches, shared state, and order-dependent calculations - all of which fly in the face of good engineering practices.

Thankfully, there's a way to have steering and clean code - and it's actually very straightforward.

Enter the Context


The solution to these problems lies in adding contextual information to a steering decision maker. Instead of taking the weighted sum of a number of input forces, we flip the problem on its head. First, we generate a series of slots which correspond to fixed directions. These directions can simply be compass headings; there can be as few as 4 or as many as hundreds of slots, depending on the resolution your steering needs. I find that for most purposes 8 slots is about perfect, but 32 is another good choice if you're willing to do a little more computation to get better, smoother results.

Once these directions are established, we pass them to a series of evaluators. Each evaluator determines a score for the direction. This can be thought of as analogous to the idea of steering forces; the more likely a character is to want to go in the given direction, the higher the score should be. I tend to normalize scores to [0, 1] for simplicity, but you can use any scoring method that makes sense.

Scoring can be used to give a low or zero score to a direction if the direction should be avoided. This is excellent for steering around traps, obstacles, other characters in a flock, and so on.

Now we have a list of potential directions to take, along with a series of scores from each evaluator. The next step is to combine the decisions made by each evaluator. This is where game-specific logic can come into play. For example, if your directions are evenly distributed around a circle (as would be the case for moving in a free 2D world, or along the ground in a 3D environment) combining evaluated scores is pretty simple. If you use normalized scores, you can simply multiply all of them together for a given direction to determine the overall "desire" for a character to move in that direction.

Andrew Fray's original lecture also describes doing this a different way for a racing game where most directions are roughly "forwards". In this case, you can do more sophisticated things like eliminate entire sets of directions based on the presence of obstacles. Normalized scores are slightly less useful here, but still handy for simplicity's sake.

Either way, once all of our directions are scored and the scores are combined, it's time to decide where to go. The basic principle is that we take the highest scoring direction and move towards it; but there are other tricks that can lead to smoother steering without needing to score a large number of directions. For instance, you can look at the highest scoring direction, then the scores of two or three directions to either side, and do a weighted average to pick a general trending direction instead of just going straight for the highest-scoring vector.

Once the final direction is chosen, you can easily blend it with the character's current orientation to achieve gentle turning. I do this by simply performing a linear interpolation between the chosen direction and the current direction of movement; by adjusting the weights of the interpolation, it's easy to get characters to turn faster or slower depending on what looks and feels best.

Examples and Tricks


So we have a general framework for this "contextual steering", but that leaves a major question: what, exactly, is context?

This will vary heavily based on the type of game you're building, but the basic idea is straightforward: context is anything that might influence how likely a character is to move in a certain direction. This can be expressed in terms of "desirability" and "danger" - the more desirable a direction, the higher its score. The more dangerous a direction, or undesirable if you prefer, the lower its score.

Pursuing a Target


Steering towards a target position is easy: for a given direction being evaluated, take the dot product of the (normalized) direction vector and the (normalized) vector from the character to the target point. You can clamp this score to [0, 1] if you like, or keep the negative scores for directions that face away from the target, depending on how you want to combine the results of each evaluator.

Avoiding a Target


As before, take the dot product of the candidate direction vector with the vector towards the target to avoid. Flip the sign of the result, and you're done! The character will now faithfully steer away from the given point.

Handling Obstacles


Static obstacles that lie between a character and the desired destination can be handled by simply setting the blocked direction's score to zero. The character will naturally tend to steer away from the obstacle and try and move around it instead. A simple way to do this is cast a ray in the direction of the candidate vector, similar to any other line-of-sight check, and if a direction is obstructed, zero out its score.

Controlling Speed


A simple trick to accomplish speed control is to scale the score of a candidate direction by how fast you want the character to move. If you're using multiplication of normalized scores, speed control is simply a matter of adding an evaluator that chooses how fast to move. This can be combined with other systems to coordinate moving through choke points, for example.

Flocking


If you have a large number of characters all steering using this system, you can coordinate them into "flocks" fairly easily. The trick is to add a pre-processing step which computes a "dispersion" or "separation" force just like in traditional flocking. Then, we add an evaluator which takes the dot product of the dispersion vector with each of the candidate vectors, and adds that score to the other scores produced by different evaluators. The result is that characters will tend to favor directions which move them towards the separating positions, leading to very visually pleasing grouping behavior. As a bonus, when combined with movement speed scaling, we can have characters flow in crowds and self-organize with minimal effort.

Computational Efficiency


Sometimes, when steering huge numbers of characters, it can be impractical to have each character steer every frame. With contextual steering, it's trivial to address this performance problem. Simply have each evaluator score the candidate directions, and provide an estimate for how long the character can move in that direction before the score becomes invalid. When it comes time to choose a final direction, simply pick the lowest time for which that direction can be valid, and don't steer again until that time elapses. Better yet, combine this with simple movement speed scaling to have characters move at slightly different speeds, and you can get free time-slicing of your steering computations!

Conclusion


Steering remains a powerful paradigm for controlling character movement. However, with some simple adjustments to the concept and a little clever application of logic, we can accomplish highly context-specific behavior with a minimum of effort and zero code duplication, since each considered evaluator only has to run once per direction.

Depending on how many candidate direction slots we use, and depending on the complexity of each steering evaluator, it might be more expensive to do this than to use naive steering in some cases. However, the more complex the steering logic becomes, the better the win for using contextual information. Careful coding can also allow many context-specific decisions to be ignored when they are invalid, dropping the computation overhead substantially.

In any case, contextual steering is an excellent tool to have in your arsenal. A good implementation framework can be built in a day or two, and scoring evaluators added on as needed to produce arbitrarily rich steering behavior.

For extra credit, consider combining context information with flow fields, navmesh pathfinding, or whatever other movement control techniques strike your fancy.

Enjoy!

Redesigning an Old Game for Mobile Platforms

$
0
0
This article covers the process of remaking an 8-bit game into a brand new mobile game, adapting the game everywhere it needs to fit the new screen and control methods.

The Original Game


Alcatraz is an old Brazilian game, for an 8-bit system called MSX - a text-adventure game, with a twist: it uses a simple one-screen tile map to show the player avatar and some elements of the game. The premise of the game is quite simple: you’re a prisoner on Alcatraz, and you have to escape.


    001.png
    Alcatraz game map – the whole map.


The game was fairly known at the time, completely made in BASIC, with its listings even published on a MSX games book. One of the special attractions in the game was that the obvious solution for some of the problems never really worked, and you had to think about other means to get the job done.

The Remake


I always wanted to remake this game – in some form or another, especially translating it into English, so it could reach a broader audience.

Seeing the rise of mobile games, most of them very simple in their nature, I couldn’t see a better opportunity to bring this very addictive game into the light.

So, after choosing the mobile platform, one huge question remained: the original game was a text adventure. You had to type commands to get things done, and this obviously wasn’t desired or even feasible on mobile. So a new way to play the game had to be created.

This article is all about it: showing how the game was redesigned – with new visuals and improved gameplay, inspired by the old game on an 8-bit machine, to be able to run just about everywhere.

Also, please take into account this game was developed just by me, in the time-span of exactly 2 months, so don’t expect some AAA quality graphics on the screenshots :)

The New Visuals


The first thing noticed was that the whole game visual wouldn’t work on mobile – having the whole map on a single screen may have worked on MSX – but on mobile the graphics would be too small to be seen. This set the first game decision: the map would scroll with the player – so the game could have bigger graphics.

In the original game the map was revealed as you walked by – but you could only see the tile where you were and 1 tile around it. I never liked that about the game, so I decided to make it a little better – the player would have a “view radius”, and through some visibility checks (some basic ray casting) I would make the tiles far away fade into the darkness accordingly to their distance to the player – and even taking into consideration some other tiles (light passes through the prison bars, so you can actually see a little bit of the tile behind it, even if your passage is blocked). As in the original game, once you visited a tile, it would remain visible.


    002.png
    Visibility comparison: on the left, the original – you can’t see beyond your position. On the right, the new version – you can see beyond the bars, the tiles to the left are a little darker, but visible.

    
As you can see by the screenshot above, the graphics style has been kept – but enhanced a little bit so it wouldn’t look so outdated. Still the 8-bit style is kept, especially in the game’s characters.

Then comes the next challenge: a new way to input actions, since there is no keyboard to type commands on mobile games. The first option was a given: a virtual joystick to move the player avatar around the map.

The next option was inspired by the old-school graphic adventures: using icons to represent the actions the player could take. And since I can’t just throw a huge number of icons on screen (the player would be lost) – I had to think about the whole game solution, and reduce the icons on screen to just a few selected actions.

What those actions are? I managed to reduce all game commands to 6 actions (7 if you count the one used to pause the game): look (used as an ‘examine’ command), get, drop, talk, use and give. With this, you can take every action in the game, and it actually works pretty well. To examine the bed, you touch the look icon, then the bed icon, and it’s done.


003.png
    The new game interface: 6 possible actions the player can select with a touch.


Of course, sometimes you need to interact one object with another – this was done in a two-step process: you select one action (ex: “Use”), then you touch the first object (ex: a mug). You will see the selected object to the right of the selected action, and the game will wait for you to select another object (ex: the cell bars) to use the first object on. Sounds complicated, but it’s really simple.


004.png
    The game is waiting for you to use the mug somewhere.


In the original game you had to press a key to see the objects on your current position. The same was true for your inventory items. This was also changed with two panels on screen: one that shows objects on your position, and another that shows what you’re carrying.

And just for the sake of it, you can also select objects that are shown in the map. So touching a door in the lower panels or touching it on the visible map has the same effect – in fact, there is a part of the game where an object doesn’t show in the panel, and you have to touch it on the map.

One of the problems that appeared later in development: the game was intended for the mobile world, but still, it should be ready to be ported to desktop – so the Virtual Joystick had to be optional. The whole GUI was re-designed to be “moveable” – if the Virtual Joystick is enabled, the GUI Icons and objects are placed more to the left, otherwise they are centered on screen.


    005.png
    The interface, without the Virtual Joystick

    

The New Gameplay


The original game was very fun – but probably due to memory restrictions (less than 32k!), it was rather short and the ending was a little abrupt. To improve things, the story was changed and expanded into three levels – the first one in the prison itself, and a second one, on the sewers below and a final third just outside the prison, but still on the island.

Some parts of the original game were kept, so if you played the original, you will recognize some puzzles. But beyond that, the game got other improvements, especially regarding the NPCs.

You could barely interact with NPCs in the original game: most of the time you could only give them something. This was changed, and now you can actually talk to them, and they react to a number of actions.


    006.png

    
Not only the possible interactions increased, but you also have more NPCs: in the original you were the only prisoner on Alcatraz (or if there were others, you never saw them) – now there are others which may or may not help you in your escape, and in some cases you won’t be able to progress in the game without talking to someone.

Besides NPC interaction, the game has now more interactions with the level itself: You can break a wall, blow up stuff, events occur when you step on certain positions, or over an amount of time; the level now can have some animations, and even trigger some effects according to player actions.

The game, which took place entirely on a single map – now it's expanded into 3 levels, which gives more depth to the story and the way you escape. In order not to alienate players with lots of texts, all dialogs were kept as simple as possible.

Later during development, some other ideas popped up: the best of them was the high score list. The game has no points, but the high score will store the name of players who finish the game. The first 10 to win the game (per platform) will have their name on the “eternals” list – their name will be held there forever, or as long as the server is online ;)


    007.png
    The game high score list, showing fake player names during testing :)

    
The high score list has also a top 10 for daily players, monthly and yearly. Those lists are reset every day, month and year as their name implies, so even players who don’t get a slot in the “eternals” list, still can see their names listed.  

Another idea that made it into the game was to have 2 different endings. It’s not something very elaborate, just the ending text that changes a bit if you do (or didn’t do) something during your escape.

Conclusion


As in most games, one plague haunted me: the feature creep. Even as I’m writing this article, new ideas for the game are popping up in my head. Some of them were implemented in the game (like the high score, the different endings, some new objects to interact with, even some jokes…) but there is a point when you must say: “that’s it. It’s done”.

When I first started this remake, the idea was to do it almost like the original, and in just a month. But so many ideas appeared, I couldn’t let them all slip away. So what was supposed to be a 1 level game, became a 3 level one, with tons of extra stuff… and it took 2 months to get everything done.

If you are curious about the game, you can play it for free on your Android device, and soon enough also on iOS. You can check other games I’ve developed on my site: Icon Games.

The primary tools used to develop this game were Photoshop for graphics, and for the programming, I used a language called "Monkey", which is free for HTML5 games and allows a game to be easily ported to several platforms.


Article Update Log

31 May 2013: Initial release
1st June 2013 Changed article image and added Wikipedia link to MSX

Configuration And Tweaking

$
0
0

A Configuration and Tweak System


Setting up a configuration system for a game sounds like a trivial task.  What exactly is there to store beyond some graphics, sound and controller information? For the final released game, those items cover most of the needs of a simple game, but during development it is handy to store considerably more information.  Simple items such as auto loading a specific level you are working on, if bounding boxes are displayed and other items can greatly speed debugging.  Of course it is possible to write different systems, one for the primary configuration and another for tweakables, but that is a duplication of effort and not required.  Presented in this article is configuration system which supports both standard configuration and development time configuration.

This article builds on the CMake environment presented in the articles here and extends from the updated version presented with the SIMD articles here.  The code for the article can be found here starting at the tag ‘ConfigSystem’ and contained in the "Game" directory.

Goals


The primary goals of the configuration system are fairly simple: provide configuration serialization without getting in the way of normal game programming or requiring special base classes.  While this seems simple enough, there are some tricky items to deal with.  An example could be the choice of a skin for the in-game UI.  The configuration data will be loaded when the game starts up in order to setup the main window’s position, size and if it is fullscreen or not, but the primary game UI is created later after the window is setup.  While it is possible to simply set a global flag for later inspection by the UI, it is often preferable to keep the data with the objects which use them.  In order to solve this sort of delayed configuration, the system maintains a key value store of the configuration such that access is available at any point during execution.

Keeping the solution as simple and non-intrusive as possible is another important goal.  It should take no more than a minute or two to hook up configuration file persistence without requiring multiple changes.  If it is needed to change a local variable to be attached to a configuration item it should not be required to change the local to a global or move it to a centralized location.  The system should work with the local value just as well as member variables and globals in order to remain non-intrusive.

Finally, while not a requirement of the configuration data directly, it should be possible to control and display the items from within the game itself.  For this purpose, a secondary library is supplied which wraps the open source library AntTweakBar (http://anttweakbar.sourceforge.net/doc/) and connects it to variables in the game.  This little library is a decent enough starting point to get going after hacking it a bit to fit into the CMake build environment.  Eventually the library will likely be replaced with the chosen UI library for the game being written as part of these articles.  For the time being though, it serves the purpose as something quick to use with some nice abilities.

Using the System


A basic overview of using the configuration system is presented through a series of small examples.  For full examples the current repository contains an application called XO which is the beginnings of a game and includes a number of useful additions beyond the scope of this article.  It currently builds off of SFML 2.0 and includes a test integration of the ‘libRocket’ UI framework in addition to a number of utilities for logging and command line argument parsing.  For more detailed examples, please see the application being created.

The Singleton


The configuration system requires a singleton object to store the in memory database.  While there are many ways to implement singletons, the choice of singleton style here is to use a scoped object somewhere within the startup of the game in order to explicitly control creation and shutdown.  A very simple example of usage:

#include <Config/Config.hpp>

int main( int argc, char** argv )
{
  Config::Initializer  configInit( "config.json" );
  return 0;
}

Compared to other solutions, such as the Pheonix singleton, there are no questions as to the lifetime of the object which is very important in controlling when data is loaded and saved.

Simple Global Configuration Items


The first use of the configuration system will show a simple global configuration item.  This will be shown without any of the helpers which ease usage in order to provide a general overview of the classes involved.  The example is simply a modification of the standby “Hello World!” example:

#include <Config/Config.hpp>
#include <string>
#include <iostream>

std::string gMessage( "Hello World!" );
Config::TypedItem< std::string > gMessageItem( "HelloWorld/Message", gMessage );


int main( int argc, char** argv )
{
  Config::Initializer  configInit( "HelloWorld.json" );


  // Initialize the message from the configuration.
  // If the item does not exist, the initial value is retained.
  Config::Instance->Initialize( gMessageItem );

  std::cout << gMessage;

  // Update the message in the configuration registry.
  // This example never changes the value but it is
  // possible to modify it in the json file after
  // the first run.
  Config::Instance->Store( gMessageItem );

  return 0;
}

When you run this the first time, the output is as expected: “Hello World!”.  Additionally, the executable will create the file “HelloWorld.json” with the following contents:

{
  "Registry" :
  [
    {
      "Name"  : "HelloWorld&#092;/Message",
      "Value" : "Hello World!"
    }
  ]
}

If you edit the value string in the JSON file to be “Goodbye World!” and rerun the example, the output will be changed to the new string.  The default value is overwritten by the value read from the configuration file.  This is not in itself all that useful, but it does show the basics of using the system.

Auto Initialization and Macros


In order to ease the usage of the configuration system there is a utility class and a set of macros.  Starting with the utility class, we can greatly simplify the global configuration item.  Rewrite the example as follows:

#include <Config/Config.hpp>
#include <string>
#include <iostream>

std::string gMessage( "Hello World!" );
Config::InitializerList gMessageItem( "HelloWorld/Message", gMessage );


int main( int argc, char** argv )
{
  Config::Initializer  configInit( "HelloWorld.json" );

  std::cout << gMessage;

  return 0;
}

The InitializerList class works with any global or static item and automates the initialization and storage of the item.  This system uses a safe variation of static initialization in order to build a list of all items wrapped with the InitializerList class.  When the configuration initializer is created and the configuration is loaded, items in the list are automatically configured.  At shutdown, the configuration data is updated from current values and as such the user does not need to worry about the global and static types when the InitializerList is in use.

Note:  
Using the static initializer from a static library in release builds will generally cause the object to be stripped as it is not directly referenced.  This means that the item will not be configured in such a scenario.  While this can be worked around, it is not currently done in this implementation.  If you require this functionality before I end up adding it, let me know and I’ll get it added.


A further simplification using macros is also possible.  The two lines defining the variable and wrapping it with an initializer list are helpfully combined into the CONFIG_VAR macro.  The macro takes the type of the variable, the name, the key to be used in the registry and the default starting value.  The macro expands identically to the two lines and is not really needed, but it does make things more readable at times.

Scoped Configuration


Other forms of configuration such as local scoped variables and members can be defined in similar manners to the global items.  Using the InitializerList class is safe in the case of locals and members as it will initialize from the registry on creation and of course store to the registry on destruction.  The class automatically figures out if the configuration is loaded and deals with the referenced item appropriately.  So, for instance the following addition to the example works as intended:

#include <Config/Config.hpp>
#include <string>
#include <iostream>

CONFIG_VAR( std::string, gMessage, "HelloWorld/Message", "Hello World!" );


int main( int argc, char** argv )
{
  Config::Initializer  configInit( "HelloWorld.json" );

  CONFIG_VAR( int32_t, localVar, "HelloWorld/localVar", 1234 );

  std::cout << gMessage << " : " << localVar;

  return 0;
}

The currently configured message will be printed out followed by “: 1234” and the configuration JSON will reflect the new variable.  Changing the variable in the configuration file will properly be reflected in a second run of the program and if you changed the value within the program it would be reflected in the configuration file.

Class Member Configuration


Configuring classes using the system is not much more difficult than using globals, the primary difference is in splitting the header file declaration from the implementation initialization and adding some dynamic key building abilities if appropriate.  Take the following example of a simple window class:

class MyWindow
{
public:
  MyWindow( const std::string& name );

private:
  const std::string mName;
  Math::Vector2i    mPosition;
  Math::Vector2i    mSize;
};

MyWindow::MyWindow( const std::string& name )
:  mName( name )
,  mPosition( Math::Vector2i::Zero() )
,  mSize( Math::Vector2i::Zero() )
{
}

In order to add configuration persistence to this class simply make the following modifications:

class MyWindow
{
public:
  MyWindow( const std::string& name );

private:
  const std::string mName;
  CONFIG_MEMBER( Math::Vector2i,    mPosition );
  CONFIG_MEMBER( Math::Vector2i,    mSize );
};

MyWindow::MyWindow( const std::string& name )
:  mName( name )
,  CONFIG_INIT( mPosition, name+"/Position", Math::Vector2i::Zero() )
,  CONFIG_INIT( mSize, name+"/Size", Math::Vector2i::Zero() )
{
}

Each differently named window will now have configuration data automatically initialized from and stored in the configuration registry.  On first run, the values will be zero’d and after the user moves the windows and closes them, they will be properly persisted and restored next use.

Once again, the macros are not required and are simply a small utility to create the specific type instance and the helper object which hooks it to the configuration system.  While it would be possible to wrap the actual instance item within the configuration binding helpers and avoid the macro, it was preferable to leave the variables untouched so as not to affect other pieces of code.  This was a tradeoff required to prevent intrusive behavior when converting items to be configured.

Adding New Types


Adding new types to the configuration system is intended to be fairly simple.  It is required to add a specialized template class for your type and implement three items: the constructor, a load and save function.  The following structure will be serialized in the example:

struct MyStruct
{
  int32_t     Test1;
  uint32_t    Test2;
  float       Test3;
  std::string Test4;
};

While prior examples only dealt with single types, it is quite simple to deal with composites such as this structure given the underlying nature of the JSON implementation used for serialization; the outline of the implementation is as follows:

#include <Config/Serializers.hpp>

namespace Config
{
  template<>
  struct Serializer< MyStruct > : public Config::Item
  {
    Serializer( const std::string& key ) : Item( key )    {}

   protected:
    bool _Load( MyStruct& ms, const JSONValue& inval );
    JSONValue* _Save( const MyStruct& inval );
  };
}

That is everything you need to do to handle your type, though of course we need to fill in the _Load and _Save functions which is also quite simple.  The _Load function is:

inline bool Serializer< MyStruct >::_Load( MyStruct& ms, const JSONValue& inval )
{
  if( inval.IsObject() )
  {
    const JSONObject& obj = inval.AsObject();
    ms.Test1 = (int32_t)obj.at( L"Test1" )->AsNumber();
    ms.Test2 = (uint32_t)obj.at( L"Test2" )->AsNumber();
    ms.Test3 = (float)obj.at( L"Test3" )->AsNumber();
    ms.Test4 = string_cast< std::string >( obj.at( L"Test4" )->AsString() );
    return true;
  }
  return false;
}

Obviously this code does very little error checking and can cause problems if the keys do not exist.  But other than adding further error checks, this code is representative of how easy the JSON serialization is in the case of reading value data.  The save function is just as simplistic:

inline JSONValue* Serializer< MyStruct >::_Save( const MyStruct& inval )
{
  JSONObject obj;
  obj[ L"Test1" ] = new JSONValue( (double)inval.Test1 );
  obj[ L"Test2" ] = new JSONValue( (double)inval.Test2 );
  obj[ L"Test3" ] = new JSONValue( (double)inval.Test3 );
  obj[ L"Test4" ] = new JSONValue( string_cast< std::wstring >( inval.Test4 ) );
  return new JSONValue( obj );
}

This implementation shows just how easy it is to implement new type support thanks to both the simplicity of the library requirements and the JSON object serialization format in use.

Note:  
The JSON library used works with L literals or std::wstring by default, the string_cast functions are simple helpers to convert std::string to/from std::wstring.  These conversions are not code page aware or in anyway safe to use with real unicode strings, they simply trim/expand the width of the char type since most of the data in use is never intended to be presented to the user.


The Tweak UI


As mentioned in the usage overview, the UI for tweaking configuration data is currently incorporated into the beginnings of a game application called XO.  The following image shows a sample of configuration display, some debugging utility panels and a little test of the UI library I incorporated into the example.  While this discussion may seem related to the configuration system itself, that is only a side affect of both systems going together.  There is no requirement that the panels refer only to data marked for persistence, the tweak UI can refer to any data persisted or not.  This allows hooking up panels to debug just about anything you could require.


Attached Image: TweakPanels.jpg


The ‘Debug Panel’ is the primary panel which shows the current position and size of the application window, if the window is fullscreen or not and the fullscreen mode selection if you wish to change to fullscreen.  Below that basic information are buttons which allow you to toggle open or closed the ‘UI Debugger’ and the ‘Joystick Debugger’ panels.  The panels are also integrated into the configuration system such that they remember their display state, position and size information.  And finally, if compiled with the CMake controlled value ENABLE_DEVBUILD turned off, all of the debugging windows compile out of the build removing reliance on the AntTweakBar library.

The panels are simply examples and won’t be discussed.  How to create your own panels and hook them up will be gone over briefly in the remainder of the article.

A Basic Panel


Creating a basic debug panel and hooking it up for display in the testbed is fairly easy, though it uses a form of initialization not everyone will be familiar with.  Due to the fact that AntTweakBar provides quite a number of different settings and abilities, I found it preferable to wrap up the creation in a manner which does not require a lot of default arguments, filling in structures or other repetitive details.  The solution is generally called chained initialization which looks rather odd at first but can reduce the amount of typing in complicated initialization scenarios.  Let’s create a simple empty panel in order to start explaining chaining:

TweakUtils::Panel myPanel = TweakUtils::Panel::Create( "My Panel" );

If that were hooked into the system and displayed it would be a default blue colored panel with white text and no content.  Nothing too surprising there, but let’s say we want to differentiate the panel for quick identification by turning it bright red with black text.  In a traditional initialization system you would likely have default arguments in the Create function which could be redefined.  Unfortunately given the number of options possible in a panel, such default arguments become exceptionally long chains.  Consider that a panel can have defaults for position, size, color, font color, font size, iconized or not, and even a potential callback to update or read data items it needs to function; the number of default arguments gets out of hand.  Chaining the initialization cleans things up, though it looks a bit odd as mentioned:

TweakUtils::Panel myPanel = TweakUtils::Panel::Create( "My Panel" )
  .Color( 200, 40, 40 )
  .DarkText();

If you look at the example and say “Huh???”, don’t feel bad, I said the same thing when I first discovered this initialization pattern.  There is nothing really fancy going on here, it is normal C++ code.  Color is a member function of Panel with the following declaration:

Panel& Color( uint8_t r, uint8_t g, uint8_t b, uint8_t a=200 );

Because Panel::Create returns a Panel instance, the call to Color works off the returned instance and modifies the rgba values in the object, returning a reference to itself which just happens to be the originally created panel instance.  DarkText works off the reference and modifies the text color, once again returning a reference to the original panel instance.  You can chain such modifiers as long as you want as long as they all return a reference to the panel.  At the end of the chain, the modified panel object is assigned to your variable with all the modifications in place.  When you have many possible options, this chaining is often cleaner than definition structures or default arguments.  This is especially apparent with default arguments where you may wish to add only one option but if that option were at the end of the defaults, you would have to write all the intermediates just to get to the final argument.

Adding a Button


With the empty panel modified as desired, it is time to add something useful to it.  For the moment, just adding a simple button which logs when it is pressed will be enough.  Adding a button also uses the initializer chaining though there is one additional requirement I will discuss after the example:

TweakUtils::Panel myPanel = TweakUtils::Panel::Create( "My Panel" )
  .Color( 200, 40, 40 )
  .DarkText();
  .Button( "My Button", []{ LOG( INFO ) << "My Button was pressed."; } ).End();

Using a lambda as the callback for button press, we simply log event.  But you may be wondering what the End function is doing.  When adding controls to the panel the controls don’t return references to the panel, they return references to the created control.  In this way, if it were supported, you could add additional settings to the button such as a unique color.  The initialization chain would affect the control being defined and not the panel itself even if the functions were named the same.  When you are done setting up the control, End is called to return the owning Panel object such that further chaining is possible.  So, adding to the example:

static uint32_t sMyTestValue = 0;
TweakUtils::Panel myPanel = TweakUtils::Panel::Create( "My Panel" )
  .Color( 200, 40, 40 )
  .DarkText();
  .Button( "My Button", []{ LOG( INFO ) << "My Button was pressed."; } ).End()
  .Variable< uint32_t >( "My Test", &someVariable ).End();

Adds an editable uint32_t variable to the panel.  Panel variables can be most fundamental types, std::string and the math library Vector2i, Vector3f and Quaternionf types.  With the Vector3f and Quaternionf types, AntTweakBar displays a graphical representation of direction and orientation respectively which helps when debugging math problems.  Further and more detailed examples exist in the XO application within the repository.

Note:  
The current implementation of the TweakUI is fairly preliminary which means that it is both dirty and subject to rapid change.  As with the configuration system, it gets the required job done but it is missing some features which would be nice to have.

An additional note, in order to prevent direct dependencies, the Vector and Quaternion types are handled in a standalone header.  If you do not desire them, simply do not include the header and there will be no dependencies on the math library.


Adding a Panel to the Screen


Adding a panel to the system can be done in a number of ways.  The obvious method is to create a panel, hook up a key in the input processing and toggle it from there.  This is perfectly viable and is in fact how the primary 'Debug Panel’ works.  I wanted something a little easier though and as such I added a quick (and dirty) panel management ability to the application framework itself.  The function RegisterPanel exists in the AppWindow class where you can hand a pointer to your panel over and it will be added to the ‘Debug Panel’ as a new toggle button.  At the bottom of the ‘Debug Panel’ in the screen shot, you see the ‘Joystick Debugger’ button, that button is the result of registering the panel in this manner.  It is a quick and simple way to add panels without having to bind specific keys to each panel.

Note:  
Currently the 'Debug Panel' is bound to the F5 function key and all panels default to hidden.  Pressing F5 will open/close the panel, which the first time will be very small in the upper left corner.  Move it, resize it and exit the application.  The next run it will be shown or not at the location and size of the last exit.

Additionally worth noting, the current panel creation may change to better integrate with other sections of code.  The chained initialization is likely to remain unchanged but the returned types may be modified a bit.


Conclusion


This article provides a brief overview of the configuration system I am using in my open source testbed tutorials project.  It is not a perfect solution, nor is it actually intended to be.  It sets out to solve a couple fairly simple goals with a few less-common items thrown in, all without trying to be 100% complete for every possible usage.  Only currently in-use items are fairly well tested and debugged and additions will be made only as needed or requested.

The supplied tweak UI is a good starting point until such time as you have your own UI items such as graphics and sound options.  Even after such items exist, the live tweak abilities of the debug panels are highly useful since a panel can be added quite quickly to test modified values during live gameplay.

Of course, it is always important to reiterate that the code is live and undergoing modifications continually.  Some of the information presented here may be out of date (and eventually updated) but hopefully with the overview it won’t be too far off.

Five Common Mistakes in Game Usability Testing And How To Avoid Them

$
0
0
A couple of weeks ago we held a massive game usability testing session at the Gamefounders game accelerator, the first of its kind in Europe. In this article I will share with you our experience from the testing sessions.

We didn´t expect to have so many test subjects and moderating the tests was a real challenge as you can see in the picture below.


testing-sessions-in-full-swing.jpg


The testing day consisted of two groups of twenty-five youngsters, average age about fifteen. What surprised us the most was their good verbal command of the English language (because they were Estonian and the tests were carried out in Estonia) and also their eagerness to let loose and just wreck the games completely.

What we did notice however was a general lack of knowledge in how to moderate the testing sessions. One may think it doesn´t matter how you ask the questions, but it does matter a great deal. Even the same question will bring you different answers, depending on how and when you presented them.

Without stalling too much, here are the most frequent testing errors and how to avoid them


Too much guidance


When you are moderating a testing session, try to talk about the game or app as little as possible. It is perfectly fine to be mute and not give the player any background information about the game at all.


draw-n-guess.jpg


Let them figure it out by themselves. Players need to understand the mechanics of the game from the moment of installation to the very first moment of playing it. If they don´t, then you have some work to do.

Assuming too much


Don´t assume the player always understands your in-game menu. Before testing the game itself, try to get the test subjects to speak about the menus and items in the game. Do the players understand what each setting and button does? How do they think they can interact with the items in the game or even options in the menu?

During the sessions I witnessed teams skipping past the start screen, which is a bad move. You might have usability errors in the system and not even know it.

Do check if the options also include easy mode and differed handicapped modes for players with disabilities. The options might change the colour scheme for players with colour blindness, enable closed captions for players who can`t hear and change the game pace for players with cognitive or mobility problems.

Testing with just one demographic


If you are making casual games which should appeal to several different age and gender groups then you should test the games with all of them. With learning games aimed at small children you might want to test the game with their parents who actually buy the games.

If they can´t understand the concept then chances are they won´t buy the game.

Talking too much


Don´t distract the players with too many questions and take them away from the game world.  Instead, ask them to play the game and verbalise their experience. Ask them what they are feeling at the moment and try to make the questions as open-ended as possible. Is something frustrating them? Is something triggering a strong emotional response?

The less you interrupt the player, the better. Try to limit the number of moderators to one per player. The player tends to get confused if suddenly somebody else starts asking the questions.


huebrix-the-game.jpg


Try to observe the body language – are they relaxed or tense, does their body react to certain actions in the game. When do they have that special glare in their eyes etc.

Not recording the sessions


Taking notes during the test sessions is a good thing, but do also record the actual tests. For games I suggest using a combination of a screen recorder (there`s a nifty app for iOS apps out which also records the face of the player with the inside camera) and a video camera aimed at the face of the test subject.

Couple this setup with a skin response sensor and you will have a great way of validating your test results.

Extra tip


Use skin response sensors and eye tracking tools if possible. The sensor, which works like a lie detector, will show you what the player is feeling by measuring strong emotional responses. If you are testing video games for Xbox or PS then there is also a sensor available, which is built into the game controller itself, giving you a nice non-intrusive way to test your game.

Should you need the maximum results then you can also use an eye tracking device for in-depth data.

Conclusion


That`s it for now. I hope you got some good input on how to organize your own testing sessions and remember to always test your game even while you´re still in development mode. The sooner you get the real customer input, the higher the overall success rate will be!

Tools of a Game Designer: What I use and What is out There

$
0
0
There are a variety of ways to go about designing a game. Luckily enough I’ve had enough projects to work on and enough freedom to try different ways to design them. Some ways have completely failed me and others have shown real promise. In this post I will discuss both the general design tools and methods that are out there as well as what works for me as a designer.

My basic template for designing a game is:

  1. Come up with the aesthetic(s)
  2. Find what dynamics support the aesthetic(s)
  3. Build mechanics that make the dynamics work
  4. Use iterative design to test how close my idea of the game is to the actual game
  5. Go through the entire game with player empathy in mind
  6. See what target market works best for the game
  7. Testing, testing, testing, and more testing

Before you start building your game you need to decide what the mechanics, dynamics, and aesthetics (MDA) are. It is generally suggested that you begin with your aesthetics first even though mechanics and dynamics are usually referred to first. I can confirm that moving from aesthetics to dynamics to mechanics works better in terms of overall game quality and consistency because I have tried both. When you think of aesthetics you might be thinking of how the game looks, but in this instance it actually refers to how the player feels when they play the game. Once you figure out what you want the player to feel when they play your game, you can figure out what actions they need to do to cause those feelings. The actions the player takes are called dynamics. For example, say I wanted the player to feel really sad or evil. To make the player feel sad or evil I might have a dynamic where they need to kill off one of their cute and loveable pets in order to do something. Remember that dynamics are pretty broad actions such as leveling up or attacking. After you’ve figured out your dynamics you can figure out the mechanics. The mechanics are the extremely detailed rules that dictate what exactly happens when an action takes place. Where dynamics are broad actions, mechanics are what specifically happens when the player does those actions. To go back to the “killing a pet” example, the mechanics for killing your pet might be that every time you kill one of your pets the other pets level up. Once I figure out my MDA I will immediately, if I haven’t already, make a prototype to test whether or not my mechanics and dynamics actually cause me to feel the desired aesthetic.

Making a prototype, testing it, documenting what was successful and what caused problems, and then making a new prototype that tries to fix those problems is called iterative design. Much like the scientific method it involves:

  1. Coming up with a prototype
  2. Playing and testing that prototype
  3. Recording data
  4. Looking at the data to make sure it supports the overall MDA and making note of the problems that cause it not to be successful
  5. Making a new prototype that attempts to fix those problems.

As a game designer, iterative design is my favorite method for solving problems and testing new ideas. At the end of the day, I can think all I want about what kind of an effect such-and-such a mechanic will have on the player, but you get a much better idea of what it will do once you actually implement and test it. While it might seem like it takes a lot of time away from the other elements of production, in the end it will help immensely. While you’re designing and prototyping the game you are actually making versions, or at the very least sections of the game, that can be used later in production. It allows your team to work together to make quick and to the point prototypes that will end up strengthening your team. This is especially helpful if the team or members of the team haven’t worked together yet. It will be much easier in the long run to have them make mistakes and learn how to work with one another on prototypes than on the polished version. Iterative design can be a very useful tool, but without having good player empathy, you will never be able to fully utilize it.

Player empathy is the ability to look and play your game through the eyes of a player and not someone who knows what you or anyone on your team knows about the game. It is the most important tool you can use as a game designer because what you think the player might do at any given point could be completely different from what they actually do. For this reason it’s very important to make sure you can see your puzzles and levels without the knowledge that comes with working on them. How you actually accomplish this is basically a form of roleplaying. For example, say I’m making a casual puzzle game and I’m currently trying to think of a control scheme and mechanic to use for it. At some point I think that a cool control scheme to use would be the typical one found in first person shooters. So W, A, S, D moves the characters and the mouse is used for looking in different directions as well as shooting in a specific direction. Now I ask myself, if I were the typical type of player that goes for casual puzzle games, would I be able to figure out this control scheme and would I be able to use it? If it wasn’t immediately obvious to me that the FPS control scheme was too complicated for that particular type of game and I wasn’t really sure what casual players were used to I would try to play every popular casual game and then the unpopular casual games.  While playing those games I would make note of what the norm and popular game elements are as well as what the unusual and unpopular game elements are. Those points of data would hopefully give me enough information to look at my idea through the eyes of a casual player. When using player empathy I try to ask myself these general questions first:

  1. Will they be able to understand and play it?
  2. Will it be fun to a particular type of play style?

After I answer the general questions, more specific questions come up based on what type of player I am looking to test or more likely what type of game I’m trying to make. If I’m designing a FPS/RPG I will make sure that the RPG elements in the game are fun and make sense to FPS players and that the RPG players will be able to have fun and understand the FPS elements. Depending on who your game is for you will most likely need to pay attention to more than one type of player that will play your game. If you just look at your game through one particular play style or worse, what kind of player you are, then you’re not getting a good sense for how the elements in your game will be received. It’s important to remember that what types of players you base your decisions on will ultimately dictate what target market the gameplay is targeted for.

When you release a game it can be very nerve wracking to see how many people play it and what kind of feedback you get. To get the biggest amount of people to play your game you might want to make your game as generally appealing as possible. However, I would advise against it, because most of your time will be used to make sure that there is something for everyone in your game rather than making a consistent and high quality experience. If you were to make a generally appealing game you would have to make sure the gameplay is easy enough for new players while keeping in mind that hardcore players will want it to be challenging. You would need to make sure that the theme of the game appeals to everyone, which means doing lots and lots of research and focus testing just on the particular theme that you’re using. All the time you spend on making the game appealing to the masses is wasted, because after all that work is done, you still don’t have a game. All you would have is a whole lot of constraints, a lot less time, a story or aesthetic that you might not even care about, and a hell of a lot of play testing to do. Now if you start instead with a specific target market in mind or if you let the MDA dictate what specific target market would find the game appealing then you’ll be able to test with those players in mind and you will hopefully enjoy what you’re doing a lot more. Having a specific target market will allow you to focus on making a game that is tailored to a narrow audience. You might not get as many players, but what players you do get will have a high quality game that is meant for them. The best way to get a target market is to let the game’s development and direction dictate what target market you’re going for. It might seem backwards, but waiting for the game to take shape to see what target market it suits gives you more time for development and allows you to make the game how it should be made, instead of changing it to suit a particular market. This is especially helpful if the direction the game is going is something important to you. You’re even likely to put more polish, time, sweat, blood, tears, and thought into it then if you were just worried about selling one million copies. With this in mind, don’t wait till the project is close to shipping to choose a target market. You should choose one fairly early because it lets you focus your testing on specific types of problems rather than trying to accommodate every type of play style and person out there.

You and other people on your team should begin testing it as soon as you have a working prototype. During the tests you need to make sure you or someone else is documenting everything that works and everything that doesn’t work. The data you should collect should range from where on the level they died or failed the mission to what mechanic is being used the most. All this data will help you in making decisions and course corrections later in the production timeline. For example, say you have a variety of weapons in your game and are trying to find what weapons are working and what aren’t. Testing finds that one of the weapons, Light Pistol, is being used less than 1%. Less than 1% would dictate that a drastic change needs to occur. It might be better to take the weapon out completely to reduce the amount of time your art department spends on texturing, modeling, and polishing it. However, if the Light Pistol was extremely important to the story or the game in some way, than you might want to make it more powerful. Making sure you organize the data is also important. Using software such as Excel or Google Analytics will help to make all the data you collect actually useable to the people that need it. Without organizing the data, people will be unable to make any sense of it or find specific points of data that applies to them. Along with testing within the team you should get people that have never heard or played the game before to play it. Make sure that you don’t help public play testers with the game at all. You won’t be around when someone 5,000 miles away plays your game and isn’t sure what to do so it’s better to let play testers make mistakes. When players make mistakes or are unable to do something in game, it shows you what needs to be fixed. After play testing has finished, review the data and try to solve the problems that came up. If it isn’t immediately obvious what needs to be done to solve a problem, try making a few prototypes with different fixes. Then test those prototypes to see which fix is the most successful. Be sure have a questionnaire ready for them to answer after they finish play testing. Questionnaires are important because it allows you to see if your observations were correct and to gather data that you can’t observe, such as if they would play again. You’ll need to test for a lot of things to make sure your game is accessible and entertaining, but something paramount to a game’s success is flow and immersion.

Flow is the concept of making sure the game has enough challenge to meet the skills of the players that play it. Have too much challenge and the game is frustrating and difficult. Have too little challenge and the game is boring and no fun to play. Immersion is the idea that a player will constantly believe that they are in the world that the game is portraying and will forget that they are playing a game. Obvious ways that immersion is broken include when the game crashes or has glitches. More subtle ways of breaking it include having inconsistent art styles between the cut scene graphics and the game engine graphics, as well as taking control from the player during a cut scene. With flow you can help both how entertained they are and how immersed they are in the game world. One way immersion is gained with flow is when the player enters the flow zone. The player is in the flow zone when the challenge of the game meets the skill of the player. In the flow zone they are more immersed in the game and will sometimes lose track of time. This loss of time is due to the game being difficult enough to require they pay attention, but not so difficult that they are constantly reminded that they are playing a game. If you’ve ever started playing a game at some point during the day and looked up to notice it’s now nighttime and somehow 4 hours have passed then you have been in the flow zone. The idea of having good flow could be summarized in making sure the attention of the player stays on the game. However, when you design elements that improve immersion and make sure the game allows the player to enter into the flow zone, than the player will have more believability and trust in the game world. Ultimately this trust and believability will help in portraying the story of the game and will cause the player to be more susceptible to the emotions you set out to cause. If you’d like to learn more about flow then I recommend reading Flow: The Psychology of Optimal Experience by Mihaly Csikszentmihalyi. If you’d like to read more about how flow applies to game design then I recommend reading Jenova Chen’s thesis, Flow in Games.  A new technique, that is slowly gaining steam, called dynamic difficulty adjustment helps with flow by changing how difficult the game is based on the skill of the player.

Dynamic difficulty adjustment (DDA) is the process of changing how difficult the game is on the fly. There are numerous systems around that deal with DDA and one such system involves taking input from the player such as health lost, accuracy, time it takes to solve a puzzle as well as many others. After the system records this data it then changes the later difficulties in the game to meet those data points. The problems with it, pointed out by Jenova Chen in this thesis on flow, is that the system doesn’t know if the data it is collecting is representative of the actual skill of the player. Say you’re playing a game and you decide that you want to get to the top of a specific building or mountain just to see if you can. While doing this the system would see that it’s taking a lot of time for you to finish an objective and if you’re avoiding enemies it might think that you don’t know how to deal with them. Trying to help you, the system might change the next level to be easier to navigate and populate it with enemies that are easier to beat. While I love the idea of DDA, the obvious problems with it keep me from trying to implement it in any games I make. What you can take from DDA, flow, and player empathy is that building up to more difficult areas can sometimes help players become more and more experienced with the game. This technique doesn’t help players that struggle to get through the first few levels. It also doesn’t help players that breeze through a majority of the levels and find the last few levels extremely boring. Use that technique sparingly and change how quickly it ramps up in difficulty based on testing and your target market. Using a dynamic difficulty system by itself in your own project will most likely be too time consuming with how much you will need to tweak it. Hopefully companies will crop up whose purpose it is to produce and update a DDA system that a game development company can then buy and use within their game. Much like companies that produce physics or animation engines that game developers buy for their games, these completed and updated DDA systems would allow the game developer to work more on the game and less on the technical aspects of it. Whatever tools you use to design and develop your game, don’t be afraid to try ones that you aren’t familiar with.

The great thing about game design and development is that since it is fairly new, compared to other mediums of expression, it has a lot of room to grow. Due to this growth, new ways to design and develop crop up all the time so don’t be afraid to try different methods of design, because you never know what might work for you. Just keep in mind that what decides if your game is liked or not is how much effort you put into the production of the game. Ideas are cheap, whether or not the player gets the concept, is able to play it, and is entertained by it is due to your player empathy and how well you use game design and development tools.
Viewing all 17825 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>