diff --git a/magic/src/rails.c b/magic/src/rails.c index 7a08a3430..80b02879f 100644 --- a/magic/src/rails.c +++ b/magic/src/rails.c @@ -3,7 +3,27 @@ #include "SDL_mixer.h" #include +#define SEG_NONE 0 + +#define SEG_LEFT 1 +#define SEG_RIGHT 2 +#define SEG_TOP 4 +#define SEG_BOTTOM 8 + +#define SEG_LEFT_RIGHT (SEG_LEFT | SEG_RIGHT) +#define SEG_TOP_BOTTOM (SEG_TOP | SEG_BOTTOM) +#define SEG_RIGHT_TOP (SEG_RIGHT | SEG_TOP) +#define SEG_RIGHT_BOTTOM (SEG_RIGHT | SEG_BOTTOM) +#define SEG_LEFT_TOP (SEG_LEFT | SEG_TOP) +#define SEG_LEFT_BOTTOM (SEG_LEFT | SEG_BOTTOM) +#define SEG_LEFT_RIGHT_TOP (SEG_LEFT | SEG_RIGHT | SEG_TOP) +#define SEG_LEFT_RIGHT_BOTTOM (SEG_LEFT | SEG_RIGHT | SEG_BOTTOM) +#define SEG_LEFT_TOP_BOTTOM (SEG_LEFT | SEG_TOP | SEG_BOTTOM) +#define SEG_RIGHT_TOP_BOTTOM (SEG_RIGHT | SEG_TOP | SEG_BOTTOM) +#define SEG_LEFT_RIGHT_TOP_BOTTOM (SEG_LEFT | SEG_RIGHT | SEG_TOP | SEG_BOTTOM) + Mix_Chunk * rails_snd; +unsigned int img_w, img_h; unsigned int rails_segments_x, rails_segments_y; //how many segments do we have? static int rails_math_ceil(int x, int y); //ceil() in cstdlib returns float and is relative slow, so we'll use our one static Uint8 * rails_status_of_segments; //a place to store an info about bitmap used for selected segment @@ -17,7 +37,7 @@ void rails_drag(magic_api * api, int which, SDL_Surface * canvas, SDL_Surface * snapshot, int ox, int oy, int x, int y, SDL_Rect * update_rect); -SDL_Surface * rails_one, * rails_three, * rails_four; +SDL_Surface * rails_one, * rails_three, * rails_four, * rails_corner; Uint32 rails_api_version(void) { @@ -38,18 +58,23 @@ int rails_init(magic_api * api) char fname[1024]; Uint8 i; //is always < 3, so Uint8 seems to be a good idea - rails_images=(char **)malloc(sizeof(char *)*3); + rails_images=(char **)malloc(sizeof(char *)*4); - for (i = 0; i < 3; i++) + for (i = 0; i < 4; i++) rails_images[i]=(char *)malloc(sizeof(char)*1024); snprintf(rails_images[0], 1024*sizeof(char), "%s/images/magic/rails_one.png", api->data_directory); snprintf(rails_images[1], 1024*sizeof(char), "%s/images/magic/rails_three.png", api->data_directory); snprintf(rails_images[2], 1024*sizeof(char), "%s/images/magic/rails_four.png", api->data_directory); + snprintf(rails_images[3], 1024*sizeof(char), "%s/images/magic/rails_three.png", api->data_directory); rails_one=IMG_Load(rails_images[0]); rails_three=IMG_Load(rails_images[1]); rails_four=IMG_Load(rails_images[2]); + rails_corner=IMG_Load(rails_images[3]); + + img_w = rails_one->w; + img_h = rails_one->h; snprintf(fname, sizeof(fname), "%s/sounds/magic/rails.wav", api->data_directory); rails_snd = Mix_LoadWAV(fname); @@ -107,9 +132,10 @@ void rails_shutdown(magic_api * api) SDL_FreeSurface(rails_one); SDL_FreeSurface(rails_three); SDL_FreeSurface(rails_four); + SDL_FreeSurface(rails_corner); SDL_FreeSurface(canvas_backup); - for (i = 0; i < 3; i++) + for (i = 0; i < 4; i++) free(rails_images[i]); free(rails_images); free(rails_status_of_segments); @@ -124,8 +150,8 @@ void rails_switchin(magic_api * api, int which, int mode, SDL_Surface * canvas) canvas->format->Rmask, canvas->format->Gmask, canvas->format->Bmask, canvas->format->Amask); SDL_BlitSurface(canvas, NULL, canvas_backup, NULL); - rails_segments_x=rails_math_ceil(canvas->w,40); - rails_segments_y=rails_math_ceil(canvas->h,40); + rails_segments_x=rails_math_ceil(canvas->w,img_w); + rails_segments_y=rails_math_ceil(canvas->h,img_h); rails_status_of_segments=(Uint8 *)calloc(rails_segments_x*rails_segments_y,sizeof(Uint8)); } @@ -151,8 +177,8 @@ inline unsigned int rails_get_segment(int x, int y) int xx; //segments are numerated just like pixels int yy; //in computer graphics: left upper (=1), ... ,right upper, //left bottom, ... , right bottom - xx=rails_math_ceil(x, 40); - yy=rails_math_ceil(y, 40); + xx=rails_math_ceil(x, img_w); + yy=rails_math_ceil(y, img_h); return (yy-1)*rails_segments_x+xx; @@ -160,8 +186,8 @@ inline unsigned int rails_get_segment(int x, int y) inline void rails_extract_coords_from_segment(unsigned int segment, Sint16 * x, Sint16 * y) { //extracts the coords of the beginning and the segment - *x=((segment%rails_segments_x)-1)*40; //useful to set update_rect as small as possible - *y=(int)(segment/rails_segments_x)*40; + *x=((segment%rails_segments_x)-1)*img_w; //useful to set update_rect as small as possible + *y=(int)(segment/rails_segments_x)*img_h; } static void rails_flip(void * ptr, SDL_Surface * dest, SDL_Surface * src) @@ -206,65 +232,46 @@ void rails_click(magic_api * api, int which, int mode, static Uint8 rails_select_image(Uint8 segment) { int take_up, take_down, take_left, take_right; + int val_up, val_down, val_left, val_right; take_up=segment-rails_segments_x; - if (take_up<=0) take_up=-1; //= upper sector doesn't exist + if (take_up<=0) val_up = SEG_NONE; + else val_up = rails_status_of_segments[take_up]; take_down=segment+rails_segments_x; - if (take_down>rails_segments_x*rails_segments_y) take_down=-1; //= lower sector doesn't exist - else take_down=segment+rails_segments_x; + if (take_down>rails_segments_x*rails_segments_y) val_down = SEG_NONE; + else val_down = rails_status_of_segments[take_down]; - if ((segment%rails_segments_x)==1) take_left=-1; - else take_left=segment-1; + if ((segment%rails_segments_x)==1) val_left=SEG_NONE; + else val_left = rails_status_of_segments[segment-1]; - if ((segment%rails_segments_x)==0) take_right=-1; - else take_right=segment+1; + if ((segment%rails_segments_x)==0) val_right=SEG_NONE; + else val_right = rails_status_of_segments[segment+1]; - if ((take_up!=-1) && (take_down!=-1) && (take_left!=-1) && (take_right!=-1)) //all the neighbours exists - { - if ( (rails_status_of_segments[take_left]==2) && (rails_status_of_segments[take_right]==2) && - (rails_status_of_segments[take_up]==1) && (rails_status_of_segments[take_down]==1)) - return 4; - } + if ( (val_left & SEG_RIGHT) && (val_right & SEG_LEFT) && + (val_up & SEG_BOTTOM) && (val_down & SEG_TOP)) + return SEG_LEFT_RIGHT_TOP_BOTTOM; - - if ((take_left!=-1) && (take_right!=-1)) //at least 2 neightbours exists - { - if (take_up!=-1) - if ( (rails_status_of_segments[take_left]==2) && (rails_status_of_segments[take_right]==2) && - (rails_status_of_segments[take_up]==1)) - return 31; + if ( (val_left & SEG_RIGHT) && (val_right & SEG_LEFT) && + (val_up & SEG_BOTTOM)) + return SEG_LEFT_RIGHT_TOP; - if (take_down!=-1) - if ( (rails_status_of_segments[take_left]==2) && (rails_status_of_segments[take_right]==2) && - (rails_status_of_segments[take_down]==1)) - return 32; + if ( (val_left & SEG_RIGHT) && (val_right & SEG_LEFT) && + (val_down & SEG_TOP)) + return SEG_LEFT_RIGHT_BOTTOM; - if ( (rails_status_of_segments[take_left]==2) && (rails_status_of_segments[take_right]==2)) - return 1; - } - - if ((take_up!=-1) && (take_down!=-1)) - { - if (take_left!=-1) - if ( (rails_status_of_segments[take_left]==2) && (rails_status_of_segments[take_up]==1) && - (rails_status_of_segments[take_down]==1)) - return 33; - - if (take_right!=-1) - if ( (rails_status_of_segments[take_right]==2) && (rails_status_of_segments[take_up]==1) && - (rails_status_of_segments[take_down]==1)) - return 34; - } + if ( (val_right & SEG_LEFT) && + (val_down & SEG_TOP) && (val_up & SEG_BOTTOM) ) + return SEG_LEFT_TOP_BOTTOM; + + if ( (val_right & SEG_LEFT) && + (val_down & SEG_TOP) && (val_up & SEG_BOTTOM) ) + return SEG_RIGHT_TOP_BOTTOM; + if ( (val_right & SEG_LEFT) && (val_left & SEG_RIGHT)) + return SEG_LEFT_RIGHT; - if (rails_status_of_segments[segment]==0) return 1; - - if (rails_status_of_segments[segment]==1) return 2; - - if (rails_status_of_segments[segment]==2) return 1; - - return 0; + return SEG_TOP_BOTTOM; } static void rails_draw(void * ptr, int which, SDL_Surface * canvas, SDL_Surface * last, @@ -277,66 +284,90 @@ static void rails_draw(void * ptr, int which, SDL_Surface * canvas, SDL_Surface use_temp=0; rails_segment_modified=rails_get_segment(x,y); - - result=SDL_CreateRGBSurface(SDL_ANYFORMAT, 40, 40, rails_one->format->BitsPerPixel, - rails_one->format->Rmask, rails_one->format->Gmask, rails_one->format->Bmask, rails_one->format->Amask); - - temp=SDL_CreateRGBSurface(SDL_ANYFORMAT, 40, 40, rails_one->format->BitsPerPixel, - rails_one->format->Rmask, rails_one->format->Gmask, rails_one->format->Bmask, rails_one->format->Amask); //modification_rect.x and modification_rect.y are set by function rails_extract_coords_from_segment(rails_segment_modified, &modification_rect.x, &modification_rect.y); - modification_rect.h=40; - modification_rect.w=40; + modification_rect.h=img_w; + modification_rect.w=img_h; image=rails_select_image(rails_segment_modified); //select the image to display + + if (rails_status_of_segments[rails_segment_modified] == image) + return; + rails_status_of_segments[rails_segment_modified]=image; //and write it to global table + + result=SDL_CreateRGBSurface(SDL_ANYFORMAT, img_w, img_h, rails_one->format->BitsPerPixel, + rails_one->format->Rmask, rails_one->format->Gmask, rails_one->format->Bmask, rails_one->format->Amask); + + temp=SDL_CreateRGBSurface(SDL_ANYFORMAT, img_w, img_h, rails_one->format->BitsPerPixel, + rails_one->format->Rmask, rails_one->format->Gmask, rails_one->format->Bmask, rails_one->format->Amask); + SDL_BlitSurface(canvas_backup, &modification_rect, result, NULL); switch(image) { case 0: - case 2: + case SEG_TOP_BOTTOM: SDL_BlitSurface(canvas_backup, &modification_rect, result, NULL); SDL_BlitSurface(rails_one, NULL, result, NULL); break; - case 1: + case SEG_LEFT_RIGHT: SDL_BlitSurface(canvas_backup, &modification_rect, result, NULL); rails_rotate(api, temp, rails_one, 1); use_temp=1; break; - case 4: + case SEG_LEFT_RIGHT_TOP_BOTTOM: SDL_BlitSurface(canvas_backup, &modification_rect, result, NULL); SDL_BlitSurface(rails_four, NULL, result, NULL); break; - case 31: + case SEG_LEFT_RIGHT_TOP: SDL_BlitSurface(rails_three, NULL, result, NULL); break; - case 32: + case SEG_LEFT_RIGHT_BOTTOM: rails_flip(api, temp, rails_three); use_temp=1; break; - case 33: + case SEG_LEFT_TOP_BOTTOM: rails_rotate(api, temp, rails_three, 0); use_temp=1; break; - case 34: + case SEG_RIGHT_TOP_BOTTOM: rails_rotate(api, temp, rails_three, 1); use_temp=1; break; + + case SEG_RIGHT_TOP: + SDL_BlitSurface(rails_corner, NULL, result, NULL); + break; + + case SEG_RIGHT_BOTTOM: + rails_flip(api, temp, rails_corner); + use_temp=1; + break; + + case SEG_LEFT_TOP: + rails_rotate(api, temp, rails_corner, 0); + use_temp=1; + break; + + case SEG_LEFT_BOTTOM: + rails_rotate(api, temp, rails_corner, 0); + use_temp=1; + break; } if (use_temp) SDL_BlitSurface(temp, NULL, result, NULL); - + SDL_FreeSurface(temp); SDL_BlitSurface(result, NULL, canvas, &modification_rect); SDL_FreeSurface(result);