Wednesday, 11 December 2013

Scripting and AI

Scripts are very high-level programming languages used to reduce the time it takes to compile code. These are usually files that can be opened with text editors like notepad, and can be edited. These scripts are used with programs and are loaded when the program runs. Scripts are usually used for data, loaded into the program such as variables that the user would typically initialize in code. Without the use of scripts, whenever the user compiles their code, changes a single variable and recompile their code again, the compiler will load in the whole program even though a single variable changed. This can become really tedious when debugging or balancing in video games (stats, weapons, enemy AI, etc). When a variable in a script is changed, all the compiler has to do is to reload the script again instead of all the code, and it will run instantly.

There are many different scripting languages, but one of the main scripting languages being used recently by a lot of developers is LUA.
Some features of LUA are:

  • Compiled to bytecode
  • Hot swapping
  • Highly embeddable
  • Highly customizable
  • Dynamic typing
Some Pros of LUA are:
  • Iteration Times
  • Expressivity
  • Designer-accessibility
Some Cons of LUA are:
  • Performance
  • Designer-accessibility
Scripts such as LUA give designers an easier time to balance or change attributes to the game itself without touch the code which really helps with the developing process. At the same time they can hinder or ruin the programmer's work by using the scripts. These scripts are essentially the pillars of the Engine itself and their components can be implemented in C++ or LUA. The scripts is basically a special sauce or the thing that glues everything together.

Typically scripts are used for data and what scripts should do are to save out the state of the scripts, drive the system with data and define the structure for both. LUA can define structures for engine-allocated data blocks, and the engine controls the lifetime of these blocks. LUA reads and write to the blocks but it is never allowed to allocate it's own dynamic memory. This essentially give the user a fluid design environment and it allows for the developers to put all their hacks, because every game has their own unique hacks or a "different" way to implement a feature.

 Generally what you want your scripts to deal with are:
  • Health/Damage/Death/Stats
  • Weapons/Equipment/Items/Abilities
  • Artificial Intelligence and Behaviours
  • Heads Up Display/User Interface/Menus
  • Missions/Levels/Objectives(Quests)
The difference between C++ and scripts is that C++ code is technology that can be used for other things such as for another game, it is a framework for your games. Scripts are the stuff the make the game unique from all the other games.

Scripts are also called DSLs or Domain Specific Languages which is a language designed to be highly adept at solving a specific class of problems these can include LUA, Python, Lisp, etc. DSLs are used for AI because firstly, for code cleanliness and the effects of mapping code directly into the problem, secondly, it eliminates low-level concerns that do not apply to the specific problem and finally, it speeds up productivity and removes excess overhead  that are not related to the problem.

The benefits for avoiding low level issues is that there is no manual memory management in code, no complex syntax and no complications such as undefined behaviour. It doesn't require a high level of knowledge in programming and it reduces the probability of severe bugs to occur in the code. DSLs should be simple that even the user with basic programming knowledge can use it. The goal of using DSLs is to place all data and logic into the DSL and out of the core engine code. 

The first things to do when created a DSL is to:
  • Identify the core problems the AI must solve
  • Select algorithms and solution for each problem
  • Break down the solutions into discrete chunks
  • Implement DSL concepts for each chunk
When implementing DSLs it is ideally better to keep syntax simple and clean, deploy simple code for parsing, map syntax elements to constants or classes and excute the DSL code in some fashion. The syntax should be able to parse easily, everything should be easy to understand and must make sense and use specific operations rather than general ones. 
When executing DSLs build a miniature interpreter, embed the DSL in C++, Lua, etc. or compile to another language. 

Everyone can benefit from the use of DSLs. Programmers have a safer environment, Junior team members can do critical AI work, Designers can write logic directly, code reviewers will be less burdened and QA testing will be optimal.


Monday, 9 December 2013

Nav Mesh

Navigation is important when developing video games because it creates an immersive and fun experience and Non-playable Characters (NPCs) play a huge roll in this. With navigation, it allows for NPCs to be able to "sense" the location around them, and react according to the situation. This allows for less scripting when trying to create AI and also create a more dynamic AI because instead of following a script on how the NPC should move, it reacts to the world itself.

The most basic use of an NPC command, is to go from point A to point B. The  steps used for this are:

  1. NPCs figure out their location relative to the world
  2. Get the coordinates of the point the NPC will travel to
  3. Find a path to the destination
  4. Scan for any objects that will be in the way of the NPC
Other uses for AI/NPC navigation is target scanning, monitor threat perception, determine spawn locations, and the ability to reuse levels.

Insomniac games uses navigation by:

  1. Game AI: set up NPC's navigation requirements (e.g. Go-To Command)
  2. Navigation: Path-Finding & smoothing
  3. Steering: Locate Obstacles in the path and avoid them
  4. Game AI: Transform steering output to animation-input
  5. Final Position & Orientation of NPC
Nav meshes are used as a layout of the level, that are used for AI navigation. These Nav meshes are divided into sections where the AI navigates through them to go to their end point. These sections also have properties such as elevation or areas where the AI will not go such as certain building roofs where the enemies can climb or jump to, or areas such as lava or water where the enemies will avoid.
To move around these sections in Resistance 2, A* is almost always used because hardly 10% of the nav SPU budget was used for it even with their coop mode with a maximum number of 100 NPCs using navigation on screen.

The AI steering in R2 was light weight or simple and barely satisfied the needs of the programmers/designers. The main issue Insomniac focused on was the issue where when animation around corners did not slow down enough and  a NPC had to not only get to the first bend point but also orientate towards the bend point along the path. What they used to fix this problem was using a bezier curve approach for the bend points. The used of bezier curves ensured that the NPCs will stay on the nav-mesh.

There are many areas of a level where a nav mesh alone will not be enough for navigation. Objects such as ladders, tunnels or actions such as teleporting or jumping will not work with the current nav mesh, because these are considered non mesh links. To fix this problem, Insomniac uses a custom clue boxes which help connect that specific point to the actual mesh itself.


This picture shows that there is a custom link where the AI is suppose to jump, so a custom clue is added at the bottom of the jump, and at the top of the jump. This lets the NPC jump up onto the high level mesh or jump down to the lower level mesh. Although this does have a problem where multiple NPCs will be using this custom link. Instead of creating multiple custom links around the edges, there are other alternatives such as finding a different path. 



This picture shows there is a hybrid climbing through the window, which is the most effective path to get to the 2nd floor, but since its occupied, another path opens up allowing for the 2nd hybrid to use this path (the door way) to get to the 2nd floor. Not only does is this efficient in terms of having multiple enemies able to navigate at once, it creates dynamic gameplay where there are enemies coming form multiple different paths. 

To create a nav mesh there are a few steps:
  1. Voxelize the scene geometry
  2. Build navigable voxels
  3. Clear Voxels NPC height above and below custom-override-polys
  4. Render custom-override-polys into the best filtered voxel grid
  5. Build watershed partitioning
  6. Trace catchment basin's contours with filtering
  7. Triangulate/tesselate to generate the nav mesh
Custom-override-polys are meshes created by the designers to fix areas of the original mesh that are disconnected or unwanted areas of the mesh. They basically override what the original mesh was in the unwanted area, and replaces it with the custom mesh to create a final desirable mesh that can be used for the game.



Nav meshes are really helpful when the developers want dynamic AI for their NPCs. It lets the NPCs use the level fully and create a more dynamic gameplay for the players. Nav meshes remove the need to use boring linear pathing since it allows the NPC do what they want, depending on the situation. It is always changing and different so the player cannot predict easily what the enemy's behaviour will be.



Friday, 6 December 2013

Ogre Particles Scipts

In our game, Bullet Devil: Attack of the Elements, we will be using the particle system with the Ogre engine. What we will be mainly using them for is to show off the effects of our elemental attacks in the game. One of the core mechanics we have in our game is the use of elements, where elements counter each other to deal extra damage as well as have unique effects. Other uses for the particle system is to create more appealing visual effects on things such as when a player shoots, or for our enemies making them look more fantasy like.

Currently, in our game we have 1 working particle effect that we are quite satisfied with, and that is our ice effect which has blue snowflakes and moves upwards around a character. What this effect shows (and what other elemental particles will show), is that that character (player or enemy) has been hit with that elemental attack and has a status effect now.


Ogre Particles uses their own scripts to setup attributes for their particles. These attributes include the amount of particles the user wishes to emit, the size of the particles, the type of emitter, the velocity of the particles, and many other attributes. By changing values and adding new attributes to their particle script, the user can create a large variety of particles.  

To create a particle script, the first thing the user must do is to create a text document but instead of ending the file name with .txt, the user should end their text document with .particle because ogre parses .particle files automatically. In the ogre particle script there are 2 main parts, the particle properties section and the emitter section. The particle properties section deals with the size of the particle, the amount of particles to be created per emitter, how many emitters the user wants. The emitter section has the type of emitter (usually box or point), the angle of where the particles will be emitted from, the rate that they will emit, the time each particle will live, the up direction of the particles and velocity. Of course there are many other attributes but these are most commonly used for most particle systems. 




This is a fireworks particle script using ogre particles. One thing unique about this script is that there are 2 emitters, this is because for fireworks, there are 2 parts to it, when the fireworks are shot into the air, and then the explosion. The affectors are what functions that will effect the particles in some way. This specific one interpolates 2 colours together to change the particle from 1 colour to another. 

The first thing in your .particle file is to write what your particle script will be called at the top of your file using particle_system particleScriptName{}, replacing particleScriptName with the name of your own particle script. Next is to get a material or picture of your particle, from a separate .material file (can also be edited with a text editor). Particle_width and particle_height change the size of the actual particle. Quota is the number of particles to be emitted. Billboard_type is how the particles will be rendered and orientate, the point billboard is used if you want the particles to orientate towards the camera. 

For emitters, you start with the emitter type, in this case it is a box, so the script is emitter Box {}. The first attribute for this box emitter is the name of the emiiter. This emitter has a special case because it emits a second emitter called explosion. Angle deals with the range where the particles can spread, 0 being one direction to 180 being the around the emitter. Emission rate is how many particles per second should be emitted, (I've found out from my own experience and asking someone else that your emission rate should be 1/10 of your quota). Time_to_live is self explanatory. Direction is where the up vector is for your emitter. Velocity is the speed of your particles. 

There are many more attributes to explain and most of them have a predefined value when they are not defined in the script itself or in some cases, if the values are set to 0. I can't explain every single attribute for ogre's particle script but they all can be found through Ogre's manual from their SDK (which I use frequently). It has many attributes that I still haven't tested myself, but I do plan to experiment with these to create more interesting particle effects.