Developing a Game: SamuraiDuel

Now-a-days, I am developing a game called SamuraiDuel. It is going to be a 2D game and being built on OpenGL, SDL2, Box2D and CEGUI all in the language, C++.

SamuraiDuel Title
SamuraiDuel Title

Before starting to develop the game, I first developed the base of a very low level Game Engine which I should call a GL Engine, GL SDK or something like that, in order to work with OpenGL with ease. Of course, I called it BAC GL Engine 2 (I tried to make one before but it has some big flaws and so, I put ‘2’ this time after the name).

I am not satisfied with that name. If you had one in your mind, please do comment below.

SamuraiDuel is going to be a side scroller fast paced pixelated game. Of course, it will take time to get completed and once it is completed, this is the place where I will confirm this.

There is the screenshot of the game! I hope that you like that…

SamuraiDuelDevelopment4

All pixel arts are made by me and I think it looks fair.

That’s all that I have to say! If you want some features in it or just has something to tell, comment below and tell that to me! It will be really appreciable.

UPDATE: The project is closed and is no more under development due to lack of funding and maybe, motivation. Sorry guys! But who knows… I might complete it someday!

C++ Programming Series: References

I believe that my series is getting complex with every post being published! This has to be done because we should also be getting more complex and more logical with every topic we discuss.

Today’s topic is References. Before proceeding on, let us discuss few problems with functions. The first one is that we don’t know any methods of getting multiple outputs. The second one is that we don’t make any change in the variable that we pass into the function via parameters.

The following code expresses the second problem with functions:

void multiplyBy2(int variable)
{
  variable *= 2;
  //No returning
}

int main()
{
  int variable = 2;
  mulitplyBy2(variable); //This should change the variable's value to 4
  cout << variable << endl; //Prints 2, not 4
  return 0;
}

NOTE: We can have same names for variables having completely isolated scopes. Note that multiplyBy2 has a parameter called variable and main function also has a variable called variable. Sounds confusing!

We have a solution for that and that is, to return that variable in the function and then, put that into any variable or just call that temporary return value directly.

But we expect the method above to change the variable’s value which is not the case here! Why? Well, the point is that when we pass the variable via the parameter of the function, we are actually copying that variable into another completely new variable. This new variable has a very limited scope i.e we can only access it inside the function.

Let us discuss a very simple example of what copying is:

int value1 = 2;

int value2 = value1; //Here, value1 is copied into value2
value2*=2; //value2 is a different variable; it will not effect value1 in any case!

cout << value1 << endl; //Prints 2, not 4
cout << value2 << endl; //Prints 4

The highlighted codes shows what is actually happening in the function, multiplyBy2() in the example, given above.

How to do it in the way that we want? The answer is right inside the topic of this post: References. There is another way and that one is through Pointers which is way more complex but we will discuss it later on.

What is a reference? Reference is just another name given to the same variable. In our real life, we can have the reference case of a bird called ‘raven’. Raven is a black bird. So, people can refer to ‘raven’ by calling it as ‘black bird’. In a very similar way, variables can have references as well.

//Consider that there is a bird called 'raven'
int raven = 10;

//That 'black_bird' is a reference to 'raven' 
int& black_bird = raven;

//Now, what we do with 'black_bird' is actually,
//what we are doing with 'raven' as well and vice versa...
black_bird*=2; //Both gets 20
raven+=5; //Both gets 25

cout << raven << endl; //Prints 25
cout << black_bird << endl; //Prints 25

The highlighted line shows how to make reference to a variable. It is pretty simple; just put ampersand or ‘&’ after the type of the variable that we are going to refer to.

int& is considered a type which we can call as ‘reference to an integer’. Same will be for any type reference as well.

Time to make some change in the multiplyBy2() function!

//Notice the ampersand before the variable's name
void multiplyBy2(int& variable)
{
  variable *= 2;
}

int main()
{
  int variable = 2;
  mulitplyBy2(variable); //Now, we are not copying, we are referencing!
  cout << variable << endl; //This time, it prints 4
  return 0;
}

Now that, the second problem is solved, the first problem is solved as well. We can have multiple outputs by having more parameters to the function. These parameters are going to be references and whatever is going to be changed with these references, this change is going to happen with the actual variables which are passed as parameters in the function.

//The first two parameters represent inputs
//and the next three represent outputs
void get3TimesDivision( float number1, float number2,
float& division1, float& division2, float& division3 )
{
  division1 = number1 / number2;
  division2 = division1 / number2;
  division3 = division2 / number2;
}

int main()
{
  //Multiple Outputs using References
  float div1 = 0.0f, div2 = 0.0f, div3 = 0.0f;
  get3TimesDivision( 8.0f, 2.0f, div1, div2, div3 );

  cout << div1 << endl; //Prints 4
  cout << div2 << endl; //Prints 2
  cout << div3 << endl; //Prints 1

  return 0;
}

Note the point that where we want to have references, we cannot have constants or temporary values there. In the above case, if the parameters, number1 and number2, are references to float, we cannot pass 8.0f and 2.0f into the function. We must pass variables of type float with the respective values, into the function.

That’s all! References are a great way to deal with outputs. Just try to modify all the previous functions that we created together, to have references and not copies. Practice them very well. They are going to be used extensively!

C++ Programming Series: Headers and Prototypes (Part 2, Last)

In this post, we are going to discuss some confusions that you might have got in the previous post. You might have read #include "func.h" in that post and not #include <func.h>. Actually, both have different meanings!

If we type angle brackets (<>) instead of double quotes (“”) for func.h, the compiler will check for that file in the C++ base files directory and project specified include directory. From C++ base files, I mean those files which also includes the most commonly used iostream, math.h, string, etc, that are the files of standard C++. All these C++ standard files are header files although they may not have .h at the end of their names.

If we type double quotes as in the previous post, the compiler will check for that file in local project directory. This directory is the same directory where the IDE adds all our files to.

In a nutshell,

  • #include <file_name> – searches the file in base and project specified include directory.
  • #include “file_name” – searches the file in local project directory.

Now, we know what double quotes and angle brackets do with #include. But we actually, don’t know what #include do! #include simply, copy the codes from the file and then, paste it into that file where it is called.

This is something that we don’t need to know. What we need to know is the fact that C++ don’t allow more than one definitions. You can’t just do like that:

void func()
{
  //code here...
}

//Another time: gives error!
void func()
{
  //code here...
}

It might be possible that we include things twice or, the other and most common case is that the file that we are including, includes another file that is already included in our file! To make it clear, see the code below:

#include "a" //'a' file contains function 'func()'
#include "b" //'b' file includes file 'a'
//'func()' is defined twice
//So, gives error!

That hash(#) before the include suggests that the command after it, is a preprocessor directive and not a C++ code. These directives runs before the compilation of the actual program. There are many of these. You can check out preprocessor directives in details here.

In order to make sure that something is defined just once, you can use preprocessor directives like that:

#ifndef SOMETHING //This means 'if not defined preprocessor term called SOMETHING'
#define
  //code here
#endif //This ends the '#ifndef' statement

The above code just acts similar to the C++ if-statement that we discussed before.

SOMETHING can be anything. It can be an integer, a group of characters, a float, etc.

#define PI 3.14 //Now, PI is equal to 3.14

int main()
{
  cout << PI << endl; //We can use it as a regular double
  PI++; //Gives error; preprocessor definations are constants!
  return 0;
}

I hope that you got all of the above things. Just practice using headers and prototypes. Find errors and then, try to fix them yourself. I got a new exciting series called My Pixels where I have showcased some of my hand drawn pixel arts or sprites! Just check that out and see ya!

My Pixels: Lonely Jug

Hmmm… Guess what? Another Pixel Art! This time, the grid size is 128 by 128, not 64 by 64! It gets 4 times longer and lengthier (and so, harder as well) to get a good pixels on the go! I found myself, not very good with bigger and tiny grid sizes! This time, not so special! Just a lonely jug on the straw…

Grid Size: 128*128

Lonely Jug Pixel Art
Lonely Jug

I also make a low resolution version of it, by using linear interpolation. It may look better to you than the above one!

Grid Size: 64*64

Lonely Jug (low resolution) Pixel Art
Lonely Jug (low resolution)