XFjG-J,RbdBX ( @ (//(  0/80@0?/8 0( ?G@POWOXOP?H0@/7@O_``h_hPX 0(P_oppxow_g@O/8'' 7p`o?G/7 0??H/8`/o?GOX@H0?/pOW?H/8 7OP?G/7( P0@PX@O0@ 0O @H/@' 00@@P0?'_OP@H( 7/7' ^^^^^^^^^^^^^^^^^^^^^^^^^^TeeBBBBeTT^^^^^^^eBDJ33333JJDBeZ^^^^TD33==#####==3JDBT^^^^eJ=###=3DeZ^^TB3# #=3JBZ^^T3#  #=JBT^^J# Sll #=JBZ^T# %,68??86,/@A*< ##45('.6787-9%:;*<=#$+&,--.,/01)2 3 $%&&'%($!)* ##  !"#     ??d76ŗ]C@ good_guy_spr  xՖ; D{'͐!(]fi cت=F[[4;[x/\Sk 5cIʻ&f~ֈ9\G@y 5-n 9i;ӊؑ)JA~p?K/ `vzr2D bad_guy_spr  xՖ; qٸ{'͔AJk6eM„eE26(2xMqrR"(@Fti_5GNi9#AI5mn #pj_cv(bC?Qi~J˽??xZtx;+Kգ+,p U& blocking_spr  Xxs5a3 b(fdH@Q@5P@Ul [A;V?j揚?j揚O]i>Cs direction_limiter //argument0 = direction; while (argument0 < 0) { argument0 += 360; } while (argument0 > 360) { argument0 -= 360; } return argument0;  blocking_obj  good_guy_obj [emy_health = 100; can_attack = 1; turn_speed = 15; move_speed = 8; global.info = 0; nearest = -1;0000000[can_attack = 1;0000000[Oif (instance_exists(bad_guy_obj) == true) { nearest = instance_nearest(x,y,bad_guy_obj); } if (keyboard_check_direct(vk_up) == true) { move_contact_solid(direction,move_speed); } if (keyboard_check_direct(vk_left) == true) { direction += turn_speed; } if (keyboard_check_direct(vk_down) == true) { move_contact_solid(direction_limiter(direction+180),move_speed); } if (keyboard_check_direct(vk_right) == true) { direction -= turn_speed; } if (keyboard_check_direct(vk_space) == true) { if (nearest > 0) { if (point_distance(x,y,nearest.x,nearest.y) < 50) { if (can_attack == 1) { nearest.my_health -= 1; can_attack = 0; alarm[0] = 5; } } } } image_angle = direction;0000000[draw_sprite_ext(sprite_index,image_index,x,y,image_xscale,image_yscale,image_angle,c_white,image_alpha); draw_text(x - 5,y + 15,string(my_health)); 0000000I[Yif (global.info == 1) { global.info = 0; } else { global.info = 1; } 0000000 bad_guy_obj [move_speed = 2; //max movement per step max_dist_start = 500; //max distance allowed to roam from start position flee_dist = 400; //distance to flee when hurt sight_dist = 300; //distance at which we can detect player attack_dist = 50; //distance at which we can attack player max_health = 10; //max health for bad guy my_health = max_health; //set current health to max health flee_health = 5; //bad guy will flee if health is less than this health_regen = 0.025; //amount of health to regenerate per step my_damage = 5; //amount of damage we do to player can_attack = 1; //trigger to allow us to attack attack_speed = room_speed; //speed at which we attack think_time = room_speed * 20; //time before we choose new roam location //set starting locations startx = x; starty = y; //init other location variables, these are set properly later roamx = x; roamy = y; fleex = x; fleey = y;0000000[*can_attack = 1; //allow us to attack again0000000[var rand,rand1; //setup some temporary variables //set random distance and direction rand = floor(random(max_dist_start)); rand1 = floor(random(360)); //set roam location to random point roamx = startx + lengthdir_x(rand,rand1); roamy = starty + lengthdir_y(rand,rand1); //keep re-choosing random location until it lies within the room while (roamx > room_width || roamy > room_height || roamx < 0 || roamy < 0) { rand = floor(random(max_dist_start)); rand1 = floor(random(360)); roamx = startx + lengthdir_x(rand,rand1); roamy = starty + lengthdir_y(rand,rand1); //further fine time roam location, so that it does not lie within a wall while (place_free(roamx,roamy) == false) { rand = floor(random(max_dist_start)); rand1 = floor(random(360)); roamx = startx + lengthdir_x(rand,rand1); roamy = starty + lengthdir_y(rand,rand1); } } //the above set of while loops are quite a bad way of doing this, but it works well for the example. as the locations are completely //random there is theoretically a chance it will never find a good location and crash the game. alarm[0] = think_time; //reset alarm0000000[ var tempx,tempy; //setup temp variable for death code at bottom //if we cant see player if (point_distance(x,y,good_guy_obj.x,good_guy_obj.y) > sight_dist || collision_line(x,y,good_guy_obj.x,good_guy_obj.y,blocking_obj,1,1) > 0) { if (my_health == max_health) //if we are at full health { mp_potential_step(roamx,roamy,move_speed,false); //move towards roam location } //regenerate health my_health += health_regen; if (my_health > max_health) //ensure health isnt above max { my_health = max_health; } } else //if we can see player and player is within sight range { if (point_distance(x,y,good_guy_obj.x,good_guy_obj.y) > attack_dist) //if player is outside of attack range { if (my_health > flee_health) //if we dont want to flee { mp_potential_step(good_guy_obj.x,good_guy_obj.y,move_speed,false); //move towards player } } else //if player is within attack range { if (can_attack == 1) //if we can attack { good_guy_obj.my_health -= my_damage; //deal damage //down allow us to attack again until alarm[1] is triggered can_attack = 0; alarm[1] = attack_speed; } } } //if we need to flee because of health, and player is close if (my_health < flee_health && point_distance(x,y,good_guy_obj.x,good_guy_obj.y) < flee_dist) { //choose a location to flee towards that is on the opposite side of starting location to player fleex = startx + lengthdir_x(max_dist_start,direction_limiter(point_direction(startx,starty,good_guy_obj.x,good_guy_obj.y) + 180)); fleey = starty + lengthdir_y(max_dist_start,direction_limiter(point_direction(startx,starty,good_guy_obj.x,good_guy_obj.y) + 180)); mp_potential_step(fleex,fleey,move_speed * 1.5,false); //move towards flee location } //if we are close to roam location if (point_distance(x,y,roamx,roamy) <= move_speed+1) { alarm[0] = 1; } //make sprite point in direction we are moving. this is a very cheap way of doing this, not accurate at all. but this is not the point of the example image_angle = point_direction(xprevious,yprevious,x,y); //if we have been killed if (my_health <= 0) { //set random location to spawn new enemy tempx = floor(random(room_width)); tempy = floor(random(room_height)); //ensure random location does not lie inside a wall or the player, and that it is not too close to the player while (place_free(tempx,tempy) == false && point_distance(tempx,tempy,good_guy_obj.x,good_guy_obj.y) < sight_dist) { tempx = floor(random(room_width)); tempy = floor(random(room_height)); } instance_create(tempx,tempy,bad_guy_obj); //create new bad guy instance_destroy(); //destroy ourselves } 0000000[<//draw our sprite draw_sprite_ext(sprite_index,image_index,x,y,image_xscale,image_yscale,image_angle,c_white,image_alpha); //draw our health draw_text(x - 5,y + 15,string(my_health)); //if AI information should be shown if (global.info == 1) { //start location draw_set_color(c_black); draw_circle(startx,starty,2,1); draw_circle(startx,starty,4,1); draw_circle(startx,starty,6,1); draw_point(startx,starty); draw_set_color(c_blue); //flee location draw_circle(fleex,fleey,4,1); //max roam distance draw_circle(startx,starty,max_dist_start,1); draw_set_color(c_aqua); //roam location draw_circle(roamx,roamy,4,1); //sight range draw_circle(x,y,sight_dist,1); draw_set_color(c_red); //attack range draw_circle(x,y,attack_dist,1); draw_set_color(c_black); }0000000room0         @ˆ@̆@͆` І`@ӆ@ ن@@چ@`ۆ``܆`݆`ކ  ``  @@@@@@ ````@@   @    `@@` `!"%+, 012345678 9@:@; =@> @?`@`A`B`CDE F@G`HIJKLM N@OQ`R@`S `T`U`V`W`X`Y``Z@`[ `\`]^_`a b@cefg@i`j`k`l@m@n ps v wxyz {@|`}`~@  ``` `@`@ @`XGame InformationX {\rtf1\ansi\ansicpg1252\deff0\deflang3081{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\fnil Arial;}} {\colortbl ;\red0\green0\blue0;\red0\green0\blue255;\red128\green255\blue255;\red255\green0\blue0;} \viewkind4\uc1\pard\cf1\fs24 Basic A.I. by TemplarGFX \par \par this is an example of how program basic A.I. into an enemy. \par \par what this A.I. does : \par \par \par While avoiding walls, it roams around its starting position, as long as : \par A) The Player is outside its sight range or \par B) It cannot see the player due to walls and \par C) its not hurt \par \par It will come after the player to attack (while avoiding walls) as long as : \par A) Its not hurt \par B) It can see the player \par C) The Player is within sight range \par \par It will attack the player if the player is close enough \par \par If its health is lower than a set amount, it will flee from the player stopping at a safe distance \par while the player is either out of sight range, or not in line-of-sight, health will regenerate \par \par \f1 \par \f0 Additional information for example : \par \par Control the "Good Guy" with the cursor keys \par Attack with Space \par \par health displayed under both "Good Guy" and "Bad Guy" \par *note Good Guy has health, but absolutely nothing happens if health reaches or drops below 0 \par \par \par press \b i\b0 to toggle visual AI information as follows : \par \par Small set of \b Black\b0 circles = Starting position \par Small \cf2\b Blue \cf1\b0 circle = Flee destination marker (this is almost never actually reached by the AI, used more for direction) \par Large \cf2\b Blue \cf1\b0 circle (centred on starting position) = Maximum roam distance \par Small \cf3\b Aqua \cf1\b0 circle = Roaming destination \par Large \cf3\b Aqua \cf1\b0 circle (centred on Bad Guy) = Sight range \par Medium \cf4\b Red\cf1 \b0 circle (centred on Bad Guy) = Attack Range \par \par there are many things done here that \i could\i0 be done a better/more efficient way, but this example is not intended to be used directly, more for you to study and learn from to create your own basic AI. \par \par good_guy_obj has no commenting on code, as this is not part of the AI \par The comments in bad_guy_obj talk about player, in this example player is good_guy_obj \par \par \par also note, there is a script in this example called direction_limiter(). this script takes any number (generally a direction) and ensures it lies between 0 and 360. \par \par \b Please, if you use ANY of this in a game in your own, please credit myself (TemplarGFX) \par \par thankyou and I hope this helps someone\cf2\f1 \par } Sprites good_guy_spr bad_guy_spr blocking_sprSounds BackgroundsPathsScriptsdirection_limiter Fonts Time LinesObjects blocking_obj good_guy_obj bad_guy_objRoomsroom0 Game Information Global Game Settings