X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Ftoons.c;h=048696f6cd365fb4322959f5d7da4fcced91bfed;hb=7a821f79cb735d048869b503279c402800afa44a;hp=c067d2d460ee1e9fd1d55308b671216780114bcb;hpb=3fd727f8ab7628eaab0be7de31658d7d468d6c8d;p=rocksndiamonds.git diff --git a/src/libgame/toons.c b/src/libgame/toons.c index c067d2d4..048696f6 100644 --- a/src/libgame/toons.c +++ b/src/libgame/toons.c @@ -35,31 +35,40 @@ int getAnimationFrame(int num_frames, int delay, int mode, int start_frame, sync_frame += start_frame * delay; - if (mode & ANIM_LOOP) /* normal, looping animation */ + if (mode & ANIM_LOOP) /* looping animation */ { frame = (sync_frame % (delay * num_frames)) / delay; } - else if (mode & ANIM_LINEAR) /* normal, non-looping animation */ + else if (mode & ANIM_LINEAR) /* linear (non-looping) animation */ { frame = sync_frame / delay; if (frame > num_frames - 1) frame = num_frames - 1; } - else if (mode & ANIM_PINGPONG) /* use border frames once */ + else if (mode & ANIM_PINGPONG) /* oscillate (border frames once) */ { int max_anim_frames = 2 * num_frames - 2; frame = (sync_frame % (delay * max_anim_frames)) / delay; frame = (frame < num_frames ? frame : max_anim_frames - frame); } - else if (mode & ANIM_PINGPONG2) /* use border frames twice */ + else if (mode & ANIM_PINGPONG2) /* oscillate (border frames twice) */ { int max_anim_frames = 2 * num_frames; frame = (sync_frame % (delay * max_anim_frames)) / delay; frame = (frame < num_frames ? frame : max_anim_frames - frame - 1); } + else if (mode & ANIM_RANDOM) /* play frames in random order */ + { + /* note: expect different frames for the same delay cycle! */ + + if (gfx.anim_random_frame < 0) + frame = SimpleRND(num_frames); + else + frame = gfx.anim_random_frame % num_frames; + } if (mode & ANIM_REVERSE) /* use reverse animation direction */ frame = num_frames - frame - 1; @@ -72,6 +81,20 @@ int getAnimationFrame(int num_frames, int delay, int mode, int start_frame, /* toon animation functions */ /* ========================================================================= */ +static int get_toon_direction(char *direction_string_raw) +{ + char *direction_string = getStringToLower(direction_string_raw); + int direction = (strcmp(direction_string, "left") == 0 ? MV_LEFT : + strcmp(direction_string, "right") == 0 ? MV_RIGHT : + strcmp(direction_string, "up") == 0 ? MV_UP : + strcmp(direction_string, "down") == 0 ? MV_DOWN : + MV_NO_MOVING); + + free(direction_string); + + return direction; +} + void InitToonScreen(Bitmap *save_buffer, void (*update_function)(void), void (*prepare_backbuffer_function)(void), @@ -145,67 +168,76 @@ boolean AnimateToon(int toon_nr, boolean restart) struct ToonInfo *anim = &screen_info.toons[toon_nr]; Bitmap *anim_bitmap = screen_info.toons[toon_nr].bitmap; GC anim_clip_gc = anim_bitmap->stored_clip_gc; + int direction = get_toon_direction(anim->direction); if (restart) { - horiz_move = (anim->direction & (ANIMDIR_LEFT | ANIMDIR_RIGHT)); - vert_move = (anim->direction & (ANIMDIR_UP | ANIMDIR_DOWN)); - anim_delay_value = anim->move_delay * screen_info.frame_delay_value; + horiz_move = (direction & (MV_LEFT | MV_RIGHT)); + vert_move = (direction & (MV_UP | MV_DOWN)); + anim_delay_value = anim->step_delay * screen_info.frame_delay_value; frame = getAnimationFrame(anim->anim_frames, anim->anim_delay, - anim->anim_mode, anim->start_frame, + anim->anim_mode, anim->anim_start_frame, animation_frame_counter++); if (horiz_move) { - if (anim->position == ANIMPOS_UP) + int pos_bottom = screen_info.height - anim->height; + + if (strcmp(anim->position, "top") == 0) pos_y = 0; - else if (anim->position == ANIMPOS_DOWN) - pos_y = screen_info.height - anim->height; - else if (anim->position == ANIMPOS_UPPER) - pos_y = SimpleRND((screen_info.height - anim->height) / 2); + else if (strcmp(anim->position, "bottom") == 0) + pos_y = pos_bottom; + else if (strcmp(anim->position, "upper") == 0) + pos_y = SimpleRND(pos_bottom / 2); + else if (strcmp(anim->position, "lower") == 0) + pos_y = pos_bottom / 2 + SimpleRND(pos_bottom / 2); else - pos_y = SimpleRND(screen_info.height - anim->height); + pos_y = SimpleRND(pos_bottom); - if (anim->direction == ANIMDIR_RIGHT) + if (direction == MV_RIGHT) { - delta_x = anim->stepsize; + delta_x = anim->step_offset; pos_x = -anim->width + delta_x; } else { - delta_x = -anim->stepsize; + delta_x = -anim->step_offset; pos_x = screen_info.width + delta_x; } + delta_y = 0; } else { - if (anim->position == ANIMPOS_LEFT) + int pos_right = screen_info.width - anim->width; + + if (strcmp(anim->position, "left") == 0) pos_x = 0; - else if (anim->position == ANIMPOS_RIGHT) - pos_x = screen_info.width - anim->width; + else if (strcmp(anim->position, "right") == 0) + pos_x = pos_right; else - pos_x = SimpleRND(screen_info.width - anim->width); + pos_x = SimpleRND(pos_right); - if (anim->direction == ANIMDIR_DOWN) + if (direction == MV_DOWN) { - delta_y = anim->stepsize; + delta_y = anim->step_offset; pos_y = -anim->height + delta_y; } else { - delta_y = -anim->stepsize; + delta_y = -anim->step_offset; pos_y = screen_info.width + delta_y; } + delta_x = 0; } } - if (pos_x <= -anim->width - anim->stepsize || - pos_x >= screen_info.width + anim->stepsize || - pos_y <= -anim->height - anim->stepsize || - pos_y >= screen_info.height + anim->stepsize) + if (pos_x <= -anim->width - anim->step_offset || + pos_x >= screen_info.width + anim->step_offset || + pos_y <= -anim->height - anim->step_offset || + pos_y >= screen_info.height + anim->step_offset) return TRUE; if (!DelayReached(&anim_delay, anim_delay_value)) @@ -230,8 +262,8 @@ boolean AnimateToon(int toon_nr, boolean restart) else if (pos_y > screen_info.height) pos_y = screen_info.height; - pad_x = (horiz_move ? anim->stepsize : 0); - pad_y = (vert_move ? anim->stepsize : 0); + pad_x = (horiz_move ? anim->step_offset : 0); + pad_y = (vert_move ? anim->step_offset : 0); src_x = anim->src_x + frame * anim->width; src_y = anim->src_y; dest_x = pos_x; @@ -269,7 +301,7 @@ boolean AnimateToon(int toon_nr, boolean restart) pos_y += delta_y; frame = getAnimationFrame(anim->anim_frames, anim->anim_delay, - anim->anim_mode, anim->start_frame, + anim->anim_mode, anim->anim_start_frame, animation_frame_counter++); return FALSE; @@ -279,6 +311,7 @@ void HandleAnimation(int mode) { static unsigned long animstart_delay = -1; static unsigned long animstart_delay_value = 0; + static boolean anim_running = FALSE; static boolean anim_restart = TRUE; static boolean reset_delay = TRUE; static int toon_nr = 0; @@ -287,16 +320,25 @@ void HandleAnimation(int mode) if (!setup.toons) return; + /* this may happen after reloading graphics and redefining "num_toons" */ + if (toon_nr >= screen_info.num_toons) + anim_restart = TRUE; + switch(mode) { case ANIM_START: screen_info.prepare_backbuffer_function(); + + anim_running = TRUE; anim_restart = TRUE; reset_delay = TRUE; return; case ANIM_CONTINUE: + if (!anim_running) + return; + break; case ANIM_STOP: @@ -308,6 +350,8 @@ void HandleAnimation(int mode) screen_info.update_function(); setup.direct_draw = draw_mode; + anim_running = FALSE; + return; default: @@ -329,7 +373,7 @@ void HandleAnimation(int mode) toon_nr = SimpleRND(screen_info.num_toons); } - anim_restart = reset_delay = AnimateToon(toon_nr,anim_restart); + anim_restart = reset_delay = AnimateToon(toon_nr, anim_restart); } void InitAnimation()