© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2023
B. TyersGameMaker Fundamentalshttps://doi.org/10.1007/978-1-4842-8713-2_17

17. AI

Ben Tyers1  
(1)
Worthing, West Sussex, UK
 

Most games will have an enemy that exhibits some basic AI (Artificial Intelligence). This chapter serves as an introduction to some basic AI.

Some of the functions the AI may have:
  • Avoid the player

  • Guard an area and attack the player if they get too close

  • Calculate the best play in a card game

  • Shoot a projectile at the player

  • Shoot at a player if they see them

Generally, you will evaluate some code and determine if it is true or false (or some other value) and make something happen as a result.

This section will start with a basic system and will add more features in stages.

Make three very basic sprites (32x32 in size) spr_wall, spr_player and spr_enemy, set the origin as center, then assign them to obj_wall, obj_player, and obj_enemy.

Open up obj_player and place the following code in its Step Event:
/// @description movement
var hor=4*keyboard_check(vk_right)-keyboard_check(vk_left);
var vert=4*keyboard_check(vk_down)-keyboard_check(vk_up);
if !position_meeting(x+hor+(sign(hor)*16),y,obj_wall)
{
      x+=hor;
}
if !position_meeting(x,y+vert+(sign(vert)*16),obj_wall)
{
      y+=vert;
}

The preceding code will provide basic movement and prevent the player moving through a wall object.

Basically the code uses a key press and that there is not a wall in the way, if there is not, then it’s position is changed. sign(value) returns -1 for a negative value and 1 for a positive value. It is not perfect, but it will suffice for testing.

An example usage of sign()would be for setting the image_xscale of an instance so it points to the correct direction when moving left or right.

For example, the following in a Step Event:
/// @description Example
if keyboard_check(vk_left)
{
      hspeed=-2;
}
if keyboard_check(vk_right)
{
      hspeed=2;
}
dir=sign(hspeed);
image_xscale=dir;
Set up the room like that shown in Figure 17-1.

An illustration of room setup in gird form with some blocks arranged as a maze and an icon to travel through the gaps.

Figure 17-1

Example room set up

Check the movement works by testing.

Basic Enemy AI

Next, we’ll set up an enemy obj, place the following in its Create Event:
/// @description Set Flag
can_see=false;

This code will set an initial flag. We’ll use and change this when the enemy can or can’t see the player.

In the Step Event of this object, put the following code. This will check for a line of sight to the player. If the player is not hidden behind a wall, the enemy will move toward the player:
/// @description if there is a direct line of sight  to the player
if (collision_line(x, y,obj_player.x,obj_player.y, obj_wall,true,false))   !=noone
{
      can_see=false;
}
else
{
      can_see=true;
      mp_potential_step_object(obj_player.x, obj_player.y, 5, obj_wall);
}
Finally create a Draw Event for this object with the following code, just for testing:
/// @description Drawing code
draw_self();
if can_see
{
      if distance_to_object(obj_player)>2 mp_potential_step (obj_player.x,obj_player.y,2,true);
}

This will draw its own sprite, and a line between itself and player if can_see is true.

Load snd_ouch from the resources.

Place the following in obj_enemy with a Collision Event with obj_player:
/// @description Play audio
audio_play_sound(snd_ouch,1,false);
instance_destroy();

The preceding code will play the sound snd_ouch upon collision with the obj_player, and then destroy itself.

Place a few extra instances of obj_enemy, as shown in Figure 17-2 and test so far.

A testing gird with some blocks arranged as random shapes.

Figure 17-2

Showing additional obj_enemy added

Enemy Shooting

Next create a sprite spr_bullet from the resources, rotate, and set the size as 32x13 as shown in Figure 17-3.

An illustration of the sprite bullet settings. It has 3 options in a column and has a magnified image on the working space.

Figure 17-3

Setting up a bullet sprite

Assign this sprite an object obj_bullet.

Put this code in a Collision Event with obj_player:
/// @description On collision
audio_play_sound(snd_ouch,1,false);
instance_destroy();

plays a sound and destroys itself upon collision with obj_player

Change the Create Event of obj_enemy to:
/// @description Set Flag
can_see=false;
can_shoot=true;

sets an additional flag for shooting control

Change the Step Event of obj_enemy to:
/// @description if there is a direct line of sight  to the player
if (collision_line(x, y,obj_player.x,obj_player.y, obj_wall,true,false))   !=noone
{
      can_see=false;
}
else
{
      can_see=true;
      mp_potential_step_object(obj_player.x, obj_player.y, 5, obj_wall);
}
if can_see && can_shoot
{
      bullet=instance_create_layer(x,y,"Instances",obj_bullet);
      bullet.direction=point_direction(x,y,obj_player.x,obj_player.y);
      bullet.image_angle=bullet.direction;
      bullet.speed=5;
      can_shoot=false;
      alarm[0]=room_speed*3;
}
Finally, pop in an Alarm[0] Event with the following:
/// @description Allow shooting again
can_shoot=true;

Set flag so it can shoot again.

Now test the game, if an enemy has a line of sight to the player, it will shoot a bullet every three seconds.

Basic Projects

  1. A)

    Set an instance that moves randomly left and right across the top of the window (wrapping as needed). Set it to drop a collectible object every five seconds. Player to collect these items. Draw a basic HUD on screen.

     
  2. B)

    Set up a player that can be moved with arrow keys. Set an enemy to shoot projectiles at the player, getting more frequent as the player gets closer. Destroy projectile when outside room.

     

Advanced Projects

  1. C)

    Set an enemy that changes direction every five seconds away from the player.

     

Useful Functions

collision_rectangle(); Allows you to get a list of all instances in a gen area

collision_line_list(); Returns all instances that collide with a line

point_in_circle(); Return instances within a circular region

point_in_rectangle(); Return true or false, depending on whether a given coordinate falls in an area

point_in_triangle(); Returns instances within a triangular region

Summary

You now know some basic functions to make enemies react to player input and positions. You can gradually build upon this to create more complex enemy interactions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.252.199