X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ftools.c;h=7e24e5016f0ac0dc049e8e2154ae62b1bdddef33;hb=c5ee7e4524f10322894b2547337e4c973a80a552;hp=fe3291faea48c4958ac3fdfda7554a5b736e6020;hpb=ed4b7eed89c292042403561e1ed1449e60888b45;p=rocksndiamonds.git diff --git a/src/tools.c b/src/tools.c index fe3291fa..7e24e501 100644 --- a/src/tools.c +++ b/src/tools.c @@ -1,35 +1,42 @@ /*********************************************************** -* Rocks'n'Diamonds -- McDuffin Strikes Back! * +* Rocks'n'Diamonds -- McDuffin Strikes Back! * *----------------------------------------------------------* -* (c) 1995-98 Artsoft Entertainment * -* Holger Schemel * -* Oststrasse 11a * -* 33604 Bielefeld * -* phone: ++49 +521 290471 * -* email: aeglos@valinor.owl.de * +* (c) 1995-2002 Artsoft Entertainment * +* Holger Schemel * +* Detmolder Strasse 189 * +* 33604 Bielefeld * +* Germany * +* e-mail: info@artsoft.org * *----------------------------------------------------------* -* tools.c * +* tools.c * ***********************************************************/ -#include - -#ifdef __FreeBSD__ -#include -#endif +#include "libgame/libgame.h" #include "tools.h" #include "game.h" #include "events.h" -#include "sound.h" -#include "misc.h" -#include "buttons.h" -#include "joystick.h" #include "cartoons.h" #include "network.h" +#include "tape.h" -#ifdef MSDOS -extern boolean wait_for_vsync; -#endif +/* tool button identifiers */ +#define TOOL_CTRL_ID_YES 0 +#define TOOL_CTRL_ID_NO 1 +#define TOOL_CTRL_ID_CONFIRM 2 +#define TOOL_CTRL_ID_PLAYER_1 3 +#define TOOL_CTRL_ID_PLAYER_2 4 +#define TOOL_CTRL_ID_PLAYER_3 5 +#define TOOL_CTRL_ID_PLAYER_4 6 + +#define NUM_TOOL_BUTTONS 7 + +/* forward declaration for internal use */ +static void UnmapToolButtons(); +static void HandleToolButtons(struct GadgetInfo *); + +static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS]; +static int request_gadget_id = -1; void SetDrawtoField(int mode) { @@ -61,10 +68,55 @@ void SetDrawtoField(int mode) } } +void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height) +{ + if (game_status == PLAYING) + { + if (force_redraw) + { + x = gfx.sx - TILEX; + y = gfx.sy - TILEY; + width = gfx.sxsize + 2 * TILEX; + height = gfx.sysize + 2 * TILEY; + } + + if (force_redraw || setup.direct_draw) + { + int xx, yy; + int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY; + int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY; + + if (setup.direct_draw) + SetDrawtoField(DRAW_BACKBUFFER); + + for(xx=BX1; xx<=BX2; xx++) + for(yy=BY1; yy<=BY2; yy++) + if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2) + DrawScreenField(xx, yy); + DrawAllPlayers(); + + if (setup.direct_draw) + SetDrawtoField(DRAW_DIRECT); + } + + if (setup.soft_scrolling) + { + int fx = FX, fy = FY; + + fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0); + fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0); + + BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY); + } + } + + BlitBitmap(drawto, window, x, y, width, height, x, y); +} + void BackToFront() { int x,y; - Drawable buffer = (drawto_field == window ? backbuffer : drawto_field); + DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field); if (setup.direct_draw && game_status == PLAYING) redraw_mask &= ~REDRAW_MAIN; @@ -75,42 +127,59 @@ void BackToFront() if (redraw_mask & REDRAW_FIELD) redraw_mask &= ~REDRAW_TILES; - /* - if (redraw_mask & REDRAW_FIELD || - (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING)) - redraw_mask &= ~REDRAW_TILES; - */ - - if (!redraw_mask) + if (redraw_mask == REDRAW_NONE) return; + if (global.fps_slowdown && game_status == PLAYING) + { + static boolean last_frame_skipped = FALSE; + boolean skip_even_when_not_scrolling = TRUE; + boolean just_scrolling = (ScreenMovDir != 0); + boolean verbose = FALSE; + + if (global.fps_slowdown_factor > 1 && + (FrameCounter % global.fps_slowdown_factor) && + (just_scrolling || skip_even_when_not_scrolling)) + { + redraw_mask &= ~REDRAW_MAIN; + + last_frame_skipped = TRUE; + + if (verbose) + printf("FRAME SKIPPED\n"); + } + else + { + if (last_frame_skipped) + redraw_mask |= REDRAW_FIELD; + + last_frame_skipped = FALSE; + + if (verbose) + printf("frame not skipped\n"); + } + } + /* synchronize X11 graphics at this point; if we would synchronize the display immediately after the buffer switching (after the XFlush), this could mean that we have to wait for the graphics to complete, although we could go on doing calculations for the next frame */ - XSync(display, FALSE); - - /* -#ifdef MSDOS - wait_for_vsync = TRUE; -#endif - */ + SyncDisplay(); if (redraw_mask & REDRAW_ALL) { - XCopyArea(display,backbuffer,window,gc, - 0,0, WIN_XSIZE,WIN_YSIZE, - 0,0); + BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); redraw_mask = 0; } if (redraw_mask & REDRAW_FIELD) { if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER) - XCopyArea(display,backbuffer,window,gc, - REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, - REAL_SX,REAL_SY); + { + BlitBitmap(backbuffer, window, + REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY); + } else { int fx = FX, fy = FY; @@ -126,7 +195,7 @@ void BackToFront() ABS(ScreenMovPos) == ScrollStepSize || redraw_tiles > REDRAWTILES_THRESHOLD) { - XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY); + BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY); #ifdef DEBUG #if 0 @@ -143,56 +212,51 @@ void BackToFront() #endif } } + redraw_mask &= ~REDRAW_MAIN; } if (redraw_mask & REDRAW_DOORS) { if (redraw_mask & REDRAW_DOOR_1) - XCopyArea(display,backbuffer,window,gc, - DX,DY, DXSIZE,DYSIZE, - DX,DY); + BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY); if (redraw_mask & REDRAW_DOOR_2) { if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2) - XCopyArea(display,backbuffer,window,gc, - VX,VY, VXSIZE,VYSIZE, - VX,VY); + BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY); else { if (redraw_mask & REDRAW_VIDEO_1) - XCopyArea(display,backbuffer,window,gc, - VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS, - VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE, - VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS); + BlitBitmap(backbuffer, window, + VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS, + VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE, + VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS); if (redraw_mask & REDRAW_VIDEO_2) - XCopyArea(display,backbuffer,window,gc, - VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS, - VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE, - VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS); + BlitBitmap(backbuffer, window, + VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS, + VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE, + VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS); if (redraw_mask & REDRAW_VIDEO_3) - XCopyArea(display,backbuffer,window,gc, - VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS, - VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE, - VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS); + BlitBitmap(backbuffer, window, + VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS, + VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE, + VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS); } } if (redraw_mask & REDRAW_DOOR_3) - XCopyArea(display, backbuffer, window, gc, - EX, EY, EXSIZE, EYSIZE, - EX, EY); + BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY); redraw_mask &= ~REDRAW_DOORS; } - if (redraw_mask & REDRAW_MICROLEV) + if (redraw_mask & REDRAW_MICROLEVEL) { - XCopyArea(display,backbuffer,window,gc, - MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE, - MICROLEV_XPOS,MICROLEV_YPOS); - XCopyArea(display,backbuffer,window,gc, - SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE, - SX,MICROLABEL_YPOS); - redraw_mask &= ~REDRAW_MICROLEV; + BlitBitmap(backbuffer, window, + MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE, + MICROLEV_XPOS, MICROLEV_YPOS); + BlitBitmap(backbuffer, window, + SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE, + SX, MICROLABEL_YPOS); + redraw_mask &= ~REDRAW_MICROLEVEL; } if (redraw_mask & REDRAW_TILES) @@ -200,96 +264,134 @@ void BackToFront() for(x=0; x FC_SPECIAL2) - font_type = FC_RED; + if (mask_mode == USE_MASKING) + DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame); + else + DrawGraphicExt(dst_bitmap, x, y, graphic, frame); +} - font_width = (font_size == FS_BIG ? FONT1_XSIZE : - font_type < FC_SPECIAL1 ? FONT2_XSIZE : - font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE); - font_height = (font_size == FS_BIG ? FONT1_XSIZE : - font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE); - font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT); - font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) * - FONT_LINES_PER_FONT); +inline boolean checkDrawGraphicAnimation(int x, int y, int graphic) +{ + int lx = LEVELX(x), ly = LEVELY(y); - while (*text) - { - char c = *text++; + return (IN_SCR_FIELD(x, y) && + GfxFrame[lx][ly] % graphic_info[graphic].anim_delay == 0); +} - if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW) - { - print_inverse = TRUE; - continue; - } +inline boolean checkDrawLevelGraphicAnimation(int x, int y, int graphic) +{ + return (IN_SCR_FIELD(SCREENX(x), SCREENY(y)) && + GfxFrame[x][y] % graphic_info[graphic].anim_delay == 0); +} - if (c >= 'a' && c <= 'z') - c = 'A' + (c - 'a'); - else if (c == 'ä' || c == 'Ä') - c = 91; - else if (c == 'ö' || c == 'Ö') - c = 92; - else if (c == 'ü' || c == 'Ü') - c = 93; +inline boolean DrawGraphicAnimation(int x, int y, int graphic) +{ + int lx = LEVELX(x), ly = LEVELY(y); - if (c >= 32 && c <= 95) - { - int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width; - int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start; - int dest_x = x, dest_y = y; +#if 0 + if (!checkDrawGraphicAnimation(x, y, graphic)) + return FALSE; +#else + if (!IN_SCR_FIELD(x, y)) + return FALSE; +#endif - if (print_inverse) - { - XCopyArea(display, pix[font_pixmap], d, gc, - FONT_CHARS_PER_LINE * font_width, - 3 * font_height + font_start, - font_width, font_height, x, y); - - XSetClipOrigin(display, clip_gc[font_pixmap], - dest_x - src_x, dest_y - src_y); - XCopyArea(display, pix[font_pixmap], drawto, clip_gc[font_pixmap], - 0, 0, font_width, font_height, dest_x, dest_y); - } - else - XCopyArea(display, pix[font_pixmap], d, gc, - src_x, src_y, font_width, font_height, dest_x, dest_y); - } + DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY, + graphic, GfxFrame[lx][ly], NO_MASKING); + MarkTileDirty(x, y); - x += font_width; - } + return TRUE; +} + +boolean DrawLevelGraphicAnimation(int x, int y, int graphic) +{ + return DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic); +} + +boolean DrawLevelElementAnimation(int x, int y, int element) +{ + return DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element)); +} + +inline void ContinueLevelGraphicAnimation(int x, int y, int graphic) +{ + if (GfxFrame[x][y] % graphic_info[graphic].anim_delay != 0) + return; + + DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic); +} + +void ContinueLevelElementAnimation(int x, int y, int element) +{ + ContinueLevelGraphicAnimation(x, y, el2img(element)); } void DrawAllPlayers() @@ -422,10 +551,10 @@ void DrawAllPlayers() void DrawPlayerField(int x, int y) { - if (!IS_PLAYER(x,y)) + if (!IS_PLAYER(x, y)) return; - DrawPlayer(PLAYERINFO(x,y)); + DrawPlayer(PLAYERINFO(x, y)); } void DrawPlayer(struct PlayerInfo *player) @@ -435,11 +564,12 @@ void DrawPlayer(struct PlayerInfo *player) int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy); int sx = SCREENX(jx), sy = SCREENY(jy); int sxx = 0, syy = 0; - int element = Feld[jx][jy]; - int graphic, phase; + int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy]; + int graphic; + int frame = 0; + boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE); - if (!player->active || player->gone || - !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy))) + if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy))) return; #if DEBUG @@ -452,19 +582,23 @@ void DrawPlayer(struct PlayerInfo *player) } #endif - if (element == EL_EXPLODING) + if (element == EL_EXPLOSION) return; /* draw things in the field the player is leaving, if needed */ - if (last_jx != jx || last_jy != jy) + if (player_is_moving) { - if (Store[last_jx][last_jy]) + if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element)) { DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]); - DrawLevelFieldThruMask(last_jx, last_jy); + + if (last_element == EL_DYNAMITE_ACTIVE) + DrawDynamite(last_jx, last_jy); + else + DrawLevelFieldThruMask(last_jx, last_jy); } - else if (Feld[last_jx][last_jy] == EL_DYNAMIT) + else if (last_element == EL_DYNAMITE_ACTIVE) DrawDynamite(last_jx, last_jy); else DrawLevelField(last_jx, last_jy); @@ -473,10 +607,10 @@ void DrawPlayer(struct PlayerInfo *player) { if (player->GfxPos) { - if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL) - DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER); + if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL) + DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY); else - DrawLevelElement(next_jx, next_jy, EL_LEERRAUM); + DrawLevelElement(next_jx, next_jy, EL_EMPTY); } else DrawLevelField(next_jx, next_jy); @@ -493,22 +627,93 @@ void DrawPlayer(struct PlayerInfo *player) if (Store[jx][jy]) DrawLevelElement(jx, jy, Store[jx][jy]); - else if (element != EL_DYNAMIT && element != EL_DYNABOMB) + else if (!IS_ACTIVE_BOMB(element)) DrawLevelField(jx, jy); + else + DrawLevelElement(jx, jy, EL_EMPTY); /* draw player himself */ - if (player->MovDir == MV_LEFT) - graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT); - else if (player->MovDir == MV_RIGHT) - graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT); - else if (player->MovDir == MV_UP) - graphic = GFX_SPIELER1_UP; - else /* MV_DOWN || MV_NO_MOVING */ - graphic = GFX_SPIELER1_DOWN; + if (game.emulation == EMU_SUPAPLEX) + { + static int last_dir = MV_LEFT; + int action = (player->programmed_action ? player->programmed_action : + player->action); + boolean action_moving = + (player_is_moving || + ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) && + !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)))); + + graphic = IMG_SP_MURPHY; - graphic += player->index_nr * 3*HEROES_PER_LINE; - graphic += player->Frame; + if (player->Pushing) + { + if (player->MovDir == MV_LEFT) + graphic = IMG_SP_MURPHY_PUSHING_LEFT; + else if (player->MovDir == MV_RIGHT) + graphic = IMG_SP_MURPHY_PUSHING_RIGHT; + else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT) + graphic = IMG_SP_MURPHY_PUSHING_LEFT; + else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT) + graphic = IMG_SP_MURPHY_PUSHING_RIGHT; + } + else if (player->snapped) + { + if (player->MovDir == MV_LEFT) + graphic = IMG_SP_MURPHY_SNAPPING_LEFT; + else if (player->MovDir == MV_RIGHT) + graphic = IMG_SP_MURPHY_SNAPPING_RIGHT; + else if (player->MovDir == MV_UP) + graphic = IMG_SP_MURPHY_SNAPPING_UP; + else if (player->MovDir == MV_DOWN) + graphic = IMG_SP_MURPHY_SNAPPING_DOWN; + } + else if (action_moving) + { + if (player->MovDir == MV_LEFT) + graphic = IMG_SP_MURPHY_MOVING_LEFT; + else if (player->MovDir == MV_RIGHT) + graphic = IMG_SP_MURPHY_MOVING_RIGHT; + else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT) + graphic = IMG_SP_MURPHY_MOVING_LEFT; + else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT) + graphic = IMG_SP_MURPHY_MOVING_RIGHT; + else + graphic = IMG_SP_MURPHY_MOVING_LEFT; + + frame = getGraphicAnimationFrame(graphic, -1); + } + + if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT) + last_dir = player->MovDir; + } + else + { + if (player->MovDir == MV_LEFT) + graphic = (player->Pushing ? IMG_PLAYER1_PUSHING_LEFT : + player->is_moving ? IMG_PLAYER1_MOVING_LEFT : + IMG_PLAYER1_LEFT); + else if (player->MovDir == MV_RIGHT) + graphic = (player->Pushing ? IMG_PLAYER1_PUSHING_RIGHT : + player->is_moving ? IMG_PLAYER1_MOVING_RIGHT : + IMG_PLAYER1_RIGHT); + else if (player->MovDir == MV_UP) + graphic = (player->Pushing ? IMG_PLAYER1_PUSHING_UP : + player->is_moving ? IMG_PLAYER1_MOVING_UP : + IMG_PLAYER1_UP); + else /* MV_DOWN || MV_NO_MOVING */ + graphic = (player->Pushing ? IMG_PLAYER1_PUSHING_DOWN : + player->is_moving ? IMG_PLAYER1_MOVING_DOWN : + IMG_PLAYER1_DOWN); + + graphic = PLAYER_NR_GFX(graphic, player->index_nr); + +#if 0 + frame = player->Frame; +#else + frame = getGraphicAnimationFrame(graphic, player->Frame); +#endif + } if (player->GfxPos) { @@ -521,69 +726,131 @@ void DrawPlayer(struct PlayerInfo *player) if (!setup.soft_scrolling && ScreenMovPos) sxx = syy = 0; - DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING); +#if 0 + if (player->Frame) + printf("-> %d\n", player->Frame); +#endif + + DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING); + + if (SHIELD_ON(player)) + { + int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE : + IMG_SHIELD_NORMAL_ACTIVE); + int frame = getGraphicAnimationFrame(graphic, -1); + + DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING); + } +#if 0 if (player->Pushing && player->GfxPos) +#else + if (player->Pushing && player_is_moving) +#endif { int px = SCREENX(next_jx), py = SCREENY(next_jy); - if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER || - Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL) - DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT, + if ((sxx || syy) && + (element == EL_SOKOBAN_FIELD_EMPTY || + Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)) + DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0, NO_CUTTING); else { int element = Feld[next_jx][next_jy]; - int graphic = el2gfx(element); + int graphic = el2img(element); +#if 1 + int frame = 0; +#endif - if (element == EL_FELSBROCKEN && sxx) + if ((sxx || syy) && IS_PUSHABLE(element)) { - int phase = (player->GfxPos / (TILEX/4)); + graphic = el_dir_act2img(element, player->MovDir, ACTION_MOVING); +#if 1 + frame = getGraphicAnimationFrame(graphic, player->GfxPos); + + frame = getGraphicAnimationFrame(graphic, player->Frame); +#endif +#if 0 + printf("-> %d [%d]\n", player->Frame, player->GfxPos); +#endif + +#if 0 + /* !!! FIX !!! */ if (player->MovDir == MV_LEFT) - graphic += phase; - else - graphic += (phase+4)%4; + frame = 3 - frame; +#endif + +#if 0 + frame = (player->GfxPos / (TILEX / 4)); + + if (player->MovDir == MV_RIGHT) + frame = (frame + 4) % 4; +#endif } - DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING); + DrawGraphicShifted(px, py, sxx, syy, graphic, frame, + NO_CUTTING, NO_MASKING); } } - /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */ + /* draw things in front of player (active dynamite or dynabombs) */ - if (element == EL_DYNAMIT || element == EL_DYNABOMB) + if (IS_ACTIVE_BOMB(element)) { - graphic = el2gfx(element); + graphic = el2img(element); - if (element == EL_DYNAMIT) +#if 0 + if (element == EL_DYNAMITE_ACTIVE) { - if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6) - phase = 6; + if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6) + frame = 6; } else { - if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3) - phase = 7 - phase; + if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3) + frame = 7 - frame; } +#else + +#if 0 + frame = getGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]); +#else + frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]); +#endif + +#endif - if (game_emulation == EMU_SUPAPLEX) - DrawGraphic(sx, sy, GFX_SP_DISK_RED); + if (game.emulation == EMU_SUPAPLEX) + DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame); else - DrawGraphicThruMask(sx, sy, graphic + phase); + DrawGraphicThruMask(sx, sy, graphic, frame); } - if ((last_jx != jx || last_jy != jy) && - Feld[last_jx][last_jy] == EL_EXPLODING) + if (player_is_moving && last_element == EL_EXPLOSION) { - int phase = Frame[last_jx][last_jy]; - int delay = 2; + int stored = Store[last_jx][last_jy]; + int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION : + stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON : + IMG_SP_EXPLOSION); + int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2); + int phase = ExplodePhase[last_jx][last_jy] - 1; + int frame = getGraphicAnimationFrame(graphic, phase - delay); - if (phase > 2) - DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), - GFX_EXPLOSION + ((phase - 1) / delay - 1)); + if (phase >= delay) + DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame); } + /* draw elements that stay over the player */ + /* handle the field the player is leaving ... */ + if (player_is_moving && IS_OVER_PLAYER(last_element)) + DrawLevelField(last_jx, last_jy); + + /* ... and the field the player is entering */ + if (IS_OVER_PLAYER(element)) + DrawLevelField(jx, jy); + if (setup.direct_draw) { int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX; @@ -591,117 +858,79 @@ void DrawPlayer(struct PlayerInfo *player) int x_size = TILEX * (1 + ABS(jx - last_jx)); int y_size = TILEY * (1 + ABS(jy - last_jy)); - XCopyArea(display, drawto_field, window, gc, - dest_x, dest_y, x_size, y_size, dest_x, dest_y); + BlitBitmap(drawto_field, window, + dest_x, dest_y, x_size, y_size, dest_x, dest_y); SetDrawtoField(DRAW_DIRECT); } MarkTileDirty(sx,sy); } -static int getGraphicAnimationPhase(int frames, int delay, int mode) +void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y) { - int phase; + Bitmap *src_bitmap = graphic_info[graphic].bitmap; + int offset_x = graphic_info[graphic].offset_x; + int offset_y = graphic_info[graphic].offset_y; + int src_x = graphic_info[graphic].src_x + frame * offset_x; + int src_y = graphic_info[graphic].src_y + frame * offset_y; + + *bitmap = src_bitmap; + *x = src_x; + *y = src_y; +} - if (mode == ANIM_OSCILLATE) +void DrawGraphic(int x, int y, int graphic, int frame) +{ +#if DEBUG + if (!IN_SCR_FIELD(x, y)) { - int max_anim_frames = 2 * frames - 2; - phase = (FrameCounter % (delay * max_anim_frames)) / delay; - phase = (phase < frames ? phase : max_anim_frames - phase); + printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic); + printf("DrawGraphic(): This should never happen!\n"); + return; } - else - phase = (FrameCounter % (delay * frames)) / delay; - - if (mode == ANIM_REVERSE) - phase = -phase; +#endif - return(phase); + DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame); + MarkTileDirty(x, y); } -void DrawGraphicAnimationExt(int x, int y, int graphic, - int frames, int delay, int mode, int mask_mode) +#if 0 +void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic) { - int phase = getGraphicAnimationPhase(frames, delay, mode); + Bitmap *src_bitmap; + int src_x, src_y; - if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y))) - { - if (mask_mode == USE_MASKING) - DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase); - else - DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase); - } + getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y); + BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y); } +#endif -void DrawGraphicAnimation(int x, int y, int graphic, - int frames, int delay, int mode) +void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic, + int frame) { - DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING); -} +#if 1 + Bitmap *src_bitmap; + int src_x, src_y; -void DrawGraphicAnimationThruMask(int x, int y, int graphic, - int frames, int delay, int mode) -{ - DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING); -} + getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); +#else + Bitmap *src_bitmap = graphic_info[graphic].bitmap; + int src_x = graphic_info[graphic].src_x; + int src_y = graphic_info[graphic].src_y; + int offset_x = graphic_info[graphic].offset_x; + int offset_y = graphic_info[graphic].offset_y; -void DrawGraphic(int x, int y, int graphic) -{ -#if DEBUG - if (!IN_SCR_FIELD(x,y)) - { - printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic); - printf("DrawGraphic(): This should never happen!\n"); - return; - } + src_x += frame * offset_x; + src_y += frame * offset_y; #endif - DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic); - MarkTileDirty(x,y); -} - -void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic) -{ - if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN) - { - graphic -= GFX_START_ROCKSSCREEN; - XCopyArea(display, pix[PIX_BACK], d, gc, - SX + (graphic % GFX_PER_LINE) * TILEX, - SY + (graphic / GFX_PER_LINE) * TILEY, - TILEX, TILEY, x, y); - } - else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE) - { - graphic -= GFX_START_ROCKSMORE; - XCopyArea(display, pix[PIX_MORE], d, gc, - (graphic % MORE_PER_LINE) * TILEX, - (graphic / MORE_PER_LINE) * TILEY, - TILEX, TILEY, x, y); - } - else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES) - { - graphic -= GFX_START_ROCKSHEROES; - XCopyArea(display, pix[PIX_HEROES], d, gc, - (graphic % HEROES_PER_LINE) * TILEX, - (graphic / HEROES_PER_LINE) * TILEY, - TILEX, TILEY, x, y); - } - else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT) - { - graphic -= GFX_START_ROCKSFONT; - XCopyArea(display, pix[PIX_BIGFONT], d, gc, - (graphic % FONT_CHARS_PER_LINE) * TILEX, - (graphic / FONT_CHARS_PER_LINE) * TILEY + - FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY, - TILEX, TILEY, x, y); - } - else - XFillRectangle(display, d, gc, x, y, TILEX, TILEY); + BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y); } -void DrawGraphicThruMask(int x, int y, int graphic) +void DrawGraphicThruMask(int x, int y, int graphic, int frame) { #if DEBUG - if (!IN_SCR_FIELD(x,y)) + if (!IN_SCR_FIELD(x, y)) { printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic); printf("DrawGraphicThruMask(): This should never happen!\n"); @@ -709,148 +938,126 @@ void DrawGraphicThruMask(int x, int y, int graphic) } #endif - DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic); - MarkTileDirty(x,y); + DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic, + frame); + MarkTileDirty(x, y); } -void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic) +void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic, + int frame) { +#if 1 + Bitmap *src_bitmap; int src_x, src_y; - int tile = graphic; - Pixmap src_pixmap; GC drawing_gc; - if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN) - { - src_pixmap = pix[PIX_BACK]; - drawing_gc = clip_gc[PIX_BACK]; - graphic -= GFX_START_ROCKSSCREEN; - src_x = SX + (graphic % GFX_PER_LINE) * TILEX; - src_y = SY + (graphic / GFX_PER_LINE) * TILEY; - } - else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE) - { - src_pixmap = pix[PIX_MORE]; - drawing_gc = clip_gc[PIX_MORE]; - graphic -= GFX_START_ROCKSMORE; - src_x = (graphic % MORE_PER_LINE) * TILEX; - src_y = (graphic / MORE_PER_LINE) * TILEY; - } - else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES) - { - src_pixmap = pix[PIX_HEROES]; - drawing_gc = clip_gc[PIX_HEROES]; - graphic -= GFX_START_ROCKSHEROES; - src_x = (graphic % HEROES_PER_LINE) * TILEX; - src_y = (graphic / HEROES_PER_LINE) * TILEY; - } - else - { - DrawGraphicExt(d, gc, dest_x,dest_y, graphic); - return; - } + getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); + drawing_gc = src_bitmap->stored_clip_gc; +#else + GC drawing_gc = src_bitmap->stored_clip_gc; + Bitmap *src_bitmap = graphic_info[graphic].bitmap; + int src_x = graphic_info[graphic].src_x; + int src_y = graphic_info[graphic].src_y; + int offset_x = graphic_info[graphic].offset_x; + int offset_y = graphic_info[graphic].offset_y; + + src_x += frame * offset_x; + src_y += frame * offset_y; - if (tile_clipmask[tile] != None) - { - XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]); - XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y); - XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc, - src_x, src_y, TILEX, TILEY, dest_x, dest_y); - } - else - { -#if DEBUG - printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile); #endif - XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y); - XCopyArea(display, src_pixmap, drawto_field, drawing_gc, - src_x, src_y, TILEX, TILEY, dest_x, dest_y); - } + SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y); + BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y); } void DrawMiniGraphic(int x, int y, int graphic) { - DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic); - MarkTileDirty(x/2, y/2); + DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic); + MarkTileDirty(x / 2, y / 2); } -void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic) +void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y) { - if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN) - { - graphic -= GFX_START_ROCKSSCREEN; - XCopyArea(display, pix[PIX_BACK], d, gc, - MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX, - MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY, - MINI_TILEX, MINI_TILEY, x, y); - } - else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE) - { - graphic -= GFX_START_ROCKSMORE; - XCopyArea(display, pix[PIX_MORE], d, gc, - MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX, - MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY, - MINI_TILEX, MINI_TILEY, x, y); - } - else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT) + Bitmap *src_bitmap = graphic_info[graphic].bitmap; + int mini_startx = 0; + int mini_starty = src_bitmap->height * 2 / 3; + int src_x = mini_startx + graphic_info[graphic].src_x / 2; + int src_y = mini_starty + graphic_info[graphic].src_y / 2; + + if (src_x + MINI_TILEX > src_bitmap->width || + src_y + MINI_TILEY > src_bitmap->height) { - graphic -= GFX_START_ROCKSFONT; - XCopyArea(display, pix[PIX_SMALLFONT], d, gc, - (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE, - (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE + - FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT, - MINI_TILEX, MINI_TILEY, x, y); + /* graphic of desired size seems not to be contained in this image; + dirty workaround: get it from the middle of the normal sized image */ + + getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y); + src_x += (TILEX / 2 - MINI_TILEX / 2); + src_y += (TILEY / 2 - MINI_TILEY / 2); } - else - XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY); + + *bitmap = src_bitmap; + *x = src_x; + *y = src_y; +} + +void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic) +{ + Bitmap *src_bitmap; + int src_x, src_y; + + getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y); + BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y); } -void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, +void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame, int cut_mode, int mask_mode) { + Bitmap *src_bitmap; + GC drawing_gc; + int src_x; + int src_y; + int offset_x; + int offset_y; + int width = TILEX, height = TILEY; int cx = 0, cy = 0; - int src_x, src_y, dest_x, dest_y; - int tile = graphic; - Pixmap src_pixmap; - GC drawing_gc; + int dest_x, dest_y; if (graphic < 0) { - DrawGraphic(x, y, graphic); + DrawGraphic(x, y, graphic, frame); return; } - if (dx || dy) /* Verschiebung der Grafik? */ + if (dx || dy) /* shifted graphic */ { - if (x < BX1) /* Element kommt von links ins Bild */ + if (x < BX1) /* object enters playfield from the left */ { x = BX1; width = dx; cx = TILEX - dx; dx = 0; } - else if (x > BX2) /* Element kommt von rechts ins Bild */ + else if (x > BX2) /* object enters playfield from the right */ { x = BX2; width = -dx; dx = TILEX + dx; } - else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */ + else if (x==BX1 && dx < 0) /* object leaves playfield to the left */ { width += dx; cx = -dx; dx = 0; } - else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */ + else if (x==BX2 && dx > 0) /* object leaves playfield to the right */ width -= dx; - else if (dx) /* allg. Bewegung in x-Richtung */ + else if (dx) /* general horizontal movement */ MarkTileDirty(x + SIGN(dx), y); - if (y < BY1) /* Element kommt von oben ins Bild */ + if (y < BY1) /* object enters playfield from the top */ { - if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */ + if (cut_mode==CUT_BELOW) /* object completely above top border */ return; y = BY1; @@ -858,13 +1065,13 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, cy = TILEY - dy; dy = 0; } - else if (y > BY2) /* Element kommt von unten ins Bild */ + else if (y > BY2) /* object enters playfield from the bottom */ { y = BY2; height = -dy; dy = TILEY + dy; } - else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */ + else if (y==BY1 && dy < 0) /* object leaves playfield to the top */ { height += dy; cy = -dy; @@ -872,46 +1079,33 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, } else if (dy > 0 && cut_mode == CUT_ABOVE) { - if (y == BY2) /* Element unterhalb des Bildes */ + if (y == BY2) /* object completely above bottom border */ return; height = dy; cy = TILEY - dy; dy = TILEY; MarkTileDirty(x, y + 1); - } /* Element verläßt unten das Bild */ + } /* object leaves playfield to the bottom */ else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW)) height -= dy; - else if (dy) /* allg. Bewegung in y-Richtung */ + else if (dy) /* general vertical movement */ MarkTileDirty(x, y + SIGN(dy)); } - if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN) - { - src_pixmap = pix[PIX_BACK]; - drawing_gc = clip_gc[PIX_BACK]; - graphic -= GFX_START_ROCKSSCREEN; - src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx; - src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy; - } - else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE) - { - src_pixmap = pix[PIX_MORE]; - drawing_gc = clip_gc[PIX_MORE]; - graphic -= GFX_START_ROCKSMORE; - src_x = (graphic % MORE_PER_LINE) * TILEX + cx; - src_y = (graphic / MORE_PER_LINE) * TILEY + cy; - } - else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES) - { - src_pixmap = pix[PIX_HEROES]; - drawing_gc = clip_gc[PIX_HEROES]; - graphic -= GFX_START_ROCKSHEROES; - src_x = (graphic % HEROES_PER_LINE) * TILEX + cx; - src_y = (graphic / HEROES_PER_LINE) * TILEY + cy; - } - else /* big font graphics currently not allowed (and not needed) */ - return; + src_bitmap = graphic_info[graphic].bitmap; + src_x = graphic_info[graphic].src_x; + src_y = graphic_info[graphic].src_y; + offset_x = graphic_info[graphic].offset_x; + offset_y = graphic_info[graphic].offset_y; + + drawing_gc = src_bitmap->stored_clip_gc; + + src_x += frame * offset_x; + src_y += frame * offset_y; + + src_x += cx; + src_y += cy; dest_x = FX + x * TILEX + dx; dest_y = FY + y * TILEY + dy; @@ -927,147 +1121,131 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, if (mask_mode == USE_MASKING) { - if (tile_clipmask[tile] != None) - { - XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]); - XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y); - XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc, - src_x, src_y, TILEX, TILEY, dest_x, dest_y); - } - else - { -#if DEBUG - printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile); -#endif - - XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y); - XCopyArea(display, src_pixmap, drawto_field, drawing_gc, - src_x, src_y, width, height, dest_x, dest_y); - } + SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y); + BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height, + dest_x, dest_y); } else - XCopyArea(display, src_pixmap, drawto_field, gc, - src_x, src_y, width, height, dest_x, dest_y); + BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height, + dest_x, dest_y); MarkTileDirty(x,y); } void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic, - int cut_mode) + int frame, int cut_mode) +{ + DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING); +} + +inline static int getFramePosition(int x, int y) +{ + int frame_pos = -1; /* default: global synchronization */ +#if 0 + int element = Feld[x][y]; + + if (element == EL_QUICKSAND_FULL || + element == EL_MAGIC_WALL_FULL || + element == EL_BD_MAGIC_WALL_FULL) + frame_pos = -1; + else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element)) + frame_pos = ABS(MovPos[x][y]) / (TILEX / 8); +#else + + frame_pos = ABS(MovPos[x][y]) / (TILEX / 8); + + frame_pos = GfxFrame[x][y]; + +#endif + + return frame_pos; +} + +inline static int getGfxAction(int x, int y) { - DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING); + int gfx_action = ACTION_DEFAULT; + +#if 0 + if (GfxAction[x][y] != ACTION_DEFAULT) + gfx_action = GfxAction[x][y]; + else if (IS_MOVING(x, y)) + gfx_action = ACTION_MOVING; +#else + gfx_action = GfxAction[x][y]; +#endif + +#if DEBUG + if (gfx_action < 0) + printf("getGfxAction: THIS SHOULD NEVER HAPPEN: GfxAction[%d][%d] == %d\n", + x, y, gfx_action); +#endif + + return gfx_action; } void DrawScreenElementExt(int x, int y, int dx, int dy, int element, int cut_mode, int mask_mode) { int ux = LEVELX(x), uy = LEVELY(y); - int graphic = el2gfx(element); - int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8); - int phase4 = phase8 / 2; - int phase2 = phase8 / 4; - int dir = MovDir[ux][uy]; - - if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER) - { - graphic += 4 * !phase2; - - if (dir == MV_UP) - graphic += 1; - else if (dir == MV_LEFT) - graphic += 2; - else if (dir == MV_DOWN) - graphic += 3; - } - else if (element == EL_SP_SNIKSNAK) - { - if (dir == MV_LEFT) - graphic = GFX_SP_SNIKSNAK_LEFT; - else if (dir == MV_RIGHT) - graphic = GFX_SP_SNIKSNAK_RIGHT; - else if (dir == MV_UP) - graphic = GFX_SP_SNIKSNAK_UP; - else - graphic = GFX_SP_SNIKSNAK_DOWN; + int graphic; + int frame; - graphic += (phase8 < 4 ? phase8 : 7 - phase8); - } - else if (element == EL_SP_ELECTRON) + if (IN_LEV_FIELD(ux, uy)) { - graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL); - } - else if (element == EL_MAULWURF || element == EL_PINGUIN || - element == EL_SCHWEIN || element == EL_DRACHE) - { - if (dir == MV_LEFT) - graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT : - element == EL_PINGUIN ? GFX_PINGUIN_LEFT : - element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT); - else if (dir == MV_RIGHT) - graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT : - element == EL_PINGUIN ? GFX_PINGUIN_RIGHT : - element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT); - else if (dir == MV_UP) - graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP : - element == EL_PINGUIN ? GFX_PINGUIN_UP : - element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP); - else - graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN : - element == EL_PINGUIN ? GFX_PINGUIN_DOWN : - element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN); + int move_dir = MovDir[ux][uy]; + int move_pos = getFramePosition(ux, uy); + int gfx_action = getGfxAction(ux, uy); - graphic += phase4; - } - else if (element == EL_SONDE) - { - graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL); - } - else if (element == EL_SALZSAEURE) - { - graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL); - } - else if (element == EL_BUTTERFLY || element == EL_FIREFLY) - { - graphic += !phase2; - } - else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode) - { - if (element != EL_SP_INFOTRON) - graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1); + SetRandomAnimationValue(ux, uy); + + graphic = el_dir_act2img(element, move_dir, gfx_action); + frame = getGraphicAnimationFrame(graphic, move_pos); } - else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER || - element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL) + else { - graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE); + graphic = el2img(element); + frame = getGraphicAnimationFrame(graphic, 0); } - else if (IS_AMOEBOID(element)) + + if (element == EL_WALL_GROWING) { - graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT); - graphic += (x + 2 * y + 4) % 4; + boolean left_stopped = FALSE, right_stopped = FALSE; + + if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy])) + left_stopped = TRUE; + if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy])) + right_stopped = TRUE; + + if (left_stopped && right_stopped) + graphic = IMG_WALL; + else if (left_stopped) + { + graphic = IMG_WALL_GROWING_ACTIVE_RIGHT; + frame = graphic_info[graphic].anim_frames - 1; + } + else if (right_stopped) + { + graphic = IMG_WALL_GROWING_ACTIVE_LEFT; + frame = graphic_info[graphic].anim_frames - 1; + } } - else if (element == EL_MAUER_LEBT) + else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING) { - boolean links_massiv = FALSE, rechts_massiv = FALSE; - - if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy])) - links_massiv = TRUE; - if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy])) - rechts_massiv = TRUE; + graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 : + element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 : + element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 : + element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 : + IMG_AMOEBA_DEAD_PART1); - if (links_massiv && rechts_massiv) - graphic = GFX_MAUERWERK; - else if (links_massiv) - graphic = GFX_MAUER_R; - else if (rechts_massiv) - graphic = GFX_MAUER_L; + graphic += (x + 2 * y + 4) % 4; } if (dx || dy) - DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode); + DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode); else if (mask_mode == USE_MASKING) - DrawGraphicThruMask(x, y, graphic); + DrawGraphicThruMask(x, y, graphic, frame); else - DrawGraphic(x, y, graphic); + DrawGraphic(x, y, graphic, frame); } void DrawLevelElementExt(int x, int y, int dx, int dy, int element, @@ -1090,10 +1268,17 @@ void DrawLevelElementShifted(int x, int y, int dx, int dy, int element, DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING); } +#if 0 +void DrawOldScreenElementThruMask(int x, int y, int element) +{ + DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING); +} + void DrawScreenElementThruMask(int x, int y, int element) { DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING); } +#endif void DrawLevelElementThruMask(int x, int y, int element) { @@ -1105,8 +1290,10 @@ void DrawLevelFieldThruMask(int x, int y) DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING); } -void ErdreichAnbroeckeln(int x, int y) +void DrawCrumbledSand(int x, int y) { + Bitmap *src_bitmap; + int src_x, src_y; int i, width, height, cx,cy; int ux = LEVELX(x), uy = LEVELY(y); int element, graphic; @@ -1124,12 +1311,19 @@ void ErdreichAnbroeckeln(int x, int y) element = Feld[ux][uy]; - if (element == EL_ERDREICH) + if (element == EL_SAND || + element == EL_LANDMINE || + element == EL_TRAP || + element == EL_TRAP_ACTIVE) { if (!IN_SCR_FIELD(x, y)) return; - graphic = GFX_ERDENRAND; + graphic = IMG_SAND_CRUMBLED; + + src_bitmap = graphic_info[graphic].bitmap; + src_x = graphic_info[graphic].src_x; + src_y = graphic_info[graphic].src_y; for(i=0; i<4; i++) { @@ -1138,11 +1332,14 @@ void ErdreichAnbroeckeln(int x, int y) uxx = ux + xy[i][0]; uyy = uy + xy[i][1]; if (!IN_LEV_FIELD(uxx, uyy)) - element = EL_BETON; + element = EL_STEELWALL; else element = Feld[uxx][uyy]; - if (element == EL_ERDREICH) + if (element == EL_SAND || + element == EL_LANDMINE || + element == EL_TRAP || + element == EL_TRAP_ACTIVE) continue; if (i == 1 || i == 2) @@ -1160,17 +1357,19 @@ void ErdreichAnbroeckeln(int x, int y) cy = (i == 3 ? TILEY - snip : 0); } - XCopyArea(display, pix[PIX_BACK], drawto_field, gc, - SX + (graphic % GFX_PER_LINE) * TILEX + cx, - SY + (graphic / GFX_PER_LINE) * TILEY + cy, - width, height, FX + x * TILEX + cx, FY + y * TILEY + cy); + BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, + width, height, FX + x * TILEX + cx, FY + y * TILEY + cy); } MarkTileDirty(x, y); } else { - graphic = GFX_ERDENRAND; + graphic = IMG_SAND_CRUMBLED; + + src_bitmap = graphic_info[graphic].bitmap; + src_x = graphic_info[graphic].src_x; + src_y = graphic_info[graphic].src_y; for(i=0; i<4; i++) { @@ -1181,7 +1380,11 @@ void ErdreichAnbroeckeln(int x, int y) uxx = ux + xy[i][0]; uyy = uy + xy[i][1]; - if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH || + if (!IN_LEV_FIELD(uxx, uyy) || + (Feld[uxx][uyy] != EL_SAND && + Feld[uxx][uyy] != EL_LANDMINE && + Feld[uxx][uyy] != EL_TRAP && + Feld[uxx][uyy] != EL_TRAP_ACTIVE) || !IN_SCR_FIELD(xx, yy)) continue; @@ -1200,10 +1403,8 @@ void ErdreichAnbroeckeln(int x, int y) cy = (i==0 ? TILEY-snip : 0); } - XCopyArea(display, pix[PIX_BACK], drawto_field, gc, - SX + (graphic % GFX_PER_LINE) * TILEX + cx, - SY + (graphic / GFX_PER_LINE) * TILEY + cy, - width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy); + BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, + width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy); MarkTileDirty(xx, yy); } @@ -1213,7 +1414,7 @@ void ErdreichAnbroeckeln(int x, int y) void DrawScreenElement(int x, int y, int element) { DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING); - ErdreichAnbroeckeln(x, y); + DrawCrumbledSand(x, y); } void DrawLevelElement(int x, int y, int element) @@ -1225,12 +1426,12 @@ void DrawLevelElement(int x, int y, int element) void DrawScreenField(int x, int y) { int ux = LEVELX(x), uy = LEVELY(y); - int element; + int element, content; if (!IN_LEV_FIELD(ux, uy)) { if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy) - element = EL_LEERRAUM; + element = EL_EMPTY; else element = BorderElement; @@ -1239,34 +1440,37 @@ void DrawScreenField(int x, int y) } element = Feld[ux][uy]; + content = Store[ux][uy]; if (IS_MOVING(ux, uy)) { int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT); boolean cut_mode = NO_CUTTING; - if (Store[ux][uy] == EL_MORAST_LEER || - Store[ux][uy] == EL_SIEB_LEER || - Store[ux][uy] == EL_SIEB2_LEER || - Store[ux][uy] == EL_AMOEBE_NASS) + if (element == EL_QUICKSAND_EMPTYING || + element == EL_MAGIC_WALL_EMPTYING || + element == EL_BD_MAGIC_WALL_EMPTYING || + element == EL_AMOEBA_DRIPPING) cut_mode = CUT_ABOVE; - else if (Store[ux][uy] == EL_MORAST_VOLL || - Store[ux][uy] == EL_SIEB_VOLL || - Store[ux][uy] == EL_SIEB2_VOLL) + else if (element == EL_QUICKSAND_FILLING || + element == EL_MAGIC_WALL_FILLING || + element == EL_BD_MAGIC_WALL_FILLING) cut_mode = CUT_BELOW; if (cut_mode == CUT_ABOVE) - DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING); + DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING); else - DrawScreenElement(x, y, EL_LEERRAUM); + DrawScreenElement(x, y, EL_EMPTY); if (horiz_move) DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING); - else + else if (cut_mode == NO_CUTTING) DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode); + else + DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode); - if (Store[ux][uy] == EL_SALZSAEURE) - DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE); + if (content == EL_ACID) + DrawLevelElementThruMask(ux, uy + 1, EL_ACID); } else if (IS_BLOCKED(ux, uy)) { @@ -1274,6 +1478,7 @@ void DrawScreenField(int x, int y) int sx, sy; int horiz_move; boolean cut_mode = NO_CUTTING; + int element_old, content_old; Blocked2Moving(ux, uy, &oldx, &oldy); sx = SCREENX(oldx); @@ -1281,24 +1486,31 @@ void DrawScreenField(int x, int y) horiz_move = (MovDir[oldx][oldy] == MV_LEFT || MovDir[oldx][oldy] == MV_RIGHT); - if (Store[oldx][oldy] == EL_MORAST_LEER || - Store[oldx][oldy] == EL_SIEB_LEER || - Store[oldx][oldy] == EL_SIEB2_LEER || - Store[oldx][oldy] == EL_AMOEBE_NASS) + element_old = Feld[oldx][oldy]; + content_old = Store[oldx][oldy]; + + if (element_old == EL_QUICKSAND_EMPTYING || + element_old == EL_MAGIC_WALL_EMPTYING || + element_old == EL_BD_MAGIC_WALL_EMPTYING || + element_old == EL_AMOEBA_DRIPPING) cut_mode = CUT_ABOVE; - DrawScreenElement(x, y, EL_LEERRAUM); - element = Feld[oldx][oldy]; + DrawScreenElement(x, y, EL_EMPTY); if (horiz_move) - DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING); + DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old, + NO_CUTTING); + else if (cut_mode == NO_CUTTING) + DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old, + cut_mode); else - DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode); + DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old, + cut_mode); } else if (IS_DRAWABLE(element)) DrawScreenElement(x, y, element); else - DrawScreenElement(x, y, EL_LEERRAUM); + DrawScreenElement(x, y, EL_EMPTY); } void DrawLevelField(int x, int y) @@ -1327,13 +1539,7 @@ void DrawMiniElement(int x, int y, int element) { int graphic; - if (!element) - { - DrawMiniGraphic(x, y, -1); - return; - } - - graphic = el2gfx(element); + graphic = el2img(element); DrawMiniGraphic(x, y, graphic); } @@ -1342,102 +1548,252 @@ void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y) int x = sx + scroll_x, y = sy + scroll_y; if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy) - DrawMiniElement(sx, sy, EL_LEERRAUM); - else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy) - DrawMiniElement(sx, sy, EL_BETON); - else + DrawMiniElement(sx, sy, EL_EMPTY); + else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy) DrawMiniElement(sx, sy, Feld[x][y]); + else + { + int steel_type, steel_position; + int border[6][2] = + { + { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT }, + { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT }, + { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT }, + { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT }, + { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL }, + { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL } + }; + + steel_type = (BorderElement == EL_STEELWALL ? 0 : 1); + steel_position = (x == -1 && y == -1 ? 0 : + x == lev_fieldx && y == -1 ? 1 : + x == -1 && y == lev_fieldy ? 2 : + x == lev_fieldx && y == lev_fieldy ? 3 : + x == -1 || x == lev_fieldx ? 4 : + y == -1 || y == lev_fieldy ? 5 : -1); + + if (steel_position != -1) + DrawMiniGraphic(sx, sy, border[steel_position][steel_type]); + } } -void DrawMicroElement(int xpos, int ypos, int element) +void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y) { - int graphic; - - if (element == EL_LEERRAUM) - return; - - graphic = el2gfx(element); + Bitmap *src_bitmap = graphic_info[graphic].bitmap; + int mini_startx = src_bitmap->width * 3 / 4; + int mini_starty = src_bitmap->height * 2 / 3; + int src_x = mini_startx + graphic_info[graphic].src_x / 8; + int src_y = mini_starty + graphic_info[graphic].src_y / 8; - if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE) + if (src_x + MICRO_TILEX > src_bitmap->width || + src_y + MICRO_TILEY > src_bitmap->height) { - graphic -= GFX_START_ROCKSMORE; - XCopyArea(display, pix[PIX_MORE], drawto, gc, - MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX, - MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY, - MICRO_TILEX, MICRO_TILEY, xpos, ypos); + /* graphic of desired size seems not to be contained in this image; + dirty workaround: get it from the middle of the normal sized image */ + + getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y); + src_x += (TILEX / 2 - MICRO_TILEX / 2); + src_y += (TILEY / 2 - MICRO_TILEY / 2); } - else - XCopyArea(display, pix[PIX_BACK], drawto, gc, - MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX, - MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY, - MICRO_TILEX, MICRO_TILEY, xpos, ypos); + + *bitmap = src_bitmap; + *x = src_x; + *y = src_y; +} + +void DrawMicroElement(int xpos, int ypos, int element) +{ + Bitmap *src_bitmap; + int src_x, src_y; + int graphic = el2img(element); + + getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y); + BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY, + xpos, ypos); } void DrawLevel() { int x,y; + SetDrawBackgroundMask(REDRAW_NONE); ClearWindow(); for(x=BX1; x<=BX2; x++) for(y=BY1; y<=BY2; y++) DrawScreenField(x, y); - if (setup.soft_scrolling) - XCopyArea(display, fieldbuffer, backbuffer, gc, - FX, FY, SXSIZE, SYSIZE, SX, SY); - - redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER); + redraw_mask |= REDRAW_FIELD; } -void DrawMiniLevel(int scroll_x, int scroll_y) +void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y) { int x,y; - for(x=0; x= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy) + { + int lx = from_x + x, ly = from_y + y; + + if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy) DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY, - Ur[x][y]); - else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1) + Ur[lx][ly]); + else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1 + && BorderElement != EL_EMPTY) DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY, BorderElement); + } + } + + redraw_mask |= REDRAW_MICROLEVEL; +} - XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE); +#define MICROLABEL_EMPTY 0 +#define MICROLABEL_LEVEL_NAME 1 +#define MICROLABEL_CREATED_BY 2 +#define MICROLABEL_LEVEL_AUTHOR 3 +#define MICROLABEL_IMPORTED_FROM 4 +#define MICROLABEL_LEVEL_IMPORT_INFO 5 - if (level.name) +#define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE) + +static void DrawMicroLevelLabelExt(int mode) +{ + char label_text[MAX_MICROLABEL_SIZE + 1]; + + DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE); + + strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name : + mode == MICROLABEL_CREATED_BY ? "created by" : + mode == MICROLABEL_LEVEL_AUTHOR ? level.author : + mode == MICROLABEL_IMPORTED_FROM ? "imported from" : + mode == MICROLABEL_LEVEL_IMPORT_INFO ? + leveldir_current->imported_from : ""), + MAX_MICROLABEL_SIZE); + label_text[MAX_MICROLABEL_SIZE] = '\0'; + + if (strlen(label_text) > 0) { - int len = strlen(level.name); - int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2; + int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2; int lypos = MICROLABEL_YPOS; - DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2); + DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2); + } + + redraw_mask |= REDRAW_MICROLEVEL; +} + +void DrawMicroLevel(int xpos, int ypos, boolean restart) +{ + static unsigned long scroll_delay = 0; + static unsigned long label_delay = 0; + static int from_x, from_y, scroll_direction; + static int label_state, label_counter; + + if (restart) + { + from_x = from_y = 0; + scroll_direction = MV_RIGHT; + label_state = 1; + label_counter = 0; + + DrawMicroLevelExt(xpos, ypos, from_x, from_y); + DrawMicroLevelLabelExt(label_state); + + /* initialize delay counters */ + DelayReached(&scroll_delay, 0); + DelayReached(&label_delay, 0); + + return; + } + + /* scroll micro level, if needed */ + if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) && + DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY)) + { + switch (scroll_direction) + { + case MV_LEFT: + if (from_x > 0) + from_x--; + else + scroll_direction = MV_UP; + break; + + case MV_RIGHT: + if (from_x < lev_fieldx - STD_LEV_FIELDX) + from_x++; + else + scroll_direction = MV_DOWN; + break; + + case MV_UP: + if (from_y > 0) + from_y--; + else + scroll_direction = MV_RIGHT; + break; + + case MV_DOWN: + if (from_y < lev_fieldy - STD_LEV_FIELDY) + from_y++; + else + scroll_direction = MV_LEFT; + break; + + default: + break; + } + + DrawMicroLevelExt(xpos, ypos, from_x, from_y); } - redraw_mask |= REDRAW_MICROLEV; + /* redraw micro level label, if needed */ + if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 && + strcmp(level.author, ANONYMOUS_NAME) != 0 && + strcmp(level.author, leveldir_current->name) != 0 && + DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY)) + { + int max_label_counter = 23; + + if (leveldir_current->imported_from != NULL) + max_label_counter += 14; + + label_counter = (label_counter + 1) % max_label_counter; + label_state = (label_counter >= 0 && label_counter <= 7 ? + MICROLABEL_LEVEL_NAME : + label_counter >= 9 && label_counter <= 12 ? + MICROLABEL_CREATED_BY : + label_counter >= 14 && label_counter <= 21 ? + MICROLABEL_LEVEL_AUTHOR : + label_counter >= 23 && label_counter <= 26 ? + MICROLABEL_IMPORTED_FROM : + label_counter >= 28 && label_counter <= 35 ? + MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY); + DrawMicroLevelLabelExt(label_state); + } } int REQ_in_range(int x, int y) @@ -1452,12 +1808,15 @@ int REQ_in_range(int x, int y) return 0; } +#define MAX_REQUEST_LINES 13 +#define MAX_REQUEST_LINE_LEN 7 + boolean Request(char *text, unsigned int req_state) { int mx, my, ty, result = -1; unsigned int old_door_state; -#ifndef MSDOS +#if defined(PLATFORM_UNIX) /* pause network game while waiting for request to answer */ if (options.network && game_status == PLAYING && @@ -1467,153 +1826,176 @@ boolean Request(char *text, unsigned int req_state) old_door_state = GetDoorState(); + UnmapAllGadgets(); + CloseDoor(DOOR_CLOSE_1); - /* Alten Türinhalt sichern */ - XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc, - DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, - DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1); + /* save old door content */ + BlitBitmap(bitmap_db_door, bitmap_db_door, + DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, + DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1); + + SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1); - /* Fragetext schreiben */ - XFillRectangle(display, pix[PIX_DB_DOOR], gc, - DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE); + /* clear door drawing field */ + DrawBackground(DX, DY, DXSIZE, DYSIZE); - for(ty=0; ty<13; ty++) + /* write text for request */ + for(ty=0; ty < MAX_REQUEST_LINES; ty++) { + char text_line[MAX_REQUEST_LINE_LEN + 1]; int tx, tl, tc; - char txt[256]; if (!*text) break; - for(tl=0,tx=0; tx<7; tl++,tx++) + for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++) { tc = *(text + tx); - if (!tc || tc == 32) + if (!tc || tc == ' ') break; } + if (!tl) { text++; ty--; continue; } - sprintf(txt, text); - txt[tl] = 0; - DrawTextExt(pix[PIX_DB_DOOR], gc, - DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16, - txt, FS_SMALL, FC_YELLOW); - text += tl + (tc == 32 ? 1 : 0); + + strncpy(text_line, text, tl); + text_line[tl] = 0; + + DrawText(DX + 50 - (tl * 14)/2, DY + 8 + ty * 16, + text_line, FS_SMALL, FC_YELLOW); + + text += tl + (tc == ' ' ? 1 : 0); } if (req_state & REQ_ASK) { - DrawYesNoButton(BUTTON_OK, DB_INIT); - DrawYesNoButton(BUTTON_NO, DB_INIT); + MapGadget(tool_gadget[TOOL_CTRL_ID_YES]); + MapGadget(tool_gadget[TOOL_CTRL_ID_NO]); } else if (req_state & REQ_CONFIRM) { - DrawConfirmButton(BUTTON_CONFIRM, DB_INIT); + MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]); } else if (req_state & REQ_PLAYER) { - DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT); - DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT); - DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT); - DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT); + MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]); + MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]); + MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]); + MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]); } + /* copy request gadgets to door backbuffer */ + BlitBitmap(drawto, bitmap_db_door, + DX, DY, DXSIZE, DYSIZE, + DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1); + OpenDoor(DOOR_OPEN_1); + +#if 0 ClearEventQueue(); +#endif if (!(req_state & REQUEST_WAIT_FOR)) - return(FALSE); + { + SetDrawBackgroundMask(REDRAW_FIELD); + + return FALSE; + } if (game_status != MAINMENU) InitAnimation(); button_status = MB_RELEASED; + request_gadget_id = -1; + + SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1); + while(result < 0) { - if (XPending(display)) + if (PendingEvent()) { - XEvent event; + Event event; - XNextEvent(display, &event); + NextEvent(&event); switch(event.type) { - case ButtonPress: - case ButtonRelease: - case MotionNotify: + case EVENT_BUTTONPRESS: + case EVENT_BUTTONRELEASE: + case EVENT_MOTIONNOTIFY: { - int choice; - - if (event.type == MotionNotify) + if (event.type == EVENT_MOTIONNOTIFY) { + if (!PointerInWindow(window)) + continue; /* window and pointer are on different screens */ + + if (!button_status) + continue; + motion_status = TRUE; - mx = ((XMotionEvent *) &event)->x; - my = ((XMotionEvent *) &event)->y; + mx = ((MotionEvent *) &event)->x; + my = ((MotionEvent *) &event)->y; } else { motion_status = FALSE; - mx = ((XButtonEvent *) &event)->x; - my = ((XButtonEvent *) &event)->y; - if (event.type==ButtonPress) - button_status = ((XButtonEvent *) &event)->button; + mx = ((ButtonEvent *) &event)->x; + my = ((ButtonEvent *) &event)->y; + if (event.type == EVENT_BUTTONPRESS) + button_status = ((ButtonEvent *) &event)->button; else button_status = MB_RELEASED; } - if (req_state & REQ_ASK) - choice = CheckYesNoButtons(mx,my,button_status); - else if (req_state & REQ_CONFIRM) - choice = CheckConfirmButton(mx,my,button_status); - else - choice = CheckPlayerButtons(mx,my,button_status); + /* this sets 'request_gadget_id' */ + HandleGadgets(mx, my, button_status); - switch(choice) + switch(request_gadget_id) { - case BUTTON_OK: + case TOOL_CTRL_ID_YES: result = TRUE; break; - case BUTTON_NO: + case TOOL_CTRL_ID_NO: result = FALSE; break; - case BUTTON_CONFIRM: + case TOOL_CTRL_ID_CONFIRM: result = TRUE | FALSE; break; - case BUTTON_PLAYER_1: + case TOOL_CTRL_ID_PLAYER_1: result = 1; break; - case BUTTON_PLAYER_2: + case TOOL_CTRL_ID_PLAYER_2: result = 2; break; - case BUTTON_PLAYER_3: + case TOOL_CTRL_ID_PLAYER_3: result = 3; break; - case BUTTON_PLAYER_4: + case TOOL_CTRL_ID_PLAYER_4: result = 4; break; default: break; } + break; } - case KeyPress: - switch(XLookupKeysym((XKeyEvent *)&event, - ((XKeyEvent *)&event)->state)) + case EVENT_KEYPRESS: + switch(GetEventKey((KeyEvent *)&event, TRUE)) { - case XK_Return: + case KSYM_Return: result = 1; break; - case XK_Escape: + case KSYM_Escape: result = 0; break; @@ -1624,8 +2006,8 @@ boolean Request(char *text, unsigned int req_state) result = 0; break; - case KeyRelease: - key_joystick_mapping = 0; + case EVENT_KEYRELEASE: + ClearPlayerAction(); break; default: @@ -1652,20 +2034,26 @@ boolean Request(char *text, unsigned int req_state) if (game_status != MAINMENU) StopAnimation(); + UnmapToolButtons(); + if (!(req_state & REQ_STAY_OPEN)) { CloseDoor(DOOR_CLOSE_1); if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1)) { - XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc, - DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE, - DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1); + BlitBitmap(bitmap_db_door, bitmap_db_door, + DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE, + DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1); OpenDoor(DOOR_OPEN_1); } } -#ifndef MSDOS + RemapAllGadgets(); + + SetDrawBackgroundMask(REDRAW_FIELD); + +#if defined(PLATFORM_UNIX) /* continue network game after request */ if (options.network && game_status == PLAYING && @@ -1673,7 +2061,7 @@ boolean Request(char *text, unsigned int req_state) SendToServer_ContinuePlaying(); #endif - return(result); + return result; } unsigned int OpenDoor(unsigned int door_state) @@ -1682,9 +2070,9 @@ unsigned int OpenDoor(unsigned int door_state) if (door_state & DOOR_COPY_BACK) { - XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc, - DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE, - DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1); + BlitBitmap(bitmap_db_door, bitmap_db_door, + DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE, + DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1); door_state &= ~DOOR_COPY_BACK; } @@ -1697,10 +2085,10 @@ unsigned int CloseDoor(unsigned int door_state) { unsigned int new_door_state; - XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc, - DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1); - XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc, - VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2); + BlitBitmap(backbuffer, bitmap_db_door, + DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1); + BlitBitmap(backbuffer, bitmap_db_door, + VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2); new_door_state = MoveDoor(door_state); @@ -1709,7 +2097,12 @@ unsigned int CloseDoor(unsigned int door_state) unsigned int GetDoorState() { - return(MoveDoor(DOOR_GET_STATE)); + return MoveDoor(DOOR_GET_STATE); +} + +unsigned int SetDoorState(unsigned int door_state) +{ + return MoveDoor(door_state | DOOR_SET_STATE); } unsigned int MoveDoor(unsigned int door_state) @@ -1723,6 +2116,16 @@ unsigned int MoveDoor(unsigned int door_state) if (door_state == DOOR_GET_STATE) return(door1 | door2); + if (door_state & DOOR_SET_STATE) + { + if (door_state & DOOR_ACTION_1) + door1 = door_state & DOOR_ACTION_1; + if (door_state & DOOR_ACTION_2) + door2 = door_state & DOOR_ACTION_2; + + return(door1 | door2); + } + if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1) door_state &= ~DOOR_OPEN_1; else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1) @@ -1736,59 +2139,77 @@ unsigned int MoveDoor(unsigned int door_state) { stepsize = 20; door_delay_value = 0; - StopSound(SND_OEFFNEN); + + StopSound(SND_MENU_DOOR_OPENING); + StopSound(SND_MENU_DOOR_CLOSING); + } + + if (global.autoplay_leveldir) + { + door_state |= DOOR_NO_DELAY; + door_state &= ~DOOR_CLOSE_ALL; } if (door_state & DOOR_ACTION) { if (!(door_state & DOOR_NO_DELAY)) - PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT); + { + /* opening door sound has priority over simultaneously closing door */ + if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2)) + PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT); + else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2)) + PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT); + } start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0); for(x=start; x<=DXSIZE; x+=stepsize) { - WaitUntilDelayReached(&door_delay, door_delay_value); + Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap; + GC gc = bitmap->stored_clip_gc; + + if (!(door_state & DOOR_NO_DELAY)) + WaitUntilDelayReached(&door_delay, door_delay_value); if (door_state & DOOR_ACTION_1) { int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x); int j = (DXSIZE - i) / 3; - XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc, - DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2, - DXSIZE,DYSIZE - i/2, DX, DY); - - XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2); - - XSetClipOrigin(display, clip_gc[PIX_DOOR], - DX - i, (DY + j) - DOOR_GFX_PAGEY1); - XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR], - DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j); - XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR], - DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i, - DY + 140 + j); - XSetClipOrigin(display, clip_gc[PIX_DOOR], - DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j)); - XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR], - DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY); - XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR], - DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j); - - XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR], - DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63, - DX, DY + 77 - j); - XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR], - DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77, - DX, DY + 203 - j); - XSetClipOrigin(display, clip_gc[PIX_DOOR], - DX - i, (DY + j) - DOOR_GFX_PAGEY1); - XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR], - DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63, - DX + DXSIZE - i, DY + 77 + j); - XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR], - DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j, - DX + DXSIZE - i, DY + 203 + j); + BlitBitmap(bitmap_db_door, drawto, + DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2, + DXSIZE,DYSIZE - i/2, DX, DY); + + ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2); + + SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1); + BlitBitmapMasked(bitmap, drawto, + DXSIZE, DOOR_GFX_PAGEY1, i, 77, + DX + DXSIZE - i, DY + j); + BlitBitmapMasked(bitmap, drawto, + DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, + DX + DXSIZE - i, DY + 140 + j); + SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j)); + BlitBitmapMasked(bitmap, drawto, + DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, + DX, DY); + BlitBitmapMasked(bitmap, drawto, + DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, + DX, DY + 140 - j); + + BlitBitmapMasked(bitmap, drawto, + DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63, + DX, DY + 77 - j); + BlitBitmapMasked(bitmap, drawto, + DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77, + DX, DY + 203 - j); + SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1); + BlitBitmapMasked(bitmap, drawto, + DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63, + DX + DXSIZE - i, DY + 77 + j); + BlitBitmapMasked(bitmap, drawto, + DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j, + DX + DXSIZE - i, DY + 203 + j); redraw_mask |= REDRAW_DOOR_1; } @@ -1798,29 +2219,30 @@ unsigned int MoveDoor(unsigned int door_state) int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x); int j = (VXSIZE - i) / 3; - XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc, - DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2, - VXSIZE, VYSIZE - i/2, VX, VY); - - XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2); - - XSetClipOrigin(display, clip_gc[PIX_DOOR], - VX - i, (VY + j) - DOOR_GFX_PAGEY2); - XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR], - VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j); - XSetClipOrigin(display, clip_gc[PIX_DOOR], - VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j)); - XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR], - VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY); - - XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR], - VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2, - VX, VY + VYSIZE / 2 - j); - XSetClipOrigin(display, clip_gc[PIX_DOOR], - VX - i, (VY + j) - DOOR_GFX_PAGEY2); - XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR], - VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j, - VX + VXSIZE - i, VY + VYSIZE / 2 + j); + BlitBitmap(bitmap_db_door, drawto, + DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2, + VXSIZE, VYSIZE - i/2, VX, VY); + + ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2); + + SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2); + BlitBitmapMasked(bitmap, drawto, + VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, + VX + VXSIZE-i, VY+j); + SetClipOrigin(bitmap, gc, + VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j)); + BlitBitmapMasked(bitmap, drawto, + VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, + VX, VY); + + BlitBitmapMasked(bitmap, drawto, + VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, + i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j); + SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2); + BlitBitmapMasked(bitmap, drawto, + VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, + i, VYSIZE / 2 - j, + VX + VXSIZE - i, VY + VYSIZE / 2 + j); redraw_mask |= REDRAW_DOOR_2; } @@ -1833,177 +2255,293 @@ unsigned int MoveDoor(unsigned int door_state) } if (setup.quick_doors) - StopSound(SND_OEFFNEN); + { + StopSound(SND_MENU_DOOR_OPENING); + StopSound(SND_MENU_DOOR_CLOSING); + } if (door_state & DOOR_ACTION_1) door1 = door_state & DOOR_ACTION_1; if (door_state & DOOR_ACTION_2) door2 = door_state & DOOR_ACTION_2; - return(door1 | door2); + return (door1 | door2); } -int ReadPixel(Drawable d, int x, int y) +void DrawSpecialEditorDoor() +{ + /* draw bigger toolbox window */ + BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, + DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8, + EX - 4, EY - 12); + BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, + EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4, + EX - 4, EY - 4); + + redraw_mask |= REDRAW_ALL; +} + +void UndrawSpecialEditorDoor() +{ + /* draw normal tape recorder window */ + BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, + EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12, + EX - 4, EY - 12); + + redraw_mask |= REDRAW_ALL; +} + +#ifndef TARGET_SDL +int ReadPixel(DrawBuffer *bitmap, int x, int y) { XImage *pixel_image; unsigned long pixel_value; - pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap); + pixel_image = XGetImage(display, bitmap->drawable, + x, y, 1, 1, AllPlanes, ZPixmap); pixel_value = XGetPixel(pixel_image, 0, 0); XDestroyImage(pixel_image); return pixel_value; } +#endif -int el2gfx(int element) +/* ---------- new tool button stuff ---------------------------------------- */ + +/* graphic position values for tool buttons */ +#define TOOL_BUTTON_YES_XPOS 2 +#define TOOL_BUTTON_YES_YPOS 250 +#define TOOL_BUTTON_YES_GFX_YPOS 0 +#define TOOL_BUTTON_YES_XSIZE 46 +#define TOOL_BUTTON_YES_YSIZE 28 +#define TOOL_BUTTON_NO_XPOS 52 +#define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS +#define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS +#define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE +#define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE +#define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS +#define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS +#define TOOL_BUTTON_CONFIRM_GFX_YPOS 30 +#define TOOL_BUTTON_CONFIRM_XSIZE 96 +#define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE +#define TOOL_BUTTON_PLAYER_XSIZE 30 +#define TOOL_BUTTON_PLAYER_YSIZE 30 +#define TOOL_BUTTON_PLAYER_GFX_XPOS 5 +#define TOOL_BUTTON_PLAYER_GFX_YPOS 185 +#define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2) +#define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2) +#define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \ + + 0 * TOOL_BUTTON_PLAYER_XSIZE) +#define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \ + + 1 * TOOL_BUTTON_PLAYER_XSIZE) +#define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \ + + 0 * TOOL_BUTTON_PLAYER_XSIZE) +#define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \ + + 1 * TOOL_BUTTON_PLAYER_XSIZE) +#define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \ + + 0 * TOOL_BUTTON_PLAYER_YSIZE) +#define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \ + + 0 * TOOL_BUTTON_PLAYER_YSIZE) +#define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \ + + 1 * TOOL_BUTTON_PLAYER_YSIZE) +#define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \ + + 1 * TOOL_BUTTON_PLAYER_YSIZE) + +static struct { - switch(element) + int xpos, ypos; + int x, y; + int width, height; + int gadget_id; + char *infotext; +} toolbutton_info[NUM_TOOL_BUTTONS] = +{ + { + TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS, + TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS, + TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE, + TOOL_CTRL_ID_YES, + "yes" + }, + { + TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS, + TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS, + TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE, + TOOL_CTRL_ID_NO, + "no" + }, + { + TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS, + TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS, + TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE, + TOOL_CTRL_ID_CONFIRM, + "confirm" + }, + { + TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS, + TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS, + TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE, + TOOL_CTRL_ID_PLAYER_1, + "player 1" + }, + { + TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS, + TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS, + TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE, + TOOL_CTRL_ID_PLAYER_2, + "player 2" + }, + { + TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS, + TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS, + TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE, + TOOL_CTRL_ID_PLAYER_3, + "player 3" + }, + { + TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS, + TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS, + TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE, + TOOL_CTRL_ID_PLAYER_4, + "player 4" + } +}; + +void CreateToolButtons() +{ + int i; + + for (i=0; i= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4) { - if (IS_CHAR(element)) - return GFX_CHAR_START + (element - EL_CHAR_START); - else if (element >= EL_SP_START && element <= EL_SP_END) - { - int nr_element = element - EL_SP_START; - int gfx_per_line = 8; - int nr_graphic = - (nr_element / gfx_per_line) * MORE_PER_LINE + - (nr_element % gfx_per_line); + int player_nr = id - TOOL_CTRL_ID_PLAYER_1; - return GFX_START_ROCKSMORE + nr_graphic; - } - else - return -1; + getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr), + &deco_bitmap, &deco_x, &deco_y); + deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2; + deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2; } + + gi = CreateGadget(GDI_CUSTOM_ID, id, + GDI_INFO_TEXT, toolbutton_info[i].infotext, + GDI_X, DX + toolbutton_info[i].x, + GDI_Y, DY + toolbutton_info[i].y, + GDI_WIDTH, toolbutton_info[i].width, + GDI_HEIGHT, toolbutton_info[i].height, + GDI_TYPE, GD_TYPE_NORMAL_BUTTON, + GDI_STATE, GD_BUTTON_UNPRESSED, + GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y, + GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y, + GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y, + GDI_DECORATION_POSITION, deco_xpos, deco_ypos, + GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY, + GDI_DECORATION_SHIFTING, 1, 1, + GDI_EVENT_MASK, event_mask, + GDI_CALLBACK_ACTION, HandleToolButtons, + GDI_END); + + if (gi == NULL) + Error(ERR_EXIT, "cannot create gadget"); + + tool_gadget[id] = gi; + } +} + +void FreeToolButtons() +{ + int i; + + for (i=0; icustom_id; +} + +int get_next_element(int element) +{ + switch(element) + { + case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL; + case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY; + case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL; + case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE; + case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL; + case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE; + case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET; + + default: return element; + } +} + +int el2img(int element) +{ + int graphic = element_info[element].graphic[ACTION_DEFAULT]; + +#if DEBUG + if (graphic < 0) + Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...", + element, graphic); +#endif + + return graphic; +} + +int el_dir2img(int element, int direction) +{ + return el_dir_act2img(element, direction, ACTION_DEFAULT); +} + +int el_dir_act2img(int element, int direction, int action) +{ +#if DEBUG + if (element < 0) + { + printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: element == %d\n", + element); + + return IMG_EMPTY; + } + + if (action < 0) + { + printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: action == %d\n", + action); + + return IMG_EMPTY; } +#endif + + direction = MV_DIR_BIT(direction); + + return element_info[element].direction_graphic[action][direction]; }