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 / FONT3_XSIZE + 10];
323 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
324 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
326 va_start(ap, format);
327 vsprintf(buffer, format, ap);
330 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
331 buffer, FS_SMALL, font_type);
334 void DrawTextF(int x, int y, int font_type, char *format, ...)
336 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
339 va_start(ap, format);
340 vsprintf(buffer, format, ap);
343 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
346 void DrawText(int x, int y, char *text, int font_size, int font_type)
348 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
351 redraw_mask |= REDRAW_FIELD;
353 redraw_mask |= REDRAW_DOOR_1;
356 void DrawTextExt(Drawable d, GC gc, int x, int y,
357 char *text, int font_size, int font_type)
359 int font_width, font_height, font_start;
361 boolean print_inverse = FALSE;
363 if (font_size != FS_SMALL && font_size != FS_BIG)
364 font_size = FS_SMALL;
365 if (font_type < FC_RED || font_type > FC_SPECIAL2)
368 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
369 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
370 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
371 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
372 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
373 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
374 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
375 FONT_LINES_PER_FONT);
381 if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
383 print_inverse = TRUE;
387 if (c >= 'a' && c <= 'z')
389 else if (c == 'ä' || c == 'Ä')
391 else if (c == 'ö' || c == 'Ö')
393 else if (c == 'ü' || c == 'Ü')
396 if (c >= 32 && c <= 95)
398 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
399 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
400 int dest_x = x, dest_y = y;
404 XCopyArea(display, pix[font_pixmap], d, gc,
405 FONT_CHARS_PER_LINE * font_width,
406 3 * font_height + font_start,
407 font_width, font_height, x, y);
409 XSetClipOrigin(display, clip_gc[font_pixmap],
410 dest_x - src_x, dest_y - src_y);
411 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
412 0, 0, font_width, font_height, dest_x, dest_y);
415 XCopyArea(display, pix[font_pixmap], d, gc,
416 src_x, src_y, font_width, font_height, dest_x, dest_y);
423 void DrawAllPlayers()
427 for(i=0; i<MAX_PLAYERS; i++)
428 if (stored_player[i].active)
429 DrawPlayer(&stored_player[i]);
432 void DrawPlayerField(int x, int y)
434 if (!IS_PLAYER(x, y))
437 DrawPlayer(PLAYERINFO(x, y));
440 void DrawPlayer(struct PlayerInfo *player)
442 int jx = player->jx, jy = player->jy;
443 int last_jx = player->last_jx, last_jy = player->last_jy;
444 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
445 int sx = SCREENX(jx), sy = SCREENY(jy);
446 int sxx = 0, syy = 0;
447 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
449 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
451 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
455 if (!IN_LEV_FIELD(jx,jy))
457 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
458 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
459 printf("DrawPlayerField(): This should never happen!\n");
464 if (element == EL_EXPLODING)
467 /* draw things in the field the player is leaving, if needed */
469 if (player_is_moving)
471 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
473 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
474 DrawLevelFieldThruMask(last_jx, last_jy);
476 else if (last_element == EL_DYNAMIT)
477 DrawDynamite(last_jx, last_jy);
479 DrawLevelField(last_jx, last_jy);
481 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
485 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
486 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
488 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
491 DrawLevelField(next_jx, next_jy);
495 if (!IN_SCR_FIELD(sx, sy))
498 if (setup.direct_draw)
499 SetDrawtoField(DRAW_BUFFERED);
501 /* draw things behind the player, if needed */
504 DrawLevelElement(jx, jy, Store[jx][jy]);
505 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
506 DrawLevelField(jx, jy);
508 /* draw player himself */
510 if (game.emulation == EMU_SUPAPLEX)
512 static int last_dir = MV_LEFT;
513 int action = (player->programmed_action ? player->programmed_action :
515 boolean action_moving =
517 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
518 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
520 graphic = GFX_SP_MURPHY;
524 if (player->MovDir == MV_LEFT)
525 graphic = GFX_MURPHY_PUSH_LEFT;
526 else if (player->MovDir == MV_RIGHT)
527 graphic = GFX_MURPHY_PUSH_RIGHT;
528 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
529 graphic = GFX_MURPHY_PUSH_LEFT;
530 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
531 graphic = GFX_MURPHY_PUSH_RIGHT;
533 else if (player->snapped)
535 if (player->MovDir == MV_LEFT)
536 graphic = GFX_MURPHY_SNAP_LEFT;
537 else if (player->MovDir == MV_RIGHT)
538 graphic = GFX_MURPHY_SNAP_RIGHT;
539 else if (player->MovDir == MV_UP)
540 graphic = GFX_MURPHY_SNAP_UP;
541 else if (player->MovDir == MV_DOWN)
542 graphic = GFX_MURPHY_SNAP_DOWN;
544 else if (action_moving)
546 if (player->MovDir == MV_LEFT)
547 graphic = GFX_MURPHY_GO_LEFT;
548 else if (player->MovDir == MV_RIGHT)
549 graphic = GFX_MURPHY_GO_RIGHT;
550 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
551 graphic = GFX_MURPHY_GO_LEFT;
552 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
553 graphic = GFX_MURPHY_GO_RIGHT;
555 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
558 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
559 last_dir = player->MovDir;
563 if (player->MovDir == MV_LEFT)
565 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
566 else if (player->MovDir == MV_RIGHT)
568 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
569 else if (player->MovDir == MV_UP)
570 graphic = GFX_SPIELER1_UP;
571 else /* MV_DOWN || MV_NO_MOVING */
572 graphic = GFX_SPIELER1_DOWN;
574 graphic += player->index_nr * 3 * HEROES_PER_LINE;
575 graphic += player->Frame;
580 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
581 sxx = player->GfxPos;
583 syy = player->GfxPos;
586 if (!setup.soft_scrolling && ScreenMovPos)
589 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
591 if (player->Pushing && player->GfxPos)
593 int px = SCREENX(next_jx), py = SCREENY(next_jy);
595 if (element == EL_SOKOBAN_FELD_LEER ||
596 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
597 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
601 int element = Feld[next_jx][next_jy];
602 int graphic = el2gfx(element);
604 if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK) && sxx)
606 int phase = (player->GfxPos / (TILEX / 4));
608 if (player->MovDir == MV_LEFT)
611 graphic += (phase + 4) % 4;
614 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
618 /* draw things in front of player (EL_DYNAMIT or EL_DYNABOMB) */
620 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
622 graphic = el2gfx(element);
624 if (element == EL_DYNAMIT)
626 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
631 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
635 if (game.emulation == EMU_SUPAPLEX)
636 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
638 DrawGraphicThruMask(sx, sy, graphic + phase);
641 if (player_is_moving && last_element == EL_EXPLODING)
643 int phase = Frame[last_jx][last_jy];
647 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
648 GFX_EXPLOSION + ((phase - 1) / delay - 1));
651 /* draw elements that stay over the player */
652 /* handle the field the player is leaving ... */
653 if (player_is_moving && IS_OVER_PLAYER(last_element))
654 DrawLevelField(last_jx, last_jy);
655 /* ... and the field the player is entering */
656 if (IS_OVER_PLAYER(element))
657 DrawLevelField(jx, jy);
659 if (setup.direct_draw)
661 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
662 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
663 int x_size = TILEX * (1 + ABS(jx - last_jx));
664 int y_size = TILEY * (1 + ABS(jy - last_jy));
666 XCopyArea(display, drawto_field, window, gc,
667 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
668 SetDrawtoField(DRAW_DIRECT);
671 MarkTileDirty(sx,sy);
674 static int getGraphicAnimationPhase(int frames, int delay, int mode)
678 if (mode == ANIM_OSCILLATE)
680 int max_anim_frames = 2 * frames - 2;
681 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
682 phase = (phase < frames ? phase : max_anim_frames - phase);
685 phase = (FrameCounter % (delay * frames)) / delay;
687 if (mode == ANIM_REVERSE)
693 void DrawGraphicAnimationExt(int x, int y, int graphic,
694 int frames, int delay, int mode, int mask_mode)
696 int phase = getGraphicAnimationPhase(frames, delay, mode);
698 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
700 if (mask_mode == USE_MASKING)
701 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
703 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
707 void DrawGraphicAnimation(int x, int y, int graphic,
708 int frames, int delay, int mode)
710 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
713 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
714 int frames, int delay, int mode)
716 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
719 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
721 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
723 graphic -= GFX_START_ROCKSSCREEN;
724 *pixmap_nr = PIX_BACK;
725 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
726 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
728 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
730 graphic -= GFX_START_ROCKSMORE;
731 *pixmap_nr = PIX_MORE;
732 *x = (graphic % MORE_PER_LINE) * TILEX;
733 *y = (graphic / MORE_PER_LINE) * TILEY;
735 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
737 graphic -= GFX_START_ROCKSHEROES;
738 *pixmap_nr = PIX_HEROES;
739 *x = (graphic % HEROES_PER_LINE) * TILEX;
740 *y = (graphic / HEROES_PER_LINE) * TILEY;
742 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
744 graphic -= GFX_START_ROCKSFONT;
745 *pixmap_nr = PIX_BIGFONT;
746 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
747 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
748 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
752 *pixmap_nr = PIX_MORE;
758 void DrawGraphic(int x, int y, int graphic)
761 if (!IN_SCR_FIELD(x,y))
763 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
764 printf("DrawGraphic(): This should never happen!\n");
769 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
773 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
778 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
779 XCopyArea(display, pix[pixmap_nr], d, gc,
780 src_x, src_y, TILEX, TILEY, x, y);
783 void DrawGraphicThruMask(int x, int y, int graphic)
786 if (!IN_SCR_FIELD(x,y))
788 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
789 printf("DrawGraphicThruMask(): This should never happen!\n");
794 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
798 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
806 if (graphic == GFX_LEERRAUM)
809 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
810 src_pixmap = pix[pixmap_nr];
811 drawing_gc = clip_gc[pixmap_nr];
813 if (tile_clipmask[tile] != None)
815 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
816 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
817 XCopyArea(display, src_pixmap, d, tile_clip_gc,
818 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
823 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
826 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
827 XCopyArea(display, src_pixmap, d, drawing_gc,
828 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
832 void DrawMiniGraphic(int x, int y, int graphic)
834 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
835 MarkTileDirty(x/2, y/2);
838 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
840 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
842 graphic -= GFX_START_ROCKSSCREEN;
843 *pixmap = pix[PIX_BACK];
844 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
845 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
847 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
849 graphic -= GFX_START_ROCKSMORE;
850 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
851 *pixmap = pix[PIX_MORE];
852 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
853 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
855 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
857 graphic -= GFX_START_ROCKSFONT;
858 *pixmap = pix[PIX_SMALLFONT];
859 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
860 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
861 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
865 *pixmap = pix[PIX_MORE];
866 *x = MINI_MORE_STARTX;
867 *y = MINI_MORE_STARTY;
871 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
876 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
877 XCopyArea(display, pixmap, d, gc,
878 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
881 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
882 int cut_mode, int mask_mode)
884 int width = TILEX, height = TILEY;
886 int src_x, src_y, dest_x, dest_y;
894 DrawGraphic(x, y, graphic);
898 if (dx || dy) /* Verschiebung der Grafik? */
900 if (x < BX1) /* Element kommt von links ins Bild */
907 else if (x > BX2) /* Element kommt von rechts ins Bild */
913 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
919 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
921 else if (dx) /* allg. Bewegung in x-Richtung */
922 MarkTileDirty(x + SIGN(dx), y);
924 if (y < BY1) /* Element kommt von oben ins Bild */
926 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
934 else if (y > BY2) /* Element kommt von unten ins Bild */
940 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
946 else if (dy > 0 && cut_mode == CUT_ABOVE)
948 if (y == BY2) /* Element unterhalb des Bildes */
954 MarkTileDirty(x, y + 1);
955 } /* Element verläßt unten das Bild */
956 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
958 else if (dy) /* allg. Bewegung in y-Richtung */
959 MarkTileDirty(x, y + SIGN(dy));
962 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
963 src_pixmap = pix[pixmap_nr];
964 drawing_gc = clip_gc[pixmap_nr];
966 dest_x = FX + x * TILEX + dx;
967 dest_y = FY + y * TILEY + dy;
970 if (!IN_SCR_FIELD(x,y))
972 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
973 printf("DrawGraphicShifted(): This should never happen!\n");
978 if (mask_mode == USE_MASKING)
980 if (tile_clipmask[tile] != None)
982 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
983 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
984 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
985 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
990 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
993 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
994 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
995 src_x, src_y, width, height, dest_x, dest_y);
999 XCopyArea(display, src_pixmap, drawto_field, gc,
1000 src_x, src_y, width, height, dest_x, dest_y);
1005 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1008 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1011 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1012 int cut_mode, int mask_mode)
1014 int ux = LEVELX(x), uy = LEVELY(y);
1015 int graphic = el2gfx(element);
1016 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1017 int phase4 = phase8 / 2;
1018 int phase2 = phase8 / 4;
1019 int dir = MovDir[ux][uy];
1021 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1023 graphic += 4 * !phase2;
1027 else if (dir == MV_LEFT)
1029 else if (dir == MV_DOWN)
1032 else if (element == EL_SP_SNIKSNAK)
1035 graphic = GFX_SP_SNIKSNAK_LEFT;
1036 else if (dir == MV_RIGHT)
1037 graphic = GFX_SP_SNIKSNAK_RIGHT;
1038 else if (dir == MV_UP)
1039 graphic = GFX_SP_SNIKSNAK_UP;
1041 graphic = GFX_SP_SNIKSNAK_DOWN;
1043 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1045 else if (element == EL_SP_ELECTRON)
1047 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1049 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1050 element == EL_SCHWEIN || element == EL_DRACHE)
1053 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1054 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1055 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1056 else if (dir == MV_RIGHT)
1057 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1058 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1059 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1060 else if (dir == MV_UP)
1061 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1062 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1063 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1065 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1066 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1067 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1071 else if (element == EL_SONDE)
1073 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1075 else if (element == EL_SALZSAEURE)
1077 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1079 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1083 else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
1084 IS_GEM(element)) && !cut_mode)
1086 if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
1089 graphic += (4 - phase4) % 4;
1090 else if (dir == MV_RIGHT)
1093 graphic += phase2 * 2;
1095 else if (element != EL_SP_INFOTRON)
1099 if (element == EL_SP_ZONK)
1102 graphic += (4 - phase4) % 4;
1103 else if (dir == MV_RIGHT)
1106 graphic += phase2 * 2;
1108 else if (element != EL_SP_INFOTRON)
1109 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1113 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1114 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1116 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1118 else if (IS_AMOEBOID(element))
1120 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1121 graphic += (x + 2 * y + 4) % 4;
1123 else if (element == EL_MAUER_LEBT)
1125 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1127 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1128 links_massiv = TRUE;
1129 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1130 rechts_massiv = TRUE;
1132 if (links_massiv && rechts_massiv)
1133 graphic = GFX_MAUERWERK;
1134 else if (links_massiv)
1135 graphic = GFX_MAUER_R;
1136 else if (rechts_massiv)
1137 graphic = GFX_MAUER_L;
1141 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1142 else if (mask_mode == USE_MASKING)
1143 DrawGraphicThruMask(x, y, graphic);
1145 DrawGraphic(x, y, graphic);
1148 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1149 int cut_mode, int mask_mode)
1151 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1152 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1153 cut_mode, mask_mode);
1156 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1159 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1162 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1165 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1168 void DrawScreenElementThruMask(int x, int y, int element)
1170 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1173 void DrawLevelElementThruMask(int x, int y, int element)
1175 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1178 void DrawLevelFieldThruMask(int x, int y)
1180 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1183 void ErdreichAnbroeckeln(int x, int y)
1185 int i, width, height, cx,cy;
1186 int ux = LEVELX(x), uy = LEVELY(y);
1187 int element, graphic;
1189 static int xy[4][2] =
1197 if (!IN_LEV_FIELD(ux, uy))
1200 element = Feld[ux][uy];
1202 if (element == EL_ERDREICH)
1204 if (!IN_SCR_FIELD(x, y))
1207 graphic = GFX_ERDENRAND;
1213 uxx = ux + xy[i][0];
1214 uyy = uy + xy[i][1];
1215 if (!IN_LEV_FIELD(uxx, uyy))
1218 element = Feld[uxx][uyy];
1220 if (element == EL_ERDREICH)
1223 if (i == 1 || i == 2)
1227 cx = (i == 2 ? TILEX - snip : 0);
1235 cy = (i == 3 ? TILEY - snip : 0);
1238 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1239 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1240 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1241 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1244 MarkTileDirty(x, y);
1248 graphic = GFX_ERDENRAND;
1252 int xx, yy, uxx, uyy;
1256 uxx = ux + xy[i][0];
1257 uyy = uy + xy[i][1];
1259 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1260 !IN_SCR_FIELD(xx, yy))
1263 if (i == 1 || i == 2)
1267 cx = (i == 1 ? TILEX - snip : 0);
1275 cy = (i==0 ? TILEY-snip : 0);
1278 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1279 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1280 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1281 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1283 MarkTileDirty(xx, yy);
1288 void DrawScreenElement(int x, int y, int element)
1290 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1291 ErdreichAnbroeckeln(x, y);
1294 void DrawLevelElement(int x, int y, int element)
1296 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1297 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1300 void DrawScreenField(int x, int y)
1302 int ux = LEVELX(x), uy = LEVELY(y);
1305 if (!IN_LEV_FIELD(ux, uy))
1307 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1308 element = EL_LEERRAUM;
1310 element = BorderElement;
1312 DrawScreenElement(x, y, element);
1316 element = Feld[ux][uy];
1318 if (IS_MOVING(ux, uy))
1320 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1321 boolean cut_mode = NO_CUTTING;
1323 if (Store[ux][uy] == EL_MORAST_LEER ||
1324 Store[ux][uy] == EL_SIEB_LEER ||
1325 Store[ux][uy] == EL_SIEB2_LEER ||
1326 Store[ux][uy] == EL_AMOEBE_NASS)
1327 cut_mode = CUT_ABOVE;
1328 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1329 Store[ux][uy] == EL_SIEB_VOLL ||
1330 Store[ux][uy] == EL_SIEB2_VOLL)
1331 cut_mode = CUT_BELOW;
1333 if (cut_mode == CUT_ABOVE)
1334 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1336 DrawScreenElement(x, y, EL_LEERRAUM);
1339 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1341 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1343 if (Store[ux][uy] == EL_SALZSAEURE)
1344 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1346 else if (IS_BLOCKED(ux, uy))
1351 boolean cut_mode = NO_CUTTING;
1353 Blocked2Moving(ux, uy, &oldx, &oldy);
1356 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1357 MovDir[oldx][oldy] == MV_RIGHT);
1359 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1360 Store[oldx][oldy] == EL_SIEB_LEER ||
1361 Store[oldx][oldy] == EL_SIEB2_LEER ||
1362 Store[oldx][oldy] == EL_AMOEBE_NASS)
1363 cut_mode = CUT_ABOVE;
1365 DrawScreenElement(x, y, EL_LEERRAUM);
1366 element = Feld[oldx][oldy];
1369 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1371 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1373 else if (IS_DRAWABLE(element))
1374 DrawScreenElement(x, y, element);
1376 DrawScreenElement(x, y, EL_LEERRAUM);
1379 void DrawLevelField(int x, int y)
1381 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1382 DrawScreenField(SCREENX(x), SCREENY(y));
1383 else if (IS_MOVING(x, y))
1387 Moving2Blocked(x, y, &newx, &newy);
1388 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1389 DrawScreenField(SCREENX(newx), SCREENY(newy));
1391 else if (IS_BLOCKED(x, y))
1395 Blocked2Moving(x, y, &oldx, &oldy);
1396 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1397 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1401 void DrawMiniElement(int x, int y, int element)
1407 DrawMiniGraphic(x, y, -1);
1411 graphic = el2gfx(element);
1412 DrawMiniGraphic(x, y, graphic);
1415 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1417 int x = sx + scroll_x, y = sy + scroll_y;
1419 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1420 DrawMiniElement(sx, sy, EL_LEERRAUM);
1421 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1422 DrawMiniElement(sx, sy, Feld[x][y]);
1425 int steel_type, steel_position;
1428 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1429 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1430 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1431 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1432 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1433 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1436 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1437 steel_position = (x == -1 && y == -1 ? 0 :
1438 x == lev_fieldx && y == -1 ? 1 :
1439 x == -1 && y == lev_fieldy ? 2 :
1440 x == lev_fieldx && y == lev_fieldy ? 3 :
1441 x == -1 || x == lev_fieldx ? 4 :
1442 y == -1 || y == lev_fieldy ? 5 : -1);
1444 if (steel_position != -1)
1445 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1449 void DrawMicroElement(int xpos, int ypos, int element)
1453 if (element == EL_LEERRAUM)
1456 graphic = el2gfx(element);
1458 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1460 graphic -= GFX_START_ROCKSMORE;
1461 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
1462 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1463 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1464 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1465 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1468 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1469 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1470 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1471 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1480 for(x=BX1; x<=BX2; x++)
1481 for(y=BY1; y<=BY2; y++)
1482 DrawScreenField(x, y);
1487 redraw_mask |= REDRAW_FIELD;
1491 if (setup.soft_scrolling)
1492 XCopyArea(display, fieldbuffer, backbuffer, gc,
1493 FX, FY, SXSIZE, SYSIZE, SX, SY);
1495 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1501 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1505 for(x=0; x<size_x; x++)
1506 for(y=0; y<size_y; y++)
1507 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1509 redraw_mask |= REDRAW_FIELD;
1512 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1516 /* determine border element for this level */
1519 XFillRectangle(display, drawto, gc,
1520 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1522 if (lev_fieldx < STD_LEV_FIELDX)
1523 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1524 if (lev_fieldy < STD_LEV_FIELDY)
1525 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1527 xpos += MICRO_TILEX;
1528 ypos += MICRO_TILEY;
1530 for(x=-1; x<=STD_LEV_FIELDX; x++)
1532 for(y=-1; y<=STD_LEV_FIELDY; y++)
1534 int lx = from_x + x, ly = from_y + y;
1536 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1537 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1539 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1540 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1545 redraw_mask |= REDRAW_MICROLEVEL;
1548 static void DrawMicroLevelLabelExt(int mode)
1550 char label_text[100];
1552 XFillRectangle(display, drawto,gc,
1553 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1555 strcpy(label_text, (mode == 1 ? level.name :
1556 mode == 2 ? "created by" :
1557 mode == 3 ? level.author : ""));
1559 if (strlen(label_text) > 0)
1561 int size, lxpos, lypos;
1563 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1565 size = strlen(label_text);
1566 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1567 lypos = MICROLABEL_YPOS;
1569 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1572 redraw_mask |= REDRAW_MICROLEVEL;
1575 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1577 static unsigned long scroll_delay = 0;
1578 static unsigned long label_delay = 0;
1579 static int from_x, from_y, scroll_direction;
1580 static int label_state, label_counter;
1584 from_x = from_y = 0;
1585 scroll_direction = MV_RIGHT;
1589 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1590 DrawMicroLevelLabelExt(label_state);
1592 /* initialize delay counters */
1593 DelayReached(&scroll_delay, 0);
1594 DelayReached(&label_delay, 0);
1599 /* scroll micro level, if needed */
1600 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1601 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1603 switch (scroll_direction)
1609 scroll_direction = MV_UP;
1613 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1616 scroll_direction = MV_DOWN;
1623 scroll_direction = MV_RIGHT;
1627 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1630 scroll_direction = MV_LEFT;
1637 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1640 /* redraw micro level label, if needed */
1641 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1642 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1643 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1644 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1646 label_counter = (label_counter + 1) % 23;
1647 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1648 label_counter >= 9 && label_counter <= 12 ? 2 :
1649 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1650 DrawMicroLevelLabelExt(label_state);
1654 int REQ_in_range(int x, int y)
1656 if (y > DY+249 && y < DY+278)
1658 if (x > DX+1 && x < DX+48)
1660 else if (x > DX+51 && x < DX+98)
1666 boolean Request(char *text, unsigned int req_state)
1668 int mx, my, ty, result = -1;
1669 unsigned int old_door_state;
1672 /* pause network game while waiting for request to answer */
1673 if (options.network &&
1674 game_status == PLAYING &&
1675 req_state & REQUEST_WAIT_FOR)
1676 SendToServer_PausePlaying();
1679 old_door_state = GetDoorState();
1683 CloseDoor(DOOR_CLOSE_1);
1685 /* save old door content */
1686 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1687 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1688 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1690 /* clear door drawing field */
1691 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1693 /* write text for request */
1694 for(ty=0; ty<13; ty++)
1702 for(tl=0,tx=0; tx<7; tl++,tx++)
1705 if (!tc || tc == 32)
1716 DrawTextExt(drawto, gc,
1717 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1718 txt, FS_SMALL, FC_YELLOW);
1719 text += tl + (tc == 32 ? 1 : 0);
1722 if (req_state & REQ_ASK)
1724 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1725 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1727 else if (req_state & REQ_CONFIRM)
1729 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1731 else if (req_state & REQ_PLAYER)
1733 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1734 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1735 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1736 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1739 /* copy request gadgets to door backbuffer */
1740 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1741 DX, DY, DXSIZE, DYSIZE,
1742 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1744 OpenDoor(DOOR_OPEN_1);
1747 if (!(req_state & REQUEST_WAIT_FOR))
1750 if (game_status != MAINMENU)
1753 button_status = MB_RELEASED;
1755 request_gadget_id = -1;
1759 if (XPending(display))
1763 XNextEvent(display, &event);
1771 if (event.type == MotionNotify)
1778 if (!XQueryPointer(display, window, &root, &child,
1779 &root_x, &root_y, &win_x, &win_y, &mask))
1785 motion_status = TRUE;
1786 mx = ((XMotionEvent *) &event)->x;
1787 my = ((XMotionEvent *) &event)->y;
1791 motion_status = FALSE;
1792 mx = ((XButtonEvent *) &event)->x;
1793 my = ((XButtonEvent *) &event)->y;
1794 if (event.type==ButtonPress)
1795 button_status = ((XButtonEvent *) &event)->button;
1797 button_status = MB_RELEASED;
1800 /* this sets 'request_gadget_id' */
1801 HandleGadgets(mx, my, button_status);
1803 switch(request_gadget_id)
1805 case TOOL_CTRL_ID_YES:
1808 case TOOL_CTRL_ID_NO:
1811 case TOOL_CTRL_ID_CONFIRM:
1812 result = TRUE | FALSE;
1815 case TOOL_CTRL_ID_PLAYER_1:
1818 case TOOL_CTRL_ID_PLAYER_2:
1821 case TOOL_CTRL_ID_PLAYER_3:
1824 case TOOL_CTRL_ID_PLAYER_4:
1836 switch(XLookupKeysym((XKeyEvent *)&event,
1837 ((XKeyEvent *)&event)->state))
1850 if (req_state & REQ_PLAYER)
1855 key_joystick_mapping = 0;
1859 HandleOtherEvents(&event);
1863 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1865 int joy = AnyJoystick();
1867 if (joy & JOY_BUTTON_1)
1869 else if (joy & JOY_BUTTON_2)
1875 /* don't eat all CPU time */
1879 if (game_status != MAINMENU)
1884 if (!(req_state & REQ_STAY_OPEN))
1886 CloseDoor(DOOR_CLOSE_1);
1888 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1890 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1891 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1892 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1893 OpenDoor(DOOR_OPEN_1);
1900 /* continue network game after request */
1901 if (options.network &&
1902 game_status == PLAYING &&
1903 req_state & REQUEST_WAIT_FOR)
1904 SendToServer_ContinuePlaying();
1910 unsigned int OpenDoor(unsigned int door_state)
1912 unsigned int new_door_state;
1914 if (door_state & DOOR_COPY_BACK)
1916 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1917 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1918 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1919 door_state &= ~DOOR_COPY_BACK;
1922 new_door_state = MoveDoor(door_state);
1924 return(new_door_state);
1927 unsigned int CloseDoor(unsigned int door_state)
1929 unsigned int new_door_state;
1931 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1932 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1933 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1934 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1936 new_door_state = MoveDoor(door_state);
1938 return(new_door_state);
1941 unsigned int GetDoorState()
1943 return(MoveDoor(DOOR_GET_STATE));
1946 unsigned int MoveDoor(unsigned int door_state)
1948 static int door1 = DOOR_OPEN_1;
1949 static int door2 = DOOR_CLOSE_2;
1950 static unsigned long door_delay = 0;
1951 int x, start, stepsize = 2;
1952 unsigned long door_delay_value = stepsize * 5;
1954 if (door_state == DOOR_GET_STATE)
1955 return(door1 | door2);
1957 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1958 door_state &= ~DOOR_OPEN_1;
1959 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1960 door_state &= ~DOOR_CLOSE_1;
1961 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1962 door_state &= ~DOOR_OPEN_2;
1963 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1964 door_state &= ~DOOR_CLOSE_2;
1966 if (setup.quick_doors)
1969 door_delay_value = 0;
1970 StopSound(SND_OEFFNEN);
1973 if (door_state & DOOR_ACTION)
1975 if (!(door_state & DOOR_NO_DELAY))
1976 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1978 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1980 for(x=start; x<=DXSIZE; x+=stepsize)
1982 WaitUntilDelayReached(&door_delay, door_delay_value);
1984 if (door_state & DOOR_ACTION_1)
1986 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1987 int j = (DXSIZE - i) / 3;
1989 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1990 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1991 DXSIZE,DYSIZE - i/2, DX, DY);
1993 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1995 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1996 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1997 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1998 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1999 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2000 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2002 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2003 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2004 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2005 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2006 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2007 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2009 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2010 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2012 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2013 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2015 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2016 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2017 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2018 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2019 DX + DXSIZE - i, DY + 77 + j);
2020 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2021 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2022 DX + DXSIZE - i, DY + 203 + j);
2024 redraw_mask |= REDRAW_DOOR_1;
2027 if (door_state & DOOR_ACTION_2)
2029 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2030 int j = (VXSIZE - i) / 3;
2032 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2033 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2034 VXSIZE, VYSIZE - i/2, VX, VY);
2036 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2038 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2039 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2040 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2041 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2042 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2043 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2044 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2045 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2047 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2048 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2049 VX, VY + VYSIZE / 2 - j);
2050 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2051 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2052 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2053 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2054 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2056 redraw_mask |= REDRAW_DOOR_2;
2061 if (game_status == MAINMENU)
2066 if (setup.quick_doors)
2067 StopSound(SND_OEFFNEN);
2069 if (door_state & DOOR_ACTION_1)
2070 door1 = door_state & DOOR_ACTION_1;
2071 if (door_state & DOOR_ACTION_2)
2072 door2 = door_state & DOOR_ACTION_2;
2074 return(door1 | door2);
2077 int ReadPixel(Drawable d, int x, int y)
2079 XImage *pixel_image;
2080 unsigned long pixel_value;
2082 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2083 pixel_value = XGetPixel(pixel_image, 0, 0);
2085 XDestroyImage(pixel_image);
2090 /* ---------- new tool button stuff ---------------------------------------- */
2092 /* graphic position values for tool buttons */
2093 #define TOOL_BUTTON_YES_XPOS 2
2094 #define TOOL_BUTTON_YES_YPOS 250
2095 #define TOOL_BUTTON_YES_GFX_YPOS 0
2096 #define TOOL_BUTTON_YES_XSIZE 46
2097 #define TOOL_BUTTON_YES_YSIZE 28
2098 #define TOOL_BUTTON_NO_XPOS 52
2099 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2100 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2101 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2102 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2103 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2104 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2105 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2106 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2107 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2108 #define TOOL_BUTTON_PLAYER_XSIZE 30
2109 #define TOOL_BUTTON_PLAYER_YSIZE 30
2110 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2111 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2112 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2113 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2114 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2115 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2116 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2117 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2118 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2119 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2120 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2121 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2122 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2123 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2124 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2125 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2126 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2127 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2128 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2129 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2138 } toolbutton_info[NUM_TOOL_BUTTONS] =
2141 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2142 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2143 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2148 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2149 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2150 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2155 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2156 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2157 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2158 TOOL_CTRL_ID_CONFIRM,
2162 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2163 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2164 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2165 TOOL_CTRL_ID_PLAYER_1,
2169 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2170 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2171 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2172 TOOL_CTRL_ID_PLAYER_2,
2176 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2177 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2178 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2179 TOOL_CTRL_ID_PLAYER_3,
2183 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2184 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2185 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2186 TOOL_CTRL_ID_PLAYER_4,
2191 void CreateToolButtons()
2195 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2197 Pixmap gd_pixmap = pix[PIX_DOOR];
2198 Pixmap deco_pixmap = None;
2199 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2200 struct GadgetInfo *gi;
2201 unsigned long event_mask;
2202 int gd_xoffset, gd_yoffset;
2203 int gd_x1, gd_x2, gd_y;
2206 event_mask = GD_EVENT_RELEASED;
2208 gd_xoffset = toolbutton_info[i].xpos;
2209 gd_yoffset = toolbutton_info[i].ypos;
2210 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2211 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2212 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2214 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2216 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2217 &deco_pixmap, &deco_x, &deco_y);
2218 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2219 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2222 gi = CreateGadget(GDI_CUSTOM_ID, id,
2223 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2224 GDI_X, DX + toolbutton_info[i].x,
2225 GDI_Y, DY + toolbutton_info[i].y,
2226 GDI_WIDTH, toolbutton_info[i].width,
2227 GDI_HEIGHT, toolbutton_info[i].height,
2228 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2229 GDI_STATE, GD_BUTTON_UNPRESSED,
2230 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2231 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2232 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2233 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2234 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2235 GDI_DECORATION_SHIFTING, 1, 1,
2236 GDI_EVENT_MASK, event_mask,
2237 GDI_CALLBACK_ACTION, HandleToolButtons,
2241 Error(ERR_EXIT, "cannot create gadget");
2243 tool_gadget[id] = gi;
2247 static void UnmapToolButtons()
2251 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2252 UnmapGadget(tool_gadget[i]);
2255 static void HandleToolButtons(struct GadgetInfo *gi)
2257 request_gadget_id = gi->custom_id;
2260 int el2gfx(int element)
2264 case EL_LEERRAUM: return -1;
2265 case EL_ERDREICH: return GFX_ERDREICH;
2266 case EL_MAUERWERK: return GFX_MAUERWERK;
2267 case EL_FELSBODEN: return GFX_FELSBODEN;
2268 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2269 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2270 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2271 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2272 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2273 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2274 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2275 case EL_SPIELER1: return GFX_SPIELER1;
2276 case EL_SPIELER2: return GFX_SPIELER2;
2277 case EL_SPIELER3: return GFX_SPIELER3;
2278 case EL_SPIELER4: return GFX_SPIELER4;
2279 case EL_KAEFER: return GFX_KAEFER;
2280 case EL_KAEFER_R: return GFX_KAEFER_R;
2281 case EL_KAEFER_O: return GFX_KAEFER_O;
2282 case EL_KAEFER_L: return GFX_KAEFER_L;
2283 case EL_KAEFER_U: return GFX_KAEFER_U;
2284 case EL_FLIEGER: return GFX_FLIEGER;
2285 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2286 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2287 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2288 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2289 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2290 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2291 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2292 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2293 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2294 case EL_FIREFLY: return GFX_FIREFLY;
2295 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2296 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2297 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2298 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2299 case EL_MAMPFER: return GFX_MAMPFER;
2300 case EL_ROBOT: return GFX_ROBOT;
2301 case EL_BETON: return GFX_BETON;
2302 case EL_DIAMANT: return GFX_DIAMANT;
2303 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2304 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2305 case EL_TROPFEN: return GFX_TROPFEN;
2306 case EL_BOMBE: return GFX_BOMBE;
2307 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2308 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2309 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2310 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2311 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2312 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2313 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2314 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2315 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2316 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2317 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2318 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2319 case EL_LIFE: return GFX_LIFE;
2320 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2321 case EL_DYNAMIT: return GFX_DYNAMIT;
2322 case EL_BADEWANNE: return GFX_BADEWANNE;
2323 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2324 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2325 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2326 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2327 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2328 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2329 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2330 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2331 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2332 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2333 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2334 case EL_PFORTE1: return GFX_PFORTE1;
2335 case EL_PFORTE2: return GFX_PFORTE2;
2336 case EL_PFORTE3: return GFX_PFORTE3;
2337 case EL_PFORTE4: return GFX_PFORTE4;
2338 case EL_PFORTE1X: return GFX_PFORTE1X;
2339 case EL_PFORTE2X: return GFX_PFORTE2X;
2340 case EL_PFORTE3X: return GFX_PFORTE3X;
2341 case EL_PFORTE4X: return GFX_PFORTE4X;
2342 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2343 case EL_PACMAN: return GFX_PACMAN;
2344 case EL_PACMAN_R: return GFX_PACMAN_R;
2345 case EL_PACMAN_O: return GFX_PACMAN_O;
2346 case EL_PACMAN_L: return GFX_PACMAN_L;
2347 case EL_PACMAN_U: return GFX_PACMAN_U;
2348 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2349 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2350 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2351 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2352 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2353 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2354 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2355 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2356 case EL_MAUER_X: return GFX_MAUER_X;
2357 case EL_MAUER_Y: return GFX_MAUER_Y;
2358 case EL_MAUER_XY: return GFX_MAUER_XY;
2359 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2360 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2361 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2362 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2363 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2364 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2365 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2366 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2367 case EL_MAMPFER2: return GFX_MAMPFER2;
2368 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2369 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2370 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2371 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2372 case EL_DYNABOMB: return GFX_DYNABOMB;
2373 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2374 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2375 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2376 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2377 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2378 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2379 case EL_MAULWURF: return GFX_MAULWURF;
2380 case EL_PINGUIN: return GFX_PINGUIN;
2381 case EL_SCHWEIN: return GFX_SCHWEIN;
2382 case EL_DRACHE: return GFX_DRACHE;
2383 case EL_SONDE: return GFX_SONDE;
2384 case EL_PFEIL_L: return GFX_PFEIL_L;
2385 case EL_PFEIL_R: return GFX_PFEIL_R;
2386 case EL_PFEIL_O: return GFX_PFEIL_O;
2387 case EL_PFEIL_U: return GFX_PFEIL_U;
2388 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2389 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2390 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2391 case EL_SP_ZONK: return GFX_SP_ZONK;
2392 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2393 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2394 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2395 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2396 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2397 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2398 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2399 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2400 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2401 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2402 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2403 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2404 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2405 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2406 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2407 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2408 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2409 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2410 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2414 if (IS_CHAR(element))
2415 return GFX_CHAR_START + (element - EL_CHAR_START);
2416 else if (element >= EL_SP_START && element <= EL_SP_END)
2418 int nr_element = element - EL_SP_START;
2419 int gfx_per_line = 8;
2421 (nr_element / gfx_per_line) * MORE_PER_LINE +
2422 (nr_element % gfx_per_line);
2424 return GFX_START_ROCKSMORE + nr_graphic;