⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unit.c

📁 国外游戏开发者杂志1997年第六期配套代码
💻 C
字号:
//unit.c,  misc code

#include "..\\include\\move.h"
#define __GLOBAL__
#include "..\\include\\globals.h"
#include "..\\include\\prototyp.h"

extern long total_open[],total_iterations[],total_closed[],total_sort[];

void add_unit(long x,long y) {
//Add a unit on pixel position x,y
unit_type *u;
unit_list=realloc(unit_list,sizeof(unit_type)*(number_of_units+1));
u=&unit_list[number_of_units];
u->x=u->xd=(x/32)*32;
u->y=u->yd=(y/32)*32;
u->original_goal=u->final_goal=(x/32)+(y/32)*MAP_X;
u->frame=0;
u->direction=rand()%8;
u->parameter=0;
u->walk_count=0;
u->speed=1<<rand()%5;
u->path_size=0;
u->leader_path_size=0;
u->request_path=NO_PATH_REQUESTED;
u->delay=0;
u->index=number_of_units++;
}

void clear_unit_selection(void) {
//Clear unit selection
long i=0;
for(i=0;i<number_of_units;i++)
	unit_list[i].parameter&=0xffff ^ U_SELECTED;
selected_units=0;
}

void move_selected_units(long x,long y) {
long i;
if (!number_of_units) return;
for(i=0;i<number_of_units;i++)
	if (unit_list[i].parameter & U_SELECTED)
		{
		switch(PATH_METHOD)
			{case DELAYED_LOCKED_CUTTED_PATH_METHOD:
				unit_list[i].delay=rand()%32;
			 default:
				unit_list[i].original_goal=unit_list[i].request_path=x+y*MAP_X;
			 }
		}


}



long get_unit_frame_tile_index(long direction,long frame) {
//Get tile that corresponds with unit frame walking in direction
//If return value is negative unit should be shown flipped
long index;
if (direction<5)
	index=UNIT_START+direction*UNIT_DIR_ANIMATION_SIZE+frame;
else
	index=-(UNIT_START+(8-direction)*UNIT_DIR_ANIMATION_SIZE+frame);
return index;
}

void move_to(unit_type *u,long xd,long yd) {
//Move unit to neighbouring tile at xd,yd
long dx=xd-u->x/32,dy=yd-u->y/32,i=0;
for(;i<8;i++)
	if ((direction_delta[i][0]==dx) && (direction_delta[i][1]==dy))
		break;
if (i==8) return;//Shouldn't happen
u->walk_count=32/u->speed;
u->xd=xd;
u->yd=yd;
u->direction=i;
u->frame=0;
}

long next_unit_frame(unit_type *u) {
//Advance frame, and move unit.  Return 0 if no more frames to go else 1
long i;
//Are we delayed ?
if (u->delay>0) return 1;
//Are we moving because of walk_count ?
if (u->walk_count>0)
	{//It is moving.
	 u->x+=u->speed*direction_delta[u->direction][0];
	 u->y+=u->speed*direction_delta[u->direction][1];
	 u->frame=(u->frame+1)%UNIT_DIR_ANIMATION_SIZE;
	 if (--u->walk_count>0)
		return 1;
	 }
return 0;
}

void check_for_collisions(unit_type *u) {
//Check if moving to the next position in the path will cause a unit
//collision
long xd,yd,size,xdd,ydd;
unsigned short *path;
xd=u->path[u->path_position]%MAP_X;
yd=u->path[u->path_position]/MAP_X;
if (is_tile_busy(xd,yd))
	{//Yep, red alert
	 //We can either wait, or move around it
	 xdd=u->original_goal%MAP_X;ydd=u->original_goal/MAP_X;
	 if (destination_adjust(&xdd,&ydd))
		{switch(SEARCH_METHOD)
			{case REGULAR_ASTAR_METHOD:
				path=regular_path(u,xdd,ydd,&size,AVOID_UNITS | AVOID_OBSTACLES);
			 break;
			 case OPTIMIZED_ASTAR_METHOD:
			 case OPTIMIZED_ASTAR_DISTRIBUTED_METHOD:
				path=fast_path(u,xdd,ydd,&size,AVOID_UNITS | AVOID_OBSTACLES);
				if (search_busy!=-1)
					{//If search still busy, kill path
					 //and let it be recalculated by
					 //determine_path in parse_unit()
					 free(u->path);
					 u->path_size=0;
					 u->path=NULL;
					 u->path_position=0;
					 return;
					 }
			 break;
			 case OPTIMIZED_BIDIRECTIONAL_ASTAR_METHOD:
			 case OPTIMIZED_BIDIRECTIONAL_ASTAR_DISTRIBUTED_METHOD:
				path=bidirectional_fast_path(u,xdd,ydd,&size,AVOID_UNITS | AVOID_OBSTACLES);
				if (search_busy!=-1)
					{//If search still busy, kill path
					 //and let it be recalculated by
					 //determine_path in parse_unit()
					 free(u->path);
					 u->path_size=0;
					 u->path=NULL;
					 u->path_position=0;
					 return;
					 }
			 break;
			 case SEARCH_ALL:
				path=regular_path(u,xdd,ydd,&size,AVOID_UNITS | AVOID_OBSTACLES);
				free(path);
				path=fast_path(u,xdd,ydd,&size,AVOID_UNITS | AVOID_OBSTACLES);
				free(path);
				path=bidirectional_fast_path(u,xdd,ydd,&size,AVOID_UNITS | AVOID_OBSTACLES);
			 break;
			 }
		 if (path!=NULL)
			{//We have a new path
			 free(u->path);
			 u->path_size=size;
			 u->path=path;
			 u->path_position=1;
			 u->final_goal=xdd+ydd*MAP_X;
			 }
		 else
			{//Don't try anymore
			 free(u->path);
			 u->path_size=0;
			 u->path=NULL;
			 u->path_position=0;
			 }
		 }
	 else
		u->delay=1+rand()%32;
	}
}


void unit_follow_path(unit_type *u) {
//Unit follows it path using one of the methods
//Some methods need evaluation during the path, others just need to follow
//their path as the path search already avoided collisions
switch(PATH_METHOD)
	{case STEP_BASED_PATH_METHOD:
		check_for_collisions(u);
		if (u->path_size==0)
		//If path has been killed, no need to follow
			return;
		if (u->delay>0)
		//Unit has to wait, don't move further in path
			return;
		//It is now certain that we are going there. Occupy tile
		set_tile_busy(u->path[u->path_position]%MAP_X,u->path[u->path_position]/MAP_X);
	 default:
	 //Move to next position in path
		move_to(u,u->path[u->path_position]%MAP_X,u->path[u->path_position]/MAP_X);
	}
if (++u->path_position>=u->path_size)
	{//What do we do when we are at the end of the path
	 switch(PATH_METHOD)
		{case DELAYED_LOCKED_CUTTED_PATH_METHOD:
		 case LOCKED_CUTTED_PATH_METHOD:
		 case GREEDY_PATH_METHOD:
		 //With some methods we need to recalculate path if we
		 //haven't arrived at the final goal yet
			if (u->final_goal!=u->path[u->path_position-1])
				u->request_path=u->original_goal;
		 default:u->path_size=0;
			 free(u->path);
			 break;
		 }
	 }
}

void parse_unit(unit_type *u) {
//Parse several unit fields
//Unremark the following lines to stop all units if search becomes
//distributed
/*switch(SEARCH_METHOD)
	{case OPTIMIZED_ASTAR_DISTRIBUTED_METHOD:
	 case OPTIMIZED_BIDIRECTIONAL_ASTAR_DISTRIBUTED_METHOD:
	 if ((search_busy!=-1) && (search_busy!=u->index))
		//Search is busy. We do nothing until search has
		//been resolved
		 return;
	 break;
	 }*/
if (u->delay>0)
	{u->delay--;
	 set_tile_busy(u->x/32,u->y/32);
	 return;
	 }
if (u->walk_count>0)
	{//Advance
	 if (next_unit_frame(u))
		return;
	 }
//Remark here if first lines were unremarked
if ((u->request_path!=NO_PATH_REQUESTED) && (search_busy!=-1) && (search_busy!=u->index))
		{
		 //Lock next position
		 u->delay=1+rand()%8;
		 set_tile_busy(u->x/32,u->y/32);
		 return;
		 }
else
//End remark here
if ((u->request_path!=NO_PATH_REQUESTED) || (search_busy==u->index))
	{if (determine_path(u))
		{//We have a path
		 switch(SEARCH_METHOD)
			{case OPTIMIZED_ASTAR_DISTRIBUTED_METHOD:
			 case OPTIMIZED_BIDIRECTIONAL_ASTAR_DISTRIBUTED_METHOD:
			 if (search_busy!=-1)
				{//Path is too long to be caluclated
				 //during this run.  We'll continue
				 //in the next frame.
				 set_tile_busy(u->x/32,u->y/32);
				 return;
				 }
			}
		 switch(PATH_METHOD)
			{case STEP_BASED_PATH_METHOD:
			 //For step based methods we leave the occupying
			 //to the routine which moves the unit because we
			 //are never sure if indeed a unit is going to
			 //move to the expected location
			 break;
			 default:
				occupy_path(u);
			 }
		 }
	}
if (u->path_size>0)
	{//Free current position
	 set_tile_not_busy(u->x/32,u->y/32);
	 unit_follow_path(u);
	 return;
	 }
//Lock next position
set_tile_busy(u->x/32,u->y/32);
}

void show_units(long x,long y) {
//Copy units to screenbuffer
//X and Y are pixel coordinates of upper left corner to show
long i,rx,ry,tile_index;unit_type *u;
for(i=0;i<number_of_units;i++)
	{u=&unit_list[i];
	 //Parse unit commands
	 parse_unit(u);
	 rx=u->x-x;ry=u->y-y;
	 if ((member(rx,-32,SCREEN_X)) && (member(ry,-32,SCREEN_Y)))
		{//Get index of tile
		 tile_index=get_unit_frame_tile_index(u->direction,u->frame);
		 //Copy unit to screen
		 if (tile_index<0)
			flip_clip_copy_player_image(rx,ry,32,32,&image_memory[(-tile_index)*1024],4);
		 else
			clip_copy_player_image(rx,ry,32,32,&image_memory[tile_index*1024],4);
		 //Check if unit is selected
		 if (select_left_x!=-1)
			{if (((member(select_left_x,rx,rx+32))
			 || (member(rx,select_left_x,select_right_x)))
			 &&
			 ((member(select_left_y,ry,ry+32))
			 || (member(ry,select_left_y,select_right_y))))
				{//Select unit
				 u->parameter|=U_SELECTED;
				 selected_units=1;
				 }
			 else
				//Deselect unit
				u->parameter&=0xffff^U_SELECTED;
			 }
		 if (u->parameter & U_SELECTED)
			v_rectangle(rx,ry,rx+32,ry+32,CL_WHITE);
		 }
	 }
}


void switch_path_method(long new_method) {
//Switch between path methods.  To do this all paths have to be stopped etc...
long i;unit_type *u;
switch(PATH_METHOD)
	{case STEP_BASED_PATH_METHOD:
	 case DELAYED_LOCKED_CUTTED_PATH_METHOD:
	 case LOCKED_PATH_METHOD:
	 case LOCKED_CUTTED_PATH_METHOD:
	 case GREEDY_PATH_METHOD:
		for(i=0;i<number_of_units;i++)
			{u=&unit_list[i];
			 if (u->path_size>0)
				{free(u->path);
				 u->path_size=0;
				 }
			 u->request_path=NO_PATH_REQUESTED;
			 u->walk_count=0;
			 u->delay=0;
			 u->x=(u->x/32)*32;
			 u->y=(u->y/32)*32;
			 u->original_goal=u->final_goal=u->x/32+(u->y/32)*MAP_X;
			 }
		break;
	 }
for(i=0;i<MAP_X*MAP_Y;map[i++].parameters&=0xffff^TILE_BUSY);
PATH_METHOD=new_method;
search_busy=-1;
}







⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -