1 /***********************************************************
2 * Mirror Magic -- McDuffin's Revenge *
3 *----------------------------------------------------------*
4 * (c) 1994-2001 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
22 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
24 SetDrawtoField(DRAW_BACKBUFFER);
26 redraw_mask |= REDRAW_FIELD;
29 void DrawGraphicAnimation_MM(int x, int y, int graphic, int frame)
34 getGraphicSource(graphic, frame, &bitmap, &src_x, &src_y);
36 BlitBitmap(bitmap, drawto_field, src_x, src_y, TILEX, TILEY,
37 FX + x * TILEX, FY + y * TILEY);
40 void DrawGraphic_MM(int x, int y, int graphic)
43 if (!IN_SCR_FIELD(x,y))
45 printf("DrawGraphic_MM(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
46 printf("DrawGraphic_MM(): This should never happen!\n");
51 DrawGraphicExt_MM(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
56 void DrawGraphicExt_MM(DrawBuffer *d, int x, int y, int graphic)
61 getGraphicSource(graphic, 0, &bitmap, &src_x, &src_y);
63 BlitBitmap(bitmap, d, src_x, src_y, TILEX, TILEY, x, y);
66 void DrawGraphicThruMask_MM(int x, int y, int graphic)
69 if (!IN_SCR_FIELD(x,y))
71 printf("DrawGraphicThruMask_MM(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
72 printf("DrawGraphicThruMask_MM(): This should never happen!\n");
77 DrawGraphicThruMaskExt_MM(drawto_field, FX + x * TILEX, FY + y * TILEY,
83 void DrawGraphicThruMaskExt_MM(DrawBuffer *d, int dest_x, int dest_y,
89 if (graphic == IMG_EMPTY)
92 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
94 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
97 void DrawMiniGraphic_MM(int x, int y, int graphic)
99 DrawMiniGraphicExt_MM(drawto, SX + x * MINI_TILEX, SY + y * MINI_TILEY,
102 MarkTileDirty(x / 2, y / 2);
105 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
107 getSizedGraphicSource(graphic, 0, TILESIZE / 4, bitmap, x, y);
110 void DrawMiniGraphicExt_MM(DrawBuffer *d, int x, int y, int graphic)
115 getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
117 BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
120 void DrawGraphicShifted_MM(int x,int y, int dx,int dy, int graphic,
121 int cut_mode, int mask_mode)
123 int width = TILEX, height = TILEY;
125 int src_x, src_y, dest_x, dest_y;
130 DrawGraphic_MM(x, y, graphic);
135 if (dx || dy) /* Verschiebung der Grafik? */
137 if (x < BX1) /* Element kommt von links ins Bild */
144 else if (x > BX2) /* Element kommt von rechts ins Bild */
150 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
156 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
158 else if (dx) /* allg. Bewegung in x-Richtung */
159 MarkTileDirty(x + SIGN(dx), y);
161 if (y < BY1) /* Element kommt von oben ins Bild */
163 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
171 else if (y > BY2) /* Element kommt von unten ins Bild */
177 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
183 else if (dy > 0 && cut_mode == CUT_ABOVE)
185 if (y == BY2) /* Element unterhalb des Bildes */
191 MarkTileDirty(x, y + 1);
192 } /* Element verläßt unten das Bild */
193 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
197 else if (dy) /* allg. Bewegung in y-Richtung */
199 MarkTileDirty(x, y + SIGN(dy));
203 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
208 dest_x = FX + x * TILEX + dx;
209 dest_y = FY + y * TILEY + dy;
212 if (!IN_SCR_FIELD(x,y))
214 printf("DrawGraphicShifted_MM(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
215 printf("DrawGraphicShifted_MM(): This should never happen!\n");
220 if (mask_mode == USE_MASKING)
221 BlitBitmapMasked(src_bitmap, drawto_field,
222 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
224 BlitBitmap(src_bitmap, drawto_field,
225 src_x, src_y, width, height, dest_x, dest_y);
230 void DrawGraphicShiftedThruMask_MM(int x,int y, int dx,int dy, int graphic,
233 DrawGraphicShifted_MM(x, y, dx, dy, graphic, cut_mode, USE_MASKING);
236 void DrawScreenElementExt_MM(int x, int y, int dx, int dy, int element,
237 int cut_mode, int mask_mode)
239 int ux = LEVELX(x), uy = LEVELY(y);
240 int graphic = el2gfx(element);
241 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
242 int phase2 = phase8 / 4;
243 int dir = MovDir[ux][uy];
245 if (element == EL_PACMAN)
247 graphic = (phase2 ? IMG_MM_PACMAN_RIGHT : IMG_MM_PACMAN_EATING_RIGHT);
251 else if (dir == MV_LEFT)
253 else if (dir == MV_DOWN)
258 DrawGraphicShifted_MM(x, y, dx, dy, graphic, cut_mode, mask_mode);
259 else if (mask_mode == USE_MASKING)
260 DrawGraphicThruMask_MM(x, y, graphic);
262 DrawGraphic_MM(x, y, graphic);
265 void DrawLevelElementExt_MM(int x, int y, int dx, int dy, int element,
266 int cut_mode, int mask_mode)
268 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
269 DrawScreenElementExt_MM(SCREENX(x), SCREENY(y), dx, dy, element,
270 cut_mode, mask_mode);
273 void DrawScreenElementShifted_MM(int x, int y, int dx, int dy, int element,
276 DrawScreenElementExt_MM(x, y, dx, dy, element, cut_mode, NO_MASKING);
279 void DrawLevelElementShifted_MM(int x, int y, int dx, int dy, int element,
282 DrawLevelElementExt_MM(x, y, dx, dy, element, cut_mode, NO_MASKING);
285 void DrawScreenElementThruMask_MM(int x, int y, int element)
287 DrawScreenElementExt_MM(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
290 void DrawLevelElementThruMask_MM(int x, int y, int element)
292 DrawLevelElementExt_MM(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
295 void DrawLevelFieldThruMask_MM(int x, int y)
297 DrawLevelElementExt_MM(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
300 void DrawScreenElement_MM(int x, int y, int element)
302 DrawScreenElementExt_MM(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
305 void DrawLevelElement_MM(int x, int y, int element)
307 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
308 DrawScreenElement_MM(SCREENX(x), SCREENY(y), element);
311 void DrawScreenField_MM(int x, int y)
313 int element = Feld[x][y];
315 if (!IN_LEV_FIELD(x, y))
320 int horiz_move = (MovDir[x][y] == MV_LEFT || MovDir[x][y] == MV_RIGHT);
322 DrawScreenElement_MM(x, y, EL_EMPTY);
325 DrawScreenElementShifted_MM(x, y, MovPos[x][y], 0, element, NO_CUTTING);
327 DrawScreenElementShifted_MM(x, y, 0, MovPos[x][y], element, NO_CUTTING);
329 else if (IS_BLOCKED(x, y))
335 Blocked2Moving(x, y, &oldx, &oldy);
339 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
340 MovDir[oldx][oldy] == MV_RIGHT);
342 DrawScreenElement_MM(x, y, EL_EMPTY);
344 element = Feld[oldx][oldy];
347 DrawScreenElementShifted_MM(sx, sy, MovPos[oldx][oldy], 0, element,
350 DrawScreenElementShifted_MM(sx, sy, 0, MovPos[oldx][oldy], element,
353 else if (IS_DRAWABLE(element))
355 DrawScreenElement_MM(x, y, element);
359 DrawScreenElement_MM(x, y, EL_EMPTY);
363 void DrawLevelField_MM(int x, int y)
365 DrawScreenField_MM(x, y);
368 void DrawMiniElement_MM(int x, int y, int element)
374 DrawMiniGraphic_MM(x, y, IMG_EMPTY);
379 graphic = el2gfx(element);
381 DrawMiniGraphic_MM(x, y, graphic);
384 void DrawMiniElementOrWall_MM(int sx, int sy, int scroll_x, int scroll_y)
386 int x = sx + scroll_x, y = sy + scroll_y;
388 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
389 DrawMiniElement_MM(sx, sy, EL_EMPTY);
390 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
391 DrawMiniElement_MM(sx, sy, Feld[x][y]);
394 void DrawField_MM(int x, int y)
396 int element = Feld[x][y];
398 DrawElement_MM(x, y, element);
407 for (x = 0; x < lev_fieldx; x++)
408 for (y = 0; y < lev_fieldy; y++)
411 redraw_mask |= REDRAW_FIELD;
414 void DrawWallsExt_MM(int x, int y, int element, int draw_mask)
417 int graphic = el2gfx(WALL_BASE(element));
421 getMiniGraphicSource(graphic, &bitmap, &gx, &gy);
423 DrawGraphic_MM(x, y, IMG_EMPTY);
426 if (IS_WALL_WOOD(element) || IS_WALL_AMOEBA(element) ||
427 IS_DF_WALL_WOOD(element))
429 if (IS_WALL_ICE(element) || IS_WALL_AMOEBA(element))
433 for (i = 0; i < 4; i++)
435 int dest_x = SX + x * TILEX + MINI_TILEX * (i % 2);
436 int dest_y = SY + y * TILEY + MINI_TILEY * (i / 2);
438 if (!((1 << i) & draw_mask))
441 if (element & (1 << i))
442 BlitBitmap(bitmap, drawto, gx, gy, MINI_TILEX, MINI_TILEY,
445 ClearRectangle(drawto, dest_x, dest_y, MINI_TILEX, MINI_TILEY);
451 void DrawWalls_MM(int x, int y, int element)
453 DrawWallsExt_MM(x, y, element, HIT_MASK_ALL);
456 void DrawWallsAnimation_MM(int x, int y, int element, int phase, int bit_mask)
462 DrawWalls_MM(x, y, element);
467 for (i = 0; i < 4; i++)
469 if (element & (1 << i))
475 int dst_x = SX + x * TILEX + (i % 2) * MINI_TILEX;
476 int dst_y = SY + y * TILEY + (i / 2) * MINI_TILEY;
478 if (bit_mask & (1 << i))
480 graphic = (IS_WALL_AMOEBA(element) ?
481 IMG_MM_AMOEBA_WALL_GROWING :
482 IMG_MM_ICE_WALL_SHRINKING);
487 graphic = (IS_WALL_AMOEBA(element) ?
493 getSizedGraphicSource(graphic, frame, MINI_TILESIZE, &bitmap,
496 BlitBitmap(bitmap, drawto, src_x, src_y, MINI_TILEX, MINI_TILEY,
504 void DrawElement_MM(int x, int y, int element)
506 if (element == EL_EMPTY)
507 DrawGraphic_MM(x, y, IMG_EMPTY);
508 else if (IS_WALL(element))
509 DrawWalls_MM(x, y, element);
511 else if (IS_WALL_CHANGING(element) && IS_WALL_CHANGING(Feld[x][y]))
513 int wall_element = Feld[x][y] - EL_WALL_CHANGING + Store[x][y];
515 DrawWalls_MM(x, y, wall_element);
518 else if (element == EL_PACMAN)
519 DrawLevelField_MM(x, y);
520 else if (element == EL_FUSE_ON &&
524 DrawGraphic_MM(x, y, IMG_MM_FUSE);
526 DrawGraphic_MM(x, y, el2gfx(element));
529 void DrawMicroWalls_MM(int x, int y, int element)
532 int graphic = el2gfx(WALL_BASE(element));
536 getMicroGraphicSource(graphic, &bitmap, &gx, &gy);
538 for (i = 0; i < 4; i++)
540 int xpos = MICROLEV_XPOS + x * MICRO_TILEX + MICRO_WALLX * (i % 2);
541 int ypos = MICROLEV_YPOS + y * MICRO_TILEY + MICRO_WALLY * (i / 2);
543 if (element & (1 << i))
544 BlitBitmap(bitmap, drawto, gx, gy, MICRO_WALLX, MICRO_WALLY, xpos, ypos);
546 ClearRectangle(drawto, xpos, ypos, MICRO_WALLX, MICRO_WALLY);
550 void DrawMicroElement_MM(int x, int y, int element)
553 int graphic = el2gfx(element);
556 if (element == EL_EMPTY)
559 if (IS_WALL(element))
561 DrawMicroWalls_MM(x, y, element);
566 getMicroGraphicSource(graphic, &bitmap, &gx, &gy);
568 BlitBitmap(bitmap, drawto, gx, gy, MICRO_TILEX, MICRO_TILEY,
569 MICROLEV_XPOS + x * MICRO_TILEX, MICROLEV_YPOS + y * MICRO_TILEY);
572 void DrawMicroLevelExt_MM(int xpos, int ypos)
576 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
578 for (x = 0; x < STD_LEV_FIELDX; x++)
579 for (y = 0; y < STD_LEV_FIELDY; y++)
580 DrawMicroElement_MM(x, y, Ur[x][y]);
582 redraw_mask |= REDRAW_FIELD;
585 void DrawMiniLevel_MM(int size_x, int size_y, int scroll_x, int scroll_y)
589 for(x = 0; x < size_x; x++)
590 for(y = 0; y < size_y; y++)
591 DrawMiniElementOrWall_MM(x, y, scroll_x, scroll_y);
593 redraw_mask |= REDRAW_FIELD;
596 int REQ_in_range(int x, int y)
598 if (y > DY + 249 && y < DY + 278)
600 if (x > DX + 1 && x < DX + 48)
602 else if (x > DX + 51 && x < DX + 98)
609 Pixel ReadPixel(DrawBuffer *bitmap, int x, int y)
611 return GetPixel(bitmap, x, y);
614 void SetRGB(unsigned int pixel,
615 unsigned short red, unsigned short green, unsigned short blue)
619 int get_base_element(int element)
621 if (IS_MIRROR(element))
622 return EL_MIRROR_START;
623 else if (IS_MIRROR_FIXED(element))
624 return EL_MIRROR_FIXED_START;
625 else if (IS_POLAR(element))
626 return EL_POLAR_START;
627 else if (IS_POLAR_CROSS(element))
628 return EL_POLAR_CROSS_START;
629 else if (IS_BEAMER(element))
630 return EL_BEAMER_RED_START + BEAMER_NR(element) * 16;
631 else if (IS_FIBRE_OPTIC(element))
632 return EL_FIBRE_OPTIC_START + FIBRE_OPTIC_NR(element) * 2;
633 else if (IS_MCDUFFIN(element))
634 return EL_MCDUFFIN_START;
635 else if (IS_LASER(element))
636 return EL_LASER_START;
637 else if (IS_RECEIVER(element))
638 return EL_RECEIVER_START;
639 else if (IS_DF_MIRROR(element))
640 return EL_DF_MIRROR_START;
641 else if (IS_DF_MIRROR_AUTO(element))
642 return EL_DF_MIRROR_AUTO_START;
643 else if (IS_PACMAN(element))
644 return EL_PACMAN_START;
645 else if (IS_GRID_STEEL(element))
646 return EL_GRID_STEEL_START;
647 else if (IS_GRID_WOOD(element))
648 return EL_GRID_WOOD_START;
649 else if (IS_GRID_STEEL_FIXED(element))
650 return EL_GRID_STEEL_FIXED_START;
651 else if (IS_GRID_WOOD_FIXED(element))
652 return EL_GRID_WOOD_FIXED_START;
653 else if (IS_GRID_STEEL_AUTO(element))
654 return EL_GRID_STEEL_AUTO_START;
655 else if (IS_GRID_WOOD_AUTO(element))
656 return EL_GRID_WOOD_AUTO_START;
657 else if (IS_WALL_STEEL(element))
658 return EL_WALL_STEEL_START;
659 else if (IS_WALL_WOOD(element))
660 return EL_WALL_WOOD_START;
661 else if (IS_WALL_ICE(element))
662 return EL_WALL_ICE_START;
663 else if (IS_WALL_AMOEBA(element))
664 return EL_WALL_AMOEBA_START;
665 else if (IS_DF_WALL_STEEL(element))
666 return EL_DF_WALL_STEEL_START;
667 else if (IS_DF_WALL_WOOD(element))
668 return EL_DF_WALL_WOOD_START;
669 else if (IS_CHAR(element))
670 return EL_CHAR_START;
675 int get_element_phase(int element)
677 return element - get_base_element(element);
680 int get_num_elements(int element)
682 if (IS_MIRROR(element) ||
684 IS_BEAMER(element) ||
685 IS_DF_MIRROR(element) ||
686 IS_DF_MIRROR_AUTO(element))
688 else if (IS_GRID_STEEL_FIXED(element) ||
689 IS_GRID_WOOD_FIXED(element) ||
690 IS_GRID_STEEL_AUTO(element) ||
691 IS_GRID_WOOD_AUTO(element))
693 else if (IS_MIRROR_FIXED(element) ||
694 IS_POLAR_CROSS(element) ||
695 IS_MCDUFFIN(element) ||
697 IS_RECEIVER(element) ||
698 IS_PACMAN(element) ||
699 IS_GRID_STEEL(element) ||
700 IS_GRID_WOOD(element))
706 int get_rotated_element(int element, int step)
708 int base_element = get_base_element(element);
709 int num_elements = get_num_elements(element);
710 int element_phase = element - base_element;
712 return base_element + (element_phase + step + num_elements) % num_elements;
715 static int map_element(int element)
719 case EL_WALL_STEEL: return EL_STEEL_WALL;
720 case EL_WALL_WOOD: return EL_WOODEN_WALL;
721 case EL_WALL_ICE: return EL_ICE_WALL;
722 case EL_WALL_AMOEBA: return EL_AMOEBA_WALL;
723 case EL_DF_WALL_STEEL: return EL_DF_STEEL_WALL;
724 case EL_DF_WALL_WOOD: return EL_DF_WOODEN_WALL;
726 default: return element;
730 int el2gfx(int element)
732 element = map_element(element);
737 return IMG_MM_LIGHTBALL_RED + RND(3);
740 return el2img_mm(element);
744 void RedrawPlayfield_MM()
750 void BlitScreenToBitmap_MM(Bitmap *target_bitmap)
752 BlitBitmap(drawto_field, target_bitmap,
753 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);