📜 ⬆️ ⬇️

Game Maker AI - How to start?

Game Maker is a development platform (in the initial concept of 2D) games. At the moment, the most popular Game Maker 8.0 \ 8.1 and Game Maker Studio. The latter, by the way, supports cross-platform development (which, probably, is almost the only factor in the survival of the engine as a whole).

Recently, GM has been losing its popularity in the shadow of such giants as Unity3D / Cryengine / Unreal. I think the loss of demand for this engine is completely unreasonable, because to create many games (for example, for Android) there is no need for the latest 3D development technologies and other "unnecessary" functions that are very demanding of the user's system. When using Game Maker to develop such games, you can achieve a sufficiently high performance without visible sacrifices from the graphics or functionality.

So, more to the point. For some time I have been developing games in the GM environment. And one fine day I faced an interesting task - to develop an acceptable AI for the TDS (Top Down Shooter) game. Frankly, until that moment I did not come across the development of artificial intelligence, and the task at first just put me in a dead end. I spent the next three days looking for a solution (of course, by trial and error), and I learned quite a lot during these 3 days. Based on my short and painful experience, I will try to describe the main methods and third-party libraries for developing AI in Game Maker.

Embedded Game Maker Tools

Undoubtedly, GM offers its own AI development tools (on which third-party libraries are built later). It was with them that I began my journey into the world of Artificial Intelligence. These tools include path finding, distance and direction angle, and collision check functions (in my opinion, the most useful of all of the above).
A small classification of GM functions:
')
Move

mp_potential_step(x,y,stepsize,checkall) //   (x,y)   ( ) stepsize //checkall ,       (0),     (1) mp_linear_step_object(x,y,stepsize,obj) //  .   ,         obj 

As for me - very useful features, though not always. When using them, several points should be considered:
First, the object collision mask (the parameters are set in the object's spite settings).
Secondly, I strongly advise against using these functions to search for complex paths (for example, in a maze). As a rule, in such cases the performer “sticks” in the first object and tries to pass through it.
These functions should be used when searching for a shortcut on a site without a large number of solid objects.

 mp_potential_path(path,xg,yg,stepsize,factor,checkall) //       -       "   ",        (    path).      ,     

This function has one big advantage over the previous ones - if the search for the path fails, the movement does not occur. This will protect the artist from "sticking into the wall." The minus itself is that this function returns the finished path that the performer must pass. This cannot be definitely called a minus, but, say, during the battle to use the paths is extremely costly and inconvenient.

Grid Method:
The grid-based method is a very powerful tool (and is used mainly in professional games), but it requires you to do all this, thinking very carefully. You must determine which area and cell size will match the optimal solution for your game. You must also determine which objects should have an accurate collision check, this is important. All these parameters strongly influence the efficiency of the method.
- quote from GM help

Indeed, the grid is a very handy tool when designing paths. It is much more reliable than the same potential_path (since it always finds a way, if it exists). There would be a whole article left for working with the grid, so I will try to limit myself to the “minimum”:

 mp_grid_create(left,top,hcells,vcells,cellwidth,cellheight) 

The function creates a grid and returns.
cellwidth, cellheight - cell size

After creating the grid, it is worth adding forbidden zones. I used a fairly simple function for this:
 mp_grid_add_instances(id,obj,prec) // ""  ,      obj, prec ,       , id -      

This is a very convenient function, because when developing games, all “hard” objects that cannot be passed through are assigned a common parent object. If you specify this object in a call to this function, all child objects will also be checked.

So, we have a grid with impassable zones. Now it's up to you to calculate the path for our performer:

 mp_grid_path(id,path,xstart,ystart,xgoal,ygoal,allowdiag) //    (xstart,ystart)   (xgoal,ygoal)      path. allowdiag -       (    ) 


Our path is ready, if it exists of course. The minus is the same - this is the way (albeit a more correct, accurate, reliable way), and nothing can be done about it.

At first, I really liked the grid method, and it has the right to life, but not in the game of my genre (in most cases). In combat, this method is also not applicable, as is the potential_path. But in this way you can make ways for patrolling out of combat, or, for example, searching for a player after losing sight of.

Determination of distance and direction

Everything is quite simple here, only a couple of functions are responsible for this:

 point_distance(x1,y1,x2,y2) //    (x1,y1)   (x2,y2) point_direction(x1,y1,x2,y2) //    (x1,y1)   (x2,y2)   


Of course, these are not the only functions for working with distance and direction, but in most cases they are quite sufficient. Also during the search, I found a curious script that determines the difference between directions in degrees (very useful when checking for the presence of an enemy in the field of view of the contractor):

 //argument0 -   //argument1 -   var diff; diff = (argument1 - argument0) mod 360; if diff < 0 diff += 360; if abs(diff) > 180 return (360 - abs(diff)) * -sign(diff); else return diff; 


Collision check

There are several (similar) functions for determining collisions of objects with each other. It is unlikely that they can be used to determine the path, but, say, with the implementation of the shooting (of any kind of shooting) they are simply irreplaceable.

 collision_point(x,y,obj,prec,notme) //,     (x,y)    obj. prec -  , notme -    (1) collision_line(x1,y1,x2,y2,obj,prec,notme) // .    ,        (x1,y1)  (x2,y2) collision_circle(xc,yc,radius,obj,prec,notme) //         (xc,yc)   radius 


In my opinion, these functions do not need additional explanation. I can only say that they are convenient to use in the implementation of the shooting, or radar, or some guidance system for AI.

Third Party Libraries

Finally, GM’s built-in tools are behind, and you can set sail for free - into the world of libraries. Although not everything is so rosy, for there are not so many libraries for developing AI. I will try to list all that I managed to find.

Tds ai lib

TDS AI is a straightforward name for a library designed to develop AI in TDS games. In fact, this is just a collection of fairly frequently used functions that are embedded directly into the GM interface.

TDS AI functionality:


In circulation, the library is quite simple (with minimal knowledge of English, of course). With the help of this library, the executor can “teach” such things as turning toward the object , following the object , evading the object (perhaps it makes sense to use even for evading shots), checking the distance to the object and having it in sight , also random move .

This is where the library’s functionality ends. Verdict: convenient, easy to use, but not enough. After all, AI - not just a set of functions.
* link to the library can be found at the end of the article.

Behavior Tree AI

After TDS AI, I came across a few more libraries and examples, but none of them deserved attention in this article. Honestly, I was desperate - do I really have to develop the AI ​​system myself (a convenient, extensible system)? From such a thought was terrified, because I had absolutely no experience in the development of artificial intelligence.

But a miracle happened, and quite by chance I came across this masterpiece. At first, I did not fully understand its meaning, but it became interesting to me. I downloaded the source with an example, and after half an hour of studying the code, I realized that something really unique came to me. Behavior Tree is not just a set of useful functions, it is a whole system for developing AI. It is here that the structural approach to the creation of AI, necessary for convenient operation and expansion, is implemented.

On the description of the possibilities of BT AI will leave an entire article. Moreover, such an article is already there, a link to it can be found at the end of my article. Based on this, I will try to explain only the basics.

So what is the point? As I said, the essence is in the structural approach. AI, based on this library, is constructed as follows:
  1. The performer is chosen
  2. The main AI script is created. In this script, the functions are executed depending on the conditions.
  3. An update script is created that is required to continuously update the parameters used in the main script (for example, whether the executor is in battle, his HP and other parameters)
  4. In the event of creating an artist, the main script and update script are installed.
  5. In the event of a step (a kind of permanent timer) the executor is called to repeat the script


The main script works on the choice-condition-action system (selector-condition-action).


A small example of the main script BT AI:

 SelectorBegin('AI Role 1'); SequenceBegin(''); //     id Condition(SeeEnemy && Enemy>0); //   Action( Action_LookAt, point_direction(x,y, Enemy.x, Enemy.y)); //    2  Action( Action_Shoot, point_direction(x,y, Enemy.x, Enemy.y), 2); SelectorBegin('   '); // SequenceBegin('  '); Condition(point_distance(x,y, Enemy.x, Enemy.y)>256); Action(Action_MoveTo, Enemy.x-lengthdir_x(128, direction), Enemy.y-lengthdir_y(128, direction), highSpeed); SequenceEnd(); // SequenceBegin('  '); Condition(point_distance(x,y, Enemy.x, Enemy.y)<64); //  Action(Action_MoveTo, x-lengthdir_x(64, direction), y-lengthdir_y(64, direction), highSpeed); SequenceEnd(); SequenceBegin(''); //  ,     Action( Action_MoveTo, x+irandom_range(-64, 64), y+irandom_range(-64, 64), highSpeed); SequenceEnd(); SelectorEnd(); //    4  Action(Action_Shoot, point_direction(x,y, Enemy.x, Enemy.y), 2); SequenceEnd(); SelectorEnd(); 


Selector - operator selection action set
Sequence - a set of actions
Condition - condition check
Action - action. script call (first argument) with parameters (remaining arguments)

Conclusion

Finally, I’m ready to repeat that Behavior Tree is my best find in Game Maker’s AI area, and I strongly advise its use. It is on it that the same AI that I needed to do was implemented.
It would be foolish to deny that there are many other systems for developing artificial intelligence, and many of them could just pass by my attention. I would be very happy with valuable additions to my article, as well as indications of my mistakes, if any.

Thank you for attention!

Links

Source: https://habr.com/ru/post/196140/


All Articles