Cameron Nicoll's DevBlog
Sunday, 14 February 2016
Wednesday, 3 December 2014
Game Engines Blog #5: 2LoC too many?
Alright so for my final blog I'm going to do something that I have no doubt that many of my classmates have already done: My personal gripes with 2LoC and what I would do to change it. Without further preamble, let's dive headlong into it!
Camera
First things first, setting up the camera is a massive chore to me. It's the kind of thing where you don't need to make a lot of cameras unless you're doing some special effects (i.e. reflection) so setting up a function to make it easier feels like it might me spending more time making a solution than you do on the actual problem. For an idea of why I might hate the camera, here's sample code to get a perspective camera working:
cameraEnt =
pref_gfx::Camera(m_entityMgr.get(), m_cpoolMgr.get())
.Near(1.0f)
.Far(1000.0f)
.VerticalFOV(math_t::Degree(60.0f))
.Position(math_t::Vec3f(0.0f, 5.0f, 5.0f))
.Create(m_win.GetDimensions());
{
//Set camera settings
math_t::AspectRatio ar(math_t::AspectRatio::width((tl_float)m_win.GetWidth()),
math_t::AspectRatio::height((tl_float)m_win.GetHeight()));
math_t::FOV fov(math_t::Degree(60.0f), ar, math_t::p_FOV::vertical());
math_proj::FrustumPersp::Params params(fov);
params.SetFar(1000.0f).SetNear(1.0f);
math_proj::FrustumPersp fr(params);
fr.BuildFrustum();
cameraEnt->GetComponent<gfx_cs::Camera>()->SetFrustum(fr);
}
Now, setting all the variables such as field of view, near and far during the camera construction only to have to re-declare this stuff when making a frustum feels REALLY redundant. I would think that setting this stuff up in the camera would automatically handle setting up the frustum during creation. Now you might say "Oh you have no indicator to set it as perspective, that's why!" Well, there is a function where you set perspective with a boolean value, but this doesn't seem to do anything. Overall it makes the whole process of making a camera, one of the most necessary entities in a game, feel like it has six more lines than it should while being simultaneously unintuitive as I don't think most users would think to create a frustum at this point in creation of the game.
Shader Limitations
Next up is the limitations on how you can use shaders with 2LoC. Creating materials and such is actually pretty simple and I do like it...But being unable to access the geometry shader (as well as the other lesser known ones) ends up hampering development. Case in point: Dealing with particles. Normally for a particle you could just send in a single vertex and then create a quad in the geometry shader allowing for things to be much more efficient in terms of calculations since you just have to apply physics calculations to the single vertex in the shader versus doing it 4 times (assuming you have vertex indexing in the engine!) on each corner of a quad. So this not only becomes a limitation of what one can do with shaders, it also becomes a limitation of how efficient you can make your processes and hurts development in the long-run!
General user unfriendliness
There's a few other problems I can go into such as the extensive namespaces which make dealing with things difficult (I have had many times where I couldn't copy a material over to another material because as it turns out material 1 is in namespace and material 2 is in a different one...Despite both being materials) as well as things that the engine could benefit from but doesn't have for school reasons (i.e. Scripting and Particles) but above all else is just how obnoxious the engine can be to use. There are a lot of tricks that you need to sort of work out for yourself in order to get some things to work and it might be easier if we had some rudimentary documentation to go by (i.e. A list of what the different functions do) but without this it makes it very challenging to work out how to do what should be very simple things. For example, when I create an entity during runtime its mesh and material won't appear unless I call the appropriate systems and say "Initialize(ent)". I would not have guessed that I need to do this until a friend pointed it out to me.
Overall, the engine seems to suffer from a serious problem in that it's usable once you have become used to (which isn't really praise since it can apply to ANYTHING) the engine but it's very unfriendly to new users and would benefit from a bit of documentation to go with the samples provided. Even something as simple as "Here is a list of basic functions you should know but aren't immediately found and what they do:" Just to provide users with the ability to easily reference something like they would with Unity's documentation. In the end, the engine has a long way to go before I'd say it would work well as an engine for general use.
That's it! Sorry if I seem a little bit harsh but this engine has bitten me too many times to count and has left me a bit miffed. I hope you enjoyed the read, cheers!
Camera
First things first, setting up the camera is a massive chore to me. It's the kind of thing where you don't need to make a lot of cameras unless you're doing some special effects (i.e. reflection) so setting up a function to make it easier feels like it might me spending more time making a solution than you do on the actual problem. For an idea of why I might hate the camera, here's sample code to get a perspective camera working:
cameraEnt =
pref_gfx::Camera(m_entityMgr.get(), m_cpoolMgr.get())
.Near(1.0f)
.Far(1000.0f)
.VerticalFOV(math_t::Degree(60.0f))
.Position(math_t::Vec3f(0.0f, 5.0f, 5.0f))
.Create(m_win.GetDimensions());
{
//Set camera settings
math_t::AspectRatio ar(math_t::AspectRatio::width((tl_float)m_win.GetWidth()),
math_t::AspectRatio::height((tl_float)m_win.GetHeight()));
math_t::FOV fov(math_t::Degree(60.0f), ar, math_t::p_FOV::vertical());
math_proj::FrustumPersp::Params params(fov);
params.SetFar(1000.0f).SetNear(1.0f);
math_proj::FrustumPersp fr(params);
fr.BuildFrustum();
cameraEnt->GetComponent<gfx_cs::Camera>()->SetFrustum(fr);
}
Now, setting all the variables such as field of view, near and far during the camera construction only to have to re-declare this stuff when making a frustum feels REALLY redundant. I would think that setting this stuff up in the camera would automatically handle setting up the frustum during creation. Now you might say "Oh you have no indicator to set it as perspective, that's why!" Well, there is a function where you set perspective with a boolean value, but this doesn't seem to do anything. Overall it makes the whole process of making a camera, one of the most necessary entities in a game, feel like it has six more lines than it should while being simultaneously unintuitive as I don't think most users would think to create a frustum at this point in creation of the game.
Shader Limitations
Next up is the limitations on how you can use shaders with 2LoC. Creating materials and such is actually pretty simple and I do like it...But being unable to access the geometry shader (as well as the other lesser known ones) ends up hampering development. Case in point: Dealing with particles. Normally for a particle you could just send in a single vertex and then create a quad in the geometry shader allowing for things to be much more efficient in terms of calculations since you just have to apply physics calculations to the single vertex in the shader versus doing it 4 times (assuming you have vertex indexing in the engine!) on each corner of a quad. So this not only becomes a limitation of what one can do with shaders, it also becomes a limitation of how efficient you can make your processes and hurts development in the long-run!
General user unfriendliness
There's a few other problems I can go into such as the extensive namespaces which make dealing with things difficult (I have had many times where I couldn't copy a material over to another material because as it turns out material 1 is in namespace and material 2 is in a different one...Despite both being materials) as well as things that the engine could benefit from but doesn't have for school reasons (i.e. Scripting and Particles) but above all else is just how obnoxious the engine can be to use. There are a lot of tricks that you need to sort of work out for yourself in order to get some things to work and it might be easier if we had some rudimentary documentation to go by (i.e. A list of what the different functions do) but without this it makes it very challenging to work out how to do what should be very simple things. For example, when I create an entity during runtime its mesh and material won't appear unless I call the appropriate systems and say "Initialize(ent)". I would not have guessed that I need to do this until a friend pointed it out to me.
Overall, the engine seems to suffer from a serious problem in that it's usable once you have become used to (which isn't really praise since it can apply to ANYTHING) the engine but it's very unfriendly to new users and would benefit from a bit of documentation to go with the samples provided. Even something as simple as "Here is a list of basic functions you should know but aren't immediately found and what they do:" Just to provide users with the ability to easily reference something like they would with Unity's documentation. In the end, the engine has a long way to go before I'd say it would work well as an engine for general use.
That's it! Sorry if I seem a little bit harsh but this engine has bitten me too many times to count and has left me a bit miffed. I hope you enjoyed the read, cheers!
Friday, 28 November 2014
Game Design Blog #3
This week I'm going to talk about one of my favourite games, and one of the reasons I love it: Its pacing! The game in question, is the lovely, the fantastic....
So first things first, I will end up going more into depth over the overall pace of the game rather than the pace in specific levels. This is because there isn't a whole lot to write about in terms of the pacing of levels, it's not that it's bad it's just that it's pretty standard. Now then, why do I love the overall pacing for the game? Well, to put it simply the game does a good job of keeping a steady but ever-building pace. When the game starts (and after the tutorial), the player only has 2 members on their squad and they are given 4 missions which reward the players with additional squad members. By doing this the player is given a chance to experiment with their squad without the number of unused squadmates getting out of hand. After a point in the game the player unlocks an additional 4 missions which are much the same, allowing for a break before the player gets new squad members.
Another interesting thing is the Loyalty Missions. These are missions which require the player to go in with 1 squad mate preselected for them. This gives the player a chance to interact with characters they might not necessarily interact with and get used to working with them. This also serves as a strong way of preparing the player for the finale of the game in which they go in with every squad member and have to divide it up into different teams while making use of their different skill sets.
In terms of the story pacing, the game does an excellent job of providing the players with points that ramp up into action while providing brief interludes where the player doesn't have a lot of stress on them but the game isn't boring, i.e. the missions to acquire new squad members are in the slower points of the game and serve to help build up anticipation for the next big missions. The overall pacing for the story does a good job of building the players anticipation and interest until the big finale of the game which puts the player in a position where they simply do not want to stop until the end of the game.
Overall, the pacing for Mass Effect 2 is quite good at maintaining the players interest and allowing them plenty of time to learn the skills and squad members that they gain over the course of the game.
That's it for now!
Game Design Blog #2
Alright, time for Game Design blog numero two! Unlike the last blog I'm not going to talk about a specific game, rather I'm going to talk about a control scheme that has become so prevalent in a certain genre of game and put in some guesses as to how it as persisted for so long in gaming culture. What control scheme might I be talking about? Well...
That's it for now!
That's right, I'm going to be talking about the First Person Shooter (and Third Person Shooter) control scheme on the PC! The above picture is for the game Team Fortress 2 so there are some parts of it that aren't going to carry across games, but the main things that you need to focus on are WASD, R, Ctrl and Space keys. Now first of all, what do these keys represent? Well WASD is movement in the 4 cardinal directions relative to the player, R is for reloading, Ctrl is usually for crouching and Space is used for jumping. This layout has been carried across many, MANY games in the past. Why might this be?
Well if you look at the layout of the WASD keys, they're positioned in such a way that the player can leave their left hand in a position they normally have it on the keyboard allowing the fingers to line up in a normal and comfortable way. Another advantage is that the ring, middle and index fingers line up vertically with the 4 keys in to three distinct columns, allowing for easy use. Finally, the WASD keys form a sort of compass by which can easily be interpreted by the player. This analogy between the player and the game works incredibly well as the keyboard movement of forward, left, right and backward carries over perfectly between the players perspective and the perspective of the character in game.
Now let's take a look at the placement of the other keys:The position of the R key keeps it within easy reach of the player's index finger and it's also tied to a button that players can easily reach based on muscle memory as they only have to think about press R to Reload. The Space key would have been chosen as jumping is an action that players will end up using quite frequently which makes its size and position relative to the players thumb allows for easy and frequent use. Lastly, the CTRL key makes use of the players remaining finger while also staying within easy reach of a single hand.
Overall this layout allows the player to easily use one hand to perform all their movements and any necessary miscellaneous movements. However, shooters also rely heavily on the player's mouse which acts as a camera control through movement. This allows for rapid yet precise manipulation of the player's perspective. The left and right mouse buttons will also see use for a weapon's primary (left) and alternate (right) attacks. This works well as the left click on the mouse is often used for most primary actions such as selecting icons or pressing buttons, allowing the player to make an easy association between the click and the action. The same can be said for the right click which sees use for additional actions in day-to-day use.
Overall, the control scheme for shooters is one that allows the user to make many easy associations with the use of the keyboard and immediate actions in the game, as well as analogies which allow the user to perform actions with the keyboard without having to put too much thought into them. This scheme is very sensible and will likely be around for many more years to come.
That's it for now!
Game Engines 4: Valve Hammer Editor
Okay so this blog will be a bit more jumbled since I'm going to be talking primarily about 2 very different topics: Binary Space Partitioning and different methods for culling. The one thing that links these two topics is that I'll be talking about them in the context Valve's Hammer Editor (a level-editing tool for the Source Engine), and most of the talks will be in regards to how it works with Team Fortress 2 as this is the area in which I have the most experience using the editor.
First of all, let's talk about what Binary Space Partitioning is. BSP will essentially parse a file (such as a level) and continuously subdivide it into different nodes until a requirement is met. This allows a level to be broken down into far more manageable chunks. Unsurprisingly, this method was once (and still in fact today in some cases) seen primarily in Shooters as they usually end up having a variety of rooms which can be interpreted as nodes on a tree graph. In this scenario, using a BSP allows the engine to cut down on the amount of checks it needs to make for render culling as it can easily work out all the rooms attached to the one the player is currently standing in.
The practicality of this system in regards to shooters makes it no surprise that it's used in the Source engine which is primarily used to develop shooters. The system can be further enhanced by using a portal-based rendering (which is another prominent feature in the Source engine). Portal-based rendering is essentially the process of treating every door or window connecting two areas as a 'portal' that the player can see through. When the engine goes to render a scene it will use frustum culling to remove any objects that are not within view of the player...But it then encounters a problem where it will try to render an object behind a wall. In order to cut down on this, we only render the objects in one room before casting frustums from each visible portal to figure out what objects there are in a different room which we can see, once the engine knows what objects we can see in other rooms it adds them to the render list. With BSP and portal-rendering combined we can pretty effectively cut down on the demands put on the renderer as we reduce the number of rooms that are being checked for rendering and cutting down the size of the render list by a significant amount.
Now, how does the engine know where to find the portals as well as figure out ways to make subdividing the level easier? Simple, you leave it up to the level designer (or atleast someone who is making the level)! One of the things about the Hammer Editor is that it has a LOT of materials that do not get drawn during render time which are meant to be used more for letting the engine have an easier time or for gameplay (i.e. Spawn areas will often use a material that has a No Draw texture, but it will have gameplay triggers tied to the box representing the spawn). For some idea of what the editor looks like while you work in it, here's an idea:
First of all, let's talk about what Binary Space Partitioning is. BSP will essentially parse a file (such as a level) and continuously subdivide it into different nodes until a requirement is met. This allows a level to be broken down into far more manageable chunks. Unsurprisingly, this method was once (and still in fact today in some cases) seen primarily in Shooters as they usually end up having a variety of rooms which can be interpreted as nodes on a tree graph. In this scenario, using a BSP allows the engine to cut down on the amount of checks it needs to make for render culling as it can easily work out all the rooms attached to the one the player is currently standing in.
The practicality of this system in regards to shooters makes it no surprise that it's used in the Source engine which is primarily used to develop shooters. The system can be further enhanced by using a portal-based rendering (which is another prominent feature in the Source engine). Portal-based rendering is essentially the process of treating every door or window connecting two areas as a 'portal' that the player can see through. When the engine goes to render a scene it will use frustum culling to remove any objects that are not within view of the player...But it then encounters a problem where it will try to render an object behind a wall. In order to cut down on this, we only render the objects in one room before casting frustums from each visible portal to figure out what objects there are in a different room which we can see, once the engine knows what objects we can see in other rooms it adds them to the render list. With BSP and portal-rendering combined we can pretty effectively cut down on the demands put on the renderer as we reduce the number of rooms that are being checked for rendering and cutting down the size of the render list by a significant amount.
Now, how does the engine know where to find the portals as well as figure out ways to make subdividing the level easier? Simple, you leave it up to the level designer (or atleast someone who is making the level)! One of the things about the Hammer Editor is that it has a LOT of materials that do not get drawn during render time which are meant to be used more for letting the engine have an easier time or for gameplay (i.e. Spawn areas will often use a material that has a No Draw texture, but it will have gameplay triggers tied to the box representing the spawn). For some idea of what the editor looks like while you work in it, here's an idea:
I'm sorry to have brought up the Source Engine again, but I just find it to be such a great little engine that has lead to a lot of interesting games. While it may not be on the same level of flexibility as Unreal or Unity, it's still capable of producing some truly magnificent games and its level editor can give a lot of unique insights into how the engine as a whole operates (from interpreting game systems to rendering). For an idea of how flexible the level editor is, it allows for something that could be seen as making rudimentary scripts for its gameplay systems (i.e. this object will move when this condition is met) and a level designer can VERY EASILY set this all up.
That's about it for my ramble about Source. If you made it this far, then congratulations. Cheers!
(Image of the Hammer Editor gotten from: http://www.moddb.com/engines/source/images/hammer-editor )
Friday, 7 November 2014
Game Engines 3: Scripting
And now for Game Engines blog #3! This week I'll be giving a breakdown of Scripting and how it applies to game engines. First of all, what is scripting? Scripting is essentially creating a smaller program that can be executed by the game They come with a variety of perks as well which make them invaluable in game development: They can be easily used in an ECS; They can compile a lot faster than normal C++ files;And be recompiled at runtime. One of the most important things is that they can easily be edited and programmed.
First things first, how do scripts work? A script can be written in notepad (although you really shouldn't since notepad is horrible to work with) like a text file and is then interpreted by the system in such a way that it knows how to act in terms of the game system. It's pretty straightforward and it's more or less identical to how one would set up a program in C++. In fact, when you compare how scripting is supposed to work and the method in which we create our custom components for 2LoC, it's very similar with the main difference being that the custom components take longer to compile than the script.
Now, why do these features make them so great? Well for starters when it comes to an ECS you can make a script component which only needs a path assigned to it to be created, much like you would with a mesh component. This then saves you the trouble of creating custom components and custom component systems like you have to for creating a custom component with 2LoC and cuts down on the number of files that have to be linked during compilation. It also allows you to keep the number of different components you need to have in your ECS to a minimum as you aren't forced to create unique ones for each circumstance and can instead rely on multiple script components to do the same job.
Scripting also has a few perks in terms of hardware, as mentioned a few times earlier. Their very nature eliminates the need to create and link different objects for classes and cuts down on the overall amount of code drastically, allowing for developers to have much faster compile times. The other advantage to working with scripts is that they can easily be recompiled without interrupting the system overall. This is actually a huge advantage as it allows you to change code on-the-fly without having to rebuild a project. All you have to do is open the script, edit and save then recompile the scripts.
Lastly, scripts are useful for non-programming developers. They are generally easier to grasp than the underlying code of engines and are easier to play around with. The ability to edit and reload them without interrupting the game is also very useful in terms of design as it allows designers to see changes to values immediately rather than having to stop and recompile an entire project or ask a programmer to make the change for them.
Overall, scripting is an invaluable tool in game development. It allows us to save time in various areas from building the final product to quickly testing the game as we go. It also helps by reducing the complexity of developing the game and can help drastically improve a system's versatility: Case in point, Unity is used to create a large range of games in different genres while developers can only add their own code through scripts. The only difficulty comes in setting up a scripting language to work with your engine, but once that's done you've overcome the hardest problem.
Until next time!
First things first, how do scripts work? A script can be written in notepad (although you really shouldn't since notepad is horrible to work with) like a text file and is then interpreted by the system in such a way that it knows how to act in terms of the game system. It's pretty straightforward and it's more or less identical to how one would set up a program in C++. In fact, when you compare how scripting is supposed to work and the method in which we create our custom components for 2LoC, it's very similar with the main difference being that the custom components take longer to compile than the script.
Now, why do these features make them so great? Well for starters when it comes to an ECS you can make a script component which only needs a path assigned to it to be created, much like you would with a mesh component. This then saves you the trouble of creating custom components and custom component systems like you have to for creating a custom component with 2LoC and cuts down on the number of files that have to be linked during compilation. It also allows you to keep the number of different components you need to have in your ECS to a minimum as you aren't forced to create unique ones for each circumstance and can instead rely on multiple script components to do the same job.
Scripting also has a few perks in terms of hardware, as mentioned a few times earlier. Their very nature eliminates the need to create and link different objects for classes and cuts down on the overall amount of code drastically, allowing for developers to have much faster compile times. The other advantage to working with scripts is that they can easily be recompiled without interrupting the system overall. This is actually a huge advantage as it allows you to change code on-the-fly without having to rebuild a project. All you have to do is open the script, edit and save then recompile the scripts.
Lastly, scripts are useful for non-programming developers. They are generally easier to grasp than the underlying code of engines and are easier to play around with. The ability to edit and reload them without interrupting the game is also very useful in terms of design as it allows designers to see changes to values immediately rather than having to stop and recompile an entire project or ask a programmer to make the change for them.
Overall, scripting is an invaluable tool in game development. It allows us to save time in various areas from building the final product to quickly testing the game as we go. It also helps by reducing the complexity of developing the game and can help drastically improve a system's versatility: Case in point, Unity is used to create a large range of games in different genres while developers can only add their own code through scripts. The only difficulty comes in setting up a scripting language to work with your engine, but once that's done you've overcome the hardest problem.
Until next time!
Friday, 17 October 2014
Game Engines 2: Components
Time for blog #2 for Game Engines! Today I'm going to be talking about one particular topic that has become very prominent in the Game Industry and in game engines in general: Component based systems!
So first of all what is a component based system? Essentially a component system relies on two things: Entities and Components. The Entity is the container for all the components and is basically an object in the game world. The entity only has to worry about having a tag and an ID (and even then, an ID is usually enough) to allow for developers to easily track down an entity in the system. On the other hand we have the Components in the system which is the meat of the object that can then make it unique. Components can range from things such as transformations to meshes to scripts and contain different values that allow the entity to interact with the game world.
So now that we know what an Entity and a Component are, what does this mean? Basically we can have a huge range of flexibility with our Entities. In previous system designs that rely heavily on inheritance we would have to deride from a long range of classes to create an entity that can do what we want (i.e. Entity->Character->Enemy->Flying Enemy->Drone) and we would have a harder time crossing over features from different classes. With components we would only have to worry about adding something such as a Flying component, Enemy component and any components that might be specific to the Drone enemy. This allows for anyone working with the engine to easily make an entity that can fit their needs (so long as they can make their own components).
That's the general summary of how an Entity Component System works on the surface. In my next blog I'm going to go into some of the lesser well-known components that you can use in an ECS (and that isn't currently implemented into 2LoC: Scripting!
So first of all what is a component based system? Essentially a component system relies on two things: Entities and Components. The Entity is the container for all the components and is basically an object in the game world. The entity only has to worry about having a tag and an ID (and even then, an ID is usually enough) to allow for developers to easily track down an entity in the system. On the other hand we have the Components in the system which is the meat of the object that can then make it unique. Components can range from things such as transformations to meshes to scripts and contain different values that allow the entity to interact with the game world.
So now that we know what an Entity and a Component are, what does this mean? Basically we can have a huge range of flexibility with our Entities. In previous system designs that rely heavily on inheritance we would have to deride from a long range of classes to create an entity that can do what we want (i.e. Entity->Character->Enemy->Flying Enemy->Drone) and we would have a harder time crossing over features from different classes. With components we would only have to worry about adding something such as a Flying component, Enemy component and any components that might be specific to the Drone enemy. This allows for anyone working with the engine to easily make an entity that can fit their needs (so long as they can make their own components).
That's the general summary of how an Entity Component System works on the surface. In my next blog I'm going to go into some of the lesser well-known components that you can use in an ECS (and that isn't currently implemented into 2LoC: Scripting!
Subscribe to:
Posts (Atom)