1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
17 #include <machine/joystick.h>
31 extern boolean wait_for_vsync;
34 /* tool button identifiers */
35 #define TOOL_CTRL_ID_YES 0
36 #define TOOL_CTRL_ID_NO 1
37 #define TOOL_CTRL_ID_CONFIRM 2
38 #define TOOL_CTRL_ID_PLAYER_1 3
39 #define TOOL_CTRL_ID_PLAYER_2 4
40 #define TOOL_CTRL_ID_PLAYER_3 5
41 #define TOOL_CTRL_ID_PLAYER_4 6
43 #define NUM_TOOL_BUTTONS 7
45 /* forward declaration for internal use */
46 static int getGraphicAnimationPhase(int, int, int);
47 static void UnmapToolButtons();
48 static void HandleToolButtons(struct GadgetInfo *);
50 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
51 static int request_gadget_id = -1;
53 void SetDrawtoField(int mode)
55 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
66 drawto_field = fieldbuffer;
68 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
79 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
86 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
88 if (setup.direct_draw && game_status == PLAYING)
89 redraw_mask &= ~REDRAW_MAIN;
91 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
92 redraw_mask |= REDRAW_FIELD;
94 if (redraw_mask & REDRAW_FIELD)
95 redraw_mask &= ~REDRAW_TILES;
100 /* synchronize X11 graphics at this point; if we would synchronize the
101 display immediately after the buffer switching (after the XFlush),
102 this could mean that we have to wait for the graphics to complete,
103 although we could go on doing calculations for the next frame */
105 XSync(display, FALSE);
107 if (redraw_mask & REDRAW_ALL)
109 XCopyArea(display, backbuffer, window, gc,
110 0, 0, WIN_XSIZE, WIN_YSIZE,
115 if (redraw_mask & REDRAW_FIELD)
117 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
119 XCopyArea(display, backbuffer, window, gc,
120 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
125 int fx = FX, fy = FY;
127 if (setup.soft_scrolling)
129 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
130 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
133 if (setup.soft_scrolling ||
134 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
135 ABS(ScreenMovPos) == ScrollStepSize ||
136 redraw_tiles > REDRAWTILES_THRESHOLD)
138 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
142 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
144 (setup.soft_scrolling ?
145 "setup.soft_scrolling" :
146 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
147 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
148 ABS(ScreenGfxPos) == ScrollStepSize ?
149 "ABS(ScreenGfxPos) == ScrollStepSize" :
150 "redraw_tiles > REDRAWTILES_THRESHOLD"));
155 redraw_mask &= ~REDRAW_MAIN;
158 if (redraw_mask & REDRAW_DOORS)
160 if (redraw_mask & REDRAW_DOOR_1)
161 XCopyArea(display, backbuffer, window, gc,
162 DX, DY, DXSIZE, DYSIZE,
164 if (redraw_mask & REDRAW_DOOR_2)
166 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
167 XCopyArea(display,backbuffer,window,gc,
168 VX,VY, VXSIZE,VYSIZE,
172 if (redraw_mask & REDRAW_VIDEO_1)
173 XCopyArea(display,backbuffer,window,gc,
174 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
175 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
176 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
177 if (redraw_mask & REDRAW_VIDEO_2)
178 XCopyArea(display,backbuffer,window,gc,
179 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
180 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
181 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
182 if (redraw_mask & REDRAW_VIDEO_3)
183 XCopyArea(display,backbuffer,window,gc,
184 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
185 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
186 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
189 if (redraw_mask & REDRAW_DOOR_3)
190 XCopyArea(display, backbuffer, window, gc,
191 EX, EY, EXSIZE, EYSIZE,
193 redraw_mask &= ~REDRAW_DOORS;
196 if (redraw_mask & REDRAW_MICROLEVEL)
198 XCopyArea(display,backbuffer,window,gc,
199 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
200 MICROLEV_XPOS, MICROLEV_YPOS);
201 XCopyArea(display,backbuffer,window,gc,
202 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
203 SX, MICROLABEL_YPOS);
204 redraw_mask &= ~REDRAW_MICROLEVEL;
207 if (redraw_mask & REDRAW_TILES)
209 for(x=0; x<SCR_FIELDX; x++)
210 for(y=0; y<SCR_FIELDY; y++)
211 if (redraw[redraw_x1 + x][redraw_y1 + y])
212 XCopyArea(display, buffer, window, gc,
213 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
214 SX + x * TILEX, SY + y * TILEY);
219 for(x=0; x<MAX_BUF_XSIZE; x++)
220 for(y=0; y<MAX_BUF_YSIZE; y++)
229 long fading_delay = 300;
231 if (setup.fading && (redraw_mask & REDRAW_FIELD))
238 XFillRectangle(display,window,gc,
239 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
242 for(i=0;i<2*FULL_SYSIZE;i++)
244 for(y=0;y<FULL_SYSIZE;y++)
246 XCopyArea(display,backbuffer,window,gc,
247 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
255 for(i=1;i<FULL_SYSIZE;i+=2)
256 XCopyArea(display,backbuffer,window,gc,
257 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
263 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
264 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
265 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
269 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
270 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
271 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
275 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
276 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
277 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
281 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
282 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
283 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
287 redraw_mask &= ~REDRAW_MAIN;
296 XFillRectangle(display, backbuffer, gc,
297 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
299 if (setup.soft_scrolling && game_status == PLAYING)
301 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
302 SetDrawtoField(DRAW_BUFFERED);
305 SetDrawtoField(DRAW_BACKBUFFER);
307 if (setup.direct_draw && game_status == PLAYING)
309 XFillRectangle(display, window, gc,
310 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
311 SetDrawtoField(DRAW_DIRECT);
314 redraw_mask |= REDRAW_FIELD;
317 int getFontWidth(int font_size, int font_type)
319 return (font_size == FS_BIG ? FONT1_XSIZE :
320 font_type == FC_SPECIAL1 ? FONT3_XSIZE :
321 font_type == FC_SPECIAL2 ? FONT4_XSIZE :
322 font_type == FC_SPECIAL3 ? FONT5_XSIZE :
326 int getFontHeight(int font_size, int font_type)
328 return (font_size == FS_BIG ? FONT1_YSIZE :
329 font_type == FC_SPECIAL1 ? FONT3_YSIZE :
330 font_type == FC_SPECIAL2 ? FONT4_YSIZE :
331 font_type == FC_SPECIAL3 ? FONT5_YSIZE :
335 void DrawTextFCentered(int y, int font_type, char *format, ...)
337 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
338 int font_width = getFontWidth(FS_SMALL, font_type);
341 va_start(ap, format);
342 vsprintf(buffer, format, ap);
345 DrawText(SX + (SXSIZE - strlen(buffer) * font_width) / 2, SY + y,
346 buffer, FS_SMALL, font_type);
349 void DrawTextF(int x, int y, int font_type, char *format, ...)
351 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
354 va_start(ap, format);
355 vsprintf(buffer, format, ap);
358 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
361 void DrawText(int x, int y, char *text, int font_size, int font_type)
363 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
366 redraw_mask |= REDRAW_FIELD;
368 redraw_mask |= REDRAW_DOOR_1;
371 void DrawTextExt(Drawable d, GC gc, int x, int y,
372 char *text, int font_size, int font_type)
374 int font_width, font_height, font_start;
376 boolean print_inverse = FALSE;
378 if (font_size != FS_SMALL && font_size != FS_BIG)
379 font_size = FS_SMALL;
380 if (font_type < FC_RED || font_type > FC_SPECIAL3)
383 font_width = getFontWidth(font_size, font_type);
384 font_height = getFontHeight(font_size, font_type);
386 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
387 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
388 FONT_LINES_PER_FONT);
390 if (font_type == FC_SPECIAL3)
391 font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT;
397 if (c == '~' && font_size == FS_SMALL)
399 print_inverse = TRUE;
403 if (c >= 'a' && c <= 'z')
405 else if (c == 'ä' || c == 'Ä')
407 else if (c == 'ö' || c == 'Ö')
409 else if (c == 'ü' || c == 'Ü')
412 if (c >= 32 && c <= 95)
414 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
415 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
416 int dest_x = x, dest_y = y;
420 XCopyArea(display, pix[font_pixmap], d, gc,
421 FONT_CHARS_PER_LINE * font_width,
422 3 * font_height + font_start,
423 font_width, font_height, x, y);
425 XSetClipOrigin(display, clip_gc[font_pixmap],
426 dest_x - src_x, dest_y - src_y);
427 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
428 0, 0, font_width, font_height, dest_x, dest_y);
431 XCopyArea(display, pix[font_pixmap], d, gc,
432 src_x, src_y, font_width, font_height, dest_x, dest_y);
439 void DrawAllPlayers()
443 for(i=0; i<MAX_PLAYERS; i++)
444 if (stored_player[i].active)
445 DrawPlayer(&stored_player[i]);
448 void DrawPlayerField(int x, int y)
450 if (!IS_PLAYER(x, y))
453 DrawPlayer(PLAYERINFO(x, y));
456 void DrawPlayer(struct PlayerInfo *player)
458 int jx = player->jx, jy = player->jy;
459 int last_jx = player->last_jx, last_jy = player->last_jy;
460 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
461 int sx = SCREENX(jx), sy = SCREENY(jy);
462 int sxx = 0, syy = 0;
463 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
465 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
467 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
471 if (!IN_LEV_FIELD(jx,jy))
473 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
474 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
475 printf("DrawPlayerField(): This should never happen!\n");
480 if (element == EL_EXPLODING)
483 /* draw things in the field the player is leaving, if needed */
485 if (player_is_moving)
487 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
489 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
490 DrawLevelFieldThruMask(last_jx, last_jy);
492 else if (last_element == EL_DYNAMITE_ACTIVE)
493 DrawDynamite(last_jx, last_jy);
495 DrawLevelField(last_jx, last_jy);
497 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
501 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
502 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
504 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
507 DrawLevelField(next_jx, next_jy);
511 if (!IN_SCR_FIELD(sx, sy))
514 if (setup.direct_draw)
515 SetDrawtoField(DRAW_BUFFERED);
517 /* draw things behind the player, if needed */
520 DrawLevelElement(jx, jy, Store[jx][jy]);
521 else if (!IS_ACTIVE_BOMB(element))
522 DrawLevelField(jx, jy);
524 /* draw player himself */
526 if (game.emulation == EMU_SUPAPLEX)
528 static int last_dir = MV_LEFT;
529 int action = (player->programmed_action ? player->programmed_action :
531 boolean action_moving =
533 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
534 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
536 graphic = GFX_SP_MURPHY;
540 if (player->MovDir == MV_LEFT)
541 graphic = GFX_MURPHY_PUSH_LEFT;
542 else if (player->MovDir == MV_RIGHT)
543 graphic = GFX_MURPHY_PUSH_RIGHT;
544 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
545 graphic = GFX_MURPHY_PUSH_LEFT;
546 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
547 graphic = GFX_MURPHY_PUSH_RIGHT;
549 else if (player->snapped)
551 if (player->MovDir == MV_LEFT)
552 graphic = GFX_MURPHY_SNAP_LEFT;
553 else if (player->MovDir == MV_RIGHT)
554 graphic = GFX_MURPHY_SNAP_RIGHT;
555 else if (player->MovDir == MV_UP)
556 graphic = GFX_MURPHY_SNAP_UP;
557 else if (player->MovDir == MV_DOWN)
558 graphic = GFX_MURPHY_SNAP_DOWN;
560 else if (action_moving)
562 if (player->MovDir == MV_LEFT)
563 graphic = GFX_MURPHY_GO_LEFT;
564 else if (player->MovDir == MV_RIGHT)
565 graphic = GFX_MURPHY_GO_RIGHT;
566 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
567 graphic = GFX_MURPHY_GO_LEFT;
568 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
569 graphic = GFX_MURPHY_GO_RIGHT;
571 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
574 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
575 last_dir = player->MovDir;
579 if (player->MovDir == MV_LEFT)
581 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
582 else if (player->MovDir == MV_RIGHT)
584 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
585 else if (player->MovDir == MV_UP)
586 graphic = GFX_SPIELER1_UP;
587 else /* MV_DOWN || MV_NO_MOVING */
588 graphic = GFX_SPIELER1_DOWN;
590 graphic += player->index_nr * 3 * HEROES_PER_LINE;
591 graphic += player->Frame;
596 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
597 sxx = player->GfxPos;
599 syy = player->GfxPos;
602 if (!setup.soft_scrolling && ScreenMovPos)
605 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
607 if (player->Pushing && player->GfxPos)
609 int px = SCREENX(next_jx), py = SCREENY(next_jy);
611 if (element == EL_SOKOBAN_FELD_LEER ||
612 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
613 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
617 int element = Feld[next_jx][next_jy];
618 int graphic = el2gfx(element);
620 if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK) && sxx)
622 int phase = (player->GfxPos / (TILEX / 4));
624 if (player->MovDir == MV_LEFT)
627 graphic += (phase + 4) % 4;
630 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
634 /* draw things in front of player (active dynamite or dynabombs) */
636 if (IS_ACTIVE_BOMB(element))
638 graphic = el2gfx(element);
640 if (element == EL_DYNAMITE_ACTIVE)
642 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
647 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
651 if (game.emulation == EMU_SUPAPLEX)
652 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
654 DrawGraphicThruMask(sx, sy, graphic + phase);
657 if (player_is_moving && last_element == EL_EXPLODING)
659 int phase = Frame[last_jx][last_jy];
663 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
664 GFX_EXPLOSION + ((phase - 1) / delay - 1));
667 /* draw elements that stay over the player */
668 /* handle the field the player is leaving ... */
669 if (player_is_moving && IS_OVER_PLAYER(last_element))
670 DrawLevelField(last_jx, last_jy);
671 /* ... and the field the player is entering */
672 if (IS_OVER_PLAYER(element))
673 DrawLevelField(jx, jy);
675 if (setup.direct_draw)
677 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
678 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
679 int x_size = TILEX * (1 + ABS(jx - last_jx));
680 int y_size = TILEY * (1 + ABS(jy - last_jy));
682 XCopyArea(display, drawto_field, window, gc,
683 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
684 SetDrawtoField(DRAW_DIRECT);
687 MarkTileDirty(sx,sy);
690 static int getGraphicAnimationPhase(int frames, int delay, int mode)
694 if (mode == ANIM_OSCILLATE)
696 int max_anim_frames = 2 * frames - 2;
697 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
698 phase = (phase < frames ? phase : max_anim_frames - phase);
701 phase = (FrameCounter % (delay * frames)) / delay;
703 if (mode == ANIM_REVERSE)
709 void DrawGraphicAnimationExt(int x, int y, int graphic,
710 int frames, int delay, int mode, int mask_mode)
712 int phase = getGraphicAnimationPhase(frames, delay, mode);
714 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
716 if (mask_mode == USE_MASKING)
717 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
719 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
723 void DrawGraphicAnimation(int x, int y, int graphic,
724 int frames, int delay, int mode)
726 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
729 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
730 int frames, int delay, int mode)
732 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
735 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
737 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
739 graphic -= GFX_START_ROCKSSCREEN;
740 *pixmap_nr = PIX_BACK;
741 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
742 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
744 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
746 graphic -= GFX_START_ROCKSMORE;
747 *pixmap_nr = PIX_MORE;
748 *x = (graphic % MORE_PER_LINE) * TILEX;
749 *y = (graphic / MORE_PER_LINE) * TILEY;
751 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
753 graphic -= GFX_START_ROCKSHEROES;
754 *pixmap_nr = PIX_HEROES;
755 *x = (graphic % HEROES_PER_LINE) * TILEX;
756 *y = (graphic / HEROES_PER_LINE) * TILEY;
758 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
760 graphic -= GFX_START_ROCKSFONT;
761 *pixmap_nr = PIX_BIGFONT;
762 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
763 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
764 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
768 *pixmap_nr = PIX_MORE;
774 void DrawGraphic(int x, int y, int graphic)
777 if (!IN_SCR_FIELD(x,y))
779 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
780 printf("DrawGraphic(): This should never happen!\n");
785 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
789 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
794 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
795 XCopyArea(display, pix[pixmap_nr], d, gc,
796 src_x, src_y, TILEX, TILEY, x, y);
799 void DrawGraphicThruMask(int x, int y, int graphic)
802 if (!IN_SCR_FIELD(x,y))
804 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
805 printf("DrawGraphicThruMask(): This should never happen!\n");
810 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
814 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
822 if (graphic == GFX_LEERRAUM)
825 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
826 src_pixmap = pix[pixmap_nr];
827 drawing_gc = clip_gc[pixmap_nr];
829 if (tile_clipmask[tile] != None)
831 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
832 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
833 XCopyArea(display, src_pixmap, d, tile_clip_gc,
834 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
839 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
842 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
843 XCopyArea(display, src_pixmap, d, drawing_gc,
844 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
848 void DrawMiniGraphic(int x, int y, int graphic)
850 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
851 MarkTileDirty(x/2, y/2);
854 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
856 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
858 graphic -= GFX_START_ROCKSSCREEN;
859 *pixmap = pix[PIX_BACK];
860 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
861 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
863 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
865 graphic -= GFX_START_ROCKSMORE;
866 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
867 *pixmap = pix[PIX_MORE];
868 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
869 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
871 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
873 graphic -= GFX_START_ROCKSFONT;
874 *pixmap = pix[PIX_SMALLFONT];
875 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
876 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
877 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
881 *pixmap = pix[PIX_MORE];
882 *x = MINI_MORE_STARTX;
883 *y = MINI_MORE_STARTY;
887 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
892 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
893 XCopyArea(display, pixmap, d, gc,
894 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
897 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
898 int cut_mode, int mask_mode)
900 int width = TILEX, height = TILEY;
902 int src_x, src_y, dest_x, dest_y;
910 DrawGraphic(x, y, graphic);
914 if (dx || dy) /* Verschiebung der Grafik? */
916 if (x < BX1) /* Element kommt von links ins Bild */
923 else if (x > BX2) /* Element kommt von rechts ins Bild */
929 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
935 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
937 else if (dx) /* allg. Bewegung in x-Richtung */
938 MarkTileDirty(x + SIGN(dx), y);
940 if (y < BY1) /* Element kommt von oben ins Bild */
942 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
950 else if (y > BY2) /* Element kommt von unten ins Bild */
956 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
962 else if (dy > 0 && cut_mode == CUT_ABOVE)
964 if (y == BY2) /* Element unterhalb des Bildes */
970 MarkTileDirty(x, y + 1);
971 } /* Element verläßt unten das Bild */
972 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
974 else if (dy) /* allg. Bewegung in y-Richtung */
975 MarkTileDirty(x, y + SIGN(dy));
978 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
979 src_pixmap = pix[pixmap_nr];
980 drawing_gc = clip_gc[pixmap_nr];
985 dest_x = FX + x * TILEX + dx;
986 dest_y = FY + y * TILEY + dy;
989 if (!IN_SCR_FIELD(x,y))
991 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
992 printf("DrawGraphicShifted(): This should never happen!\n");
997 if (mask_mode == USE_MASKING)
999 if (tile_clipmask[tile] != None)
1001 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1002 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1003 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1004 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1009 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1012 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1013 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1014 src_x, src_y, width, height, dest_x, dest_y);
1018 XCopyArea(display, src_pixmap, drawto_field, gc,
1019 src_x, src_y, width, height, dest_x, dest_y);
1024 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1027 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1030 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1031 int cut_mode, int mask_mode)
1033 int ux = LEVELX(x), uy = LEVELY(y);
1034 int graphic = el2gfx(element);
1035 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1036 int phase4 = phase8 / 2;
1037 int phase2 = phase8 / 4;
1038 int dir = MovDir[ux][uy];
1040 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1042 graphic += 4 * !phase2;
1046 else if (dir == MV_LEFT)
1048 else if (dir == MV_DOWN)
1051 else if (element == EL_SP_SNIKSNAK)
1054 graphic = GFX_SP_SNIKSNAK_LEFT;
1055 else if (dir == MV_RIGHT)
1056 graphic = GFX_SP_SNIKSNAK_RIGHT;
1057 else if (dir == MV_UP)
1058 graphic = GFX_SP_SNIKSNAK_UP;
1060 graphic = GFX_SP_SNIKSNAK_DOWN;
1062 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1064 else if (element == EL_SP_ELECTRON)
1066 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1068 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1069 element == EL_SCHWEIN || element == EL_DRACHE)
1072 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1073 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1074 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1075 else if (dir == MV_RIGHT)
1076 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1077 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1078 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1079 else if (dir == MV_UP)
1080 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1081 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1082 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1084 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1085 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1086 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1090 else if (element == EL_SONDE)
1092 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1094 else if (element == EL_SALZSAEURE)
1096 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1098 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1102 else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
1103 IS_GEM(element)) && !cut_mode)
1105 if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
1108 graphic += (4 - phase4) % 4;
1109 else if (dir == MV_RIGHT)
1112 graphic += phase2 * 2;
1114 else if (element != EL_SP_INFOTRON)
1117 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1118 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1120 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1122 else if (IS_AMOEBOID(element))
1124 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1125 graphic += (x + 2 * y + 4) % 4;
1127 else if (element == EL_MAUER_LEBT)
1129 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1131 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1132 links_massiv = TRUE;
1133 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1134 rechts_massiv = TRUE;
1136 if (links_massiv && rechts_massiv)
1137 graphic = GFX_MAUERWERK;
1138 else if (links_massiv)
1139 graphic = GFX_MAUER_R;
1140 else if (rechts_massiv)
1141 graphic = GFX_MAUER_L;
1145 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1146 else if (mask_mode == USE_MASKING)
1147 DrawGraphicThruMask(x, y, graphic);
1149 DrawGraphic(x, y, graphic);
1152 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1153 int cut_mode, int mask_mode)
1155 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1156 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1157 cut_mode, mask_mode);
1160 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1163 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1166 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1169 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1172 void DrawScreenElementThruMask(int x, int y, int element)
1174 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1177 void DrawLevelElementThruMask(int x, int y, int element)
1179 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1182 void DrawLevelFieldThruMask(int x, int y)
1184 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1187 void ErdreichAnbroeckeln(int x, int y)
1189 int i, width, height, cx,cy;
1190 int ux = LEVELX(x), uy = LEVELY(y);
1191 int element, graphic;
1193 static int xy[4][2] =
1201 if (!IN_LEV_FIELD(ux, uy))
1204 element = Feld[ux][uy];
1206 if (element == EL_ERDREICH)
1208 if (!IN_SCR_FIELD(x, y))
1211 graphic = GFX_ERDENRAND;
1217 uxx = ux + xy[i][0];
1218 uyy = uy + xy[i][1];
1219 if (!IN_LEV_FIELD(uxx, uyy))
1222 element = Feld[uxx][uyy];
1224 if (element == EL_ERDREICH)
1227 if (i == 1 || i == 2)
1231 cx = (i == 2 ? TILEX - snip : 0);
1239 cy = (i == 3 ? TILEY - snip : 0);
1242 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1243 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1244 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1245 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1248 MarkTileDirty(x, y);
1252 graphic = GFX_ERDENRAND;
1256 int xx, yy, uxx, uyy;
1260 uxx = ux + xy[i][0];
1261 uyy = uy + xy[i][1];
1263 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1264 !IN_SCR_FIELD(xx, yy))
1267 if (i == 1 || i == 2)
1271 cx = (i == 1 ? TILEX - snip : 0);
1279 cy = (i==0 ? TILEY-snip : 0);
1282 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1283 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1284 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1285 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1287 MarkTileDirty(xx, yy);
1292 void DrawScreenElement(int x, int y, int element)
1294 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1295 ErdreichAnbroeckeln(x, y);
1298 void DrawLevelElement(int x, int y, int element)
1300 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1301 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1304 void DrawScreenField(int x, int y)
1306 int ux = LEVELX(x), uy = LEVELY(y);
1309 if (!IN_LEV_FIELD(ux, uy))
1311 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1312 element = EL_LEERRAUM;
1314 element = BorderElement;
1316 DrawScreenElement(x, y, element);
1320 element = Feld[ux][uy];
1322 if (IS_MOVING(ux, uy))
1324 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1325 boolean cut_mode = NO_CUTTING;
1327 if (Store[ux][uy] == EL_MORAST_LEER ||
1328 Store[ux][uy] == EL_SIEB_LEER ||
1329 Store[ux][uy] == EL_SIEB2_LEER ||
1330 Store[ux][uy] == EL_AMOEBE_NASS)
1331 cut_mode = CUT_ABOVE;
1332 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1333 Store[ux][uy] == EL_SIEB_VOLL ||
1334 Store[ux][uy] == EL_SIEB2_VOLL)
1335 cut_mode = CUT_BELOW;
1337 if (cut_mode == CUT_ABOVE)
1338 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1340 DrawScreenElement(x, y, EL_LEERRAUM);
1343 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1345 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1347 if (Store[ux][uy] == EL_SALZSAEURE)
1348 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1350 else if (IS_BLOCKED(ux, uy))
1355 boolean cut_mode = NO_CUTTING;
1357 Blocked2Moving(ux, uy, &oldx, &oldy);
1360 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1361 MovDir[oldx][oldy] == MV_RIGHT);
1363 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1364 Store[oldx][oldy] == EL_SIEB_LEER ||
1365 Store[oldx][oldy] == EL_SIEB2_LEER ||
1366 Store[oldx][oldy] == EL_AMOEBE_NASS)
1367 cut_mode = CUT_ABOVE;
1369 DrawScreenElement(x, y, EL_LEERRAUM);
1370 element = Feld[oldx][oldy];
1373 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1375 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1377 else if (IS_DRAWABLE(element))
1378 DrawScreenElement(x, y, element);
1380 DrawScreenElement(x, y, EL_LEERRAUM);
1383 void DrawLevelField(int x, int y)
1385 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1386 DrawScreenField(SCREENX(x), SCREENY(y));
1387 else if (IS_MOVING(x, y))
1391 Moving2Blocked(x, y, &newx, &newy);
1392 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1393 DrawScreenField(SCREENX(newx), SCREENY(newy));
1395 else if (IS_BLOCKED(x, y))
1399 Blocked2Moving(x, y, &oldx, &oldy);
1400 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1401 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1405 void DrawMiniElement(int x, int y, int element)
1411 DrawMiniGraphic(x, y, -1);
1415 graphic = el2gfx(element);
1416 DrawMiniGraphic(x, y, graphic);
1419 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1421 int x = sx + scroll_x, y = sy + scroll_y;
1423 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1424 DrawMiniElement(sx, sy, EL_LEERRAUM);
1425 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1426 DrawMiniElement(sx, sy, Feld[x][y]);
1429 int steel_type, steel_position;
1432 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1433 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1434 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1435 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1436 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1437 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1440 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1441 steel_position = (x == -1 && y == -1 ? 0 :
1442 x == lev_fieldx && y == -1 ? 1 :
1443 x == -1 && y == lev_fieldy ? 2 :
1444 x == lev_fieldx && y == lev_fieldy ? 3 :
1445 x == -1 || x == lev_fieldx ? 4 :
1446 y == -1 || y == lev_fieldy ? 5 : -1);
1448 if (steel_position != -1)
1449 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1453 void DrawMicroElement(int xpos, int ypos, int element)
1457 if (element == EL_LEERRAUM)
1460 graphic = el2gfx(element);
1462 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1464 graphic -= GFX_START_ROCKSMORE;
1465 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
1466 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1467 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1468 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1469 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1472 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1473 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1474 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1475 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1484 for(x=BX1; x<=BX2; x++)
1485 for(y=BY1; y<=BY2; y++)
1486 DrawScreenField(x, y);
1488 redraw_mask |= REDRAW_FIELD;
1491 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1495 for(x=0; x<size_x; x++)
1496 for(y=0; y<size_y; y++)
1497 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1499 redraw_mask |= REDRAW_FIELD;
1502 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1506 XFillRectangle(display, drawto, gc,
1507 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1509 if (lev_fieldx < STD_LEV_FIELDX)
1510 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1511 if (lev_fieldy < STD_LEV_FIELDY)
1512 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1514 xpos += MICRO_TILEX;
1515 ypos += MICRO_TILEY;
1517 for(x=-1; x<=STD_LEV_FIELDX; x++)
1519 for(y=-1; y<=STD_LEV_FIELDY; y++)
1521 int lx = from_x + x, ly = from_y + y;
1523 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1524 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1526 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1527 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1532 redraw_mask |= REDRAW_MICROLEVEL;
1535 static void DrawMicroLevelLabelExt(int mode)
1537 char label_text[100];
1539 XFillRectangle(display, drawto,gc,
1540 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1542 strcpy(label_text, (mode == 1 ? level.name :
1543 mode == 2 ? "created by" :
1544 mode == 3 ? level.author : ""));
1546 if (strlen(label_text) > 0)
1548 int size, lxpos, lypos;
1550 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1552 size = strlen(label_text);
1553 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1554 lypos = MICROLABEL_YPOS;
1556 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1559 redraw_mask |= REDRAW_MICROLEVEL;
1562 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1564 static unsigned long scroll_delay = 0;
1565 static unsigned long label_delay = 0;
1566 static int from_x, from_y, scroll_direction;
1567 static int label_state, label_counter;
1571 from_x = from_y = 0;
1572 scroll_direction = MV_RIGHT;
1576 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1577 DrawMicroLevelLabelExt(label_state);
1579 /* initialize delay counters */
1580 DelayReached(&scroll_delay, 0);
1581 DelayReached(&label_delay, 0);
1586 /* scroll micro level, if needed */
1587 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1588 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1590 switch (scroll_direction)
1596 scroll_direction = MV_UP;
1600 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1603 scroll_direction = MV_DOWN;
1610 scroll_direction = MV_RIGHT;
1614 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1617 scroll_direction = MV_LEFT;
1624 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1627 /* redraw micro level label, if needed */
1628 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1629 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1630 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1631 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1633 label_counter = (label_counter + 1) % 23;
1634 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1635 label_counter >= 9 && label_counter <= 12 ? 2 :
1636 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1637 DrawMicroLevelLabelExt(label_state);
1641 int REQ_in_range(int x, int y)
1643 if (y > DY+249 && y < DY+278)
1645 if (x > DX+1 && x < DX+48)
1647 else if (x > DX+51 && x < DX+98)
1653 boolean Request(char *text, unsigned int req_state)
1655 int mx, my, ty, result = -1;
1656 unsigned int old_door_state;
1659 /* pause network game while waiting for request to answer */
1660 if (options.network &&
1661 game_status == PLAYING &&
1662 req_state & REQUEST_WAIT_FOR)
1663 SendToServer_PausePlaying();
1666 old_door_state = GetDoorState();
1670 CloseDoor(DOOR_CLOSE_1);
1672 /* save old door content */
1673 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1674 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1675 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1677 /* clear door drawing field */
1678 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1680 /* write text for request */
1681 for(ty=0; ty<13; ty++)
1689 for(tl=0,tx=0; tx<7; tl++,tx++)
1692 if (!tc || tc == 32)
1703 DrawTextExt(drawto, gc,
1704 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1705 txt, FS_SMALL, FC_YELLOW);
1706 text += tl + (tc == 32 ? 1 : 0);
1709 if (req_state & REQ_ASK)
1711 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1712 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1714 else if (req_state & REQ_CONFIRM)
1716 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1718 else if (req_state & REQ_PLAYER)
1720 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1721 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1722 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1723 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1726 /* copy request gadgets to door backbuffer */
1727 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1728 DX, DY, DXSIZE, DYSIZE,
1729 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1731 OpenDoor(DOOR_OPEN_1);
1737 if (!(req_state & REQUEST_WAIT_FOR))
1740 if (game_status != MAINMENU)
1743 button_status = MB_RELEASED;
1745 request_gadget_id = -1;
1749 if (XPending(display))
1753 XNextEvent(display, &event);
1761 if (event.type == MotionNotify)
1768 if (!XQueryPointer(display, window, &root, &child,
1769 &root_x, &root_y, &win_x, &win_y, &mask))
1775 motion_status = TRUE;
1776 mx = ((XMotionEvent *) &event)->x;
1777 my = ((XMotionEvent *) &event)->y;
1781 motion_status = FALSE;
1782 mx = ((XButtonEvent *) &event)->x;
1783 my = ((XButtonEvent *) &event)->y;
1784 if (event.type==ButtonPress)
1785 button_status = ((XButtonEvent *) &event)->button;
1787 button_status = MB_RELEASED;
1790 /* this sets 'request_gadget_id' */
1791 HandleGadgets(mx, my, button_status);
1793 switch(request_gadget_id)
1795 case TOOL_CTRL_ID_YES:
1798 case TOOL_CTRL_ID_NO:
1801 case TOOL_CTRL_ID_CONFIRM:
1802 result = TRUE | FALSE;
1805 case TOOL_CTRL_ID_PLAYER_1:
1808 case TOOL_CTRL_ID_PLAYER_2:
1811 case TOOL_CTRL_ID_PLAYER_3:
1814 case TOOL_CTRL_ID_PLAYER_4:
1826 switch(XLookupKeysym((XKeyEvent *)&event,
1827 ((XKeyEvent *)&event)->state))
1840 if (req_state & REQ_PLAYER)
1845 key_joystick_mapping = 0;
1849 HandleOtherEvents(&event);
1853 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1855 int joy = AnyJoystick();
1857 if (joy & JOY_BUTTON_1)
1859 else if (joy & JOY_BUTTON_2)
1865 /* don't eat all CPU time */
1869 if (game_status != MAINMENU)
1874 if (!(req_state & REQ_STAY_OPEN))
1876 CloseDoor(DOOR_CLOSE_1);
1878 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1880 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1881 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1882 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1883 OpenDoor(DOOR_OPEN_1);
1890 /* continue network game after request */
1891 if (options.network &&
1892 game_status == PLAYING &&
1893 req_state & REQUEST_WAIT_FOR)
1894 SendToServer_ContinuePlaying();
1900 unsigned int OpenDoor(unsigned int door_state)
1902 unsigned int new_door_state;
1904 if (door_state & DOOR_COPY_BACK)
1906 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1907 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1908 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1909 door_state &= ~DOOR_COPY_BACK;
1912 new_door_state = MoveDoor(door_state);
1914 return(new_door_state);
1917 unsigned int CloseDoor(unsigned int door_state)
1919 unsigned int new_door_state;
1921 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1922 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1923 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1924 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1926 new_door_state = MoveDoor(door_state);
1928 return(new_door_state);
1931 unsigned int GetDoorState()
1933 return(MoveDoor(DOOR_GET_STATE));
1936 unsigned int MoveDoor(unsigned int door_state)
1938 static int door1 = DOOR_OPEN_1;
1939 static int door2 = DOOR_CLOSE_2;
1940 static unsigned long door_delay = 0;
1941 int x, start, stepsize = 2;
1942 unsigned long door_delay_value = stepsize * 5;
1944 if (door_state == DOOR_GET_STATE)
1945 return(door1 | door2);
1947 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1948 door_state &= ~DOOR_OPEN_1;
1949 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1950 door_state &= ~DOOR_CLOSE_1;
1951 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1952 door_state &= ~DOOR_OPEN_2;
1953 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1954 door_state &= ~DOOR_CLOSE_2;
1956 if (setup.quick_doors)
1959 door_delay_value = 0;
1960 StopSound(SND_OEFFNEN);
1963 if (door_state & DOOR_ACTION)
1965 if (!(door_state & DOOR_NO_DELAY))
1966 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1968 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1970 for(x=start; x<=DXSIZE; x+=stepsize)
1972 WaitUntilDelayReached(&door_delay, door_delay_value);
1974 if (door_state & DOOR_ACTION_1)
1976 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1977 int j = (DXSIZE - i) / 3;
1979 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1980 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1981 DXSIZE,DYSIZE - i/2, DX, DY);
1983 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1985 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1986 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1987 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1988 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1989 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1990 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1992 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1993 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1994 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1995 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1996 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1997 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1999 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2000 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2002 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2003 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2005 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2006 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2007 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2008 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2009 DX + DXSIZE - i, DY + 77 + j);
2010 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2011 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2012 DX + DXSIZE - i, DY + 203 + j);
2014 redraw_mask |= REDRAW_DOOR_1;
2017 if (door_state & DOOR_ACTION_2)
2019 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2020 int j = (VXSIZE - i) / 3;
2022 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2023 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2024 VXSIZE, VYSIZE - i/2, VX, VY);
2026 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2028 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2029 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2030 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2031 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2032 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2033 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2034 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2035 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2037 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2038 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2039 VX, VY + VYSIZE / 2 - j);
2040 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2041 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2042 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2043 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2044 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2046 redraw_mask |= REDRAW_DOOR_2;
2051 if (game_status == MAINMENU)
2056 if (setup.quick_doors)
2057 StopSound(SND_OEFFNEN);
2059 if (door_state & DOOR_ACTION_1)
2060 door1 = door_state & DOOR_ACTION_1;
2061 if (door_state & DOOR_ACTION_2)
2062 door2 = door_state & DOOR_ACTION_2;
2064 return (door1 | door2);
2067 void DrawSpecialEditorDoor()
2069 /* draw bigger toolbox window */
2070 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2071 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2073 redraw_mask |= REDRAW_ALL;
2076 void UndrawSpecialEditorDoor()
2078 /* draw normal tape recorder window */
2079 XCopyArea(display, pix[PIX_BACK], drawto, gc,
2080 562, 344, 108, 56, EX - 4, EY - 12);
2082 redraw_mask |= REDRAW_ALL;
2085 int ReadPixel(Drawable d, int x, int y)
2087 XImage *pixel_image;
2088 unsigned long pixel_value;
2090 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2091 pixel_value = XGetPixel(pixel_image, 0, 0);
2093 XDestroyImage(pixel_image);
2098 /* ---------- new tool button stuff ---------------------------------------- */
2100 /* graphic position values for tool buttons */
2101 #define TOOL_BUTTON_YES_XPOS 2
2102 #define TOOL_BUTTON_YES_YPOS 250
2103 #define TOOL_BUTTON_YES_GFX_YPOS 0
2104 #define TOOL_BUTTON_YES_XSIZE 46
2105 #define TOOL_BUTTON_YES_YSIZE 28
2106 #define TOOL_BUTTON_NO_XPOS 52
2107 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2108 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2109 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2110 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2111 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2112 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2113 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2114 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2115 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2116 #define TOOL_BUTTON_PLAYER_XSIZE 30
2117 #define TOOL_BUTTON_PLAYER_YSIZE 30
2118 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2119 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2120 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2121 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2122 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2123 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2124 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2125 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2126 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2127 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2128 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2129 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2130 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2131 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2132 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2133 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2134 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2135 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2136 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2137 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2146 } toolbutton_info[NUM_TOOL_BUTTONS] =
2149 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2150 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2151 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2156 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2157 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2158 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2163 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2164 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2165 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2166 TOOL_CTRL_ID_CONFIRM,
2170 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2171 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2172 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2173 TOOL_CTRL_ID_PLAYER_1,
2177 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2178 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2179 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2180 TOOL_CTRL_ID_PLAYER_2,
2184 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2185 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2186 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2187 TOOL_CTRL_ID_PLAYER_3,
2191 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2192 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2193 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2194 TOOL_CTRL_ID_PLAYER_4,
2199 static void DoNotDisplayInfoText(void *ptr)
2204 void CreateToolButtons()
2208 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2210 Pixmap gd_pixmap = pix[PIX_DOOR];
2211 Pixmap deco_pixmap = None;
2212 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2213 struct GadgetInfo *gi;
2214 unsigned long event_mask;
2215 int gd_xoffset, gd_yoffset;
2216 int gd_x1, gd_x2, gd_y;
2219 event_mask = GD_EVENT_RELEASED;
2221 gd_xoffset = toolbutton_info[i].xpos;
2222 gd_yoffset = toolbutton_info[i].ypos;
2223 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2224 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2225 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2227 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2229 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2230 &deco_pixmap, &deco_x, &deco_y);
2231 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2232 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2235 gi = CreateGadget(GDI_CUSTOM_ID, id,
2236 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2237 GDI_X, DX + toolbutton_info[i].x,
2238 GDI_Y, DY + toolbutton_info[i].y,
2239 GDI_WIDTH, toolbutton_info[i].width,
2240 GDI_HEIGHT, toolbutton_info[i].height,
2241 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2242 GDI_STATE, GD_BUTTON_UNPRESSED,
2243 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2244 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2245 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2246 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2247 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2248 GDI_DECORATION_SHIFTING, 1, 1,
2249 GDI_EVENT_MASK, event_mask,
2250 GDI_CALLBACK_ACTION, HandleToolButtons,
2251 GDI_CALLBACK_INFO, DoNotDisplayInfoText,
2255 Error(ERR_EXIT, "cannot create gadget");
2257 tool_gadget[id] = gi;
2261 static void UnmapToolButtons()
2265 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2266 UnmapGadget(tool_gadget[i]);
2269 static void HandleToolButtons(struct GadgetInfo *gi)
2271 request_gadget_id = gi->custom_id;
2274 int el2gfx(int element)
2278 case EL_LEERRAUM: return -1;
2279 case EL_ERDREICH: return GFX_ERDREICH;
2280 case EL_MAUERWERK: return GFX_MAUERWERK;
2281 case EL_FELSBODEN: return GFX_FELSBODEN;
2282 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2283 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2284 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2285 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2286 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2287 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2288 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2289 case EL_SPIELER1: return GFX_SPIELER1;
2290 case EL_SPIELER2: return GFX_SPIELER2;
2291 case EL_SPIELER3: return GFX_SPIELER3;
2292 case EL_SPIELER4: return GFX_SPIELER4;
2293 case EL_KAEFER: return GFX_KAEFER;
2294 case EL_KAEFER_R: return GFX_KAEFER_R;
2295 case EL_KAEFER_O: return GFX_KAEFER_O;
2296 case EL_KAEFER_L: return GFX_KAEFER_L;
2297 case EL_KAEFER_U: return GFX_KAEFER_U;
2298 case EL_FLIEGER: return GFX_FLIEGER;
2299 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2300 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2301 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2302 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2303 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2304 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2305 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2306 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2307 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2308 case EL_FIREFLY: return GFX_FIREFLY;
2309 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2310 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2311 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2312 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2313 case EL_MAMPFER: return GFX_MAMPFER;
2314 case EL_ROBOT: return GFX_ROBOT;
2315 case EL_BETON: return GFX_BETON;
2316 case EL_DIAMANT: return GFX_DIAMANT;
2317 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2318 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2319 case EL_TROPFEN: return GFX_TROPFEN;
2320 case EL_BOMBE: return GFX_BOMBE;
2321 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2322 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2323 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2324 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2325 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2326 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2327 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2328 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2329 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2330 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2331 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2332 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2333 case EL_LIFE: return GFX_LIFE;
2334 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2335 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2336 case EL_BADEWANNE: return GFX_BADEWANNE;
2337 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2338 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2339 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2340 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2341 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2342 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2343 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2344 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2345 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2346 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2347 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2348 case EL_PFORTE1: return GFX_PFORTE1;
2349 case EL_PFORTE2: return GFX_PFORTE2;
2350 case EL_PFORTE3: return GFX_PFORTE3;
2351 case EL_PFORTE4: return GFX_PFORTE4;
2352 case EL_PFORTE1X: return GFX_PFORTE1X;
2353 case EL_PFORTE2X: return GFX_PFORTE2X;
2354 case EL_PFORTE3X: return GFX_PFORTE3X;
2355 case EL_PFORTE4X: return GFX_PFORTE4X;
2356 case EL_DYNAMITE_INACTIVE: return GFX_DYNAMIT_AUS;
2357 case EL_PACMAN: return GFX_PACMAN;
2358 case EL_PACMAN_R: return GFX_PACMAN_R;
2359 case EL_PACMAN_O: return GFX_PACMAN_O;
2360 case EL_PACMAN_L: return GFX_PACMAN_L;
2361 case EL_PACMAN_U: return GFX_PACMAN_U;
2362 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2363 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2364 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2365 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2366 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2367 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2368 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2369 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2370 case EL_MAUER_X: return GFX_MAUER_X;
2371 case EL_MAUER_Y: return GFX_MAUER_Y;
2372 case EL_MAUER_XY: return GFX_MAUER_XY;
2373 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2374 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2375 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2376 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2377 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2378 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2379 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2380 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2381 case EL_MAMPFER2: return GFX_MAMPFER2;
2382 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2383 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2384 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2385 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2386 case EL_DYNABOMB_ACTIVE_1: return GFX_DYNABOMB;
2387 case EL_DYNABOMB_ACTIVE_2: return GFX_DYNABOMB;
2388 case EL_DYNABOMB_ACTIVE_3: return GFX_DYNABOMB;
2389 case EL_DYNABOMB_ACTIVE_4: return GFX_DYNABOMB;
2390 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2391 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2392 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2393 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2394 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2395 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2396 case EL_MAULWURF: return GFX_MAULWURF;
2397 case EL_PINGUIN: return GFX_PINGUIN;
2398 case EL_SCHWEIN: return GFX_SCHWEIN;
2399 case EL_DRACHE: return GFX_DRACHE;
2400 case EL_SONDE: return GFX_SONDE;
2401 case EL_PFEIL_L: return GFX_PFEIL_L;
2402 case EL_PFEIL_R: return GFX_PFEIL_R;
2403 case EL_PFEIL_O: return GFX_PFEIL_O;
2404 case EL_PFEIL_U: return GFX_PFEIL_U;
2405 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2406 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2407 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2408 case EL_SP_ZONK: return GFX_SP_ZONK;
2409 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2410 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2411 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2412 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2413 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2414 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2415 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2416 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2417 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2418 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2419 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2420 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2421 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2422 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2423 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2424 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2425 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2426 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2427 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2431 if (IS_CHAR(element))
2432 return GFX_CHAR_START + (element - EL_CHAR_START);
2433 else if (element >= EL_SP_START && element <= EL_SP_END)
2435 int nr_element = element - EL_SP_START;
2436 int gfx_per_line = 8;
2438 (nr_element / gfx_per_line) * MORE_PER_LINE +
2439 (nr_element % gfx_per_line);
2441 return GFX_START_ROCKSMORE + nr_graphic;