Gamestudio Links
Zorro Links
Newest Posts
M1 Oversampling
by 11honza11. 04/30/24 08:16
Trading Journey
by howardR. 04/28/24 09:55
Zorro Trader GPT
by TipmyPip. 04/27/24 13:50
Help with plotting multiple ZigZag
by M_D. 04/26/24 20:03
Data from CSV not parsed correctly
by jcl. 04/26/24 11:18
Why Zorro supports up to 72 cores?
by jcl. 04/26/24 11:09
Eigenwerbung
by jcl. 04/26/24 11:08
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
2 registered members (AndrewAMD, Quad), 500 guests, and 4 spiders.
Key: Admin, Global Mod, Mod
Newest Members
wandaluciaia, Mega_Rod, EternallyCurious, howardR, 11honza11
19049 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Page 1 of 3 1 2 3
purrfect ai lite-c #267220
05/22/09 15:43
05/22/09 15:43
Joined: May 2009
Posts: 1,816
at my pc (duh)
darkinferno Offline OP
Serious User
darkinferno  Offline OP
Serious User

Joined: May 2009
Posts: 1,816
at my pc (duh)
@george: has the purrfect AI code from aum 64 been converted to lite-c has yet? if so, where can i find it, if not, do you plan to do a conversion? i started with 3dgs when lite-c came out, i havent played with c-script...

has anyone else converted this?

Re: purrfect ai lite-c [Re: darkinferno] #267223
05/22/09 15:48
05/22/09 15:48
Joined: Aug 2004
Posts: 1,345
Kyiv, Ukraine
VeT Offline
Serious User
VeT  Offline
Serious User

Joined: Aug 2004
Posts: 1,345
Kyiv, Ukraine
Yes, it works for me in lite-c, but its deep in the project, so i'd lost a lot of time, extracting it from vars and so on.
The best way for you is to rewrite it by yourself smile


1st prize: Lite-C and Newton 2.17 by Vasilenko Vitaliy

Newton2 videos: http://tinyurl.com/NewtonVideos
LiteC+Newton2 discussion: http://tinyurl.com/NewtonWrapperDiscussion
Latest LiteC+Newton2 version(v23, from 29.10.2009): http://depositfiles.com/files/ae1l0tpro
Re: purrfect ai lite-c [Re: VeT] #267224
05/22/09 16:04
05/22/09 16:04
Joined: Oct 2007
Posts: 5,210
İstanbul, Turkey
Quad Online
Senior Expert
Quad  Online
Senior Expert

Joined: Oct 2007
Posts: 5,210
İstanbul, Turkey
well if you show me what exactly you want to be converted, i will try to convert.


3333333333
Re: purrfect ai lite-c [Re: Quad] #267225
05/22/09 16:11
05/22/09 16:11
Joined: May 2009
Posts: 1,816
at my pc (duh)
darkinferno Offline OP
Serious User
darkinferno  Offline OP
Serious User

Joined: May 2009
Posts: 1,816
at my pc (duh)
@vet: i'd love to rewrite it myself but its pretty deep and i'd hate having to use c-script smile maybe if i was already a c-scipt user going to lite-c it wouldnt be that bad but i dont think i want to learn c-script at this point in time.

@quadraxas: dont know if this is asking too much but jus the simple demo from the aum or just in an action that i could assign to entities, give them a objective and have them go to it, i could do the rest of fleshing it out but that would be the ground work...

Re: purrfect ai lite-c [Re: darkinferno] #267228
05/22/09 16:48
05/22/09 16:48
Joined: Oct 2007
Posts: 5,210
İstanbul, Turkey
Quad Online
Senior Expert
Quad  Online
Senior Expert

Joined: Oct 2007
Posts: 5,210
İstanbul, Turkey
okay, i ll try to convert the aum demo... starting now.

(the pai folder from aum64 is what you need to be converted, right?)

Last edited by Quadraxas; 05/22/09 16:48.

3333333333
Re: purrfect ai lite-c [Re: Quad] #267231
05/22/09 16:55
05/22/09 16:55
Joined: May 2009
Posts: 1,816
at my pc (duh)
darkinferno Offline OP
Serious User
darkinferno  Offline OP
Serious User

Joined: May 2009
Posts: 1,816
at my pc (duh)
yes, thats right and thanks for your effort

Re: purrfect ai lite-c [Re: darkinferno] #267241
05/22/09 18:05
05/22/09 18:05
Joined: Oct 2007
Posts: 5,210
İstanbul, Turkey
Quad Online
Senior Expert
Quad  Online
Senior Expert

Joined: Oct 2007
Posts: 5,210
İstanbul, Turkey
here it is, behaves exactly the same with c-script version:

pai.c
Code:
/////////////////////////////////////////////////////////////////////////////////////////////
// Purrfect AI is being developed by George Pirvu george@acknex.net
// 
// the maximum number of nodes that can be placed in the demo is 300
// the distance between two consecutive nodes should be smaller than 1000 quants for this demo
//
// Converted to Lite-C by Quadraxas
/////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////
#include <acknex.h>
#include <default.c>
///////////////////////////////


// maximum number of nodes that can be used in this demo
#define max_nodes 300 
// 300 x 300 (max_nodes * max_nodes)
#define max_arrays 90000 

/////////////////////////////////////////////////////////////////////////////////////////////

var number_of_nodes = -1; // stores the numbers associated to the nodes (0... up to 299 in this demo)
var current_node = 0; // the current node that scans for the other nodes
var touched_node = 0; // that's the node that is touched with the mouse pointer
var start_node = 0; 
var target_node = 0; // closest node to the player that can "see" the player

var node_to_player[max_nodes]; // distance from the node to the player
var see_player[max_nodes]; // sets the corresponding var to 1 if the node can see the player
var nodex[max_nodes]; // x coordinates for the nodes
var nodey[max_nodes]; // y coordinates for the nodes 
var node_to_node[max_arrays]; // stores the distance between any two nodes (up to 300 x 300 elements)
var visited[max_arrays]; // stores the actual path from a node to any other node (up to 300 x 300 elements)
var path[max_nodes]; // stores the elements of the actual path
var dist_to_player[max_nodes]; // holds the distance from the player to its surrounding nodes
var min_player;

var closest_distance = 999999; // will hold the distance from the closest visible node to the player
var index = 0; // used as a counter from 0 to 299
var distances_computed = 0; // will be set to 1 when the array is filled with the distances between the nodes
var next_node; // next node on the shortest path
var pathfinding_on = 1; // the player will use (or not) the path finding algorithm to go to the destination
var target_in_solid = 0; // will be set to 1 if the target entity is placed inside a solid (a level block, etc)
var nodes_visible = 0;

var i; // 4 counters with short names to make the code more readable
var j; 
var k; 
var l;

var test_var; // used for debugging

VECTOR player_pos1;
VECTOR player_pos2;
VECTOR vec_temp;

/////////////////////////////////////////////////////////////////////////////////////////////

STRING* level_wmb = "pai.wmb";
STRING* marker_mdl = "marker.mdl";
STRING* player_mdl = "player.mdl";
STRING* target_mdl = "target.mdl";
STRING* bullet_mdl = "bullet.mdl";
STRING* target_tga = "target.tga";

/////////////////////////////////////////////////////////////////////////////////////////////

BMAP* pointer_pcx = "pointer.pcx";

/////////////////////////////////////////////////////////////////////////////////////////////

SOUND* beep_sound = "beep.wav";
SOUND* door_wav = "door.wav";
SOUND* damaged_wav = "damaged.wav";
SOUND* bullet_wav = "bullet.wav";

/////////////////////////////////////////////////////////////////////////////////////////////

FONT* system_font = "system12.bmp";

/////////////////////////////////////////////////////////////////////////////////////////////

function trace_back();
function run_algorithm(); // Floyd - Dijkstra - George :) algorithm 
function follow_path();
function set_target();
function init_target();

/////////////////////////////////////////////////////////////////////////////////////////////

#define health skill40

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "spiders.c"

/////////////////////////////////////////////////////////////////////////////////////////////

ENTITY* d1_marker; // temporary pointer, guides the player along the path
ENTITY* playerd; // player's destination entity

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

TEXT* ai_txt = // displays the texts on the screen
{
	font = system_font;
	pos_x = 0;
	pos_y = 0;
	string = "Current path:   \n\nTouched:\nTarget:\nStart:";
	flags = SHOW; // remove the comment to see the debug information
}

//////////////////////////////////////////////////////////////////////////////////////////////

PANEL* ai_pan= // displays the numerical values on the screen
{
	pos_x = 0;
	pos_y = 0;
	layer = 10;
	digits = (90, 50, 4, system_font, 1, touched_node);
	digits = (90, 75, 4, system_font, 1, target_node);
	digits = (90, 100, 4, system_font, 1, start_node);

//	digits = 180, 0, 4, system_font, 1, path[0]; // display the first 15 points on the shortest path
//	digits = 220, 0, 4, system_font, 1, path[1]; // feel free to display even more if you want to
//	digits = 260, 0, 4, system_font, 1, path[2]; 
//	digits = 300, 0, 4, system_font, 1, path[3];
//	digits = 340, 0, 4, system_font, 1, path[4];
//	digits = 380, 0, 4, system_font, 1, path[5];
//	digits = 420, 0, 4, system_font, 1, path[6];
//	digits = 460, 0, 4, system_font, 1, path[7];
//	digits = 500, 0, 4, system_font, 1, path[8];
//	digits = 540, 0, 4, system_font, 1, path[9];
//	digits = 580, 0, 4, system_font, 1, path[10];
//	digits = 620, 0, 4, system_font, 1, path[11];
//	digits = 660, 0, 4, system_font, 1, path[12];
//	digits = 700, 0, 4, system_font, 1, path[13];
//	digits = 740, 0, 4, system_font, 1, path[14];

	digits(0, 0, 4, system_font, 1, player.health);

	flags = OVERLAY | SHOW; // remove the comments from the digits to see the debug information
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function set_target();
function toggle_nodes();
function fire_bullets();

function main()
{
	video_mode = 8; // set the resolution to 1024x768 pixels
	video_depth = 32; // use true color graphics
	video_screen = 1; // and start the demo in full screen mode
	
	
	on_mouse_right = set_target; // click the right mouse button to set a new target
	on_space = toggle_nodes;
	on_mouse_left = fire_bullets;
	
	vec_set(sky_color,vector(1,1,1));
	camera.arc = 80; // set the initial zoom factor
	fps_max = 100; // limit the frame rate to 100 fps
	clip_size = 0; // show all the triangles for all the models
	mouse_range = 50000; // allow the mouse pointer to click any entity up to 50,000 quants away
	level_load(level_wmb);
	wait (3); // wait for the level to be loaded
	while (distances_computed == 0) {wait (1);} // wait until the big array is filled with the distances between the nodes
	run_algorithm(); // get the shortest paths between the nodes
	media_loop ("track1.mp3", NULL, 60);
	while (1)	
	{
		index %= (number_of_nodes + 1); // limit "index" to 0... up to 299 in this demo
		if ((node_to_player[index] < closest_distance) && (see_player[index] == 1))
		// if the distance from this node to the player is smaller than the current distance to the player
		// and we are dealing with a node that can see the player
		{
			closest_distance = node_to_player[index]; // then we have a new winner!
			target_node = index; // and the target is given by the current "index" value
		}
		else // haven't found a new winner?
		{
			closest_distance = node_to_player[target_node]; // then use the previous winner
		}
		index += 1; // move on to the following node
		wait (1);
	}		
}

function init_mouse_startup()//functions ending in _startup is auto-started.
{
	mouse_map = pointer_pcx; // set the mouse pointer bitmap
	mouse_mode = 2; // and then make it visible
	while (1)
	{
		mouse_pos.x = mouse_cursor.x; // allow the mouse to move
		mouse_pos.y = mouse_cursor.y; // on the x and y axis
		wait (1);
	}
}

function set_camera_startup()
{
	while (player == NULL) {wait (1);} // wait until the player entity is loaded
	camera.pan += 45;
	camera.z = player.z + 500; // place the camera 500 quants above player's head at game start
	camera.tilt = -60; // make it look downwards
	while (1)
	{
		camera.x = player.x - camera.z / 2; // place the camera behind the player on the x axis
		camera.y = player.y - camera.z / 2;
		camera.z += 0.3 * mickey.z; // and allow the player to zoom in / out using the mouse wheel
		camera.z += 15 *  (key_q - key_a) * time_step; // or the "+" and "-" keys
		camera.z = clamp (camera.z, 250, 2000); // limit the height of the camera to 250...2000 quants
		wait (1);
	}
}

function run_algorithm()
{
	i = 0;
	j = 0;
	while (i < (number_of_nodes + 1))
	{
		while (j < (number_of_nodes + 1))
		{
			index = j + i * (number_of_nodes + 1); // compute the correct index in the array
			if (node_to_node[index] == 0) // if these nodes can't see each other
			{
				node_to_node[index] = 999999; // set a huge distance for the nodes that can't see each other
			}
			j += 1;
		}
		i += 1;
		j = 0;
	}
	i = 0;
	j = 0;
	k = 0;
	while (i < (number_of_nodes + 1))
	{
		while (j < (number_of_nodes + 1))
		{
			while (k < (number_of_nodes + 1)) // go through all the nodes
			{
				// if dist(2,10) + dist(10,15) < dist(2,15) then 10 is a point on a shorter path 
				if ( (node_to_node[j + i * (number_of_nodes + 1)] + node_to_node[i + k * (number_of_nodes + 1)]) < (node_to_node[j + k * (number_of_nodes + 1)]))
				{
					// make the change: don't use the old (2,15) (2, 10, 15 are used just as an example here)
					node_to_node[j + k * (number_of_nodes + 1)] = node_to_node[j + i * (number_of_nodes + 1)] + node_to_node[i + k * (number_of_nodes + 1)];
					visited[j + k * (number_of_nodes + 1)] = i; // store the visited point
				}
				if (j == k) // dist(1,1) = dist(2,2) = dist(3,3).... = dist(29,29) should be set to 0 (not necessary but looks nicer)
				{
					node_to_node[j + k * (number_of_nodes + 1)] = 0; // otherwise we would get d(1,1) = d(1,2) + d(2,1) if "2" is the closest node to "1"
					visited[j + k * (number_of_nodes + 1)] = 0; // same thing here; the distance between a visited node and itself should be zero
				}
				k += 1;
			}
			k = 0;
			j += 1;
		}
		k = 0;
		j = 0;
		i += 1;
	}
}

function find_path(l, j)
{
	i = 0;
	while (i < (number_of_nodes + 1)) // search from this node for the rest of the nodes (up to 299 more nodes)
	{
		if ((i != j) && (visited[i + (number_of_nodes + 1) * j] == 0)) // the current node can "see" these nodes, excepting itself of course (i != j)
		{
			if (node_to_node[l + (number_of_nodes + 1) * j] == node_to_node[l + (number_of_nodes + 1) * i] + node_to_node[i + (number_of_nodes + 1) * j]) 
			// that's a node on the shortest path because the shortest path includes it
			{
				k += 1; // move to the next array element
				path[k] = i; // and store the node number inside the array
				next_node = i; // store the new node on the shortest path because it will loose its value right away
				i = (number_of_nodes + 1) - 1; // don't test other values - eliminate other paths that have the same length (that could happen in some levels)
				if (path[k] == l) // end of search, reached the starting point (l = start_node, remember?)
				{
					return; // get out of this function
				}
			}
		}
		i += 1; // increase i if the function continues to run
	}
	j = next_node; // set the next node on the path as target
	find_path(l, j); // recursive function, search for the shortest path again (if it searched (2,10) now searches (2,9) and so on)
}

action node() // use up to 300 nodes in this demo
{
	set(my,INVISIBLE | TRANSLUCENT | PASSABLE);
	my.alpha = 25;
	my.emask |= ENABLE_SCAN | ENABLE_TOUCH | ENABLE_CLICK;
	my.event = trace_back;
	my.skill47 = 1234; // set this weird value for skill47 = I'm a node
	number_of_nodes += 1; // get a unique id number (0.. up to 299)
	my.skill48 = number_of_nodes; // and store it in skill48
	nodex[my.skill48] = my.x; // store x and y
	nodey[my.skill48] = my.y; // for this node
	wait (-1); // wait until all the nodes are placed in the level
	while (current_node <= number_of_nodes)
	{
		if (current_node == my.skill48) // I'm the current node!
		{
			c_scan(my.x, my.pan, vector(360, 30, 1000), IGNORE_ME);
			wait (1); // not needed but won't hurt anybody
			current_node += 1; // move to the next node
		}
		wait (1);
	}
	distances_computed = 1;
	while (playerd == NULL) {wait (1);} // wait until the player destination entity is created
	while (1)
	{
		node_to_player[my.skill48] = vec_dist(playerd.x, my.x); // store the distance to the player destination entity
		if (node_to_player[my.skill48] < 500) // if the player destination is closer than 500 quants to this node
		{
			// if this node can "see" the player destination entity
			if (c_trace (my.x, playerd.x, IGNORE_ME | IGNORE_MODELS | IGNORE_PASSENTS | USE_BOX) == 0) 
			{
				see_player[my.skill48] = 1; // the node can see the player destination
			}
			else
			{
				see_player[my.skill48] = 0; // this node can't see the player destination
			}
		}
		wait (1 + random(10)); // spread the cpu load over 10 consecutive frames
		if (nodes_visible == 0)
		{
			set(my,INVISIBLE);
		}
		else
		{
			reset(my,INVISIBLE);
		}
	}
}

function init_target()
{
	playerd = my; // I'm the player destination (sets the initial target)
	set(my,INVISIBLE | PASSABLE);
}

action players_action()
{
	//init vectors -set all components to 0-
	vec_zero(vec_temp);
	vec_zero(player_pos1);
	vec_zero(player_pos2);
	player = my;
	ent_create (target_mdl, my.x, init_target);
	my.skill47 = 5678; // I'm the player
	my.health = 100; // and I've got 100 health points
	var previous_target;
	while (my.health > 0)
	{
		if (vec_dist (playerd.x, my.x) <= 30)
		{
			ent_animate(me, "stand",my.skill46, ANM_CYCLE);
			my.skill46 += 2 * time_step; // "stand" animation speed
			wait (1);
		}
		else
		{
			if (pathfinding_on == 1) // need to use the path finding algorithm?
			{
				min_player = 999999; // set the minimum distance from the player destination to its surrounding nodes to a huge value
				c_scan(my.x, my.pan, vector(360, 360, 800), IGNORE_ME);
				wait (-0.2);
				k = 0; 
				while (k < (number_of_nodes + 1))
				{
					path[k] = 0; // reset the array, get rid of the previously stored path
					k += 1;
				}
				k = 0; // start with the first element of path[] array
				path[k] = target_node; // write the first path element
				previous_target = target_node;
				if (start_node != target_node)
				{
					find_path(start_node, target_node); // find the shortest path between these two nodes
					wait (2); // wait for the path to be computed
					i = k; // k = number of nodes on the shortest path
					vec_temp.x = nodex[path[i-1]]; // get the previously stored coordinates for this node
					vec_temp.y = nodey[path[i-1]]; // on x and y 
					vec_temp.z = my.z; // use player's height for z (you should use a trace to place the z on the ground if your level isn't flat)
					d1_marker = ent_create (marker_mdl, vec_temp, follow_path); // create an invisible entity that guides the player
					wait (1);
					// the player can see the second node on the path directly?
					if(c_trace (player.x, d1_marker.x, IGNORE_ME | IGNORE_MODELS | IGNORE_PASSENTS | USE_BOX) == 0) 
					{
						i -= 1; // then ignore the first point of the path (don't turn back to it)
					}
					while (i >= 0) // decrease i until it goes below zero
					{
						vec_temp.x = nodex[path[i]]; // get the previously stored coordinates for this node
						vec_temp.y = nodey[path[i]]; // on x and y 
						vec_temp.z = my.z; // use player's height for z (you should use a trace to place the z on the ground if your level isn't flat)
						d1_marker = ent_create (marker_mdl, vec_temp, follow_path); // create an invisible entity that guides the player
						wait (1);
						while (vec_dist (d1_marker.x, my.x) > 30)
						{
							ent_animate(me, "walk", my.skill46, ANM_CYCLE);
							my.skill46 += 8 * time_step; // "walk" animation speed
							my.skill1 = 6 * time_step;
							my.skill2 = 0;
							my.skill3 = 0;
							result = c_move (my, my.skill1, nullvector, IGNORE_PASSABLE | GLIDE);
							// got stuck or the player has decided to pick a new path while the player was already moving or close to the destination?
							if ( (result == 0) || (previous_target != target_node) || (vec_dist (playerd.x, my.x) < 100) ) 
							{
								break; // get out of both while loops, find the path again
							}
							vec_set (player_pos1.x, my.x);
							wait (1);
							vec_set (player_pos2.x, my.x);
						}
						// the target is visible from here?
						if(c_trace (player.x, playerd.x, IGNORE_ME | IGNORE_MODELS | IGNORE_PASSENTS | USE_BOX) == 0) 
						{
							pathfinding_on = 0; // then bypass the path finding algorithm
							i = -1; // and get out of the "while" loop to stop the path finding
						}
						i -= 1; // move on to the following node
						wait (1);
					}
					// go from the last node that can see the destination (the "playerd" entity) to the actual destination entity
					while ((vec_dist (playerd.x, my.x) > 30) && (mouse_right == 0) && (previous_target == target_node))
					{
						ent_animate(me, "walk", my.skill46, ANM_CYCLE);
						my.skill46 += 8 * time_step; // "walk" animation speed
						vec_set (vec_temp, playerd.x); 
						vec_sub (vec_temp, my.x);
						vec_to_angle (my.pan, vec_temp);
						my.tilt = 0;
						my.skill1 = 6 * time_step;
						my.skill2 = 0;
						my.skill3 = 0;
						result = c_move (my, my.skill1, nullvector, IGNORE_PASSABLE | GLIDE);
						if (result < (0.5 * my.skill1 * time_step)) // had to slow down or stop?
						{
							break; // then get out of here and compute a new path
						}
						vec_set (player_pos1, my.x);
						wait (1);
						vec_set (player_pos2, my.x);
					}
				}
			}
			else // the target is visible directly, so the player can move there without using the path finding algorithm
			{
				while ((vec_dist (playerd.x, my.x) > 30) && (mouse_right == 0))
				{
					ent_animate(me, "walk", my.skill46, ANM_CYCLE);
					my.skill46 += 8 * time_step; // "walk" animation speed
					vec_set (vec_temp, playerd.x); 
					vec_sub (vec_temp, my.x);
					vec_to_angle (my.pan, vec_temp);
					my.tilt = 0;
					my.skill1 = 8 * time_step;
					my.skill2 = 0;
					my.skill3 = 0;
					result = c_move (my, my.skill1, nullvector, IGNORE_PASSABLE | GLIDE);
					if (result < (0.5 * my.skill1 * time_step)) // had to slow down or stop?
					{
						break; // then get out of here and compute a new path
					}
					vec_set (player_pos1, my.x);
					wait (1);
					vec_set (player_pos2, my.x);
				}
				pathfinding_on = 1; // the player can now use the path finding algorithm again
			}
		}	
	}
	snd_play (damaged_wav, 80, 0);
	while (my.tilt < 90)
	{
		my.tilt += 10 * time_step;
		my.z -= 3 * time_step;
		wait (1);
	}
	wait (-2); // guess why I have used this line of code ;)
}

function trace_back()
{
	if (event_type == EVENT_SCAN)
	{
		if (you.skill47 == 1234) // scanned by a node
		{
			my.skill45 = handle(you); // store "you" because trace will destroy it
			// if this node can "see" the node that scanned it
			if (c_trace (my.x, you.x, IGNORE_ME | IGNORE_MODELS | IGNORE_PASSENTS | USE_BOX) == 0) 
			{
				you = ptr_for_handle(my.skill45); // restore the "you" pointer
				index = you.skill48 + my.skill48 * (number_of_nodes + 1);
				node_to_node[index] = vec_dist(my.x, you.x);
			}
		}	
		else // scanned by the player (skill47 = 5678)
		{
			my.skill45 = handle(you); // store "you" because trace will destroy it
			// if this node can "see" the player that scanned it
			if (c_trace (my.x, you.x, IGNORE_ME | IGNORE_MODELS | IGNORE_PASSENTS | USE_BOX) == 0) 
			{
				you = ptr_for_handle(my.skill45); // restore the "you" pointer
				dist_to_player[my.skill48] = vec_dist (my.x, you.x);
				if ((dist_to_player[my.skill48] < min_player) && (dist_to_player[my.skill48] != 0))
				{
					min_player = dist_to_player[my.skill48];
				}
				wait (2); // allow the rest of the nodes to change min_player (if they should change it)
				if (dist_to_player[my.skill48] == min_player) // this is the closest node to the player?
				{
					start_node = my.skill48;
				}
			}
			else
			{
				dist_to_player[my.skill48] = 0;
			}				
		}
	}
	if (event_type == EVENT_TOUCH)
	{
		touched_node = my.skill48; // get the number of the node that was touched with the mouse pointer
	}
}

function follow_path()
{
	set(my,INVISIBLE | PASSABLE);
	vec_set (vec_temp.x, my.x); 
	vec_sub (vec_temp.x, you.x);
	vec_to_angle (you.pan, vec_temp); // turn the player towards the path marker
	while (d1_marker == my) {wait (1);} 
	ent_remove (my); // remove the old, unused markers
}

function set_target()
{
	while (mouse_right == 1) {wait (1);} // wait for the mouse button to be released
	pathfinding_on = 0; // disable the path finding algorithm temporarily
	VECTOR pos1;
	vec_zero(pos1);
	VECTOR pos2;
	vec_zero(pos2);
	pos1.x = mouse_pos.x;
	pos1.y = mouse_pos.y;
	pos1.z = 0;
	vec_for_screen (pos1, camera);
	pos2.x = mouse_pos.x;
	pos2.y = mouse_pos.y;
	pos2.z = 50000; // use a big value here
	vec_for_screen (pos2, camera);
	c_trace (pos1.x, pos2.x, IGNORE_ME | IGNORE_MODELS | IGNORE_PASSENTS | USE_BOX);
	vec_set (playerd.x, target.x);
	playerd.z = player.z; // set the height of the target ("playerd") to player's z coordinate
	if (c_content (playerd.x,0) == 3)//content_solid
	{
		target_in_solid = 1; // for further use
		vec_set (playerd.x, player.x); // don't move the player anymore (move the destination entity at its position)
	}
	if(c_trace (player.x, playerd.x, IGNORE_ME | IGNORE_MODELS | IGNORE_PASSENTS | USE_BOX) == 0) // the player can see the destination directly?
	{
		pathfinding_on = 0; // then bypass the path finding algorithm
	}
	else
	{
		pathfinding_on = 1; // use the path finding algorithm
	}
}

function toggle_nodes()
{
	nodes_visible += 1;
	nodes_visible %= 2;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// pure game code (not related to the AI code) from here on
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

ENTITY* bullet_target;

VECTOR bullet_origin;

action passable_door() // these particular doors need to be passable because the nodes need to see each other through them
{
	while (player == NULL) {wait (1);}
	set(my,PASSABLE);
	while (vec_dist (player.x, my.x) > 100) {wait (1);}
	my.skill10 = my.y;
	snd_play (door_wav, 100, 0);
	while (my.y < my.skill10 + 120)
	{
		my.y += 10 * time_step;
		wait (1);
	}
}

function remove_bullets() // this function runs when the bullet collides with something
{
	wait (1); // wait for a frame
	ent_remove (my); // and then remove the bullet
}

function move_bullets()
{
	VECTOR temp_angle;
	vec_zero(temp_angle);
	VECTOR bullet_speed; // this vec will store the speed of the bullet
	vec_zero(bullet_speed);
	my.skill99 = 135; // uniquely identify a bullet
	
	my.emask |= ENABLE_IMPACT | ENABLE_ENTITY | ENABLE_BLOCK;
	set(my,PASSABLE);
	vec_set(temp_angle, bullet_target.x); 
	vec_sub(temp_angle, my.x); 
	vec_to_angle(my.pan, temp_angle);
	if (vec_dist (player_pos1.x, player_pos2.x) == 0) // the player is standing still?
	{
		player.pan = my.pan; // then rotate the player in the proper direction as well
	}
	my.event = remove_bullets; // when it collides with something, its event function (remove_bullets) will run
	bullet_speed.x = 50 * time_step; // adjust the speed of the bullet here
	bullet_speed.y = 0; // the bullet doesn't move sideways
	bullet_speed.z = 0; // then don't allow the gravity to have its ways with the bullet
	while (my)
	{
		if (vec_dist (my.x, bullet_origin.x) > 50) {reset(my,PASSABLE);}
		c_move (my, bullet_speed, nullvector, IGNORE_PASSABLE);
		wait (1);
	}
}

function show_target()
{
	set(my,BRIGHT);
	vec_to_angle (my.pan, normal); // orient the sprite correctly
	vec_add(my.x, normal.x); // move the sprite a bit away from the wall
	set(my,PASSABLE);
	my.scale_x = 0.2;
	my.scale_y = my.scale_x;
	while (mouse_left == 1) {wait (1);} // wait until the player releases the mouse button
	ent_remove (me); // remove the old target
}

function set_bullet_target()
{
	VECTOR pos1;
	VECTOR pos2;
	vec_zero(pos1);
	vec_zero(pos2);
	
	pos1.x = mouse_pos.x;
	pos1.y = mouse_pos.y;
	pos1.z = 0;
	vec_for_screen (pos1, camera);
	pos2.x = mouse_pos.x;
	pos2.y = mouse_pos.y;
	pos2.z = 200000; // use a big value here
	vec_for_screen (pos2, camera);
	c_trace (pos1, pos2, IGNORE_ME | IGNORE_PASSABLE | IGNORE_MODELS | IGNORE_SPRITES); 
	bullet_target = ent_create (target_tga, target, show_target);
}

function fire_bullets()
{
	if (player.health <= 0) {return;} // don't fire bullets if the player is dead
	proc_kill(4); // don't allow more than 1 copy of this function to run
	set_bullet_target();
	while (bullet_target == NULL) {wait (1);} // wait until the target sprite is displayed on the floor
	while (mouse_left == 1) // this loop runs for as long as the left mouse button is pressed
	{
		vec_for_vertex (bullet_origin.x, player, 17); // get the coordinates for the bullets' origin
		 // create the bullet and attach it the "move_bullets" function
		ent_create (bullet_mdl, bullet_origin.x, move_bullets);
		snd_play (bullet_wav, 100, 0); // play the bullet sound at a volume of 100
		wait (-0.14); // fire 7 bullets per second (0.14 * 7 = 1 second)
	}
}



spiders.c
Code:
///////////////////////////////////////////////////////////////////////////////////////////////////////
// copy the files inside this folder in your game folder
// don't forget to include spiders.wdl in your main game file
// place a model in your level and attach it the deadly_spider action
///////////////////////////////////////////////////////////////////////////////////////////////////////

SOUND* gotcha_wav = "gotcha.wav";
SOUND* dead_wav = "dead.wav";

///////////////////////////////////////////////////////////////////////////////////////////////////////

STRING* spider_mdl = "spider.mdl";

///////////////////////////////////////////////////////////////////////////////////////////////////////

function hurt_them();
function deadly_spider();

///////////////////////////////////////////////////////////////////////////////////////////////////////

function init_spider()
{
	VECTOR movement_speed;
	vec_zero(movement_speed);
	my.pan = random(360);
	movement_speed.x = (20 - random(40));
	movement_speed.y = (20 - random(40));
	while (my.z < 150)
	{
		my.x += movement_speed.x * time_step;
		my.y += movement_speed.y * time_step;
		my.z += 20 * time_step;
		wait (1);
	}
	while (my.z > 45)
	{
		my.x += movement_speed.x * time_step;
		my.y += movement_speed.y * time_step;
		my.z -= 10 * time_step;
		wait (1);
	}
	deadly_spider();
}

function generate_spiders_startup()
{
	while (player == NULL) {wait (1);}
	while (player.x < -100) {wait (1);} // wait until the player enters the big, empty area
	var i = 0;
	while (i < 5)
	{
		snd_play (gotcha_wav, 100, 0);
		ent_create (spider_mdl, vector (-362, 1335, 45), init_spider);
		ent_create (spider_mdl, vector (-286, 762, 45), init_spider);
		ent_create (spider_mdl, vector (82, 1195, 45), init_spider);
		ent_create (spider_mdl, vector (254, 826, 45), init_spider);
		ent_create (spider_mdl, vector (295, 1506, 45), init_spider);
		i += 1;
		wait (-0.5);
	}
}

function deadly_spider()
{
	VECTOR spider_speed;
	vec_zero(spider_speed);
	VECTOR in_front;
	vec_zero(in_front);
	
	my.emask |= ENABLE_ENTITY | ENABLE_IMPACT | ENABLE_BLOCK;
	my.event = hurt_them;
	my.health = 1; // "health" was defined as skill40 inside pai.wdl
	while(my.health > 0)
	{
		spider_speed.x = 8 * time_step; 
		spider_speed.y = 0;
		spider_speed.z = 0;
	//	spider_speed *= time_step;
		in_front.x = my.x + 40 * cos(my.pan);
		in_front.y = my.y + 40 * sin(my.pan);
		in_front.z = my.z;
		if (c_content(in_front,0) == 3)//content_solid
		{
			my.skill40 = my.pan;
			my.skill41 = 30 + random(90);
			while (my.pan < my.skill40 + my.skill41) // rotate 30..120 degrees
			{
				my.pan += 5 * time_step;
				wait (1);
			}
		}
		else // free to move
		{
			ent_animate(me, "run", my.skill20, ANM_CYCLE);
			my.skill20 += 10 * time_step; 
			result = c_move (me, spider_speed, nullvector,IGNORE_PASSABLE);
			if (result == 0) // got stuck?
			{
				spider_speed.x *= -1; // then reverse the movement direction
				my.skill40 = my.pan;
				my.skill41 = 30 + random(90);
				while (my.pan < my.skill40 + my.skill41) // rotate 30..120 degrees
				{
					my.pan += 5 * time_step;
					ent_animate(me, "run", my.skill20, ANM_CYCLE);
					my.skill20 -= 10 * time_step; 
					c_move (me, spider_speed, nullvector,IGNORE_PASSABLE);
					wait (1);
				}
				spider_speed.x *= -1; // restore the initial speed
			}
			if ((vec_dist (player.x, my.x) < 30) && (player.health > 0)) // collided with the player?
			{
				snd_play (gotcha_wav, 50, 0);
				player.health -= 1 * time_step; // subtract 10 health points from the entity's health
			}
		}
		wait (1);
	}
	my.skill20 = 0;
	set(my,PASSABLE);
	snd_play (dead_wav, 90, 0);
	while (my.skill20 < 95)
	{
		if (my.roll < 180) {my.roll += 25 * time_step;}
		if (my.z > 30) {my.z -= 5 * time_step;}
		ent_animate(me, "death", my.skill20, ANM_CYCLE);
		my.skill20 += 10 * time_step; 
		wait (1);
	}
	wait(-1);
}

function hurt_them()
{
	proc_kill(4);
	if (you != NULL) // collided with an entity (the player, a monster, etc)?
	{
		if (you.skill99 == 135) // hit by player's bullet?
		{
			my.health = 0; // then this spider is dead
			my.event = NULL; // so it doesn't react to events anymore
		}
	}
}




3333333333
Re: purrfect ai lite-c [Re: Quad] #267244
05/22/09 18:12
05/22/09 18:12
Joined: May 2009
Posts: 1,816
at my pc (duh)
darkinferno Offline OP
Serious User
darkinferno  Offline OP
Serious User

Joined: May 2009
Posts: 1,816
at my pc (duh)
thank you! you're a god sent... i can finally move on... i'll get it implemented and post its progress soon smile

Re: purrfect ai lite-c [Re: Quad] #267307
05/23/09 04:50
05/23/09 04:50
Joined: Aug 2003
Posts: 2,011
Bucharest, Romania
George Offline

Expert
George  Offline

Expert

Joined: Aug 2003
Posts: 2,011
Bucharest, Romania
Thank you, that's a great effort and will probably get me started in adding more features to the AI code in the near future.

Re: purrfect ai lite-c [Re: George] #267349
05/23/09 12:04
05/23/09 12:04
Joined: May 2009
Posts: 1,816
at my pc (duh)
darkinferno Offline OP
Serious User
darkinferno  Offline OP
Serious User

Joined: May 2009
Posts: 1,816
at my pc (duh)
i got it working, however, how accurate is this pathfinding? in some scenarios, the player tries to walk through walls, i take it because the nodes are reading each other incorrectly, i'm working at fixing this, this error only happens when i zoom out and chose a node thats at the other extreme end...

Page 1 of 3 1 2 3

Moderated by  George 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1