Jump to content

Road Kill Kenny

Members
  • Posts

    667
  • Joined

  • Last visited

Blog Entries posted by Road Kill Kenny

  1. Road Kill Kenny
    NPCs, whether they be ally or enemy, are a very important component for many games and a large portion of a game's game play is highly dependant on the things that NPCs do, they way they behave and, if they are enemies, the way that they try to kill you. Therefore, it is vital that your NPCs, their associated behaviours and AI are done well so as to compliment game play rather than detract from it. If these factors are not 'fit for purpose' then the player will see right through the NPCs and the game will become just another game rather than a world the player can immerse themselves into. This doesn't mean the NPCs have to be human perfect, as I said before, it simply has to be 'fit for purpose'.
     
    With this in mind I set out to firstly create my NPC classes. I had a few attempts before I got it right. Firstly I decided to make a fixed enemy NPC like a turret because I thought it would be easier than a mobile enemy for the first one. I had an idea that there would be two main types of enemies including both fixed and mobile enemies and I made base classes for each of them. The FixedEnemy class was then derived into a unique fixed enemy classes depending on the type of enemy. The FixedEnemy class also inherited from my standard Finite State Machine (FSM) class so that it could handle states of behaviour easily. Following this I created a whole bunch of behaviours that I thought would be necessary in different situations. Different behaviours could easily be slotted in to make many enemies that could behave differently if necessary. The system worked well for the fixed enemy and you can see my original blog on this part of the process here: http://www.leadwerks...a-new-frontier/
     
    After this was completed I decided to leave NPCs an AI while I worked on my new level system and level editor. I have now completed most of the editor and am re-visiting the NPCs and began creating that MobileEnemy class that I had planned. However, when I finished writing the class declaration I found that it was almost exactly the same as the FixedEnemy class. By a force of habit I had made the FixedEnemy class so flexible to the point where there was no need for two separate base classes. This was a good thing but it got me thinking and after a good 10 minutes of pondering I found that my previous thinking was rather flawed. Why were my base classes just for 'enemies' and why did I think that splitting them into fixed and mobile variants was a good idea. Evidently I had already made the class flexible enough to handle any NPC.
     
    As a result of this pondering I went on to make a pure NPC base class that inherited from the FSM class and then was derived into any unique NPC that I wanted whether enemy, ally or neutral. It was mostly just the FixedEnemy class with a different name but there were a few minor changes. This was much cleaner and I liked it. However, there was a bit of a problem. The underlying difference between a mobile NPC and a fixed NPC is that mobile NPCs require a controller for movement. I didn't want to clog up fixed NPCs with controller code that they wouldn't use and I didn't want to create new controller code for every single unique derived NPC that needed one. To solve this I thought back to how my character animator class works where each character has an animator object within it and the animator object handles all animations automatically. In the same modular fashion I created a controller mod that could be attached to any AI driven NPC in the game that requires a character controller. This class would live within the unique derived NPC classes, if applicable, and would be able to handle all the annoying movement code necessary for a lot of things. It is almost like a wrapper for the LE character controller which makes it more automated. The major functionality that I gave the module includes:
     
    SetTurnToAngle(float angle)
    SetTurnToFace(LE::TVec3 facePos)
    SetMoveToPoint(LE::TVec3)
    SetPathToPoint(LE::TVec3)
     
    I was actually rather proud of this module as it is not only code that is re-used a lot it also re-uses a lot of code within itself very well. For example the SetPathToPoint() function simply works by managing the calling of SetMoveToPoint() and SetTurnToFace() functions in a structured manner so that the controller will move from one node to the next in a path. Even the SetMoveToPoint uses the SetTurnTo Face() function to first turn to face the direction that the controller is to move.
     
    With that out of the way I just had to continue to create behaviours for mobile NPCs. I found that my previous method of having slotted behaviours still worked very well and I made no changes there. The behaviours were given access to the NPC modules so that it could call the relevant functions to get the NPC to do what the behaviour decided it should do.
     
    Now that that is all out of the way I am working on the games Alert System. Basically it is like an alarm system where if the player gets seen then an alarm gets set and all NPC's in the immediate area will know your location. This of course means stealth and in terms of stealth the mechanics is 95% with the NPCs further compounding how important NPCs are.
     
    Hope you enjoyed my stories. Sorry no more video's for you guys until official announcment
  2. Road Kill Kenny
    ::::BE WARNED THIS IS A LONG ONE::::
     
    Path finding is a technique used in many games that allows an object to find its way around obstructions to get from one point to another. There are a lot of miss understandings regarding this technique and many treat it as a mystery that is best left for the more experienced programmers. However, the big scary word 'AI' is not nearly as scary or complex as some may think. My entire path finding system only contains 4 classes, 1 struct and about 450 lines of source excluding comments. I'm sure you'd agree that this isn't really that much.
     
    On that note I'd like to point out that path finding isn't even AI itself despite popular belief and the fact that it is written about in many AI books. Path finding is simply a tool that AI utilizes to determine several points that an object must go through to physically get from 'A' to 'B' in the shortest or most favorable route possible. The AI comes in firstly when the object decides where it has to go for starters dependent on its behavior and secondly when it decides what to do with the path given to it by the path finding system. Another reason I disagree that it is AI is because the path finding doesn't belong to an object at all. It is an single external system that the objects AI consults for information.
     
    Well now that that is out of the way I'll get on with it. Today I completed a full path finding system for my game. The path finding network is nodal and it utilizes the A* path finding algorithm. The most important feature of the system is the following funtion:
     

    std::vector<Node*> GetPath(LE::TVec3 startPos, LE::TVec3 endPos)
     
    This function simple returns a list of Nodes that the object must traverse in order to get from the startPos to the endPos. How the object uses that information is up to that objects AI behaviors.
     
    Here is a quick video of it working in the game:

     
    In my mind are three important sides to path finding including:
    The Node Network
     
    Heuristic Calculation
     
    The path finding algorithm that uses the Node network as an input and outputs a path

    The Node Network
    The node network or path finding graph is simply a bunch of nodes (i.e. 3D points in space) with Links between each other representing paths that are possible to be taken without hitting obstructions. The below screenshot shows a visual representation of the nodal network.
     

     
    Each node contains a list of links that are Outgoing from themselves. That way when the algorithm assesses a node it can quickly and easily access its outgoing links.
     
    Each link contains a pointer to its start Node and its end Node as well as a cost. The cost is important for the sake of the A* algorithm as it needs to know how difficult each link is so that it can pick the optimal route. Most costs are usually calculated by distance between nodes. However, they can be increased or decreased for different reasons. For example, you may consider a higher costs than normal for travelling uphill and a lower cost for travelling downhill. The choice is up to you.
     
    I have utilized my level editor to facilitate the creation of this path network in a quick and efficient way. This way the path finding network can utilize DDD (Data Driven Design).
     
    The classes I made for nodes and links are as follows:

    class Node { public: Node::Node(u_int id, u_int subID, std::string origin, LE::TVec3 Pos); Node::~Node(); void SetPosition(LE::TVec3 Pos); std::vector<Link*> GetLinks(); void CheckLinks(); void AddLink(u_int destId); void AddLink(std::string destOrigin, u_int destID); void AddLink(Node* node); void AddLink(Link* link); void DrawNode(); // Needs more work here LE::TVec3 pos; std::string origin; u_int id; u_int subID; private: std::vector<Link*> nodeLinks; PathMan* pMan; }; class Link { public: Link::Link(u_int NodeIDA, u_int NodeIDB); Link::Link(Node* start, Node* end); Link::~Link(); Node* GetStartNode(); Node* GetEndNode(); void SetCost(float cost); void CalcCost(); //Editor only float GetCost(); bool CheckLink(); void SetBlocked(bool block); void DrawLink(); //Debugging only private: Node* startNode; Node* endNode; float linkCost; bool blocked; PathMan* pMan; };
     
    Excuse all the overloading functions. I wasn't sure which method I would want to use to AddLinks so I made a bunch of them. Now you may not understand it all as some of the stuff is specific to my game. However, you should be able to get the general gist.
     
     
    The Heuristic Estimation
    The heuristic estimation is the estimation of how far it is from any given node in the network being assessed to the destination node. The closer this estimate is to the actual distance the better. However, it does not need to be perfect. Now don't take me the wrong way this is an estimate of the distance that the object needs to travel to get from A to B not the birds eye distance.
     
    The A* algorithm will behave differently depending on if the heuristic is under or over estimated:
    Underestimating will cause the A* algorithm to take longer. The more it is underestimated the longer the process time will be. However, under estimating will always return the shortest path.

    Overestimation will cause the A* algorithm to not necessarily take the best path. However, it will finish quickly and is not a problem if the overestimation is minor.

    Getting the estimate just right will give the best balance of processing speed and accuracy. However, in order to estimate this distance perfectly you have to solve the path finding problem.... which is just stupid.

    There are a number of ways that the heuristic can be estimated including Euclidean distance, look up tables or by solving a "High Level Bucket Nodes" path.
    Euclidean Distance:This is the distance from point A to point B in a straight line. This has the potential to be either fairly accurate or grossly under-estimating depending on the geometry of your level. However, it is always garunteed to under-estimate so if you don't mind a bit of lacking in speed Euclidean distance is the way to go.

    Look Up Tables: A level can be broken up into bigger sections or buckets. The distance from each bucket to another bucket is pre-determined in a level file and the heuristic estimation simply looks up in the table the approximate distance from the bucket that start Node belongs to to the bucket that the end Node belongs to.

    ​High Level Bucket Nodes: Just like the look up tables, the level is broken up into big sections or buckets. A node is put in the middle of each bucket and a quick path finding algorithm is run to find the distance from the the bucket containing the start node and the bucket containing the end node. This means running a high level path finding algorithm using Euclidean Distance as the heuristic. Depending on the size of the level buckets and how many their are this usually is very quick and will provide a pretty close estimate.

    Each method has its pro's and con's. I guess it is just very dependent on how your level is set out and how much performance you are willing to play with. As the Euclidean heuristic will always give a good path I decided to use it just to get the path finding going. However, I may change to another to improve performance when it gets to optimization.
     
    The A* Algorithm
    The A* algorithm is a very well known and common algorithm used for many games path finding. As it is so common I'm not going to talk about it very much. It can be found in many places on the internet but beware, you will get the best information from an AI book as internet sites tend to leave out bits and pieces of information.
     
    This blog has gone long enough and I don't think I could do the A* justice without making this 3 times longer. I may write a tutorial on it using C++ someday but that's a big maybe.. I have a game to make XD.
     
    I shall bore you no further. Check out the path finding network being created in the editor. Enjoy

  3. Road Kill Kenny
    Up until this point everything has been one big question mark. Will I finish my game? Will I run into project breaking road blocks? Will I have the resources? Am I crazy to think that I can actually do this? ...
     
    All of these question weigh heavily on my mind at all times and I'm sure a lot on other individual (Yes screw the word indie) developers minds as well. The road is so long and the light at the end of the tunnel is just so far away. It can be very dis-heartening sometimes especially when it is not always "just a matter of time" but a combination of a matter of time and a matter of a lot of damn hard and innovative work.
     
    However, for the first time I am pleased to say that the light at the end of the tunnel is getting brighter every day. Major milestones are being met and now there is no doubt in my mind that I will finish and release this game.
     
    This feeling comes just after completing the first alpha build for my level editor. The editor makes everything so much easier with the DDD capabilities and the ability to allow me to throw together levels very quickly, test new mechanics in relevant scenes and ultimately make each level of my game how I want it.
     
    The below two video's show the state of the editor at the moment and what it is capable of. The second video shows a quick demo level I made in the editor which took maybe 45mins to create. That might seem slow but I'm still getting used to the editor myself and there are some usability optimizations to be made as I come across them. Enjoy:
     
    In Editor:


     
    In Game:


     
    From now on there are just a few things I need to do. The first thing is the pathfinding system which will be nodal and will utilize the A* algorithm. It is mostly complete but still needs a bit more work. I also need to finish my in game stealth / alert system which is also almost finished. Following that I will create more enemies, traps and gameplay mechanics that will make the game fun to play. Finally I will be putting these gameplay mechanics into a series of levels with story and all artwork combined to make my complete game... I plan to officially announce the game soon so stay tuned.
  4. Road Kill Kenny
    Instancing is great! It improves performance drastically and it's almost like getting 100 pizza's for the same price as 1. However, there is one instance (excuse the pun) in which instancing is not ideal and that is when you want to have the same mesh to have different materials applied. Basically the problem occurs when you apply a material to one mesh in a set of instanced meshes all of those instanced meshes change material.
     
    In my Level construction set I have multiple pre-fabricated pieces and materials. As you may have seen I can apply materials to those pieces individually in the editor. Say for example I want to have a room floor with material 'A' but then I have a corridor as well using material 'B' but some of the same meshes... How do I solve this? I few thoughts came to mind and they are as follows.
     
    1. Have Multiple GMF Files for Each Piece
     
    2. Use Some LE Commands To Try Make An Un-Instanced Mesh
     
    Now I hope you figured it out for yourself that option 2 is the way to go without me having to tell you. Option 1 is a rather outrageous work around which is a bit like the epitome of ugly!
     
    So the next question is how do you carry out step two. Well I fished around in the LE wiki for commands that may help that I have never used before and I found just the right code for it. The algorithm is as follows:
     
    1. Load the mesh from the file path - LE::LoadMesh()
    2. Create an empty mesh - LE::CreateMesh()
    3. Add the mesh from the 1st mesh to the empty mesh - LE::AddMesh()
    4. Update the new mesh - LE::UpdateMesh()
    5. Delete the first mesh - LE::FreeEntity()
     
    Although this takes a lot more than simply loading a mesh it is the quickest and cleanest workaround I could find for this problem. See below the function:
     

    LE::TMesh LoadMeshNoInstance(std::string meshPath){ LE::TMesh instMesh = LE::LoadMesh(meshPath.c_str()); LE::TMesh noInstMesh = LE::CreateMesh(); LE::AddMesh(instMesh, noInstMesh); LE::UpdateMesh(noInstMesh); LE::FreeEntity(instMesh); return noInstMesh; }
     
    PROBLEM:
     
    Now we have solved the problem of not being able to load un-instanced meshes but the global problem isn't solved just yet right....... right?
     
    Well no its not solved. You may recall the first line of this blog, "Instancing is great". We don't want to apply this non instancing loading functions to everything in the scene otherwise we will get horrible performance in run time and no body wants that!
     
    Basically the ideal outcome would be that every "same" object with the "same" material utilize instancing. For example, if you had 10 2X1m blocks with Material 'A' and 15 2X1m blocks with Material 'B', 9 of the blocks with material 'A' would be instances of the first block with material A and 14 of the 2X1m blocks with Material 'B' would be instances of the first block with material B.
     
    To solve this I will organize all of my blocks in a list. Each object has a type ID and a material ID which is inherent from my DDD system prior this problem. When a piece is to be loaded into the game it will look for a piece with a matching type ID and material ID from the list. If there is a match it will load the piece with instancing and if there is no match it will load the piece without instancing using the above function.
     
    This will add a fair bit of overhead but fortunately it is overhead in the load time of the game rather than game play time and, therefore, it is less crucial.
     
    The below image shows the result in my editor. 4 of the same piece with 4 different materials applied.

     
    Thanks for reading. Hope you enjoyed
  5. Road Kill Kenny
    I've been working on this level editor for my game to go with the level construction set idea I chose to adopt for my level management. The below video is a Vlog showing my progress with the editor.
     
    The idea behind the editor is to reduce the rather impossible grunt work known as filling in a database line by line with data to create a data. I make the level in the editor and all that information gets saved and it writes those lines for me.
     
    Current Major Features Include:
    - Loading Levels
    - Adding level pieces
    - Adding materials to pieces
    - moving and rotating pieces around the scene
     
    Features I Still Need to Make:
    - Saving Levels
    - Adding Lights
    - Adding Spawn Points
    - Adding Various Types of Triggers
    - Adding level props
    - Adding Enemies & NPC's
    - Fixing a tonne of bugs.
     
    It still has a long way to go but it is starting to show its colors.
     
    Enjoy the video:


    GUI made with pure LE commands.
  6. Road Kill Kenny
    Hi All,
     
    Currently I am working on making my level building in my game much more diverse and easy. Formerly I was having to create custom models for each room in the game. This worked but was hardly efficient, very time consuming and did not leave much hope for the end user to create and share levels either.
     
    So I set off to kill two birds with one stone:
    Make a level building system & editor to streamline level creation in my game
    Make the editor easy to use to open up the possibility of the end user gamer being able to make custom levels using the pre-made building blocks.

    So the idea around this whole system is to make lego blocks, The lego blocks get constructed together in any different way specified by the user to make a level and the user can simply slap on any texture they want. This will make level building very fast. There are a number of things that were musts for this system in my eyes:
    Data Driven (of course... did you think I would do a blog without talking about that...)
    Utilize unit lengths and snapping (no decimal point dimensions & positions)
    Optimize UV's so that the pieces can utilize different materials easily (sort of like creating a standard for Level part UV's that all pieces and materials must comply with to work)

     
    So with out further ramble, please enjoy the below video that goes through the process of me exploring this. This is part one of 3 which I will show in separate blogs.
     

     
    Problems Encountered:
     
    1. Origin of Level Pieces At first I thought that putting the origin at the center of the pieces would be a good idea. However, this turned out to be the worst idea ever as it totally screwed up the unit length idea. For example you have a 1X2m floor piece, if you put the origin in the center the origin is at 0.5X1 <-not unit scale... At first you may think this does matter but it does. consider placing a 1X2 piece next to a 2X2 piece. if 1X2 floor piece was at position (0,0,0) then the 2X2 piece would have to be at position (1.5, 0 0) otherwise it would overlap. see image below:
     

     
    So to solve this I put the origin at the very corner of each piece with each piece extruding out into the positive X Y and Z directions as shown below.
     

     
    Sure it was a stupid mistake but an easy one to make.
     
    2. There is no problem number 2
     
    Whats Next:
    The next thing I will be doing is creating the editor. This entails a bit of windows programming. I don't want it to be like the HAARP editor I made. I want it to be nice and easy to use for just about anyone who would play my game. It will be using proper save and open dialog boxes and other such Windows utilities to make it familiar. I will blog about this next time.
  7. Road Kill Kenny
    AI is something that I haven't really touched, hence the 'new frontier' title. However, overtime time learning how to program games and learning about useful techniques such as finite state machines, it did not worry me very much and I had a good idea of how I wanted it to work.
     
    There are three major things that I wanted when conceptually designing my AI system and they were:
    Diversity of AI
    Data Driven AI
    Modular AI

    Observe the below diagram. Simple enough. It depicts a turret class which is also a finite state machine and has a number of states in it, namely Idle, Attack and Seek.
     

     
    Now this all seems fine and dandy (if I may say simple as well). However, if we want to have a different type of fixed unit such as a cannon turret then we have a problem because we have to re-code all of the states of behavior even if it generally behaves the same. The image below shows how this can get out of hand.
     

     
    Now consider the below image. you can see I have taken away the behaviors from the fixed unit classes and placed them externally so that they not owned by the fixed unit. Now anything can re-use those behaviors.
     

     
    For the most part this is obvious, however, what if we want to have the same types of object utilize and chop and change different behaviors. We get what is shown below. This was ultimately my goal when creating this AI System.
     

     
    It may seem a little crazy and you might thing "WTF is going on there", but keep in mind that out of the 3 goals I had for the AI system, simplicity wasn't one of them. I just wanted to have as many options as possible. This way I can make the most out of every type of enemy or NPC in the game. There is nothing worse than only being able to use something in one single way for an entire game.
     
    The below video demonstrates this working in game, shows a bit of the Data Driven side of it and also some code. Enjoy.
     

     
    From a game design perspective, this kind of system is very good as you make the most out of each npc type and mechanic. The player see's a turret and from prior experience in the game that they first came across it they know what it does, it kills them..... However, with little effort the turret can be changed to be smarter and behave differently. The player will have to use what they know about a turret in order to figure out how to tackle the turret behaving differently... and this can be done with any number of npc's not just turrets, effectively diversifying the entire game.
     
    For example, you may start the game with the turrets not looking around, then as the player progresses you introduce turrets that look around, then ones that revolve.... Then when they think they have the turrets down pat, you introduce a room full of turrets that behave differently . This effectively keeps everything fresh even though you are using the same thing. (note this is just one example, it is important to have more than just one enemy type otherwise it could get a little bland).
     
    Anyway.....
     
    It may have been a bit much to follow perhaps because of its complexity / abstract way of doing it.... but more likely because I suck at explaining things. However, I hope you at least got the gist and learned something perhaps. I know I have.
  8. Road Kill Kenny
    Setting up how a level works can sometimes be a tricky task, especially when the a games level appearance is more abstract than say a first person shooter where everything is as you would see it in real life.
     
    My game is one example of these abstract level appearances. It Predominantly takes on a semi-top down dungeon style view where the roof of the level is missing so that the player can see inside the level.
     
    The below video blog shows how I resolved a few issues that are inherent from this style. This is still a work in progress. However, I thought I would share my technique.
     


     
    In the near future (once I have a bit more gameplay) I intend to improve this technique by making the walls fade in and out instead of abruptly being shown and hidden. This presents some challenges because, if I use a shader to do it, what will happen is that shader will affect all the walls when I set a fade because the shader will be attached to the wall material. I have a few workarounds in mind. However, I'll leave that for another time.
     
    Thanks for reading and watching. I hope to show a bit more than the one room soon.
  9. Road Kill Kenny
    So You're Not Good At It...... Then Get Off Your Butt and Get Good at It!
     
    As I started my last blog off with a lessons learned I thought I would continue the trend in all of my blogs and share a bit of what I have recently learned.
     
    More often than not, as game devs we have our weaknesses in certain areas of game dev that just makes things that much more difficult. Some of us are great programmers but bad at art, some of us are good artists that are bad at programming and of course.... there are some of us that aren't that flash at either. We will always have our deficiencies. However, the question is.... when there is a deficiency in your skill, what do you do about it?
     
    It is so easy for us to just say, "I'll get someone else to do that", or just ignore the problem out-right..... we can go on complaining about how the world is so cruel to us that xyz is so hard and you can't find anyone to fill the gaps... Unfortunatly as predominantly indie devs we don't have the luxury of resources. We have to try fill in the gaps as best we can.
     
    Instead of wishing we were good at something, how about we try and get good at it. No one starts out skilled at a lot of game dev stuff, you have to work on it and continually get better, read books, search in google, try fail try fail and try again until you get better. Also don't rely on a college to make you better at game dev as you have to work on your own to ultimately get good at it.
     
    Don't get me wrong.... there is nothing wrong with not being skilled in something, what is wrong is when you decide not to do anything about it. As for myself I, my major weaknesses are 2D art, texturing, concept art etc. I was really having a hard time wondering how I was going to deal with it. However, I feel now my new approach to all of these things will be, just keep doing it until I get better... no excuses. No one is going to pick up the pieces for me, i'm an indie and at the end of the day I can only rely on myself.
     
    Character Design
    Recently I have been focusing on character design for my game. I have put a lot of thought into it, how I want them to look, how they should act and behave. I thought up all these cool looking robots but at the end of the day I had to have a hard long think.
     
    Is the player going to be able to relate to these characters, probably not. I find a lot of the time when I am playing games I have to be able to relate to the main character on some level otherwise I just will struggle to get into it. Even a robot can have a relatable personality and that is what I decided to go for in the end, erring on the side of "not so serious" and still getting the fun factory in.
     
    The image below is of the first design for a robot I made. I thought it was rather interesting at first how it runs on tracks and such. However, it wasn't until I modeled it that I realized that it just wasn't relatable and I just didn't like it.

     
    I then went about rethinking this character. Making him more flexible, more friendly and really just to have more personality. Here is the result of rethinking the same character from a different perspective.

     
    You'll probably notice that this is the same little robot that I showed for animations in my last blog. I hope you agree that this second attempt is much better... In fact what was I thinking when I drew the first one.
     
    So finally here is just one more drawing I did tonight where I tried to design another robot and try give him personality. Now I'm not the best drawer but I gave it my best and feel I achieved enough to make it look good and personable in 3D.
     
    This here is MAV, he has a cool laid back personality. I gave him glasses, or what looks like shades, and put a little alarm light that looks a bit like a top hat. He even looks a little 'fat' and is the guy that just sits back with his guns. I'm not 100% sure about it yet but I hope I still like the design tomorrow.

     
    I want to make sure that all my main game characters are designed well and have personality that players can relate to. I am not afraid to completely redesign when I feel it just isn't good enough as the main characters are just about the most important designs in the entire game as far as artwork goes.
     
    Anyway hope you enjoyed my blog.... Excuse my lack of drawing skill.. this is just me working on my weakness and keeping on drawing until I get better.
     
    Thanks for reading
  10. Road Kill Kenny
    The Mistakes of the Past
    I just wanted to start this blog with a bit of a lessons learned. I've attempted to make some games with LE that in hind-sight were way too complex.... 50x too complex for the amount of time / resources that I have available. This is a common mistake and it is so easy to make it. So I decided to deal with the problem once and for all.
     
    After failing a few times I decided to have a long hard think. I decided, you know what, KISS dammit. Keep It Simple Stupid. Simple doesn't have to be a bad game, in fact it can be a much better game if done right. I decided I'd come up with a simple idea, give it the bare functionality that I need to make the game and just make it (NIKE) without adding any of the extra 'STUFF' that so many games get clogged with.
     
    I decided that if a feature does not contribute a certain amount of the "fun" element to the game it should be removed from the game without a second thought. This can be difficult because there are things that we can perceive as being "cool" but when it comes down to them being "Fun" the miss the mark and we've managed to miss the point of creating a game.
     
    After doing this mind changing excercise I got to work on HAARP and the game I'm currently making. I'm pleased to announce that it is going well and It has much 50x more potential to be completed and released than any of my other attempts
     
    This all being said I don't completely regret all of my failed attempts. I learned so much being over ambitious about coding and game development in general so it was not a complete waste.... and to be honest I wouldn't be where I am now if not for a few failed attempts.
     
    Of course this blog is not about the game so I won't be announcing it today until I have some substantial gameplay and artwork to show. I will say that I plan to port it to LE3D and release it on Steam and OUYA hopefully around this time next year.
     
    Animation Fun
     
    Animation has got to be one of my most favorite things to do both on the side of creativity and also on the technical side of programming it. I'm not sure what it is about it. Perhaps it is just the pleasantries of seeing life come to your little creations.
     
    I have just come to the point where I need to do the core animations for my game before I can continue coding any more. This mostly involving the animation of game characters and for me this is a 3 part process as follows:
     
    - The Art: Rigging & Animating the actual character in Blender
    - The Data Driving: Setting up the animation database & coding the AnimationShop to retrieve that data
    - The Code: Coding the animator class to manage character animations for any character that uses a LE::TController
     
    Instead of ranting on about these processes I decided to make this a half blog half vlog that is broken into three parts. Enjoy
     
    First Step: How I like to set up my animations in Blender

     
    Second Step: Setting up the database

     
    Third Step: The final result (please note, most of what you see is placeholder)
    http://www.leadwerks.../videos/_/-r164 <- Click the link for Part3
     
    It really is amazing how much the animation adds to the game, gives life to the characters and just makes everything more fun even though no extra gameplay is added. Choppy animations make the player feel disconnected and unable to relate to their character. It also ruins immersion which in my books is extremely important in a game whether it be simple of complex.
     
    So when it comes to animation I've decided to keep things simple, make them smooth and don't be afraid to spend time on it. However, I think it comes to a point where you can spend too much time on animation leading to sacrificing gameplay and I'll do my best to not let this happen. Despite this, I feel like for my main character/s must have a lot of time invested in them. I want them to be relatable and have personality even though they are robots. I know that I like to have relatable characters in a game and if they aren't animated properly it totally kills the mood. If the animation requires sacrifice for the better gameplay, the sacrifice will be in the animation of enemies and/or such as the player does not need to relate to them necessarily.
     
    Thanks for reading. I hope to officially announce this game some time in Q4 this year.
  11. Road Kill Kenny
    The last week I have been working hard to add all the missing UI elements and widgets that were previously missing in H.A.A.R.P. Before I was testing everything with just buttons and check boxes but I couldn't really go on without testing on more types of elements to ensure everything was working in the right way. Therefore, over the past few days, in my time after work, I've been madly re-coding the UI elements that I have previously made to be compatible with Data Driven Design and more specifically H.A.A.R.P itself.
     
    I have added the following Elements now:
    - Buttons
    - Check Boxes
    - Text Boxes
    - Labels
    - Sliders
    - Drop Down Boxes
    - Windows
     
    Although the above list is not a comprehensive list of all the elements you could ever think of or possibly need, I think that it is plenty for the first build of H.A.A.R.P GUI. I may have to add game specific elements or H.U.D elements later such as HP Bars etc. but I will leave that for another time.
     
    Below is a screenshot with all the elements randomly placed over the screen. Please excuse the graphics I used for most of them it is simply just for testing. You can put any graphics you want for these elements, you simply have to save the .dds files in a game folder and the click on the green folders on a selected element to change the images used.
     

     
    here is a picture of the Drop Down Box Selected. As you can see there are 8 little green folders because the Drop Box uses 8 little textures to put itself together. It could be less, however, the size and dimensions of the Drop Down Box become more restrictive.
     

     
    These little green folders automatically detect how many textures a UI element uses and displays the relevant number of folders.
     
    Element Diversity:
    There are a lot of elements in any Gui to begin with but there are also many different sub types of elements. For example, a slider element can be either horizontal or vertical. In Designing the H.A.A.R.P elements I have taken this into consideration and enabled setting of element sub types. The type ID is stored in the database and can be changed in the editor. The behavior of an element depends on the typeID specified and if I need to create more behaviors for a single type of element i simply have to code the new behavior with reference to a new typeID.
     
    Another example of this is Buttons. You can have a button that is simply an image, However, perhaps you want to only use one image for all your buttons and just write text over the top of that to make the Buttons different. Well, you can do that with H.A.A.R.P. Simply changing the Button type from 1 to 2 in the editor will do this.
     
    Font & Element Labels:
    Labels as an element is one thing, but what if you want a label for other elements so that they can be identified. For example, a slider might need a label that says "Master Volume". I could simply make another Label element, but that would just be much too much work and take up more memory than is necessary. Instead I have given every single element the ability to show its own label at a specified offset from the start Position of that element. The font style and color of the label can also be edited in the editor simply by changing a few number.
     
    Below is an image of a button element drawing its own label. As this button is actually part of the editor I had to manually write the label name, color and offsets into the database. You may notice I didn't set a font for this one.

     
    It should be noted that all this is taken out of the database including, 'whether to show or not to show a label', the label font, the label color (RGB), the label offset from the element. Everything comes from the database and nothing is hard coded. This allows for the ultimate control and ultimate re usability of the code.
     
    Saving & Deleting:
    I have recently implemented Saving of the UI elements new information back into the database. This task wasn't particularly hard as it just involved parsing the information from an element into an SQL statement string and then querying the database. However, Deleting elements was another story. Although it may sounds simple, I battled with deleting elements for 3 days in mega frustration.
     
    It may sound easy but my database is set up is to make the least amount of columns possible. Therefore, there is a Generic_Element table which holds all data that is generic among all elements. This table kinda represents all the values stored in the element base class which is inherited to make a derived element specific class. On top of this table, I also have a table for each type of element and it holds all the element specific data. In order to make this work the tables need to reference each other. Each element has a generic ID and an element specific ID so deleting becomes difficult when you have multiple tables and you have to cross reference everything correctly, not to mention it having to be in-sync with the run-time information as well.
     
    Now deleting wasn't even the hardest part, in fact it was as simple as parsing the generic ID and the element specific ID of an element into an SQL statement string and querying the database. However, once this has been completed all element above the deleted element have to have their ID's rotated downwards. This was really difficult more as a logistical thing than a coding thing. It took me a long time and much frustration to figure it out. However, I have won and the deleting algorithm is down pat now.
    Below you should be able to see what I mean about the databases.
     

    Although this setup causes problems in deleting. It is more beneficial than it is detrimental.
     
    Separating The Editor From the Game:
    When I started making and designing HAARP I decided it was very important that this "In game editor" did not interfere with the performance of the game when it is actually being played in any way. Therefore, I constructed the HAARP editor completely separate from the game code and simply given editor access to the game objects via pointers. Once the editor is turned off there is literally no effect on the game whatsoever except for a single 'if' statement. Also once a game is completed, I simply have to comment out a single #define line and it is as if the HAARP editor never existed.
     
    I am happy that I made this decision early on in the piece because the complexity of the editor is much greater than that of the actual screen state code. All the Screen state code really does is cycle through all the elements and updates them. The elements are designed in a way that they fully manage themselves and their own relationships with other variables, functions and screens.
     
    This blog turned out way longer than I had anticipated. Oh well. I hope you enjoyed it and maybe learned something.
     
    - Ken
  12. Road Kill Kenny
    There are two things I've been working on since my last blog:
    HAARP Sound Manager (For UI Sound only atm) &
    HAARP Switchboard

    The HAARP Sound Manager is not very much different to what you would expect from most games sound manager layers except for the fact that once again it is completely data driven. All data on sounds are stored in the database. Each UI element holds an ID of a sound to play at certain times for example:
     
    Button Element:
    1. Hover Sound
    2. Click Sound
     
    The challenge is how can this be set up dynamically. Well this part is actually quite simple. Each sound has an ID in the database, each Button has two sound id's stored in two different columns, one for hover sound and one for click sound. All that is needed once the data has been extracted from the database is to cross reference the sound id's that the button has with the actual sounds referenced by those id's and you can easily give a relationship dynamically based on the database values.
     
    However, things get a little trickier when you want to allow the creation of these element to sound relationships in the HAARP editor using the wires like I can already attach states. To solve this I came up with HAARP Switchboard. HAARP switchboard is basically a set of classes that allow easy visual relationships to be made between UI elements, sounds, functions and variables.
     
    Basically a swithboard can be created and that switchboard can have any number of plugs. The switchboard can be moved around the screen in edit mode and the user can plug elements into those switchboards however they want. Depending on the switchbaord being used it can hold many different types of data:
     
    For example, a post processing effect switchboard may have a plug for SSAO, Godrays, FXAA etc. and plugging check boxes into those plugs on the PPFX switchboard would link the two together and give a dynamic relationship so that when the check box is checked, that effect will be active and when it is unchecked the effect will not be active. I am even considering making the option to have dynamic switchboards which can be created by the user in game.
     
    So as I was doing the sound system I thought I would start with the simplest of simple switchboards and this is the UI Sound Switchboard which only has a single plug. The sound switchboard holds a sound in it and different sound channels from UI elements can be plugged into it and based on those relationships will play a sound. Have a look at the screenshot below:

     
    Perhaps the very first thing that you would notice is the wires going everywhere. These wires are important to show relationships between elements, sounds, screen transitions, variables and functionality.
     
    The green line is a screen state relationship. As you can see it is plugged into the options screen. If the user exits from edit mode and clicks on the options screen they will automatically be transitioned to the options screen state. (It is important to note that even these states listed are not hard coded but dynamically drawn from the databases. Later I will add functionality to create new screens in the editor).
     
    The blue lines show sound relationships to the UI elements. As you can see there are two plugs and two wires for sound. This is because a button has 2 sounds, one for initial hovering and one for when the button is clicked. Therefore, the first plug is the hover sound and the second is the Click sound. If this were a check box it would only have one sound plug for when it is clicked as no hover sound is necessary. The editor will dynamically detect the number of sound channels a UI element has and dynamically create these plugs based on that number.
     
    It should be noted that these sound channels can be unplugged by just dragging the plug onto nothing and then there will be no relationship and sound will not be played through that channel.
     
    It is arguable that the whole visual idea with wires running everywhere can make things a bit cluttered. Therefore, I have implemented features which help remove this clutter. First of all there is a wire toggle. The user will be able to toggle different types of wires so that only certain types show or none show at all. This lets the user focus only on the wires they want or no wires at all. I have also made it that when even when all the toggles are off the wires will show on the selected element. This way you will see only a few wires. I am considering have a toggle all wires on the selected element HUD to improve it even further.
     
    So the long story short is that HAARP Switchboard is the methodology or technique that I came up with to dynamically and visually make relationships between two seemingly isolated pieces of data without any hard coding of the data whatsoever. Although the sound switchboard is different to say an options menu switchboard it will still work on the same principals
     
    Other Things I've Done Since Last Time:
    Added a text box to top right with an OK button which is used to set the background texture.
    Added a number of tabs to the HAARP Editor Side panels for future use for more space and functionality
    Improved the databases dramatically so that even more settings can be set within the elements from the database, meaning less code in the main areas of the editor code


  13. Road Kill Kenny
    In my short 1 year of programming I have gone to great extents to learn not only how to code but also the techniques and methods behind game architecture that make things work and keep the integrity, re usability and productivity of my code to a maximum.
     
    Out of all the techniques I have come across there are two that really have taken the cake. These two techniques are (excluding OOP, thats a given):
    Finite State Machines
    Data Driven Design

    Data Driven Design
     
    For those of you who don'tk now or are not sure of what Data Driven Design is, here is a brief explanation.
     
    Data Driven Design is when you don't hard code any constants into the game but rather draw out all the "data" required for your game from external files such as .txt files, .xml files or databases. Pretty much any data you can think of can be stored in a database externally from the code such as the following examples
    Material Paths
    Model Paths
    Camera Follow Distance
    Prop Attachment Offsets
    UI element's, textures, scale, position, parent, target etc.
    Weapon model,
    Weapon Power
    Weapon Fire rate
    Game Settings & Key Bindings
    etc. etc. etc.

    Now anyone who knows me or has seen my posts and status updates would notice that I'm obsessed with Data Driven Design even to a point where it may even get annoying. However, I talk about it a lot for good reason. It is because the benefits of it are tremendous and it increases long term productivity and game design freedom to a new high not possible with simply coding constants.
     
    With data driven design you can store all your data in an easy to find place in a database and access it and edit it easily without having to touch your code. This means no more wading through thousands of lines of code but simply going through a logically setup database to find the data. Say you don't like the run speed of your character. You have to close the game find the speed variable and change the value. This could take a while to find in your code and you have to then recompile again. Then you load up your game and if its not good you have to repeat the process again. However with DDD you simply have to change the easy to find value in the database and restart the game.
     
    Another big pro is that you can easily make an every game with DDD. Why completely re-write the code for another RTS or FPS game if you have already coded one. With DDD you can simply change the models and values in the database and everything can look new without even recompiling. For an FPS game you can simply code only one gun, but have different stats and models in the database and already you can create pretty much any gun you'd ever want in an FPS.
     
    Well I've done a lot of rambling just then so here is a video of something I'm making called H.A.A.R.P. With HAARP I have combined the power of Finite State Machines with Data Driven Design and taken the whole thing one step further to come up with a solution that stops me from re-coding things, reducing my workload and increasing my productivity in the long term.
     

     
     
    I don't mind the time it will take to create this H.A.A.R.P implementation because as far as I've noticed so far the art assets get out of data 100x faster than code and this will allow me to concentrate more on making the game and less on coding once I've finished it so I will be able to get the art out quicker before it gets outdated.
  14. Road Kill Kenny
    As I have been developing the player editor for Elemental, I have come across a number of unexpected difficulties that were not initially obvious. I had a challenging time figuring out some of these bugs in my code so that I could get it just right. I really wanted the weapons to look like they are being held properly and armour pieces to deformed with the player without clippings like you would expect it to.
     
    There are two main types of mounting that I'm going to cover and one takes much more care and effort than the other. These two types are as follows:
     
    1. Mounting boneless static meshes (such as weapons)
    2. Mounting skinned deforming meshes (such as armour and clothing)
     
     
     
     
     
     
     
     
     
     
    Mounting Boneless Static Meshes
     
    This one is a bit of a cake walk but there were some difficulties that I came across when doing this.
     
    My method basically involves including bones in the player character mesh in the positions where the weapons would be placed. Figure 1 below shows these bones as they are in my current rig. I have created 1 bone in each hand and 2 bones on the characters back. The idea is that 'in game' the weapons will be parent to these pseudo bones so that the weapons simply follow in the characters hands or on their backback.
     

    Figure 1
     
    Here is some sample code showing the general idea:

    TModel wepL; TModel char; TEntity wepLBone; //Assuming the weapon bone is called wep_L //Find the bone wepLBone = FindChild(char, "wep_L"); //Set the matrix of the weapon to be same as bone SetEntityMatrix(wepL, GetEntityMatrix(wepLBone)); //Parent weapon to bone EntityParent(wepL, wepLBone);
     
    This method is very simple, however, if the bones are not initially set up properly, there will be complications. My mistakes were two fold. Firstly the scale of my bones was not 1,1,1 in Blender and I realised much too late. Secondly the orientation of x,y,z axis of the bones in Blender did not match the default orientation in LE. These two small mistakes made a world of trouble for a few reasons as I'll outline below.
     
    1. Wrong Scale:
    When you call SetEntityMatrix() it sets the scale as well as a number of other things. So because the scale of my bones was about (0.327,0.327,0.327) instead of (1,1,1), when I set the matrix of the weapon to the bone, it would scale the weapon down to 0.327.
     
    As an alternate to spending many hours re-doing the rig I decided to cut my losses and make a work around. For this problem it was simple. I just had to scale them up again immediately after with ScaleEntity();
    This was not ideal but I think going back and fixing the rig and redoing all the animations would have been a 'Bear Trap' as Josh has recently coined the term.
     
    One may think you could just use PositionEntity() and RotateEntity() to get the orientation right instead of SetEntityMatrix(). However, both of those functions do not work on entities that are children of another entity. They seem to return the position and rotation of the parent instead of the specific bone. This isn't entirely useful in this situation.
     
    The idea to go into blender and simply use ctrl+a to '0' the scale of the rig without actually effecting its size did occur to me. However, it badly affected the rig's orientation and was not a viable solution.
     
    The key learning here is: Always make sure your scale is (1,1,1) prior to doing any rigging, skinning and animations.
     
    2. Incorrect Bone Axis Orientation
    Simply put this problem occurred because the orientation of the bone axis in Blender were not matching that of LE. This was not Blender's fault but mine. I should have edited them correctly before skinning. The effect was that if you set the matrix of the weapon to the bone it would not line up. The model would always be moved to a relative position and rotation to the bone origin. See Figure 2
     

    Figure 2
     
    This meant that once I had set the matrix I had to tweak the position and rotation of the weapon model before parenting it to the bone. The coding of this was not all that hard but it was difficult figuring out which axis's did what and how much I had to tweak it. Imagine if Josh programmed Vec3(x,y,z) to read the x,y,z part in random orders and you'll have an understanding of how annoying this problem is.
     
    Once again I could have just redone the rig. However, that would have taken a very long time. Instead, I cut my losses and went for the work around. After all, the repositioning only has to be done once when the weapon is either taken out, sheathed or loaded and not every frame. Therefore, the performance impact is negligible.
     
    The Key Learning here is: Always ensure you have oriented the axis of your rig bones correctly before doing any skinning or animations.
     
    Mounting Skin Deforming Meshes
     
    Mounting armour and clothing is a bit of a different story as you can't simply parent the model to a bone as the mesh has to deform with a number of bones. This makes things a little more difficult. The way I did this was to skin the armour to the relevant bones and delete all the extra bones (eg. for the boots I only took the foot, toe and shin bones). Then my plan was to parent each of the individual bones in the boots to the corresponding bone on the character model. Figure 3 shows this.
     

    Figure 3
     
    Luckily, problem 2 from the static mounting was not a problem because, in this method we are parenting bones to bones instead of meshes to bones. As the bones on the boots and the bones on the character had the same messed up axis, they kind of cancelled each other out as they were in the same orientation relative to each other.
     
    Now there was only one major problem with this method and it involved the nature of parenting and animation recursion in Leadwerks. Simply put, when you animate a model in LE you set the recursion to 1 so that all children of the model are animated appropriately. Of course, this means that if I parent the boots bones to the character and animate the character, the recursion tells the boots to animate as well. Figure 4 shows how this looks. The right picture is with the boots parented and the left is without parenting.
     

    Figure 4
     
     
     
    The problem with this is that the boots only have a single animation frame which is the pose that it was exported with (or modelled in). So when the bones are parented they are moved into position but the animation causes the bones to move to their 'frame 1' positions again except relative to their parenting position.
     
    This may be a bit difficult to follow so I will demonstrate in the following video.
     
    Turn your sound up!

     
     
    As you could see my solution was to simply not parent the bones, but to just re-position them every frame. Although this probably takes a bit more processing poser I can't see any way of parenting the entity without the animation recursion stuffing it up.
     
    The key learning here is: Never parent bones to animated bones or else animation recursion will have your balls
     
    Thank you for reading. I hope you learned something useful. Feel free to comment or ask questions.
×
×
  • Create New...