A Change Of Direction

Last week we decided that producing a clone of Garry’s Mod’s Prop Hunt wasn’t the best idea, because during Prop Hunt the Prop Team has to find an object, and switch their controls to that object and then hide with it. The problem is that we couldn’t find a straight-forward way to switch the player’s controls to another object, mainly because a lot of the player input seems to rely on the model having physics for different body parts such as legs and arms.

Due to this, we have decided to switch the game idea to a Hide and Seek variant. The reason we chose to do this is because it’s relatively similar to our original idea, so we won’t lose too much progress.

We have also now set up Trello for project management, this should help us make some serious progress over the Semester, as long as we keep tasks cycling each week. So far I think it’s has really helped productivity.

I will be posting more blog posts on the production of the game as time goes on!

History of Hero Engine

heroenginelogotransparent

Early Days

There isn’t much on the roots of HeroEngine out there to find out about, but from what I have found by scouring the web, HeroEngine started development in ~2004 by Simutronics as an in-house MMO engine for their game ‘Hero’s Journey’. After showing Hero’s Journey off at various Game Developer’s Conferences (Gdconf.com, 2016), developers of other various studios started to take interest in how the game was made (Wood, 2009).

A New Licensee

In 2006, Simutronics realised that there was just as much interest in how Hero’s Journey was built as there was interest in the game itself, so they decided to split their team up and set one side to developing the game and the other to the engine. Soon after that, BioWare also started using the engine to start developing Star Wars: The Old Republic (Boyer, 2007).

New Ownership

In 2010, Simutronics sold HeroEngine to Idea Fabrik, and Idea Fabrik also hired all of the stuff currently working on Hero Engine (Simutronics Corp, 2016). Since then, Simutronics has focussed on developing mobile games.

Evolution

In 2012, Idea Fabrik released Hero Engine 2, which included a number of upgrades including graphics tool updates, engine framework improvements and multiplayer system updates. It also included the option to purchase a license from the website for $99 per year (Ideafabrik.com, 2012). This version was known as Sapphire (Wiki.heroengine.com, 2016). In 2014, the engine continued to develop and has currently evolved to the next version, Quartz (Wiki.heroengine.com, 2016). Boasting the ‘Realtime Collaborative Platform’ unique feature, allowing multiple developers to work on a game world on the cloud at the same time, Idea Fabrik seem to have high hopes for it’s future, with the next release, Amethyst, already being planned.

Bibliography

Gdconf.com. (2016). GDC 2017 | February 27 — March 3, 2017 | Moscone Convention Center | San Francisco, California. [online] Available at: http://www.gdconf.com/ [Accessed 14 Nov. 2016].

Wood, J. (2009). Hero’s Journey – Update on Hero Engine and Hero’s Journey. [online] MMORPG.com. Available at: http://www.mmorpg.com/heros-journey/progress-reports/update-on-hero-engine-and-heros-journey-1000002883 [Accessed 14 Nov. 2016].

Boyer, B. (2007). GDC: Simutronics’ HeroEngine Gets Three Licensees. [online] Gamasutra.com. Available at: http://www.gamasutra.com/php-bin/news_index.php?story=13088 [Accessed 14 Nov. 2016].

Simutronics Corp. (2016). About Us. [online] Available at: http://www.simutronics.com/about-us.html [Accessed 14 Nov. 2016].

Ideafabrik.com. (2012). HeroEngine 2 Unveiled. [online] Available at: http://www.ideafabrik.com/news/heroengine-2-unveiled [Accessed 14 Nov. 2016].

Wiki.heroengine.com. (2016). HeroEngine Sapphire – HEWIKI. [online] Available at: http://wiki.heroengine.com/wiki/HeroEngine_Sapphire [Accessed 14 Nov. 2016].

Graphics Assignment 1 – Simple OpenGL Application

Introduction

Over the Christmas holidays I developed an OpenGL application to show off some of the basic concepts in OpenGL including graphical primitives, transformations, textures and lighting. This blog post will be an overview of how I used each of these concepts, problems I had with them and alternative methods I think would have been better to use.

Primitives

Primitives are shapes that the GPU can read and manipulate directly, some examples include Triangles, Polygons, Points and Lines.

I constructed a square-based and triangle-based pyramid using the triangles, as well as some buttons from polygons. The code below shows how I created the square-based pyramid:

void drawSquareBasedPyramid()
{
 glBegin(GL_TRIANGLES);

     glVertex3f(0.f, 1.f, 0.f);
     glVertex3f(-1.f, -1.f, 1.f);
     glVertex3f(1.f, -1.f, 1.f);

     glVertex3f(0.f, 1.f, 0.f);
     glVertex3f(-1.f, -1.f, -1.f);
     glVertex3f(1.f, -1.f, -1.f);

     glVertex3f(0.f, 1.f, 0.f);
     glVertex3f(1.f,-1.f,-1.f);
     glVertex3f(1.f,-1.f,1.f);

     glVertex3f(0.f, 1.f, 0.f);
     glVertex3f(-1.f, -1.f, -1.f);
     glVertex3f(-1.f, -1.f, 1.f);

 glEnd();
}

I believe this method of rendering is called ‘Immediate Mode rendering’ and is an inefficient implementation since the program cannot send any data to the GPU before the glEnd() function is called. A better way to accomplish this task would be to use Vertex Buffer Objects (VBOs). This works as a normal buffer of data, except that once it has been filled, OpenGL then handles it instead of the program, and OpenGL will send it to the GPU as soon as the bus is free. This will allow the render thread to run asynchronously with the GPU and improve performance drastically. (Stackoverflow.com, 2011)

However, Immediate Mode has the benefit that is very simple to use, so good for beginners like myself to start off learning from.

Transformations

I didn’t use transformations too much, because I wasn’t sure if it was possible to transform objects individually, so instead I just rotated the entire scene and used translation to move the objects that are being rendered away.

Each time the display() function was called, a variable ‘angle’ was incremented until it 360, at which point it was reset to 0.

if (angle == 360)
{
angle = 0;
}
else
{
angle = angle + 0.5;
}

I then rotated by ‘angle’ and translated the scene away from the camera with the following lines of code:

glTranslatef(0.0f, 0.0f, -7.0f); // Positions the scene further away on Z-Axis.
glRotatef(angle, 0, 1, 0); // Rotates the scene by 'angle'.

I think a better method would be to use GLM, the OpenGL Math Library (Glm.g-truc.net, 2017) to do transformations which probably would have been more simple to rotate objects individually, however I had never used this before and didn’t want to dive in to something new since I was already pushed for time.

Textures

I textured my buttons with Bitmap images that I created. I used the DevIL image library in order to create textures from these images and map them to vertices.

This is the code I used to turn the images I created in to textures in my application:

// Create references to images stored.
GLuint buttonTextures;
GLuint buttonPrimitives;
GLuint buttonLighting;
GLuint buttonTransformations;

void initTextures()
{
 // Set texture parameters
 // Wrapping parameters
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

 // Filtering parameters
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);

 // Loading the files.
 buttonTextures = ilutGLLoadImage("..\\Images\\ButtonTextures.bmp");
 buttonPrimitives = ilutGLLoadImage("..\\Images\\ButtonPrimitives.bmp");
 buttonLighting = ilutGLLoadImage("..\\Images\\ButtonLighting.bmp");
 buttonTransformations = ilutGLLoadImage("..\\Images\\ButtonTransformations.bmp");

 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}

I then created the buttons and mapped the texture UV coordinates to the button vertices:

void drawButtons()
{
 glEnable(GL_TEXTURE_2D);

 // Texture Button
 glBindTexture(GL_TEXTURE_2D, buttonTextures);
 glBegin(GL_POLYGON);
 glTexCoord2f(0.0f, 0.0f);
 glVertex3f(-0.3f, -0.8f, 1.0f);
 glTexCoord2f(0.0f, 1.0f);
 glVertex3f(-0.3f, -0.6f, 1.0f);
 glTexCoord2f(1.0f, 1.0f);
 glVertex3f(0.3f, -0.6f, 1.0f);
 glTexCoord2f(1.0f, 0.0f);
 glVertex3f(0.3f, -0.8f, 1.0f);
 glEnd();

 // Primtive Button
 glBindTexture(GL_TEXTURE_2D, buttonPrimitives);
 glBegin(GL_POLYGON);
 glTexCoord2f(0.0f, 0.0f);
 glVertex3f(-0.3f, -0.5, 1.0f);
 glTexCoord2f(0.0f, 1.0f);
 glVertex3f(-0.3f, -0.3, 1.0f);
 glTexCoord2f(1.0f, 1.0f);
 glVertex3f(0.3f, -0.3, 1.0f);
 glTexCoord2f(1.0f, 0.0f);
 glVertex3f(0.3f, -0.5, 1.0f);
 glEnd();

 // Lighting Button
 glBindTexture(GL_TEXTURE_2D, buttonLighting);
 glBegin(GL_POLYGON);
 glTexCoord2f(0.0f, 0.0f);
 glVertex3f(-0.3f, -0.2, 1.0f);
 glTexCoord2f(0.0f, 1.0f);
 glVertex3f(-0.3f, 0.0, 1.0f);
 glTexCoord2f(1.0f, 1.0f);
 glVertex3f(0.3f, 0.0, 1.0f);
 glTexCoord2f(1.0f, 0.0f);
 glVertex3f(0.3f, -0.2, 1.0f);
 glEnd();

 // Transformation Button
 glBindTexture(GL_TEXTURE_2D, buttonTransformations);
 glBegin(GL_POLYGON);
 glTexCoord2f(0.0f, 0.0f);
 glVertex3f(-0.3f, 0.1, 1.0f);
 glTexCoord2f(0.0f, 1.0f);
 glVertex3f(-0.3f, 0.3, 1.0f);
 glTexCoord2f(1.0f, 1.0f);
 glVertex3f(0.3f, 0.3, 1.0f);
 glTexCoord2f(1.0f, 0.0f);
 glVertex3f(0.3f, 0.1, 1.0f);
 glEnd();

 glDisable(GL_TEXTURE_2D);
}

I think this method of creating textures was quite nice, however I think if I was to use other file formats such as PNG I would prefer to use the library paired with that image format, in this case it would be libPNG (Libpng.org, 2017). DevIL (Openil.sourceforge.net, 2017) is rarely updated and therefore it might not use the latest techniques in achieving best performance, for that reason it might be a good idea to look for a library that is updated more often too.

Alternative generic image libraries include SOIL (Lonesock.net, 2017) and FreeImage (Freeimage.sourceforge.net, 2017).

Lighting

I had a lot of trouble with lighting, and still feel like I need to practise it some more, but I did manage to get a half-working prototype although it could have been a lot better.

I initialised some basic colours and then set up the lighting here:

 
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
 glEnable(GL_LIGHTING);
 glEnable(GL_LIGHT0); // Turns on Light0.
 glEnable(GL_COLOR_MATERIAL);
 GLfloat qaAmbientLight[] = { 0.2, 0.2, 0.2, 1.0 }; // ambient light intensity
 GLfloat qaDiffuseLight[] = { 0.8, 0.8, 0.8, 1.0 }; // diffuse light intensity, note: ambient light intensity + diffuse light intense should = 1.
 GLfloat qaSpecularLight[] = { 1.0, 1.0, 1.0, 1.0 }; // specular light intensity
 glLightfv(GL_LIGHT0, GL_AMBIENT, qaAmbientLight); // Define ambient light behaviour
 glLightfv(GL_LIGHT0, GL_DIFFUSE, qaDiffuseLight); // Define diffuse ambient light behaviour
 glLightfv(GL_LIGHT0, GL_SPECULAR, qaSpecularLight); // Define specular light behaviour

I then created a standard radial light using this code:

 GLfloat qaLightPosition[] = { 1.0f, 1.0f, -5.0f, 1.0f };
 glLightfv(GL_LIGHT0, GL_POSITION, qaLightPosition); // Set properties for Light 0: Position = qaLightPosition.

I had problems with the rendering such that the pyramids would have the ambient colour but every rotation they would flash with the white, I think it might be due to the normals on the pyramids not acting right, however I spent a lot of time trying to get it to work properly by readjusting the lights position and trying to change the normals on the pyramids however it didn’t help.

I think this method was probably the right approach, but I wasn’t entirely sure on why I was having the problem. Alternative approaches include rewriting the default fragment shader, but we haven’t covered shaders yet so I didn’t want to touch them for now.

User Input

For user input, GLUT provides a nice callback function each time a mouse event occurs. So I could simply define that callback function like this:

void OnMouseClicked(int button, int state, int x, int y)
{
 // LMB pressed
 if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
 {

 }
 // RMB pressed
 if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
 {

 }

 // LMB released
 if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
 {

 }
 // RMB released
 if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
 {

 }
 std::cout << "Moused Pressed at: " << "x:" << x << " y:" << y << std::endl;

}

This allowed me to customise what happened on mouse events very well. An alternative approach would be to use a separate library specifically for handling input such as Gainput (Gainput.johanneskuhlmann.de, 2017) or SDL (Libsdl.org, 2017), and I think this would be a better approach because encapsulating the rendering logic and the user input logic makes more sense than combining them.

Bibliography

Stackoverflow.com. (2011). What does “immediate mode” mean in OpenGL?. [online] Available at: http://stackoverflow.com/questions/6733934/what-does-immediate-mode-mean-in-opengl [Accessed 12 Jan. 2017].

Glm.g-truc.net. (2017). OpenGL Mathematics. [online] Available at: http://glm.g-truc.net/0.9.8/index.html [Accessed 12 Jan. 2017].

Libpng.org. (2017). libpng Home Page. [online] Available at: http://www.libpng.org/pub/png/libpng.html [Accessed 12 Jan. 2017].

Openil.sourceforge.net. (2017). DevIL – A full featured cross-platform Image Library. [online] Available at: http://openil.sourceforge.net/ [Accessed 12 Jan. 2017].

Lonesock.net. (2017). lonesock.net: SOIL. [online] Available at: http://www.lonesock.net/soil.html [Accessed 12 Jan. 2017].

Freeimage.sourceforge.net. (2017). The FreeImage Project. [online] Available at: http://freeimage.sourceforge.net/ [Accessed 12 Jan. 2017].

Gainput.johanneskuhlmann.de. (2017). Gainput: C++ game input library. [online] Available at: http://gainput.johanneskuhlmann.de/ [Accessed 12 Jan. 2017].

Libsdl.org. (2017). Simple DirectMedia Layer – Homepage. [online] Available at: https://www.libsdl.org/ [Accessed 12 Jan. 2017].

 

 

Initial Plan For The Game

As a team we are planning on building a variant of the popular Garry’s Mod game Prop Hunt using the relatively underground Hero Engine.

I was assigned to build the mechanics of the hunters. That includes creating the objectives of the hunter team, the actual mechanics that only the hunters specifically can execute, and the win condition for the hunters.

Objectives-wise the hunters have to seek out the props after being blind-folded for a set amount of time. Once one of the hunters spot a prop, they will have to eliminate the prop by a means that we are still discussing. In Garry’s Mod the hunter is equipped with an assortment of weapons to shoot at props to lower their health. However we are not sure if we will have the time to implement a system like this. Once all the props have been eliminated the hunters will win, but if the a timer that runs while the round progresses reaches 0, the hunters will lose.

Hunters are built primarily to seek out and destroy props, so the mechanics will solely be around this aspect. Therefore, if Hero Engine’s movement system seems at all clunky we may have to look at a way of tweaking it, or if it comes to it, replacing the movement system if possible. There also needs to be a way of removing the props from play via damage or another means. We are still discussing this aspect and I will post about it in future blog posts.

The win condition of hunters is simply when all the props are eliminated, the hunters win. We will implement a global count of current props and hunters that are alive and then base the win condition from this.

Thanks for reading and I will produce more development blog posts in the future!