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 void DrawTextFCentered(int y, int font_type, char *format, ...)
319 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
323 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
324 font_type < FC_SPECIAL2 ? FONT3_XSIZE :
325 font_type < FC_SPECIAL3 ? FONT4_XSIZE :
328 va_start(ap, format);
329 vsprintf(buffer, format, ap);
332 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
333 buffer, FS_SMALL, font_type);
336 void DrawTextF(int x, int y, int font_type, char *format, ...)
338 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
341 va_start(ap, format);
342 vsprintf(buffer, format, ap);
345 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
348 void DrawText(int x, int y, char *text, int font_size, int font_type)
350 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
353 redraw_mask |= REDRAW_FIELD;
355 redraw_mask |= REDRAW_DOOR_1;
358 void DrawTextExt(Drawable d, GC gc, int x, int y,
359 char *text, int font_size, int font_type)
361 int font_width, font_height, font_start;
363 boolean print_inverse = FALSE;
365 if (font_size != FS_SMALL && font_size != FS_BIG)
366 font_size = FS_SMALL;
367 if (font_type < FC_RED || font_type > FC_SPECIAL3)
370 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
371 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
372 font_type < FC_SPECIAL2 ? FONT3_XSIZE :
373 font_type < FC_SPECIAL3 ? FONT4_XSIZE :
375 font_height = (font_size == FS_BIG ? FONT1_YSIZE :
376 font_type < FC_SPECIAL1 ? FONT2_YSIZE :
377 font_type < FC_SPECIAL2 ? FONT3_YSIZE :
378 font_type < FC_SPECIAL3 ? FONT4_YSIZE :
380 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
381 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
382 FONT_LINES_PER_FONT);
384 if (font_type == FC_SPECIAL3)
385 font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT + 3;
391 if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
393 print_inverse = TRUE;
397 if (c >= 'a' && c <= 'z')
399 else if (c == 'ä' || c == 'Ä')
401 else if (c == 'ö' || c == 'Ö')
403 else if (c == 'ü' || c == 'Ü')
406 if (c >= 32 && c <= 95)
408 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
409 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
410 int dest_x = x, dest_y = y;
414 XCopyArea(display, pix[font_pixmap], d, gc,
415 FONT_CHARS_PER_LINE * font_width,
416 3 * font_height + font_start,
417 font_width, font_height, x, y);
419 XSetClipOrigin(display, clip_gc[font_pixmap],
420 dest_x - src_x, dest_y - src_y);
421 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
422 0, 0, font_width, font_height, dest_x, dest_y);
425 XCopyArea(display, pix[font_pixmap], d, gc,
426 src_x, src_y, font_width, font_height, dest_x, dest_y);
433 void DrawAllPlayers()
437 for(i=0; i<MAX_PLAYERS; i++)
438 if (stored_player[i].active)
439 DrawPlayer(&stored_player[i]);
442 void DrawPlayerField(int x, int y)
444 if (!IS_PLAYER(x, y))
447 DrawPlayer(PLAYERINFO(x, y));
450 void DrawPlayer(struct PlayerInfo *player)
452 int jx = player->jx, jy = player->jy;
453 int last_jx = player->last_jx, last_jy = player->last_jy;
454 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
455 int sx = SCREENX(jx), sy = SCREENY(jy);
456 int sxx = 0, syy = 0;
457 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
459 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
461 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
465 if (!IN_LEV_FIELD(jx,jy))
467 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
468 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
469 printf("DrawPlayerField(): This should never happen!\n");
474 if (element == EL_EXPLODING)
477 /* draw things in the field the player is leaving, if needed */
479 if (player_is_moving)
481 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
483 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
484 DrawLevelFieldThruMask(last_jx, last_jy);
486 else if (last_element == EL_DYNAMIT)
487 DrawDynamite(last_jx, last_jy);
489 DrawLevelField(last_jx, last_jy);
491 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
495 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
496 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
498 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
501 DrawLevelField(next_jx, next_jy);
505 if (!IN_SCR_FIELD(sx, sy))
508 if (setup.direct_draw)
509 SetDrawtoField(DRAW_BUFFERED);
511 /* draw things behind the player, if needed */
514 DrawLevelElement(jx, jy, Store[jx][jy]);
515 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
516 DrawLevelField(jx, jy);
518 /* draw player himself */
520 if (game.emulation == EMU_SUPAPLEX)
522 static int last_dir = MV_LEFT;
523 int action = (player->programmed_action ? player->programmed_action :
525 boolean action_moving =
527 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
528 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
530 graphic = GFX_SP_MURPHY;
534 if (player->MovDir == MV_LEFT)
535 graphic = GFX_MURPHY_PUSH_LEFT;
536 else if (player->MovDir == MV_RIGHT)
537 graphic = GFX_MURPHY_PUSH_RIGHT;
538 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
539 graphic = GFX_MURPHY_PUSH_LEFT;
540 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
541 graphic = GFX_MURPHY_PUSH_RIGHT;
543 else if (player->snapped)
545 if (player->MovDir == MV_LEFT)
546 graphic = GFX_MURPHY_SNAP_LEFT;
547 else if (player->MovDir == MV_RIGHT)
548 graphic = GFX_MURPHY_SNAP_RIGHT;
549 else if (player->MovDir == MV_UP)
550 graphic = GFX_MURPHY_SNAP_UP;
551 else if (player->MovDir == MV_DOWN)
552 graphic = GFX_MURPHY_SNAP_DOWN;
554 else if (action_moving)
556 if (player->MovDir == MV_LEFT)
557 graphic = GFX_MURPHY_GO_LEFT;
558 else if (player->MovDir == MV_RIGHT)
559 graphic = GFX_MURPHY_GO_RIGHT;
560 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
561 graphic = GFX_MURPHY_GO_LEFT;
562 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
563 graphic = GFX_MURPHY_GO_RIGHT;
565 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
568 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
569 last_dir = player->MovDir;
573 if (player->MovDir == MV_LEFT)
575 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
576 else if (player->MovDir == MV_RIGHT)
578 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
579 else if (player->MovDir == MV_UP)
580 graphic = GFX_SPIELER1_UP;
581 else /* MV_DOWN || MV_NO_MOVING */
582 graphic = GFX_SPIELER1_DOWN;
584 graphic += player->index_nr * 3 * HEROES_PER_LINE;
585 graphic += player->Frame;
590 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
591 sxx = player->GfxPos;
593 syy = player->GfxPos;
596 if (!setup.soft_scrolling && ScreenMovPos)
599 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
601 if (player->Pushing && player->GfxPos)
603 int px = SCREENX(next_jx), py = SCREENY(next_jy);
605 if (element == EL_SOKOBAN_FELD_LEER ||
606 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
607 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
611 int element = Feld[next_jx][next_jy];
612 int graphic = el2gfx(element);
614 if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK) && sxx)
616 int phase = (player->GfxPos / (TILEX / 4));
618 if (player->MovDir == MV_LEFT)
621 graphic += (phase + 4) % 4;
624 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
628 /* draw things in front of player (EL_DYNAMIT or EL_DYNABOMB) */
630 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
632 graphic = el2gfx(element);
634 if (element == EL_DYNAMIT)
636 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
641 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
645 if (game.emulation == EMU_SUPAPLEX)
646 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
648 DrawGraphicThruMask(sx, sy, graphic + phase);
651 if (player_is_moving && last_element == EL_EXPLODING)
653 int phase = Frame[last_jx][last_jy];
657 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
658 GFX_EXPLOSION + ((phase - 1) / delay - 1));
661 /* draw elements that stay over the player */
662 /* handle the field the player is leaving ... */
663 if (player_is_moving && IS_OVER_PLAYER(last_element))
664 DrawLevelField(last_jx, last_jy);
665 /* ... and the field the player is entering */
666 if (IS_OVER_PLAYER(element))
667 DrawLevelField(jx, jy);
669 if (setup.direct_draw)
671 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
672 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
673 int x_size = TILEX * (1 + ABS(jx - last_jx));
674 int y_size = TILEY * (1 + ABS(jy - last_jy));
676 XCopyArea(display, drawto_field, window, gc,
677 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
678 SetDrawtoField(DRAW_DIRECT);
681 MarkTileDirty(sx,sy);
684 static int getGraphicAnimationPhase(int frames, int delay, int mode)
688 if (mode == ANIM_OSCILLATE)
690 int max_anim_frames = 2 * frames - 2;
691 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
692 phase = (phase < frames ? phase : max_anim_frames - phase);
695 phase = (FrameCounter % (delay * frames)) / delay;
697 if (mode == ANIM_REVERSE)
703 void DrawGraphicAnimationExt(int x, int y, int graphic,
704 int frames, int delay, int mode, int mask_mode)
706 int phase = getGraphicAnimationPhase(frames, delay, mode);
708 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
710 if (mask_mode == USE_MASKING)
711 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
713 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
717 void DrawGraphicAnimation(int x, int y, int graphic,
718 int frames, int delay, int mode)
720 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
723 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
724 int frames, int delay, int mode)
726 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
729 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
731 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
733 graphic -= GFX_START_ROCKSSCREEN;
734 *pixmap_nr = PIX_BACK;
735 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
736 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
738 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
740 graphic -= GFX_START_ROCKSMORE;
741 *pixmap_nr = PIX_MORE;
742 *x = (graphic % MORE_PER_LINE) * TILEX;
743 *y = (graphic / MORE_PER_LINE) * TILEY;
745 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
747 graphic -= GFX_START_ROCKSHEROES;
748 *pixmap_nr = PIX_HEROES;
749 *x = (graphic % HEROES_PER_LINE) * TILEX;
750 *y = (graphic / HEROES_PER_LINE) * TILEY;
752 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
754 graphic -= GFX_START_ROCKSFONT;
755 *pixmap_nr = PIX_BIGFONT;
756 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
757 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
758 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
762 *pixmap_nr = PIX_MORE;
768 void DrawGraphic(int x, int y, int graphic)
771 if (!IN_SCR_FIELD(x,y))
773 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
774 printf("DrawGraphic(): This should never happen!\n");
779 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
783 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
788 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
789 XCopyArea(display, pix[pixmap_nr], d, gc,
790 src_x, src_y, TILEX, TILEY, x, y);
793 void DrawGraphicThruMask(int x, int y, int graphic)
796 if (!IN_SCR_FIELD(x,y))
798 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
799 printf("DrawGraphicThruMask(): This should never happen!\n");
804 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
808 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
816 if (graphic == GFX_LEERRAUM)
819 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
820 src_pixmap = pix[pixmap_nr];
821 drawing_gc = clip_gc[pixmap_nr];
823 if (tile_clipmask[tile] != None)
825 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
826 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
827 XCopyArea(display, src_pixmap, d, tile_clip_gc,
828 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
833 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
836 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
837 XCopyArea(display, src_pixmap, d, drawing_gc,
838 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
842 void DrawMiniGraphic(int x, int y, int graphic)
844 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
845 MarkTileDirty(x/2, y/2);
848 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
850 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
852 graphic -= GFX_START_ROCKSSCREEN;
853 *pixmap = pix[PIX_BACK];
854 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
855 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
857 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
859 graphic -= GFX_START_ROCKSMORE;
860 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
861 *pixmap = pix[PIX_MORE];
862 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
863 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
865 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
867 graphic -= GFX_START_ROCKSFONT;
868 *pixmap = pix[PIX_SMALLFONT];
869 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
870 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
871 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
875 *pixmap = pix[PIX_MORE];
876 *x = MINI_MORE_STARTX;
877 *y = MINI_MORE_STARTY;
881 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
886 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
887 XCopyArea(display, pixmap, d, gc,
888 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
891 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
892 int cut_mode, int mask_mode)
894 int width = TILEX, height = TILEY;
896 int src_x, src_y, dest_x, dest_y;
904 DrawGraphic(x, y, graphic);
908 if (dx || dy) /* Verschiebung der Grafik? */
910 if (x < BX1) /* Element kommt von links ins Bild */
917 else if (x > BX2) /* Element kommt von rechts ins Bild */
923 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
929 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
931 else if (dx) /* allg. Bewegung in x-Richtung */
932 MarkTileDirty(x + SIGN(dx), y);
934 if (y < BY1) /* Element kommt von oben ins Bild */
936 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
944 else if (y > BY2) /* Element kommt von unten ins Bild */
950 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
956 else if (dy > 0 && cut_mode == CUT_ABOVE)
958 if (y == BY2) /* Element unterhalb des Bildes */
964 MarkTileDirty(x, y + 1);
965 } /* Element verläßt unten das Bild */
966 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
968 else if (dy) /* allg. Bewegung in y-Richtung */
969 MarkTileDirty(x, y + SIGN(dy));
972 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
973 src_pixmap = pix[pixmap_nr];
974 drawing_gc = clip_gc[pixmap_nr];
976 dest_x = FX + x * TILEX + dx;
977 dest_y = FY + y * TILEY + dy;
980 if (!IN_SCR_FIELD(x,y))
982 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
983 printf("DrawGraphicShifted(): This should never happen!\n");
988 if (mask_mode == USE_MASKING)
990 if (tile_clipmask[tile] != None)
992 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
993 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
994 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
995 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1000 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1003 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1004 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1005 src_x, src_y, width, height, dest_x, dest_y);
1009 XCopyArea(display, src_pixmap, drawto_field, gc,
1010 src_x, src_y, width, height, dest_x, dest_y);
1015 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1018 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1021 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1022 int cut_mode, int mask_mode)
1024 int ux = LEVELX(x), uy = LEVELY(y);
1025 int graphic = el2gfx(element);
1026 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1027 int phase4 = phase8 / 2;
1028 int phase2 = phase8 / 4;
1029 int dir = MovDir[ux][uy];
1031 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1033 graphic += 4 * !phase2;
1037 else if (dir == MV_LEFT)
1039 else if (dir == MV_DOWN)
1042 else if (element == EL_SP_SNIKSNAK)
1045 graphic = GFX_SP_SNIKSNAK_LEFT;
1046 else if (dir == MV_RIGHT)
1047 graphic = GFX_SP_SNIKSNAK_RIGHT;
1048 else if (dir == MV_UP)
1049 graphic = GFX_SP_SNIKSNAK_UP;
1051 graphic = GFX_SP_SNIKSNAK_DOWN;
1053 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1055 else if (element == EL_SP_ELECTRON)
1057 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1059 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1060 element == EL_SCHWEIN || element == EL_DRACHE)
1063 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1064 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1065 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1066 else if (dir == MV_RIGHT)
1067 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1068 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1069 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1070 else if (dir == MV_UP)
1071 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1072 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1073 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1075 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1076 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1077 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1081 else if (element == EL_SONDE)
1083 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1085 else if (element == EL_SALZSAEURE)
1087 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1089 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1093 else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
1094 IS_GEM(element)) && !cut_mode)
1096 if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
1099 graphic += (4 - phase4) % 4;
1100 else if (dir == MV_RIGHT)
1103 graphic += phase2 * 2;
1105 else if (element != EL_SP_INFOTRON)
1109 if (element == EL_SP_ZONK)
1112 graphic += (4 - phase4) % 4;
1113 else if (dir == MV_RIGHT)
1116 graphic += phase2 * 2;
1118 else if (element != EL_SP_INFOTRON)
1119 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1123 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1124 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1126 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1128 else if (IS_AMOEBOID(element))
1130 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1131 graphic += (x + 2 * y + 4) % 4;
1133 else if (element == EL_MAUER_LEBT)
1135 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1137 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1138 links_massiv = TRUE;
1139 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1140 rechts_massiv = TRUE;
1142 if (links_massiv && rechts_massiv)
1143 graphic = GFX_MAUERWERK;
1144 else if (links_massiv)
1145 graphic = GFX_MAUER_R;
1146 else if (rechts_massiv)
1147 graphic = GFX_MAUER_L;
1151 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1152 else if (mask_mode == USE_MASKING)
1153 DrawGraphicThruMask(x, y, graphic);
1155 DrawGraphic(x, y, graphic);
1158 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1159 int cut_mode, int mask_mode)
1161 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1162 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1163 cut_mode, mask_mode);
1166 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1169 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1172 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1175 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1178 void DrawScreenElementThruMask(int x, int y, int element)
1180 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1183 void DrawLevelElementThruMask(int x, int y, int element)
1185 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1188 void DrawLevelFieldThruMask(int x, int y)
1190 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1193 void ErdreichAnbroeckeln(int x, int y)
1195 int i, width, height, cx,cy;
1196 int ux = LEVELX(x), uy = LEVELY(y);
1197 int element, graphic;
1199 static int xy[4][2] =
1207 if (!IN_LEV_FIELD(ux, uy))
1210 element = Feld[ux][uy];
1212 if (element == EL_ERDREICH)
1214 if (!IN_SCR_FIELD(x, y))
1217 graphic = GFX_ERDENRAND;
1223 uxx = ux + xy[i][0];
1224 uyy = uy + xy[i][1];
1225 if (!IN_LEV_FIELD(uxx, uyy))
1228 element = Feld[uxx][uyy];
1230 if (element == EL_ERDREICH)
1233 if (i == 1 || i == 2)
1237 cx = (i == 2 ? TILEX - snip : 0);
1245 cy = (i == 3 ? TILEY - snip : 0);
1248 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1249 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1250 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1251 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1254 MarkTileDirty(x, y);
1258 graphic = GFX_ERDENRAND;
1262 int xx, yy, uxx, uyy;
1266 uxx = ux + xy[i][0];
1267 uyy = uy + xy[i][1];
1269 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1270 !IN_SCR_FIELD(xx, yy))
1273 if (i == 1 || i == 2)
1277 cx = (i == 1 ? TILEX - snip : 0);
1285 cy = (i==0 ? TILEY-snip : 0);
1288 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1289 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1290 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1291 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1293 MarkTileDirty(xx, yy);
1298 void DrawScreenElement(int x, int y, int element)
1300 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1301 ErdreichAnbroeckeln(x, y);
1304 void DrawLevelElement(int x, int y, int element)
1306 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1307 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1310 void DrawScreenField(int x, int y)
1312 int ux = LEVELX(x), uy = LEVELY(y);
1315 if (!IN_LEV_FIELD(ux, uy))
1317 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1318 element = EL_LEERRAUM;
1320 element = BorderElement;
1322 DrawScreenElement(x, y, element);
1326 element = Feld[ux][uy];
1328 if (IS_MOVING(ux, uy))
1330 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1331 boolean cut_mode = NO_CUTTING;
1333 if (Store[ux][uy] == EL_MORAST_LEER ||
1334 Store[ux][uy] == EL_SIEB_LEER ||
1335 Store[ux][uy] == EL_SIEB2_LEER ||
1336 Store[ux][uy] == EL_AMOEBE_NASS)
1337 cut_mode = CUT_ABOVE;
1338 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1339 Store[ux][uy] == EL_SIEB_VOLL ||
1340 Store[ux][uy] == EL_SIEB2_VOLL)
1341 cut_mode = CUT_BELOW;
1343 if (cut_mode == CUT_ABOVE)
1344 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1346 DrawScreenElement(x, y, EL_LEERRAUM);
1349 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1351 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1353 if (Store[ux][uy] == EL_SALZSAEURE)
1354 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1356 else if (IS_BLOCKED(ux, uy))
1361 boolean cut_mode = NO_CUTTING;
1363 Blocked2Moving(ux, uy, &oldx, &oldy);
1366 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1367 MovDir[oldx][oldy] == MV_RIGHT);
1369 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1370 Store[oldx][oldy] == EL_SIEB_LEER ||
1371 Store[oldx][oldy] == EL_SIEB2_LEER ||
1372 Store[oldx][oldy] == EL_AMOEBE_NASS)
1373 cut_mode = CUT_ABOVE;
1375 DrawScreenElement(x, y, EL_LEERRAUM);
1376 element = Feld[oldx][oldy];
1379 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1381 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1383 else if (IS_DRAWABLE(element))
1384 DrawScreenElement(x, y, element);
1386 DrawScreenElement(x, y, EL_LEERRAUM);
1389 void DrawLevelField(int x, int y)
1391 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1392 DrawScreenField(SCREENX(x), SCREENY(y));
1393 else if (IS_MOVING(x, y))
1397 Moving2Blocked(x, y, &newx, &newy);
1398 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1399 DrawScreenField(SCREENX(newx), SCREENY(newy));
1401 else if (IS_BLOCKED(x, y))
1405 Blocked2Moving(x, y, &oldx, &oldy);
1406 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1407 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1411 void DrawMiniElement(int x, int y, int element)
1417 DrawMiniGraphic(x, y, -1);
1421 graphic = el2gfx(element);
1422 DrawMiniGraphic(x, y, graphic);
1425 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1427 int x = sx + scroll_x, y = sy + scroll_y;
1429 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1430 DrawMiniElement(sx, sy, EL_LEERRAUM);
1431 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1432 DrawMiniElement(sx, sy, Feld[x][y]);
1435 int steel_type, steel_position;
1438 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1439 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1440 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1441 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1442 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1443 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1446 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1447 steel_position = (x == -1 && y == -1 ? 0 :
1448 x == lev_fieldx && y == -1 ? 1 :
1449 x == -1 && y == lev_fieldy ? 2 :
1450 x == lev_fieldx && y == lev_fieldy ? 3 :
1451 x == -1 || x == lev_fieldx ? 4 :
1452 y == -1 || y == lev_fieldy ? 5 : -1);
1454 if (steel_position != -1)
1455 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1459 void DrawMicroElement(int xpos, int ypos, int element)
1463 if (element == EL_LEERRAUM)
1466 graphic = el2gfx(element);
1468 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1470 graphic -= GFX_START_ROCKSMORE;
1471 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
1472 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1473 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1474 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1475 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1478 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1479 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1480 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1481 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1490 for(x=BX1; x<=BX2; x++)
1491 for(y=BY1; y<=BY2; y++)
1492 DrawScreenField(x, y);
1497 redraw_mask |= REDRAW_FIELD;
1501 if (setup.soft_scrolling)
1502 XCopyArea(display, fieldbuffer, backbuffer, gc,
1503 FX, FY, SXSIZE, SYSIZE, SX, SY);
1505 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1511 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1515 for(x=0; x<size_x; x++)
1516 for(y=0; y<size_y; y++)
1517 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1519 redraw_mask |= REDRAW_FIELD;
1522 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1526 XFillRectangle(display, drawto, gc,
1527 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1529 if (lev_fieldx < STD_LEV_FIELDX)
1530 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1531 if (lev_fieldy < STD_LEV_FIELDY)
1532 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1534 xpos += MICRO_TILEX;
1535 ypos += MICRO_TILEY;
1537 for(x=-1; x<=STD_LEV_FIELDX; x++)
1539 for(y=-1; y<=STD_LEV_FIELDY; y++)
1541 int lx = from_x + x, ly = from_y + y;
1543 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1544 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1546 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1547 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1552 redraw_mask |= REDRAW_MICROLEVEL;
1555 static void DrawMicroLevelLabelExt(int mode)
1557 char label_text[100];
1559 XFillRectangle(display, drawto,gc,
1560 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1562 strcpy(label_text, (mode == 1 ? level.name :
1563 mode == 2 ? "created by" :
1564 mode == 3 ? level.author : ""));
1566 if (strlen(label_text) > 0)
1568 int size, lxpos, lypos;
1570 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1572 size = strlen(label_text);
1573 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1574 lypos = MICROLABEL_YPOS;
1576 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1579 redraw_mask |= REDRAW_MICROLEVEL;
1582 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1584 static unsigned long scroll_delay = 0;
1585 static unsigned long label_delay = 0;
1586 static int from_x, from_y, scroll_direction;
1587 static int label_state, label_counter;
1591 from_x = from_y = 0;
1592 scroll_direction = MV_RIGHT;
1596 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1597 DrawMicroLevelLabelExt(label_state);
1599 /* initialize delay counters */
1600 DelayReached(&scroll_delay, 0);
1601 DelayReached(&label_delay, 0);
1606 /* scroll micro level, if needed */
1607 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1608 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1610 switch (scroll_direction)
1616 scroll_direction = MV_UP;
1620 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1623 scroll_direction = MV_DOWN;
1630 scroll_direction = MV_RIGHT;
1634 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1637 scroll_direction = MV_LEFT;
1644 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1647 /* redraw micro level label, if needed */
1648 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1649 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1650 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1651 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1653 label_counter = (label_counter + 1) % 23;
1654 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1655 label_counter >= 9 && label_counter <= 12 ? 2 :
1656 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1657 DrawMicroLevelLabelExt(label_state);
1661 int REQ_in_range(int x, int y)
1663 if (y > DY+249 && y < DY+278)
1665 if (x > DX+1 && x < DX+48)
1667 else if (x > DX+51 && x < DX+98)
1673 boolean Request(char *text, unsigned int req_state)
1675 int mx, my, ty, result = -1;
1676 unsigned int old_door_state;
1679 /* pause network game while waiting for request to answer */
1680 if (options.network &&
1681 game_status == PLAYING &&
1682 req_state & REQUEST_WAIT_FOR)
1683 SendToServer_PausePlaying();
1686 old_door_state = GetDoorState();
1690 CloseDoor(DOOR_CLOSE_1);
1692 /* save old door content */
1693 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1694 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1695 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1697 /* clear door drawing field */
1698 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1700 /* write text for request */
1701 for(ty=0; ty<13; ty++)
1709 for(tl=0,tx=0; tx<7; tl++,tx++)
1712 if (!tc || tc == 32)
1723 DrawTextExt(drawto, gc,
1724 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1725 txt, FS_SMALL, FC_YELLOW);
1726 text += tl + (tc == 32 ? 1 : 0);
1729 if (req_state & REQ_ASK)
1731 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1732 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1734 else if (req_state & REQ_CONFIRM)
1736 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1738 else if (req_state & REQ_PLAYER)
1740 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1741 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1742 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1743 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1746 /* copy request gadgets to door backbuffer */
1747 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1748 DX, DY, DXSIZE, DYSIZE,
1749 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1751 OpenDoor(DOOR_OPEN_1);
1757 if (!(req_state & REQUEST_WAIT_FOR))
1760 if (game_status != MAINMENU)
1763 button_status = MB_RELEASED;
1765 request_gadget_id = -1;
1769 if (XPending(display))
1773 XNextEvent(display, &event);
1781 if (event.type == MotionNotify)
1788 if (!XQueryPointer(display, window, &root, &child,
1789 &root_x, &root_y, &win_x, &win_y, &mask))
1795 motion_status = TRUE;
1796 mx = ((XMotionEvent *) &event)->x;
1797 my = ((XMotionEvent *) &event)->y;
1801 motion_status = FALSE;
1802 mx = ((XButtonEvent *) &event)->x;
1803 my = ((XButtonEvent *) &event)->y;
1804 if (event.type==ButtonPress)
1805 button_status = ((XButtonEvent *) &event)->button;
1807 button_status = MB_RELEASED;
1810 /* this sets 'request_gadget_id' */
1811 HandleGadgets(mx, my, button_status);
1813 switch(request_gadget_id)
1815 case TOOL_CTRL_ID_YES:
1818 case TOOL_CTRL_ID_NO:
1821 case TOOL_CTRL_ID_CONFIRM:
1822 result = TRUE | FALSE;
1825 case TOOL_CTRL_ID_PLAYER_1:
1828 case TOOL_CTRL_ID_PLAYER_2:
1831 case TOOL_CTRL_ID_PLAYER_3:
1834 case TOOL_CTRL_ID_PLAYER_4:
1846 switch(XLookupKeysym((XKeyEvent *)&event,
1847 ((XKeyEvent *)&event)->state))
1860 if (req_state & REQ_PLAYER)
1865 key_joystick_mapping = 0;
1869 HandleOtherEvents(&event);
1873 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1875 int joy = AnyJoystick();
1877 if (joy & JOY_BUTTON_1)
1879 else if (joy & JOY_BUTTON_2)
1885 /* don't eat all CPU time */
1889 if (game_status != MAINMENU)
1894 if (!(req_state & REQ_STAY_OPEN))
1896 CloseDoor(DOOR_CLOSE_1);
1898 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1900 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1901 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1902 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1903 OpenDoor(DOOR_OPEN_1);
1910 /* continue network game after request */
1911 if (options.network &&
1912 game_status == PLAYING &&
1913 req_state & REQUEST_WAIT_FOR)
1914 SendToServer_ContinuePlaying();
1920 unsigned int OpenDoor(unsigned int door_state)
1922 unsigned int new_door_state;
1924 if (door_state & DOOR_COPY_BACK)
1926 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1927 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1928 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1929 door_state &= ~DOOR_COPY_BACK;
1932 new_door_state = MoveDoor(door_state);
1934 return(new_door_state);
1937 unsigned int CloseDoor(unsigned int door_state)
1939 unsigned int new_door_state;
1941 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1942 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1943 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1944 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1946 new_door_state = MoveDoor(door_state);
1948 return(new_door_state);
1951 unsigned int GetDoorState()
1953 return(MoveDoor(DOOR_GET_STATE));
1956 unsigned int MoveDoor(unsigned int door_state)
1958 static int door1 = DOOR_OPEN_1;
1959 static int door2 = DOOR_CLOSE_2;
1960 static unsigned long door_delay = 0;
1961 int x, start, stepsize = 2;
1962 unsigned long door_delay_value = stepsize * 5;
1964 if (door_state == DOOR_GET_STATE)
1965 return(door1 | door2);
1967 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1968 door_state &= ~DOOR_OPEN_1;
1969 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1970 door_state &= ~DOOR_CLOSE_1;
1971 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1972 door_state &= ~DOOR_OPEN_2;
1973 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1974 door_state &= ~DOOR_CLOSE_2;
1976 if (setup.quick_doors)
1979 door_delay_value = 0;
1980 StopSound(SND_OEFFNEN);
1983 if (door_state & DOOR_ACTION)
1985 if (!(door_state & DOOR_NO_DELAY))
1986 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1988 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1990 for(x=start; x<=DXSIZE; x+=stepsize)
1992 WaitUntilDelayReached(&door_delay, door_delay_value);
1994 if (door_state & DOOR_ACTION_1)
1996 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1997 int j = (DXSIZE - i) / 3;
1999 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2000 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2001 DXSIZE,DYSIZE - i/2, DX, DY);
2003 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
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, i, 77, DX + DXSIZE - i, DY + j);
2009 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2010 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2012 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2013 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2014 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2015 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2016 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2017 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2019 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2020 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2022 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2023 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2025 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2026 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2027 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2028 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2029 DX + DXSIZE - i, DY + 77 + j);
2030 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2031 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2032 DX + DXSIZE - i, DY + 203 + j);
2034 redraw_mask |= REDRAW_DOOR_1;
2037 if (door_state & DOOR_ACTION_2)
2039 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2040 int j = (VXSIZE - i) / 3;
2042 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2043 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2044 VXSIZE, VYSIZE - i/2, VX, VY);
2046 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2048 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2049 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2050 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2051 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2052 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2053 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2054 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2055 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2057 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2058 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2059 VX, VY + VYSIZE / 2 - j);
2060 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2061 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2062 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2063 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2064 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2066 redraw_mask |= REDRAW_DOOR_2;
2071 if (game_status == MAINMENU)
2076 if (setup.quick_doors)
2077 StopSound(SND_OEFFNEN);
2079 if (door_state & DOOR_ACTION_1)
2080 door1 = door_state & DOOR_ACTION_1;
2081 if (door_state & DOOR_ACTION_2)
2082 door2 = door_state & DOOR_ACTION_2;
2084 return (door1 | door2);
2087 void DrawSpecialEditorDoor()
2089 /* draw bigger toolbox window */
2090 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2091 DOOR_GFX_PAGEX7, 60, 108, 56, EX - 4, EY - 12);
2093 /* draw background for level selection gadgets */
2094 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2095 DOOR_GFX_PAGEX7, 0, 108, 60, EX - 4, 0);
2097 redraw_mask |= REDRAW_ALL;
2100 void UndrawSpecialEditorDoor()
2102 /* draw normal tape recorder window */
2103 XCopyArea(display, pix[PIX_BACK], drawto, gc,
2104 562, 344, 108, 56, EX - 4, EY - 12);
2106 /* draw game title */
2107 XCopyArea(display, pix[PIX_BACK], drawto, gc,
2108 562, 0, 108, 60, EX - 4, 0);
2110 redraw_mask |= REDRAW_ALL;
2113 int ReadPixel(Drawable d, int x, int y)
2115 XImage *pixel_image;
2116 unsigned long pixel_value;
2118 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2119 pixel_value = XGetPixel(pixel_image, 0, 0);
2121 XDestroyImage(pixel_image);
2126 /* ---------- new tool button stuff ---------------------------------------- */
2128 /* graphic position values for tool buttons */
2129 #define TOOL_BUTTON_YES_XPOS 2
2130 #define TOOL_BUTTON_YES_YPOS 250
2131 #define TOOL_BUTTON_YES_GFX_YPOS 0
2132 #define TOOL_BUTTON_YES_XSIZE 46
2133 #define TOOL_BUTTON_YES_YSIZE 28
2134 #define TOOL_BUTTON_NO_XPOS 52
2135 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2136 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2137 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2138 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2139 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2140 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2141 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2142 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2143 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2144 #define TOOL_BUTTON_PLAYER_XSIZE 30
2145 #define TOOL_BUTTON_PLAYER_YSIZE 30
2146 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2147 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2148 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2149 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2150 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2151 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2152 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2153 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2154 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2155 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2156 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2157 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2158 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2159 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2160 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2161 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2162 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2163 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2164 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2165 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2174 } toolbutton_info[NUM_TOOL_BUTTONS] =
2177 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2178 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2179 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2184 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2185 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2186 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2191 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2192 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2193 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2194 TOOL_CTRL_ID_CONFIRM,
2198 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2199 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2200 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2201 TOOL_CTRL_ID_PLAYER_1,
2205 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2206 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2207 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2208 TOOL_CTRL_ID_PLAYER_2,
2212 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2213 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2214 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2215 TOOL_CTRL_ID_PLAYER_3,
2219 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2220 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2221 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2222 TOOL_CTRL_ID_PLAYER_4,
2227 static void DoNotDisplayInfoText(void *ptr)
2232 void CreateToolButtons()
2236 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2238 Pixmap gd_pixmap = pix[PIX_DOOR];
2239 Pixmap deco_pixmap = None;
2240 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2241 struct GadgetInfo *gi;
2242 unsigned long event_mask;
2243 int gd_xoffset, gd_yoffset;
2244 int gd_x1, gd_x2, gd_y;
2247 event_mask = GD_EVENT_RELEASED;
2249 gd_xoffset = toolbutton_info[i].xpos;
2250 gd_yoffset = toolbutton_info[i].ypos;
2251 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2252 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2253 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2255 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2257 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2258 &deco_pixmap, &deco_x, &deco_y);
2259 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2260 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2263 gi = CreateGadget(GDI_CUSTOM_ID, id,
2264 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2265 GDI_X, DX + toolbutton_info[i].x,
2266 GDI_Y, DY + toolbutton_info[i].y,
2267 GDI_WIDTH, toolbutton_info[i].width,
2268 GDI_HEIGHT, toolbutton_info[i].height,
2269 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2270 GDI_STATE, GD_BUTTON_UNPRESSED,
2271 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2272 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2273 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2274 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2275 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2276 GDI_DECORATION_SHIFTING, 1, 1,
2277 GDI_EVENT_MASK, event_mask,
2278 GDI_CALLBACK_ACTION, HandleToolButtons,
2279 GDI_CALLBACK_INFO, DoNotDisplayInfoText,
2283 Error(ERR_EXIT, "cannot create gadget");
2285 tool_gadget[id] = gi;
2289 static void UnmapToolButtons()
2293 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2294 UnmapGadget(tool_gadget[i]);
2297 static void HandleToolButtons(struct GadgetInfo *gi)
2299 request_gadget_id = gi->custom_id;
2302 int el2gfx(int element)
2306 case EL_LEERRAUM: return -1;
2307 case EL_ERDREICH: return GFX_ERDREICH;
2308 case EL_MAUERWERK: return GFX_MAUERWERK;
2309 case EL_FELSBODEN: return GFX_FELSBODEN;
2310 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2311 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2312 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2313 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2314 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2315 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2316 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2317 case EL_SPIELER1: return GFX_SPIELER1;
2318 case EL_SPIELER2: return GFX_SPIELER2;
2319 case EL_SPIELER3: return GFX_SPIELER3;
2320 case EL_SPIELER4: return GFX_SPIELER4;
2321 case EL_KAEFER: return GFX_KAEFER;
2322 case EL_KAEFER_R: return GFX_KAEFER_R;
2323 case EL_KAEFER_O: return GFX_KAEFER_O;
2324 case EL_KAEFER_L: return GFX_KAEFER_L;
2325 case EL_KAEFER_U: return GFX_KAEFER_U;
2326 case EL_FLIEGER: return GFX_FLIEGER;
2327 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2328 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2329 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2330 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2331 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2332 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2333 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2334 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2335 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2336 case EL_FIREFLY: return GFX_FIREFLY;
2337 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2338 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2339 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2340 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2341 case EL_MAMPFER: return GFX_MAMPFER;
2342 case EL_ROBOT: return GFX_ROBOT;
2343 case EL_BETON: return GFX_BETON;
2344 case EL_DIAMANT: return GFX_DIAMANT;
2345 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2346 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2347 case EL_TROPFEN: return GFX_TROPFEN;
2348 case EL_BOMBE: return GFX_BOMBE;
2349 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2350 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2351 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2352 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2353 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2354 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2355 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2356 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2357 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2358 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2359 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2360 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2361 case EL_LIFE: return GFX_LIFE;
2362 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2363 case EL_DYNAMIT: return GFX_DYNAMIT;
2364 case EL_BADEWANNE: return GFX_BADEWANNE;
2365 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2366 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2367 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2368 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2369 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2370 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2371 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2372 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2373 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2374 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2375 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2376 case EL_PFORTE1: return GFX_PFORTE1;
2377 case EL_PFORTE2: return GFX_PFORTE2;
2378 case EL_PFORTE3: return GFX_PFORTE3;
2379 case EL_PFORTE4: return GFX_PFORTE4;
2380 case EL_PFORTE1X: return GFX_PFORTE1X;
2381 case EL_PFORTE2X: return GFX_PFORTE2X;
2382 case EL_PFORTE3X: return GFX_PFORTE3X;
2383 case EL_PFORTE4X: return GFX_PFORTE4X;
2384 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2385 case EL_PACMAN: return GFX_PACMAN;
2386 case EL_PACMAN_R: return GFX_PACMAN_R;
2387 case EL_PACMAN_O: return GFX_PACMAN_O;
2388 case EL_PACMAN_L: return GFX_PACMAN_L;
2389 case EL_PACMAN_U: return GFX_PACMAN_U;
2390 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2391 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2392 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2393 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2394 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2395 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2396 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2397 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2398 case EL_MAUER_X: return GFX_MAUER_X;
2399 case EL_MAUER_Y: return GFX_MAUER_Y;
2400 case EL_MAUER_XY: return GFX_MAUER_XY;
2401 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2402 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2403 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2404 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2405 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2406 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2407 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2408 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2409 case EL_MAMPFER2: return GFX_MAMPFER2;
2410 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2411 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2412 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2413 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2414 case EL_DYNABOMB: return GFX_DYNABOMB;
2415 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2416 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2417 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2418 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2419 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2420 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2421 case EL_MAULWURF: return GFX_MAULWURF;
2422 case EL_PINGUIN: return GFX_PINGUIN;
2423 case EL_SCHWEIN: return GFX_SCHWEIN;
2424 case EL_DRACHE: return GFX_DRACHE;
2425 case EL_SONDE: return GFX_SONDE;
2426 case EL_PFEIL_L: return GFX_PFEIL_L;
2427 case EL_PFEIL_R: return GFX_PFEIL_R;
2428 case EL_PFEIL_O: return GFX_PFEIL_O;
2429 case EL_PFEIL_U: return GFX_PFEIL_U;
2430 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2431 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2432 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2433 case EL_SP_ZONK: return GFX_SP_ZONK;
2434 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2435 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2436 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2437 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2438 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2439 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2440 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2441 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2442 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2443 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2444 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2445 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2446 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2447 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2448 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2449 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2450 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2451 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2452 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2456 if (IS_CHAR(element))
2457 return GFX_CHAR_START + (element - EL_CHAR_START);
2458 else if (element >= EL_SP_START && element <= EL_SP_END)
2460 int nr_element = element - EL_SP_START;
2461 int gfx_per_line = 8;
2463 (nr_element / gfx_per_line) * MORE_PER_LINE +
2464 (nr_element % gfx_per_line);
2466 return GFX_START_ROCKSMORE + nr_graphic;