X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame_mm%2Fmm_game.c;h=5a9470999aa3bd2a1119034cb86e1b540f30b608;hb=d54216506a88ccd390a395bc9585f44b60d2d579;hp=3a0c60d1254c37a61be0950e9c33b40c83ea7069;hpb=d377d869c0e29a0008bb3fc5778e7a399e13a0ce;p=rocksndiamonds.git diff --git a/src/game_mm/mm_game.c b/src/game_mm/mm_game.c index 3a0c60d1..5a947099 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,6 +97,193 @@ 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; + +/* element masks for scanning pixels of MM elements */ +static const char mm_masks[10][16][16 + 1] = +{ + { + " ", + " XXXXX ", + " XXXXXXX ", + " XXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXXXX", + " XXXXXXXXXXXXXX", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + }, + { + " ", + " XXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + }, + { + " ", + " XXXXXX ", + " XXXXXXXXX ", + " XXXXXXXXXXX ", + "XXXXXXXXXXXXX ", + "XXXXXXXXXXXXX ", + "XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + }, + { + " ", + " XXXXXX ", + " XXXXXXXX ", + " XXXXXXXXXX ", + " XXXXXXXXXXX ", + " XXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXX XXXXX ", + }, + { + " XXXXXX XXXXXX ", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + " ", + " ", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + " XXXXXX XXXXXX ", + }, + { + " XXXXXX XXXXXX ", + "XXXXXXX XXXXXXX", + "XXXXXXX XXXXXXX", + "XXXXXXX XXXXXXX", + "XXXXXXX XXXXXXX", + "XXXXXXX XXXXXXX", + "XXXXXXX XXXXXXX", + " XXXXXX XXXXXX ", + " XXXXXX XXXXXX ", + "XXXXXXX XXXXXXX", + "XXXXXXX XXXXXXX", + "XXXXXXX XXXXXXX", + "XXXXXXX XXXXXXX", + "XXXXXXX XXXXXXX", + "XXXXXXX XXXXXXX", + " XXXXXX XXXXXX ", + }, + { + " XX XXXXX ", + " XXX XXXX ", + " XXXX XXX X", + " XXXXXXXXX XX", + " XXXXXXXXX XXX", + "XXXXXXXXX XXXX", + "XXXXXXXX XXXXX", + " XXXX XXX ", + " XXX XXXX ", + "XXXXX XXXXXXXX", + "XXXX XXXXXXXXX", + "XXX XXXXXXXXX ", + "XX XXXXXXXXX ", + "X XXX XXXX ", + " XXXX XXX ", + " XXXXX XX ", + }, + { + " XXXXX XX ", + " XXXX XXX ", + "X XXX XXXX ", + "XX XXXXXXXXX ", + "XXX XXXXXXXXX ", + "XXXX XXXXXXXXX", + "XXXXX XXXXXXXX", + " XXX XXXX ", + " XXXX XXX ", + "XXXXXXXX XXXXX", + "XXXXXXXXX XXXX", + " XXXXXXXXX XXX", + " XXXXXXXXX XX", + " XXXX XXX X", + " XXX XXXX ", + " XX XXXXX ", + }, + { + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + "XXXXXXXXXXXXXXXX", + }, + { + " ", + " XXXX ", + " XXXXXXXX ", + " XXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXXXX ", + " XXXXXXXXXX ", + " XXXXXXXX ", + " XXXX ", + " ", + }, +}; static int get_element_angle(int element) { @@ -117,6 +314,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]; @@ -275,6 +499,9 @@ static void InitLaser() laser.num_beamers = 0; laser.beamer_edge[0] = 0; + laser.dest_element = EL_EMPTY; + laser.wall_mask = 0; + AddLaserEdge(LX, LY); /* set laser starting edge */ pen_ray = GetPixelFromRGB(window, @@ -287,6 +514,14 @@ void InitGameEngine_MM() { int i, x, y; + 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; game_mm.num_pacman = 0; @@ -525,17 +760,9 @@ int ScanPixel() } else { - int graphic_mask = getMaskFromElement(element); - Bitmap *bitmap; - int src_x, src_y; - int mask_x, mask_y; - - getGraphicSource(graphic_mask, 0, &bitmap, &src_x, &src_y); + int pos = getMaskFromElement(element) - IMG_MM_MASK_MCDUFFIN_RIGHT; - mask_x = src_x + dx; - mask_y = src_y + dy; - - pixel = (ReadPixel(bitmap, mask_x, mask_y) ? 1 : 0); + pixel = (mm_masks[pos][dy / 2][dx / 2] == 'X' ? 1 : 0); } } else @@ -778,8 +1005,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; @@ -2181,9 +2407,8 @@ static void Explode_MM(int x, int y, int phase, int mode) { if (Store[x][y] == EL_BOMB) { - laser.num_damages--; DrawLaser(0, DL_LASER_DISABLED); - laser.num_edges = 0; + InitLaser(); Bang_MM(laser.start_edge.x, laser.start_edge.y); Store[x][y] = EL_EMPTY; @@ -2675,25 +2900,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; } @@ -3273,13 +3497,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; } } @@ -3290,9 +3513,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; } } @@ -3301,8 +3523,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;