X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame_mm%2Fmm_game.c;h=8b0ba849abda46977749aaa6f9e3dd38c9f0791f;hb=86eb2ffc8cf01f17a3aea2bf0b279014825ec756;hp=84242f0be78ce1a6ff95bc6f8ee7d84f6658378d;hpb=de400acbdd01156c04c9862e8d4331f11a14a282;p=rocksndiamonds.git diff --git a/src/game_mm/mm_game.c b/src/game_mm/mm_game.c index 84242f0b..8b0ba849 100644 --- a/src/game_mm/mm_game.c +++ b/src/game_mm/mm_game.c @@ -78,6 +78,16 @@ #define HEALTH_INC_DELAY 9 #define HEALTH_DELAY(x) ((x) ? HEALTH_DEC_DELAY : HEALTH_INC_DELAY) +#define BEGIN_NO_HEADLESS \ + { \ + boolean last_headless = program.headless; \ + \ + program.headless = FALSE; \ + +#define END_NO_HEADLESS \ + program.headless = last_headless; \ + } \ + /* forward declaration for internal use */ static int MovingOrBlocked2Element_MM(int, int); static void Bang_MM(int, int); @@ -87,55 +97,23 @@ static void InitMovingField_MM(int, int, int); static void ContinueMoving_MM(int, int); static void Moving2Blocked_MM(int, int, int *, int *); +/* bitmap for laser beam detection */ +static Bitmap *laser_bitmap = NULL; -#if 0 -// ============================================================================= -// TMP_dump_masks_MM (code) -// ============================================================================= - -void TMP_dump_masks_MM() -{ - int i; - - printf("static const char mm_masks[10][16][16] =\n"); - printf("{\n"); - - for (i = EL_MM_MASK_MCDUFFIN_RIGHT; i <= EL_MM_MASK_CIRCLE; i++) - { - int graphic_mask = el2gfx(i); - Bitmap *bitmap; - int src_x, src_y; - int x, y; +/* variables for laser control */ +static int last_LX = 0, last_LY = 0, last_hit_mask = 0; +static int hold_x = -1, hold_y = -1; - getGraphicSource(graphic_mask, 0, &bitmap, &src_x, &src_y); +/* variables for pacman control */ +static int pacman_nr = -1; - printf(" {\n"); - - for (y = 0; y < TILEY; y += 2) - { - printf(" \""); - - for (x = 0; x < TILEX; x += 2) - { - Pixel pixel = GetPixel(bitmap, src_x + x, src_y + y); - - printf("%c", (pixel ? 'X' : ' ')); - } - - printf("\",\n"); - } - - printf(" },\n"); - } - - printf("};\n"); -} -#endif - -// ============================================================================= -// TMP_dump_masks_MM (result) -// ============================================================================= +/* various game engine delay counters */ +static unsigned int rotate_delay = 0; +static unsigned int pacman_delay = 0; +static unsigned int energy_delay = 0; +static unsigned int overload_delay = 0; +/* element masks for scanning pixels of MM elements */ static const char mm_masks[10][16][16 + 1] = { { @@ -349,6 +327,33 @@ static int get_mirrored_angle(int laser_angle, int mirror_angle) return (reflected_angle + 16) % 16; } +static void DrawLaserLines(struct XY *points, int num_points, int mode) +{ + Pixel pixel_drawto = (mode == DL_LASER_ENABLED ? pen_ray : pen_bg); + Pixel pixel_buffer = (mode == DL_LASER_ENABLED ? WHITE_PIXEL : BLACK_PIXEL); + + DrawLines(drawto, points, num_points, pixel_drawto); + + BEGIN_NO_HEADLESS + { + DrawLines(laser_bitmap, points, num_points, pixel_buffer); + } + END_NO_HEADLESS +} + +static boolean CheckLaserPixel(int x, int y) +{ + Pixel pixel; + + BEGIN_NO_HEADLESS + { + pixel = ReadPixel(laser_bitmap, x, y); + } + END_NO_HEADLESS + + return (pixel == WHITE_PIXEL); +} + static void InitMovDir_MM(int x, int y) { int element = Feld[x][y]; @@ -522,9 +527,13 @@ void InitGameEngine_MM() { int i, x, y; -#if 0 - TMP_dump_masks_MM(); -#endif + BEGIN_NO_HEADLESS + { + /* initialize laser bitmap to current playfield (screen) size */ + ReCreateBitmap(&laser_bitmap, drawto->width, drawto->height); + ClearRectangle(laser_bitmap, 0, 0, drawto->width, drawto->height); + } + END_NO_HEADLESS /* set global game control values */ game_mm.num_cycle = 0; @@ -559,8 +568,24 @@ void InitGameEngine_MM() laser.dest_element = EL_EMPTY; laser.wall_mask = 0; + last_LX = 0; + last_LY = 0; + last_hit_mask = 0; + + hold_x = -1; + hold_y = -1; + + pacman_nr = -1; + CT = Ct = 0; + rotate_delay = 0; + pacman_delay = 0; + energy_delay = 0; + overload_delay = 0; + + ClickElement(-1, -1, -1); + for (x = 0; x < lev_fieldx; x++) { for (y = 0; y < lev_fieldy; y++) @@ -1009,8 +1034,7 @@ void DrawLaserExt(int start_edge, int num_edges, int mode) #endif /* now draw the laser to the backbuffer and (if enabled) to the screen */ - DrawLines(drawto, &laser.edge[start_edge], num_edges, - (mode == DL_LASER_ENABLED ? pen_ray : pen_bg)); + DrawLaserLines(&laser.edge[start_edge], num_edges, mode); redraw_mask |= REDRAW_FIELD; @@ -1234,6 +1258,11 @@ void DrawLaser(int start_edge, int mode) last_num_edges, start_edge); #endif + // special case when rotating first beamer: delete laser edge on beamer + // (but do not start scanning on previous edge to prevent mirror sound) + if (last_num_edges - start_edge == 1 && start_edge > 0) + DrawLaserLines(&laser.edge[start_edge - 1], 2, DL_LASER_DISABLED); + /* delete first segment from start to the first beamer */ DrawLaserExt(start_edge, last_num_edges - start_edge, DL_LASER_DISABLED); } @@ -2090,8 +2119,6 @@ boolean HitReflectingWalls(int element, int hit_mask) (IS_VERT_ANGLE(laser.current_angle) && (!(hit_mask & HIT_MASK_LEFT) || !(hit_mask & HIT_MASK_RIGHT)))) { - static int last_LX = 0, last_LY = 0, last_hit_mask = 0; - /* laser at last step touched nothing or the same side of the wall */ if (LX != last_LX || LY != last_LY || hit_mask == last_hit_mask) { @@ -2676,6 +2703,16 @@ void ClickElement(int x, int y, int button) static boolean new_button = TRUE; int element; + if (button == -1) + { + /* initialize static variables */ + click_delay = 0; + click_delay_value = CLICK_DELAY; + new_button = TRUE; + + return; + } + /* do not rotate objects hit by the laser after the game was solved */ if (game_mm.level_solved && Hit[x][y]) return; @@ -2774,8 +2811,6 @@ void ClickElement(int x, int y, int button) void RotateMirror(int x, int y, int button) { - static int hold_x = -1, hold_y = -1; - if (button == MB_RELEASED) { /* release eventually hold auto-rotating mirror */ @@ -2871,7 +2906,6 @@ void RotateMirror(int x, int y, int button) void AutoRotateMirrors() { - static unsigned int rotate_delay = 0; int x, y; if (!FrameReached(&rotate_delay, AUTO_ROTATE_DELAY)) @@ -2905,25 +2939,24 @@ boolean ObjHit(int obx, int oby, int bits) if (bits & HIT_POS_CENTER) { - if (ReadPixel(drawto, SX + obx + 15, SY + oby + 15) == pen_ray) + if (CheckLaserPixel(SX + obx + 15, + SY + oby + 15)) return TRUE; } if (bits & HIT_POS_EDGE) { for (i = 0; i < 4; i++) - if (ReadPixel(drawto, - SX + obx + 31 * (i % 2), - SY + oby + 31 * (i / 2)) == pen_ray) + if (CheckLaserPixel(SX + obx + 31 * (i % 2), + SY + oby + 31 * (i / 2))) return TRUE; } if (bits & HIT_POS_BETWEEN) { for (i = 0; i < 4; i++) - if (ReadPixel(drawto, - SX + 4 + obx + 22 * (i % 2), - SY + 4 + oby + 22 * (i / 2)) == pen_ray) + if (CheckLaserPixel(SX + 4 + obx + 22 * (i % 2), + SY + 4 + oby + 22 * (i / 2))) return TRUE; } @@ -3002,9 +3035,6 @@ void ColorCycling(void) static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode) { - static unsigned int pacman_delay = 0; - static unsigned int energy_delay = 0; - static unsigned int overload_delay = 0; int element; int x, y, i; @@ -3059,9 +3089,10 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode) if (FrameReached(&energy_delay, ENERGY_DELAY)) { - game_mm.energy_left--; - if (game_mm.energy_left >= 0) + if (game_mm.energy_left > 0) { + game_mm.energy_left--; + #if 0 BlitBitmap(pix[PIX_DOOR], drawto, DOOR_GFX_PAGEX5 + XX_ENERGY, DOOR_GFX_PAGEY1 + YY_ENERGY, @@ -3070,7 +3101,7 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode) #endif redraw_mask |= REDRAW_DOOR_1; } - else if (setup.time_limit) + else if (setup.time_limit && !game_mm.game_over) { int i; @@ -3503,13 +3534,12 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode) { if (laser.wall_mask & (1 << i)) { - if (ReadPixel(drawto, - SX + ELX * TILEX + 14 + (i % 2) * 2, - SY + ELY * TILEY + 31 * (i / 2)) == pen_ray) + if (CheckLaserPixel(SX + ELX * TILEX + 14 + (i % 2) * 2, + SY + ELY * TILEY + 31 * (i / 2))) break; - if (ReadPixel(drawto, - SX + ELX * TILEX + 31 * (i % 2), - SY + ELY * TILEY + 14 + (i / 2) * 2) == pen_ray) + + if (CheckLaserPixel(SX + ELX * TILEX + 31 * (i % 2), + SY + ELY * TILEY + 14 + (i / 2) * 2)) break; } } @@ -3520,9 +3550,8 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode) { if (laser.wall_mask & (1 << i)) { - if (ReadPixel(drawto, - SX + ELX * TILEX + 31 * (i % 2), - SY + ELY * TILEY + 31 * (i / 2)) == pen_ray) + if (CheckLaserPixel(SX + ELX * TILEX + 31 * (i % 2), + SY + ELY * TILEY + 31 * (i / 2))) break; } } @@ -3531,8 +3560,8 @@ static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode) if (laser.num_beamers > 0 || k1 < 1 || k2 < 4 || k3 < 4 || - ReadPixel(drawto, SX + ELX * TILEX + 14, SY + ELY * TILEY + 14) - == pen_ray) + CheckLaserPixel(SX + ELX * TILEX + 14, + SY + ELY * TILEY + 14)) { laser.num_edges = r; laser.num_damages = d; @@ -3681,36 +3710,35 @@ void GameActions_MM(struct MouseActionInfo action, boolean warp_mode) void MovePacMen() { - static int p = -1; int mx, my, ox, oy, nx, ny; int element; int l; - if (++p >= game_mm.num_pacman) - p = 0; + if (++pacman_nr >= game_mm.num_pacman) + pacman_nr = 0; - game_mm.pacman[p].dir--; + game_mm.pacman[pacman_nr].dir--; for (l = 1; l < 5; l++) { - game_mm.pacman[p].dir++; + game_mm.pacman[pacman_nr].dir++; - if (game_mm.pacman[p].dir > 4) - game_mm.pacman[p].dir = 1; + if (game_mm.pacman[pacman_nr].dir > 4) + game_mm.pacman[pacman_nr].dir = 1; - if (game_mm.pacman[p].dir % 2) + if (game_mm.pacman[pacman_nr].dir % 2) { mx = 0; - my = game_mm.pacman[p].dir - 2; + my = game_mm.pacman[pacman_nr].dir - 2; } else { my = 0; - mx = 3 - game_mm.pacman[p].dir; + mx = 3 - game_mm.pacman[pacman_nr].dir; } - ox = game_mm.pacman[p].x; - oy = game_mm.pacman[p].y; + ox = game_mm.pacman[pacman_nr].x; + oy = game_mm.pacman[pacman_nr].y; nx = ox + mx; ny = oy + my; element = Feld[nx][ny]; @@ -3727,11 +3755,11 @@ void MovePacMen() Feld[ox][oy] = EL_EMPTY; Feld[nx][ny] = EL_PACMAN_RIGHT - 1 + - (game_mm.pacman[p].dir - 1 + - (game_mm.pacman[p].dir % 2) * 2); + (game_mm.pacman[pacman_nr].dir - 1 + + (game_mm.pacman[pacman_nr].dir % 2) * 2); - game_mm.pacman[p].x = nx; - game_mm.pacman[p].y = ny; + game_mm.pacman[pacman_nr].x = nx; + game_mm.pacman[pacman_nr].y = ny; DrawGraphic_MM(ox, oy, IMG_EMPTY);