X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fcartoons.c;h=b2f2eb2b8f4ca5528a8d79f1a1b8b64f16c3a419;hp=2ede557a82c7fba4017843f3f6a5e78cde464994;hb=8ae535c1c76e1c33572afbcd4b2d3d9c3d7ba63e;hpb=2ae6ae8ed951e87fcba7c363705cd6ddea8de91c diff --git a/src/cartoons.c b/src/cartoons.c index 2ede557a..b2f2eb2b 100644 --- a/src/cartoons.c +++ b/src/cartoons.c @@ -1,563 +1,867 @@ -/*********************************************************** -* Rocks'n'Diamonds -- McDuffin Strikes Back! * -*----------------------------------------------------------* -* (c) 1995-2000 Artsoft Entertainment * -* Holger Schemel * -* Detmolder Strasse 189 * -* 33604 Bielefeld * -* Germany * -* e-mail: info@artsoft.org * -*----------------------------------------------------------* -* cartoons.c * -***********************************************************/ +// ============================================================================ +// Rocks'n'Diamonds - McDuffin Strikes Back! +// ---------------------------------------------------------------------------- +// (c) 1995-2014 by Artsoft Entertainment +// Holger Schemel +// info@artsoft.org +// http://www.artsoft.org/ +// ---------------------------------------------------------------------------- +// cartoons.c +// ============================================================================ #include "cartoons.h" #include "main.h" #include "tools.h" -static void HandleAnimation(int); -static boolean AnimateToon(int, boolean); -static void DrawAnim(Bitmap *, GC, int, int, int, int, int, int, int, int); +/* values for global toon animation definition */ +#define NUM_GLOBAL_TOON_ANIMS 1 +#define NUM_GLOBAL_TOON_PARTS MAX_NUM_TOONS -struct AnimInfo +/* values for global animation definition (including toons) */ +#define NUM_GLOBAL_ANIMS_AND_TOONS (NUM_GLOBAL_ANIMS + \ + NUM_GLOBAL_TOON_ANIMS) +#define NUM_GLOBAL_ANIM_PARTS_AND_TOONS MAX(NUM_GLOBAL_ANIM_PARTS_ALL, \ + NUM_GLOBAL_TOON_PARTS) + +struct GlobalAnimPartControlInfo { - int width, height; - int src_x, src_y; - int frames; - int frames_per_second; - int stepsize; - boolean pingpong; - int direction; - int position; + int nr; + int anim_nr; + int mode_nr; + + int graphic; + struct GraphicInfo graphic_info; + struct GraphicInfo control_info; + + int viewport_x; + int viewport_y; + int viewport_width; + int viewport_height; + + int x, y; + int step_xoffset, step_yoffset; + + unsigned int initial_anim_sync_frame; + unsigned int step_delay, step_delay_value; + + int init_delay_counter; + int anim_delay_counter; + int post_delay_counter; + + int drawing_stage; + + int state; + int last_game_status; }; -/* values for cartoon figures */ -#define NUM_TOONS 18 - -#define DWARF_XSIZE 40 -#define DWARF_YSIZE 48 -#define DWARF_X 2 -#define DWARF_Y 72 -#define DWARF2_Y 186 -#define DWARF_FRAMES 8 -#define DWARF_FPS 10 -#define DWARF_STEPSIZE 4 -#define JUMPER_XSIZE 48 -#define JUMPER_YSIZE 56 -#define JUMPER_X 2 -#define JUMPER_Y 125 -#define JUMPER_FRAMES 8 -#define JUMPER_FPS 10 -#define JUMPER_STEPSIZE 4 -#define CLOWN_XSIZE 80 -#define CLOWN_YSIZE 110 -#define CLOWN_X 327 -#define CLOWN_Y 10 -#define CLOWN_FRAMES 1 -#define CLOWN_FPS 10 -#define CLOWN_STEPSIZE 4 -#define BIRD_XSIZE 32 -#define BIRD_YSIZE 30 -#define BIRD1_X 2 -#define BIRD1_Y 2 -#define BIRD2_X 2 -#define BIRD2_Y 37 -#define BIRD_FRAMES 8 -#define BIRD_FPS 20 -#define BIRD_STEPSIZE 4 - -#define GAMETOON_XSIZE TILEX -#define GAMETOON_YSIZE TILEY -#define GAMETOON_FRAMES_4 4 -#define GAMETOON_FRAMES_8 8 -#define GAMETOON_FPS 20 -#define GAMETOON_STEPSIZE 4 - -#define ANIMDIR_LEFT 1 -#define ANIMDIR_RIGHT 2 -#define ANIMDIR_UP 4 -#define ANIMDIR_DOWN 8 - -#define ANIMPOS_ANY 0 -#define ANIMPOS_LEFT 1 -#define ANIMPOS_RIGHT 2 -#define ANIMPOS_UP 4 -#define ANIMPOS_DOWN 8 -#define ANIMPOS_UPPER 16 - -#define ANIM_START 0 -#define ANIM_CONTINUE 1 -#define ANIM_STOP 2 +struct GlobalAnimMainControlInfo +{ + struct GlobalAnimPartControlInfo base; + struct GlobalAnimPartControlInfo part[NUM_GLOBAL_ANIM_PARTS_AND_TOONS]; -void InitAnimation() + int nr; + int mode_nr; + + struct GraphicInfo control_info; + + int num_parts; + int part_counter; + int active_part_nr; + + boolean has_base; + + int init_delay_counter; + + int state; +}; + +struct GlobalAnimControlInfo { - HandleAnimation(ANIM_START); + struct GlobalAnimMainControlInfo anim[NUM_GLOBAL_ANIMS_AND_TOONS]; + + int nr; + int num_anims; +}; + + +/* forward declaration for internal use */ +static void DoAnimationExt(void); + +static struct GlobalAnimControlInfo global_anim_ctrl[NUM_SPECIAL_GFX_ARGS]; +static struct ToonInfo toons[MAX_NUM_TOONS]; + +static unsigned int anim_sync_frame = 0; +static unsigned int anim_sync_frame_delay = 0; +static unsigned int anim_sync_frame_delay_value = GAME_FRAME_DELAY; + +static boolean do_animations = FALSE; + + +static int getGlobalAnimationPart(struct GlobalAnimMainControlInfo *anim) +{ + struct GraphicInfo *c = &anim->control_info; + int last_anim_random_frame = gfx.anim_random_frame; + int part_nr; + + gfx.anim_random_frame = -1; // (use simple, ad-hoc random numbers) + + part_nr = getAnimationFrame(anim->num_parts, 1, + c->anim_mode, c->anim_start_frame, + anim->part_counter); + + gfx.anim_random_frame = last_anim_random_frame; + + return part_nr; } -void StopAnimation() +static void PrepareBackbuffer() +{ + if (game_status != GAME_MODE_PLAYING) + return; + + BlitScreenToBitmap(backbuffer); +} + +boolean ToonNeedsRedraw() { - HandleAnimation(ANIM_STOP); + return TRUE; } -void DoAnimation() +void InitToons() { - HandleAnimation(ANIM_CONTINUE); + int num_toons = MAX_NUM_TOONS; + int i; + + if (global.num_toons >= 0 && global.num_toons < MAX_NUM_TOONS) + num_toons = global.num_toons; + + for (i = 0; i < num_toons; i++) + { + int graphic = IMG_TOON_1 + i; + struct FileInfo *image = getImageListEntryFromImageID(graphic); + + toons[i].bitmap = graphic_info[graphic].bitmap; + + toons[i].src_x = graphic_info[graphic].src_x; + toons[i].src_y = graphic_info[graphic].src_y; + + toons[i].width = graphic_info[graphic].width; + toons[i].height = graphic_info[graphic].height; + + toons[i].anim_frames = graphic_info[graphic].anim_frames; + toons[i].anim_delay = graphic_info[graphic].anim_delay; + toons[i].anim_mode = graphic_info[graphic].anim_mode; + toons[i].anim_start_frame = graphic_info[graphic].anim_start_frame; + + toons[i].step_offset = graphic_info[graphic].step_offset; + toons[i].step_delay = graphic_info[graphic].step_delay; + + toons[i].direction = image->parameter[GFX_ARG_DIRECTION]; + toons[i].position = image->parameter[GFX_ARG_POSITION]; + } + + InitToonScreen(bitmap_db_toons, + BackToFront, PrepareBackbuffer, ToonNeedsRedraw, + toons, num_toons, + REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, + GAME_FRAME_DELAY); } -void HandleAnimation(int mode) +static void InitToonControls() { - static unsigned long animstart_delay = -1; - static unsigned long animstart_delay_value = 0; - static boolean anim_restart = TRUE; - static boolean reset_delay = TRUE; - static int toon_nr = 0; - int draw_mode; - - if (!setup.toons) - return; + struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[GAME_MODE_DEFAULT]; + struct GlobalAnimMainControlInfo *anim = &ctrl->anim[ctrl->num_anims]; + int mode_nr, anim_nr, part_nr; + int control = IMG_INTERNAL_GLOBAL_TOON_DEFAULT; + int num_toons = MAX_NUM_TOONS; + int i; + + if (global.num_toons >= 0 && global.num_toons < MAX_NUM_TOONS) + num_toons = global.num_toons; - switch(mode) + mode_nr = GAME_MODE_DEFAULT; + anim_nr = ctrl->num_anims; + + anim->nr = anim_nr; + anim->mode_nr = mode_nr; + anim->control_info = graphic_info[control]; + + anim->num_parts = 0; + anim->part_counter = 0; + anim->active_part_nr = 0; + + anim->has_base = FALSE; + + anim->init_delay_counter = 0; + + anim->state = ANIM_STATE_INACTIVE; + + part_nr = 0; + + for (i = 0; i < num_toons; i++) { - case ANIM_START: - anim_restart = TRUE; - reset_delay = TRUE; + struct GlobalAnimPartControlInfo *part = &anim->part[part_nr]; + int graphic = IMG_TOON_1 + i; + int control = graphic; + + part->nr = part_nr; + part->anim_nr = anim_nr; + part->mode_nr = mode_nr; + part->graphic = graphic; + part->graphic_info = graphic_info[graphic]; + part->control_info = graphic_info[control]; + + part->graphic_info.anim_delay *= part->graphic_info.step_delay; + + part->control_info.init_delay_fixed = 0; + part->control_info.init_delay_random = 150; + + part->control_info.x = ARG_UNDEFINED_VALUE; + part->control_info.y = ARG_UNDEFINED_VALUE; + + part->initial_anim_sync_frame = 0; + + part->step_delay = 0; + part->step_delay_value = graphic_info[control].step_delay; + + part->state = ANIM_STATE_INACTIVE; + part->last_game_status = -1; + + anim->num_parts++; + part_nr++; + } - /* Fill empty backbuffer for animation functions */ - if (setup.direct_draw && game_status == PLAYING) + ctrl->num_anims++; +} + +void InitGlobalAnimControls() +{ + int m, a, p; + int mode_nr, anim_nr, part_nr; + int graphic, control; + + anim_sync_frame = 0; + + ResetDelayCounter(&anim_sync_frame_delay); + + for (m = 0; m < NUM_SPECIAL_GFX_ARGS; m++) + { + mode_nr = m; + + struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr]; + + ctrl->nr = mode_nr; + ctrl->num_anims = 0; + + anim_nr = 0; + + for (a = 0; a < NUM_GLOBAL_ANIMS; a++) + { + struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr]; + int ctrl_id = GLOBAL_ANIM_ID_CONTROL_FIRST + a; + + control = global_anim_info[ctrl_id].graphic[GLOBAL_ANIM_ID_PART_BASE][m]; + + // if no base animation parameters defined, use default values + if (control == IMG_UNDEFINED) + control = IMG_INTERNAL_GLOBAL_ANIM_DEFAULT; + + anim->nr = anim_nr; + anim->mode_nr = mode_nr; + anim->control_info = graphic_info[control]; + + anim->num_parts = 0; + anim->part_counter = 0; + anim->active_part_nr = 0; + + anim->has_base = FALSE; + + anim->init_delay_counter = 0; + + anim->state = ANIM_STATE_INACTIVE; + + part_nr = 0; + + for (p = 0; p < NUM_GLOBAL_ANIM_PARTS_ALL; p++) { - int xx,yy; + struct GlobalAnimPartControlInfo *part = &anim->part[part_nr]; - SetDrawtoField(DRAW_BACKBUFFER); + graphic = global_anim_info[a].graphic[p][m]; + control = global_anim_info[ctrl_id].graphic[p][m]; - for(xx=0; xxnr = part_nr; + part->anim_nr = anim_nr; + part->mode_nr = mode_nr; + part->graphic = graphic; + part->graphic_info = graphic_info[graphic]; + part->control_info = graphic_info[control]; + + part->initial_anim_sync_frame = 0; + + part->step_delay = 0; + part->step_delay_value = graphic_info[control].step_delay; + + part->state = ANIM_STATE_INACTIVE; + part->last_game_status = -1; + + if (p < GLOBAL_ANIM_ID_PART_BASE) + { + anim->num_parts++; + part_nr++; + } + else + { + anim->base = *part; + anim->has_base = TRUE; + } } - if (setup.soft_scrolling && game_status == PLAYING) + if (anim->num_parts > 0 || anim->has_base) { - int fx = FX, fy = FY; + ctrl->num_anims++; + anim_nr++; + } + } + } - fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0); - fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0); + InitToonControls(); +} - BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY); - } +void DrawGlobalAnimExt(int drawing_stage) +{ + int mode_nr; - return; - break; - case ANIM_CONTINUE: - break; - case ANIM_STOP: - redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER); + if (game_status == GAME_MODE_LOADING) + do_animations = FALSE; + + if (!do_animations || !setup.toons) + return; - /* Redraw background even when in direct drawing mode */ - draw_mode = setup.direct_draw; - setup.direct_draw = FALSE; + if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_1) + DoAnimationExt(); - BackToFront(); + for (mode_nr = 0; mode_nr < NUM_SPECIAL_GFX_ARGS; mode_nr++) + { + struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr]; + int anim_nr; - setup.direct_draw = draw_mode; + if (mode_nr != GFX_SPECIAL_ARG_DEFAULT && + mode_nr != game_status) + continue; - return; - break; - default: - break; + for (anim_nr = 0; anim_nr < ctrl->num_anims; anim_nr++) + { + struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr]; + struct GraphicInfo *c = &anim->control_info; + int part_first, part_last; + int part_nr; + + if (!(anim->state & ANIM_STATE_RUNNING)) + continue; + + part_first = part_last = anim->active_part_nr; + + if (c->anim_mode & ANIM_ALL || anim->num_parts == 0) + { + int num_parts = anim->num_parts + (anim->has_base ? 1 : 0); + + part_first = 0; + part_last = num_parts - 1; + } + + for (part_nr = part_first; part_nr <= part_last; part_nr++) + { + struct GlobalAnimPartControlInfo *part = &anim->part[part_nr]; + struct GraphicInfo *g = &part->graphic_info; + Bitmap *src_bitmap; + int src_x, src_y; + int width = g->width; + int height = g->height; + int dst_x = part->x; + int dst_y = part->y; + int cut_x = 0; + int cut_y = 0; + int sync_frame; + int frame; + + if (!(part->state & ANIM_STATE_RUNNING)) + continue; + + if (part->drawing_stage != drawing_stage) + continue; + + if (part->x < 0) + { + dst_x = 0; + width += part->x; + cut_x = -part->x; + } + else if (part->x > part->viewport_width - g->width) + width -= (part->x - (part->viewport_width - g->width)); + + if (part->y < 0) + { + dst_y = 0; + height += part->y; + cut_y = -part->y; + } + else if (part->y > part->viewport_height - g->height) + height -= (part->y - (part->viewport_height - g->height)); + + dst_x += part->viewport_x; + dst_y += part->viewport_y; + + sync_frame = anim_sync_frame - part->initial_anim_sync_frame; + frame = getAnimationFrame(g->anim_frames, g->anim_delay, + g->anim_mode, g->anim_start_frame, + sync_frame); + + getFixedGraphicSource(part->graphic, frame, &src_bitmap, + &src_x, &src_y); + + src_x += cut_x; + src_y += cut_y; + + BlitToScreenMasked(src_bitmap, src_x, src_y, width, height, + dst_x, dst_y); + } + } } +} - if (reset_delay) +void DrawGlobalAnim(int drawing_stage) +{ + if (!do_animations || !setup.toons) + return; + + DrawGlobalAnimExt(drawing_stage); +} + +boolean SetGlobalAnimPart_Viewport(struct GlobalAnimPartControlInfo *part) +{ + int viewport_x; + int viewport_y; + int viewport_width; + int viewport_height; + boolean changed = FALSE; + + if (part->last_game_status == game_status) + return FALSE; + + part->last_game_status = game_status; + + part->drawing_stage = DRAW_GLOBAL_ANIM_STAGE_1; + + if (part->control_info.class == get_hash_from_key("window") || + part->control_info.class == get_hash_from_key("border")) + { + viewport_x = 0; + viewport_y = 0; + viewport_width = WIN_XSIZE; + viewport_height = WIN_YSIZE; + + part->drawing_stage = DRAW_GLOBAL_ANIM_STAGE_2; + } + else if (part->control_info.class == get_hash_from_key("door_1")) + { + viewport_x = DX; + viewport_y = DY; + viewport_width = DXSIZE; + viewport_height = DYSIZE; + } + else if (part->control_info.class == get_hash_from_key("door_2")) + { + viewport_x = VX; + viewport_y = VY; + viewport_width = VXSIZE; + viewport_height = VYSIZE; + } + else // default: "playfield" { - animstart_delay = Counter(); - animstart_delay_value = SimpleRND(3000); - reset_delay = FALSE; + viewport_x = REAL_SX; + viewport_y = REAL_SY; + viewport_width = FULL_SXSIZE; + viewport_height = FULL_SYSIZE; } - if (anim_restart) + if (viewport_x != part->viewport_x || + viewport_y != part->viewport_y || + viewport_width != part->viewport_width || + viewport_height != part->viewport_height) { - if (!DelayReached(&animstart_delay, animstart_delay_value)) - return; + part->viewport_x = viewport_x; + part->viewport_y = viewport_y; + part->viewport_width = viewport_width; + part->viewport_height = viewport_height; - toon_nr = SimpleRND(NUM_TOONS); + changed = TRUE; } - anim_restart = reset_delay = AnimateToon(toon_nr,anim_restart); + return changed; } -boolean AnimateToon(int toon_nr, boolean restart) +int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state) { - static int pos_x = 0, pos_y = 0; - static int delta_x = 0, delta_y = 0; - static int frame = 0, frame_step = 1; - static boolean horiz_move, vert_move; - static unsigned long anim_delay = 0; - static unsigned long anim_delay_value = 0; - static int width,height; - static int pad_x,pad_y; - static int cut_x,cut_y; - static int src_x, src_y; - static int dest_x, dest_y; - static struct AnimInfo toon[NUM_TOONS] = - { - { - DWARF_XSIZE, DWARF_YSIZE, - DWARF_X, DWARF_Y, - DWARF_FRAMES, - DWARF_FPS, - DWARF_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_RIGHT, - ANIMPOS_DOWN - }, - { - DWARF_XSIZE, DWARF_YSIZE, - DWARF_X, DWARF2_Y, - DWARF_FRAMES, - DWARF_FPS, - DWARF_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_LEFT, - ANIMPOS_DOWN - }, - { - JUMPER_XSIZE, JUMPER_YSIZE, - JUMPER_X, JUMPER_Y, - JUMPER_FRAMES, - JUMPER_FPS, - JUMPER_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_RIGHT, - ANIMPOS_DOWN - }, - { - CLOWN_XSIZE, CLOWN_YSIZE, - CLOWN_X, CLOWN_Y, - CLOWN_FRAMES, - CLOWN_FPS, - CLOWN_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_UP, - ANIMPOS_ANY - }, - { - BIRD_XSIZE, BIRD_YSIZE, - BIRD1_X, BIRD1_Y, - BIRD_FRAMES, - BIRD_FPS, - BIRD_STEPSIZE, - ANIM_OSCILLATE, - ANIMDIR_RIGHT, - ANIMPOS_UPPER - }, - { - BIRD_XSIZE, BIRD_YSIZE, - BIRD2_X, BIRD2_Y, - BIRD_FRAMES, - BIRD_FPS, - BIRD_STEPSIZE, - ANIM_OSCILLATE, - ANIMDIR_LEFT, - ANIMPOS_UPPER - }, - { - GAMETOON_XSIZE, GAMETOON_YSIZE, - ((GFX_SPIELER1_LEFT - GFX_START_ROCKSHEROES) % HEROES_PER_LINE)*TILEX, - ((GFX_SPIELER1_LEFT - GFX_START_ROCKSHEROES) / HEROES_PER_LINE)*TILEY, - GAMETOON_FRAMES_4, - GAMETOON_FPS, - GAMETOON_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_LEFT, - ANIMPOS_DOWN - }, - { - GAMETOON_XSIZE, GAMETOON_YSIZE, - ((GFX_SPIELER1_RIGHT - GFX_START_ROCKSHEROES) % HEROES_PER_LINE)*TILEX, - ((GFX_SPIELER1_RIGHT - GFX_START_ROCKSHEROES) / HEROES_PER_LINE)*TILEY, - GAMETOON_FRAMES_4, - GAMETOON_FPS, - GAMETOON_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_RIGHT, - ANIMPOS_DOWN - }, - { - GAMETOON_XSIZE, GAMETOON_YSIZE, - ((GFX_PINGUIN_LEFT - GFX_START_ROCKSHEROES) % HEROES_PER_LINE)*TILEX, - ((GFX_PINGUIN_LEFT - GFX_START_ROCKSHEROES) / HEROES_PER_LINE)*TILEY, - GAMETOON_FRAMES_4, - GAMETOON_FPS, - GAMETOON_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_LEFT, - ANIMPOS_DOWN - }, - { - GAMETOON_XSIZE, GAMETOON_YSIZE, - ((GFX_PINGUIN_RIGHT - GFX_START_ROCKSHEROES) % HEROES_PER_LINE)*TILEX, - ((GFX_PINGUIN_RIGHT - GFX_START_ROCKSHEROES) / HEROES_PER_LINE)*TILEY, - GAMETOON_FRAMES_4, - GAMETOON_FPS, - GAMETOON_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_RIGHT, - ANIMPOS_DOWN - }, - { - GAMETOON_XSIZE, GAMETOON_YSIZE, - ((GFX_MOLE_LEFT - GFX_START_ROCKSHEROES) % HEROES_PER_LINE)*TILEX, - ((GFX_MOLE_LEFT - GFX_START_ROCKSHEROES) / HEROES_PER_LINE)*TILEY, - GAMETOON_FRAMES_4, - GAMETOON_FPS, - GAMETOON_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_LEFT, - ANIMPOS_DOWN - }, - { - GAMETOON_XSIZE, GAMETOON_YSIZE, - ((GFX_MOLE_RIGHT - GFX_START_ROCKSHEROES) % HEROES_PER_LINE)*TILEX, - ((GFX_MOLE_RIGHT - GFX_START_ROCKSHEROES) / HEROES_PER_LINE)*TILEY, - GAMETOON_FRAMES_4, - GAMETOON_FPS, - GAMETOON_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_RIGHT, - ANIMPOS_DOWN - }, - { - GAMETOON_XSIZE, GAMETOON_YSIZE, - ((GFX_SCHWEIN_LEFT - GFX_START_ROCKSHEROES) % HEROES_PER_LINE)*TILEX, - ((GFX_SCHWEIN_LEFT - GFX_START_ROCKSHEROES) / HEROES_PER_LINE)*TILEY, - GAMETOON_FRAMES_4, - GAMETOON_FPS, - GAMETOON_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_LEFT, - ANIMPOS_DOWN - }, - { - GAMETOON_XSIZE, GAMETOON_YSIZE, - ((GFX_SCHWEIN_RIGHT - GFX_START_ROCKSHEROES) % HEROES_PER_LINE)*TILEX, - ((GFX_SCHWEIN_RIGHT - GFX_START_ROCKSHEROES) / HEROES_PER_LINE)*TILEY, - GAMETOON_FRAMES_4, - GAMETOON_FPS, - GAMETOON_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_RIGHT, - ANIMPOS_DOWN - }, - { - GAMETOON_XSIZE, GAMETOON_YSIZE, - ((GFX_DRACHE_LEFT - GFX_START_ROCKSHEROES) % HEROES_PER_LINE)*TILEX, - ((GFX_DRACHE_LEFT - GFX_START_ROCKSHEROES) / HEROES_PER_LINE)*TILEY, - GAMETOON_FRAMES_4, - GAMETOON_FPS, - GAMETOON_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_LEFT, - ANIMPOS_DOWN - }, - { - GAMETOON_XSIZE, GAMETOON_YSIZE, - ((GFX_DRACHE_RIGHT - GFX_START_ROCKSHEROES) % HEROES_PER_LINE)*TILEX, - ((GFX_DRACHE_RIGHT - GFX_START_ROCKSHEROES) / HEROES_PER_LINE)*TILEY, - GAMETOON_FRAMES_4, - GAMETOON_FPS, - GAMETOON_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_RIGHT, - ANIMPOS_DOWN - }, - { - GAMETOON_XSIZE, GAMETOON_YSIZE, - ((GFX_SONDE - GFX_START_ROCKSHEROES) % HEROES_PER_LINE)*TILEX, - ((GFX_SONDE - GFX_START_ROCKSHEROES) / HEROES_PER_LINE)*TILEY, - GAMETOON_FRAMES_8, - GAMETOON_FPS, - GAMETOON_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_LEFT, - ANIMPOS_ANY - }, - { - GAMETOON_XSIZE, GAMETOON_YSIZE, - ((GFX_SONDE - GFX_START_ROCKSHEROES) % HEROES_PER_LINE)*TILEX, - ((GFX_SONDE - GFX_START_ROCKSHEROES) / HEROES_PER_LINE)*TILEY, - GAMETOON_FRAMES_8, - GAMETOON_FPS, - GAMETOON_STEPSIZE, - ANIM_NORMAL, - ANIMDIR_RIGHT, - ANIMPOS_ANY - }, - }; - struct AnimInfo *anim = &toon[toon_nr]; - int anim_bitmap_nr = (toon_nr < 6 ? PIX_TOONS : PIX_HEROES); - Bitmap *anim_bitmap = pix[anim_bitmap_nr]; - GC anim_clip_gc = pix[anim_bitmap_nr]->stored_clip_gc; - - if (restart) + struct GraphicInfo *g = &part->graphic_info; + struct GraphicInfo *c = &part->control_info; + boolean viewport_changed = SetGlobalAnimPart_Viewport(part); + + if (viewport_changed) + state |= ANIM_STATE_RESTART; + + if (state & ANIM_STATE_RESTART) { - horiz_move = (anim->direction & (ANIMDIR_LEFT | ANIMDIR_RIGHT)); - vert_move = (anim->direction & (ANIMDIR_UP | ANIMDIR_DOWN)); - anim_delay_value = 1000/anim->frames_per_second; - frame = 0; + ResetDelayCounterExt(&part->step_delay, anim_sync_frame); + + part->init_delay_counter = + (c->init_delay_fixed + GetSimpleRandom(c->init_delay_random)); - if (horiz_move) + part->anim_delay_counter = + (c->anim_delay_fixed + GetSimpleRandom(c->anim_delay_random)); + + part->initial_anim_sync_frame = + (g->anim_global_sync ? 0 : anim_sync_frame + part->init_delay_counter); + + if (c->direction & MV_HORIZONTAL) { - if (anim->position==ANIMPOS_UP) - pos_y = 0; - else if (anim->position==ANIMPOS_DOWN) - pos_y = FULL_SYSIZE-anim->height; - else if (anim->position==ANIMPOS_UPPER) - pos_y = SimpleRND((FULL_SYSIZE-anim->height)/2); + int pos_bottom = part->viewport_height - g->height; + + if (c->position == POS_TOP) + part->y = 0; + else if (c->position == POS_UPPER) + part->y = GetSimpleRandom(pos_bottom / 2); + else if (c->position == POS_MIDDLE) + part->y = pos_bottom / 2; + else if (c->position == POS_LOWER) + part->y = pos_bottom / 2 + GetSimpleRandom(pos_bottom / 2); + else if (c->position == POS_BOTTOM) + part->y = pos_bottom; else - pos_y = SimpleRND(FULL_SYSIZE-anim->height); + part->y = GetSimpleRandom(pos_bottom); - if (anim->direction==ANIMDIR_RIGHT) + if (c->direction == MV_RIGHT) { - delta_x = anim->stepsize; - pos_x = -anim->width+delta_x; + part->step_xoffset = c->step_offset; + part->x = -g->width + part->step_xoffset; } else { - delta_x = -anim->stepsize; - pos_x = FULL_SXSIZE+delta_x; + part->step_xoffset = -c->step_offset; + part->x = part->viewport_width + part->step_xoffset; } - delta_y = 0; + + part->step_yoffset = 0; } - else + else if (c->direction & MV_VERTICAL) { - if (anim->position==ANIMPOS_LEFT) - pos_x = 0; - else if (anim->position==ANIMPOS_RIGHT) - pos_x = FULL_SXSIZE-anim->width; + int pos_right = part->viewport_width - g->width; + + if (c->position == POS_LEFT) + part->x = 0; + else if (c->position == POS_RIGHT) + part->x = pos_right; else - pos_x = SimpleRND(FULL_SXSIZE-anim->width); + part->x = GetSimpleRandom(pos_right); - if (anim->direction==ANIMDIR_DOWN) + if (c->direction == MV_DOWN) { - delta_y = anim->stepsize; - pos_y = -anim->height+delta_y; + part->step_yoffset = c->step_offset; + part->y = -g->height + part->step_yoffset; } else { - delta_y = -anim->stepsize; - pos_y = FULL_SYSIZE+delta_y; + part->step_yoffset = -c->step_offset; + part->y = part->viewport_height + part->step_yoffset; } - delta_x = 0; + + part->step_xoffset = 0; + } + else + { + part->x = 0; + part->y = 0; + + part->step_xoffset = 0; + part->step_yoffset = 0; } + + if (c->x != ARG_UNDEFINED_VALUE) + part->x = c->x; + if (c->y != ARG_UNDEFINED_VALUE) + part->y = c->y; + + if (c->step_xoffset != ARG_UNDEFINED_VALUE) + part->step_xoffset = c->step_xoffset; + if (c->step_yoffset != ARG_UNDEFINED_VALUE) + part->step_yoffset = c->step_yoffset; } - if (pos_x <= -anim->width - anim->stepsize || - pos_x >= FULL_SXSIZE + anim->stepsize || - pos_y <= -anim->height - anim->stepsize || - pos_y >= FULL_SYSIZE + anim->stepsize) - return(TRUE); + if (part->init_delay_counter > 0) + { + part->init_delay_counter--; + + return ANIM_STATE_WAITING; + } - if (!DelayReached(&anim_delay, anim_delay_value)) + if ((part->x <= -g->width && part->step_xoffset <= 0) || + (part->x >= part->viewport_width && part->step_xoffset >= 0) || + (part->y <= -g->height && part->step_yoffset <= 0) || + (part->y >= part->viewport_height && part->step_yoffset >= 0)) + return ANIM_STATE_RESTART; + + if (part->anim_delay_counter > 0) { - if ((game_status == HELPSCREEN || - (game_status == MAINMENU && redraw_mask & REDRAW_MICROLEVEL)) - && !restart) - DrawAnim(anim_bitmap, anim_clip_gc, - src_x + cut_x, src_y + cut_y, width, height, - REAL_SX + dest_x, REAL_SY + dest_y, pad_x, pad_y); - - return(FALSE); + part->anim_delay_counter--; + + if (part->anim_delay_counter == 0) + { + part->post_delay_counter = + (c->post_delay_fixed + GetSimpleRandom(c->post_delay_random)); + + if (part->post_delay_counter > 0) + return ANIM_STATE_RUNNING; + + return ANIM_STATE_RESTART | ANIM_STATE_RUNNING; + } } - if (pos_x<-anim->width) - pos_x = -anim->width; - else if (pos_x>FULL_SXSIZE) - pos_x = FULL_SXSIZE; - if (pos_y<-anim->height) - pos_y = -anim->height; - else if (pos_y>FULL_SYSIZE) - pos_y = FULL_SYSIZE; - - pad_x = (horiz_move ? anim->stepsize : 0); - pad_y = (vert_move ? anim->stepsize : 0); - src_x = anim->src_x + frame * anim->width; - src_y = anim->src_y; - dest_x = pos_x; - dest_y = pos_y; - cut_x = cut_y = 0; - width = anim->width; - height = anim->height; - - if (pos_x<0) + if (part->post_delay_counter > 0) { - dest_x = 0; - width += pos_x; - cut_x = -pos_x; + part->post_delay_counter--; + + if (part->post_delay_counter == 0) + return ANIM_STATE_RESTART; + + return ANIM_STATE_WAITING; } - else if (pos_x>FULL_SXSIZE-anim->width) - width -= (pos_x - (FULL_SXSIZE-anim->width)); - if (pos_y<0) + if (!DelayReachedExt(&part->step_delay, part->step_delay_value, + anim_sync_frame)) + return ANIM_STATE_RUNNING; + +#if 0 { - dest_y = 0; - height += pos_y; - cut_y = -pos_y; + static unsigned int last_counter = -1; + unsigned int counter = Counter(); + + printf("::: NEXT ANIM PART [%d, %d]\n", + anim_sync_frame, counter - last_counter); + + last_counter = counter; } - else if (pos_y>FULL_SYSIZE-anim->height) - height -= (pos_y - (FULL_SYSIZE-anim->height)); +#endif + + part->x += part->step_xoffset; + part->y += part->step_yoffset; + + return ANIM_STATE_RUNNING; +} - DrawAnim(anim_bitmap,anim_clip_gc, - src_x+cut_x,src_y+cut_y, width,height, - REAL_SX+dest_x,REAL_SY+dest_y, pad_x,pad_y); +void HandleGlobalAnim_Main(struct GlobalAnimMainControlInfo *anim, int action) +{ + struct GlobalAnimPartControlInfo *part; + struct GraphicInfo *c = &anim->control_info; + boolean skip = FALSE; + +#if 0 + printf("::: HandleGlobalAnim_Main: %d, %d => %d\n", + anim->mode_nr, anim->nr, anim->num_parts); + printf("::: %d, %d, %d\n", global.num_toons, setup.toons, num_toons); +#endif - pos_x += delta_x; - pos_y += delta_y; - frame += frame_step; +#if 0 + printf("::: %s(%d): %d, %d, %d [%d]\n", + (action == ANIM_START ? "ANIM_START" : + action == ANIM_CONTINUE ? "ANIM_CONTINUE" : + action == ANIM_STOP ? "ANIM_STOP" : "(should not happen)"), + anim->nr, + anim->state & ANIM_STATE_RESTART, + anim->state & ANIM_STATE_WAITING, + anim->state & ANIM_STATE_RUNNING, + anim->num_parts); +#endif - if (frame<0 || frame>=anim->frames) + switch (action) { - if (anim->pingpong) + case ANIM_START: + anim->state = ANIM_STATE_RESTART; + anim->part_counter = 0; + anim->active_part_nr = 0; + skip = TRUE; + + break; + + case ANIM_CONTINUE: + if (anim->state == ANIM_STATE_INACTIVE) + skip = TRUE; + + break; + + case ANIM_STOP: + anim->state = ANIM_STATE_INACTIVE; + skip = TRUE; + + break; + + default: + break; + } + + if (c->anim_mode & ANIM_ALL || anim->num_parts == 0) + { + int num_parts = anim->num_parts + (anim->has_base ? 1 : 0); + int i; + +#if 0 + printf("::: HandleGlobalAnim_Main: %d, %d => %d\n", + anim->mode_nr, anim->nr, num_parts); +#endif + + for (i = 0; i < num_parts; i++) { - frame_step *= -1; - frame = (frame<0 ? 1 : anim->frames-2); + part = &anim->part[i]; + + switch (action) + { + case ANIM_START: + anim->state = ANIM_STATE_RUNNING; + part->state = ANIM_STATE_RESTART; + skip = TRUE; + + break; + + case ANIM_CONTINUE: + if (part->state == ANIM_STATE_INACTIVE) + skip = TRUE; + + break; + + case ANIM_STOP: + part->state = ANIM_STATE_INACTIVE; + skip = TRUE; + + break; + + default: + break; + } + + if (skip) + continue; + + part->state = HandleGlobalAnim_Part(part, part->state); } - else - frame = (frame<0 ? anim->frames-1 : 0); + + return; } - return(FALSE); + if (skip) + return; + + if (anim->state & ANIM_STATE_RESTART) // directly after restart + anim->active_part_nr = getGlobalAnimationPart(anim); + + part = &anim->part[anim->active_part_nr]; + + part->state = ANIM_STATE_RUNNING; + + anim->state = HandleGlobalAnim_Part(part, anim->state); + + if (anim->state & ANIM_STATE_RESTART) + anim->part_counter++; +} + +void HandleGlobalAnim_Mode(struct GlobalAnimControlInfo *ctrl, int action) +{ + int i; + +#if 0 + printf("::: HandleGlobalAnim_Mode: %d => %d\n", + ctrl->nr, ctrl->num_anims); +#endif + + for (i = 0; i < ctrl->num_anims; i++) + HandleGlobalAnim_Main(&ctrl->anim[i], action); } -void DrawAnim(Bitmap *toon_bitmap, GC toon_clip_gc, - int src_x, int src_y, int width, int height, - int dest_x, int dest_y, int pad_x, int pad_y) +void HandleGlobalAnim(int action) { - int buf_x = DOOR_GFX_PAGEX3, buf_y = DOOR_GFX_PAGEY1; +#if 0 + printf("::: HandleGlobalAnim [mode == %d]\n", game_status); +#endif + + HandleGlobalAnim_Mode(&global_anim_ctrl[GAME_MODE_DEFAULT], action); + HandleGlobalAnim_Mode(&global_anim_ctrl[game_status], action); +} + +void InitAnimation() +{ + // HandleAnimation(ANIM_START); + +#if 0 + printf("::: InitAnimation\n"); +#endif + + // InitCounter(); + + InitGlobalAnimControls(); + + HandleGlobalAnim(ANIM_START); + + do_animations = TRUE; +} + +void StopAnimation() +{ + // HandleAnimation(ANIM_STOP); + +#if 0 + printf("::: StopAnimation\n"); +#endif + + HandleGlobalAnim(ANIM_STOP); + + do_animations = FALSE; +} + +static void DoAnimationExt() +{ +#if 0 + printf("::: DoAnimation [%d, %d]\n", anim_sync_frame, Counter()); +#endif #if 1 - /* special method to avoid flickering interference with BackToFront() */ - BlitBitmap(backbuffer, pix[PIX_DB_DOOR], dest_x-pad_x, dest_y-pad_y, - width+2*pad_x, height+2*pad_y, buf_x, buf_y); - SetClipOrigin(toon_bitmap, toon_clip_gc, dest_x-src_x, dest_y-src_y); - BlitBitmapMasked(toon_bitmap, backbuffer, - src_x, src_y, width, height, dest_x, dest_y); - BlitBitmap(backbuffer, window, dest_x-pad_x, dest_y-pad_y, - width+2*pad_x, height+2*pad_y, dest_x-pad_x, dest_y-pad_y); - BackToFront(); - BlitBitmap(pix[PIX_DB_DOOR], backbuffer, buf_x, buf_y, - width+2*pad_x, height+2*pad_y, dest_x-pad_x, dest_y-pad_y); + WaitUntilDelayReached(&anim_sync_frame_delay, anim_sync_frame_delay_value); + anim_sync_frame++; #else - /* normal method, causing flickering interference with BackToFront() */ - BlitBitmap(backbuffer, pix[PIX_DB_DOOR], dest_x-pad_x, dest_y-pad_y, - width+2*pad_x, height+2*pad_y, buf_x, buf_y); - SetClipOrigin(toon_bitmap,toon_clip_gc, buf_x-src_x+pad_x,buf_y-src_y+pad_y); - BlitBitmapMasked(toon_bitmap, pix[PIX_DB_DOOR], - src_x, src_y, width, height, buf_x+pad_x, buf_y+pad_y); - BlitBitmap(pix[PIX_DB_DOOR], window, buf_x, buf_y, - width+2*pad_x, height+2*pad_y, dest_x-pad_x, dest_y-pad_y); + if (DelayReached(&anim_sync_frame_delay, anim_sync_frame_delay_value)) + anim_sync_frame++; +#endif + + HandleGlobalAnim(ANIM_CONTINUE); + +#if 1 + // force screen redraw in next frame to continue drawing global animations + redraw_mask = REDRAW_ALL; #endif +} + +void DoAnimation() +{ + // HandleAnimation(ANIM_CONTINUE); - FlushDisplay(); +#if 1 + // force screen redraw in next frame to continue drawing global animations + redraw_mask = REDRAW_ALL; +#endif }