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 void UnmapToolButtons();
47 static void HandleToolButtons(struct GadgetInfo *);
49 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
50 static int request_gadget_id = -1;
52 void SetDrawtoField(int mode)
54 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
65 drawto_field = fieldbuffer;
67 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
78 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
85 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
87 if (setup.direct_draw && game_status == PLAYING)
88 redraw_mask &= ~REDRAW_MAIN;
90 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
91 redraw_mask |= REDRAW_FIELD;
93 if (redraw_mask & REDRAW_FIELD)
94 redraw_mask &= ~REDRAW_TILES;
97 if (redraw_mask & REDRAW_FIELD ||
98 (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING))
99 redraw_mask &= ~REDRAW_TILES;
105 /* synchronize X11 graphics at this point; if we would synchronize the
106 display immediately after the buffer switching (after the XFlush),
107 this could mean that we have to wait for the graphics to complete,
108 although we could go on doing calculations for the next frame */
110 XSync(display, FALSE);
114 wait_for_vsync = TRUE;
118 if (redraw_mask & REDRAW_ALL)
120 XCopyArea(display,backbuffer,window,gc,
121 0,0, WIN_XSIZE,WIN_YSIZE,
126 if (redraw_mask & REDRAW_FIELD)
128 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
130 XCopyArea(display,backbuffer,window,gc,
131 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
136 int fx = FX, fy = FY;
138 if (setup.soft_scrolling)
140 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
141 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
144 if (setup.soft_scrolling ||
145 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
146 ABS(ScreenMovPos) == ScrollStepSize ||
147 redraw_tiles > REDRAWTILES_THRESHOLD)
149 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
153 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
155 (setup.soft_scrolling ?
156 "setup.soft_scrolling" :
157 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
158 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
159 ABS(ScreenGfxPos) == ScrollStepSize ?
160 "ABS(ScreenGfxPos) == ScrollStepSize" :
161 "redraw_tiles > REDRAWTILES_THRESHOLD"));
166 redraw_mask &= ~REDRAW_MAIN;
169 if (redraw_mask & REDRAW_DOORS)
171 if (redraw_mask & REDRAW_DOOR_1)
172 XCopyArea(display,backbuffer,window,gc,
173 DX,DY, DXSIZE,DYSIZE,
175 if (redraw_mask & REDRAW_DOOR_2)
177 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
178 XCopyArea(display,backbuffer,window,gc,
179 VX,VY, VXSIZE,VYSIZE,
183 if (redraw_mask & REDRAW_VIDEO_1)
184 XCopyArea(display,backbuffer,window,gc,
185 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
186 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
187 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
188 if (redraw_mask & REDRAW_VIDEO_2)
189 XCopyArea(display,backbuffer,window,gc,
190 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
191 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
192 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
193 if (redraw_mask & REDRAW_VIDEO_3)
194 XCopyArea(display,backbuffer,window,gc,
195 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
196 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
197 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
200 if (redraw_mask & REDRAW_DOOR_3)
201 XCopyArea(display, backbuffer, window, gc,
202 EX, EY, EXSIZE, EYSIZE,
204 redraw_mask &= ~REDRAW_DOORS;
207 if (redraw_mask & REDRAW_MICROLEVEL)
209 XCopyArea(display,backbuffer,window,gc,
210 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
211 MICROLEV_XPOS, MICROLEV_YPOS);
212 XCopyArea(display,backbuffer,window,gc,
213 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
214 SX, MICROLABEL_YPOS);
215 redraw_mask &= ~REDRAW_MICROLEVEL;
218 if (redraw_mask & REDRAW_TILES)
220 for(x=0; x<SCR_FIELDX; x++)
221 for(y=0; y<SCR_FIELDY; y++)
222 if (redraw[redraw_x1 + x][redraw_y1 + y])
223 XCopyArea(display, buffer, window, gc,
224 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
225 SX + x * TILEX, SY + y * TILEY);
230 for(x=0; x<MAX_BUF_XSIZE; x++)
231 for(y=0; y<MAX_BUF_YSIZE; y++)
240 long fading_delay = 300;
242 if (setup.fading && (redraw_mask & REDRAW_FIELD))
249 XFillRectangle(display,window,gc,
250 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
253 for(i=0;i<2*FULL_SYSIZE;i++)
255 for(y=0;y<FULL_SYSIZE;y++)
257 XCopyArea(display,backbuffer,window,gc,
258 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
266 for(i=1;i<FULL_SYSIZE;i+=2)
267 XCopyArea(display,backbuffer,window,gc,
268 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
274 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
275 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
276 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
280 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
281 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
282 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
286 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
287 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
288 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
292 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
293 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
294 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
298 redraw_mask &= ~REDRAW_MAIN;
307 XFillRectangle(display, backbuffer, gc,
308 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
310 if (setup.soft_scrolling && game_status == PLAYING)
312 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
313 SetDrawtoField(DRAW_BUFFERED);
316 SetDrawtoField(DRAW_BACKBUFFER);
318 if (setup.direct_draw && game_status == PLAYING)
320 XFillRectangle(display, window, gc,
321 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
322 SetDrawtoField(DRAW_DIRECT);
325 redraw_mask |= REDRAW_FIELD;
328 void DrawTextFCentered(int y, int font_type, char *format, ...)
330 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
334 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
335 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
337 va_start(ap, format);
338 vsprintf(buffer, format, ap);
341 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
342 buffer, FS_SMALL, font_type);
345 void DrawTextF(int x, int y, int font_type, char *format, ...)
347 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
350 va_start(ap, format);
351 vsprintf(buffer, format, ap);
354 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
357 void DrawText(int x, int y, char *text, int font_size, int font_type)
359 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
362 redraw_mask |= REDRAW_FIELD;
364 redraw_mask |= REDRAW_DOOR_1;
367 void DrawTextExt(Drawable d, GC gc, int x, int y,
368 char *text, int font_size, int font_type)
370 int font_width, font_height, font_start;
372 boolean print_inverse = FALSE;
374 if (font_size != FS_SMALL && font_size != FS_BIG)
375 font_size = FS_SMALL;
376 if (font_type < FC_RED || font_type > FC_SPECIAL2)
379 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
380 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
381 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
382 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
383 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
384 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
385 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
386 FONT_LINES_PER_FONT);
392 if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
394 print_inverse = TRUE;
398 if (c >= 'a' && c <= 'z')
400 else if (c == 'ä' || c == 'Ä')
402 else if (c == 'ö' || c == 'Ö')
404 else if (c == 'ü' || c == 'Ü')
407 if (c >= 32 && c <= 95)
409 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
410 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
411 int dest_x = x, dest_y = y;
415 XCopyArea(display, pix[font_pixmap], d, gc,
416 FONT_CHARS_PER_LINE * font_width,
417 3 * font_height + font_start,
418 font_width, font_height, x, y);
420 XSetClipOrigin(display, clip_gc[font_pixmap],
421 dest_x - src_x, dest_y - src_y);
422 XCopyArea(display, pix[font_pixmap], drawto, clip_gc[font_pixmap],
423 0, 0, font_width, font_height, dest_x, dest_y);
426 XCopyArea(display, pix[font_pixmap], d, gc,
427 src_x, src_y, font_width, font_height, dest_x, dest_y);
434 void DrawAllPlayers()
438 for(i=0; i<MAX_PLAYERS; i++)
439 if (stored_player[i].active)
440 DrawPlayer(&stored_player[i]);
443 void DrawPlayerField(int x, int y)
448 DrawPlayer(PLAYERINFO(x,y));
451 void DrawPlayer(struct PlayerInfo *player)
453 int jx = player->jx, jy = player->jy;
454 int last_jx = player->last_jx, last_jy = player->last_jy;
455 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
456 int sx = SCREENX(jx), sy = SCREENY(jy);
457 int sxx = 0, syy = 0;
458 int element = Feld[jx][jy];
461 if (!player->active || player->gone ||
462 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
466 if (!IN_LEV_FIELD(jx,jy))
468 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
469 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
470 printf("DrawPlayerField(): This should never happen!\n");
475 if (element == EL_EXPLODING)
478 /* draw things in the field the player is leaving, if needed */
480 if (last_jx != jx || last_jy != jy)
482 if (Store[last_jx][last_jy])
484 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
485 DrawLevelFieldThruMask(last_jx, last_jy);
487 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
488 DrawDynamite(last_jx, last_jy);
490 DrawLevelField(last_jx, last_jy);
492 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
496 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
497 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
499 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
502 DrawLevelField(next_jx, next_jy);
506 if (!IN_SCR_FIELD(sx, sy))
509 if (setup.direct_draw)
510 SetDrawtoField(DRAW_BUFFERED);
512 /* draw things behind the player, if needed */
515 DrawLevelElement(jx, jy, Store[jx][jy]);
516 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
517 DrawLevelField(jx, jy);
519 /* draw player himself */
521 if (player->MovDir == MV_LEFT)
522 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
523 else if (player->MovDir == MV_RIGHT)
524 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
525 else if (player->MovDir == MV_UP)
526 graphic = GFX_SPIELER1_UP;
527 else /* MV_DOWN || MV_NO_MOVING */
528 graphic = GFX_SPIELER1_DOWN;
530 graphic += player->index_nr * 3*HEROES_PER_LINE;
531 graphic += player->Frame;
535 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
536 sxx = player->GfxPos;
538 syy = player->GfxPos;
541 if (!setup.soft_scrolling && ScreenMovPos)
544 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
546 if (player->Pushing && player->GfxPos)
548 int px = SCREENX(next_jx), py = SCREENY(next_jy);
550 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
551 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
552 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
556 int element = Feld[next_jx][next_jy];
557 int graphic = el2gfx(element);
559 if (element == EL_FELSBROCKEN && sxx)
561 int phase = (player->GfxPos / (TILEX/4));
563 if (player->MovDir == MV_LEFT)
566 graphic += (phase+4)%4;
569 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
573 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
575 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
577 graphic = el2gfx(element);
579 if (element == EL_DYNAMIT)
581 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
586 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
590 if (game_emulation == EMU_SUPAPLEX)
591 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
593 DrawGraphicThruMask(sx, sy, graphic + phase);
596 if ((last_jx != jx || last_jy != jy) &&
597 Feld[last_jx][last_jy] == EL_EXPLODING)
599 int phase = Frame[last_jx][last_jy];
603 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
604 GFX_EXPLOSION + ((phase - 1) / delay - 1));
607 if (setup.direct_draw)
609 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
610 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
611 int x_size = TILEX * (1 + ABS(jx - last_jx));
612 int y_size = TILEY * (1 + ABS(jy - last_jy));
614 XCopyArea(display, drawto_field, window, gc,
615 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
616 SetDrawtoField(DRAW_DIRECT);
619 MarkTileDirty(sx,sy);
622 static int getGraphicAnimationPhase(int frames, int delay, int mode)
626 if (mode == ANIM_OSCILLATE)
628 int max_anim_frames = 2 * frames - 2;
629 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
630 phase = (phase < frames ? phase : max_anim_frames - phase);
633 phase = (FrameCounter % (delay * frames)) / delay;
635 if (mode == ANIM_REVERSE)
641 void DrawGraphicAnimationExt(int x, int y, int graphic,
642 int frames, int delay, int mode, int mask_mode)
644 int phase = getGraphicAnimationPhase(frames, delay, mode);
646 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
648 if (mask_mode == USE_MASKING)
649 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
651 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
655 void DrawGraphicAnimation(int x, int y, int graphic,
656 int frames, int delay, int mode)
658 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
661 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
662 int frames, int delay, int mode)
664 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
667 void DrawGraphic(int x, int y, int graphic)
670 if (!IN_SCR_FIELD(x,y))
672 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
673 printf("DrawGraphic(): This should never happen!\n");
678 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
682 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
684 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
686 graphic -= GFX_START_ROCKSSCREEN;
687 XCopyArea(display, pix[PIX_BACK], d, gc,
688 SX + (graphic % GFX_PER_LINE) * TILEX,
689 SY + (graphic / GFX_PER_LINE) * TILEY,
692 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
694 graphic -= GFX_START_ROCKSMORE;
695 XCopyArea(display, pix[PIX_MORE], d, gc,
696 (graphic % MORE_PER_LINE) * TILEX,
697 (graphic / MORE_PER_LINE) * TILEY,
700 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
702 graphic -= GFX_START_ROCKSHEROES;
703 XCopyArea(display, pix[PIX_HEROES], d, gc,
704 (graphic % HEROES_PER_LINE) * TILEX,
705 (graphic / HEROES_PER_LINE) * TILEY,
708 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
710 graphic -= GFX_START_ROCKSFONT;
711 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
712 (graphic % FONT_CHARS_PER_LINE) * TILEX,
713 (graphic / FONT_CHARS_PER_LINE) * TILEY +
714 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
718 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
721 void DrawGraphicThruMask(int x, int y, int graphic)
724 if (!IN_SCR_FIELD(x,y))
726 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
727 printf("DrawGraphicThruMask(): This should never happen!\n");
732 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
736 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
743 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
745 src_pixmap = pix[PIX_BACK];
746 drawing_gc = clip_gc[PIX_BACK];
747 graphic -= GFX_START_ROCKSSCREEN;
748 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
749 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
751 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
753 src_pixmap = pix[PIX_MORE];
754 drawing_gc = clip_gc[PIX_MORE];
755 graphic -= GFX_START_ROCKSMORE;
756 src_x = (graphic % MORE_PER_LINE) * TILEX;
757 src_y = (graphic / MORE_PER_LINE) * TILEY;
759 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
761 src_pixmap = pix[PIX_HEROES];
762 drawing_gc = clip_gc[PIX_HEROES];
763 graphic -= GFX_START_ROCKSHEROES;
764 src_x = (graphic % HEROES_PER_LINE) * TILEX;
765 src_y = (graphic / HEROES_PER_LINE) * TILEY;
769 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
773 if (tile_clipmask[tile] != None)
775 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
776 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
777 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
778 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
783 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
786 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
787 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
788 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
792 void DrawMiniGraphic(int x, int y, int graphic)
794 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
795 MarkTileDirty(x/2, y/2);
798 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
800 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
802 graphic -= GFX_START_ROCKSSCREEN;
803 *pixmap = pix[PIX_BACK];
804 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
805 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
807 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
809 graphic -= GFX_START_ROCKSMORE;
810 *pixmap = pix[PIX_MORE];
811 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
812 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
814 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
816 graphic -= GFX_START_ROCKSFONT;
817 *pixmap = pix[PIX_SMALLFONT];
818 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
819 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
820 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
824 *pixmap = pix[PIX_MORE];
825 *x = MINI_MORE_STARTX;
826 *y = MINI_MORE_STARTY;
830 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
832 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
834 graphic -= GFX_START_ROCKSSCREEN;
835 XCopyArea(display, pix[PIX_BACK], d, gc,
836 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
837 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
838 MINI_TILEX, MINI_TILEY, x, y);
840 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
842 graphic -= GFX_START_ROCKSMORE;
843 XCopyArea(display, pix[PIX_MORE], d, gc,
844 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
845 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
846 MINI_TILEX, MINI_TILEY, x, y);
848 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
850 graphic -= GFX_START_ROCKSFONT;
851 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
852 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
853 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
854 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
855 MINI_TILEX, MINI_TILEY, x, y);
858 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
861 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
862 int cut_mode, int mask_mode)
864 int width = TILEX, height = TILEY;
866 int src_x, src_y, dest_x, dest_y;
873 DrawGraphic(x, y, graphic);
877 if (dx || dy) /* Verschiebung der Grafik? */
879 if (x < BX1) /* Element kommt von links ins Bild */
886 else if (x > BX2) /* Element kommt von rechts ins Bild */
892 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
898 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
900 else if (dx) /* allg. Bewegung in x-Richtung */
901 MarkTileDirty(x + SIGN(dx), y);
903 if (y < BY1) /* Element kommt von oben ins Bild */
905 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
913 else if (y > BY2) /* Element kommt von unten ins Bild */
919 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
925 else if (dy > 0 && cut_mode == CUT_ABOVE)
927 if (y == BY2) /* Element unterhalb des Bildes */
933 MarkTileDirty(x, y + 1);
934 } /* Element verläßt unten das Bild */
935 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
937 else if (dy) /* allg. Bewegung in y-Richtung */
938 MarkTileDirty(x, y + SIGN(dy));
941 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
943 src_pixmap = pix[PIX_BACK];
944 drawing_gc = clip_gc[PIX_BACK];
945 graphic -= GFX_START_ROCKSSCREEN;
946 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
947 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
949 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
951 src_pixmap = pix[PIX_MORE];
952 drawing_gc = clip_gc[PIX_MORE];
953 graphic -= GFX_START_ROCKSMORE;
954 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
955 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
957 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
959 src_pixmap = pix[PIX_HEROES];
960 drawing_gc = clip_gc[PIX_HEROES];
961 graphic -= GFX_START_ROCKSHEROES;
962 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
963 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
965 else /* big font graphics currently not allowed (and not needed) */
968 dest_x = FX + x * TILEX + dx;
969 dest_y = FY + y * TILEY + dy;
972 if (!IN_SCR_FIELD(x,y))
974 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
975 printf("DrawGraphicShifted(): This should never happen!\n");
980 if (mask_mode == USE_MASKING)
982 if (tile_clipmask[tile] != None)
984 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
985 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
986 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
987 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
992 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
995 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
996 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
997 src_x, src_y, width, height, dest_x, dest_y);
1001 XCopyArea(display, src_pixmap, drawto_field, gc,
1002 src_x, src_y, width, height, dest_x, dest_y);
1007 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1010 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1013 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1014 int cut_mode, int mask_mode)
1016 int ux = LEVELX(x), uy = LEVELY(y);
1017 int graphic = el2gfx(element);
1018 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1019 int phase4 = phase8 / 2;
1020 int phase2 = phase8 / 4;
1021 int dir = MovDir[ux][uy];
1023 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1025 graphic += 4 * !phase2;
1029 else if (dir == MV_LEFT)
1031 else if (dir == MV_DOWN)
1034 else if (element == EL_SP_SNIKSNAK)
1037 graphic = GFX_SP_SNIKSNAK_LEFT;
1038 else if (dir == MV_RIGHT)
1039 graphic = GFX_SP_SNIKSNAK_RIGHT;
1040 else if (dir == MV_UP)
1041 graphic = GFX_SP_SNIKSNAK_UP;
1043 graphic = GFX_SP_SNIKSNAK_DOWN;
1045 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1047 else if (element == EL_SP_ELECTRON)
1049 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1051 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1052 element == EL_SCHWEIN || element == EL_DRACHE)
1055 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1056 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1057 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1058 else if (dir == MV_RIGHT)
1059 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1060 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1061 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1062 else if (dir == MV_UP)
1063 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1064 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1065 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1067 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1068 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1069 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1073 else if (element == EL_SONDE)
1075 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1077 else if (element == EL_SALZSAEURE)
1079 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1081 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1085 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
1087 if (element != EL_SP_INFOTRON)
1088 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1090 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1091 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1093 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1095 else if (IS_AMOEBOID(element))
1097 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1098 graphic += (x + 2 * y + 4) % 4;
1100 else if (element == EL_MAUER_LEBT)
1102 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1104 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1105 links_massiv = TRUE;
1106 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1107 rechts_massiv = TRUE;
1109 if (links_massiv && rechts_massiv)
1110 graphic = GFX_MAUERWERK;
1111 else if (links_massiv)
1112 graphic = GFX_MAUER_R;
1113 else if (rechts_massiv)
1114 graphic = GFX_MAUER_L;
1118 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1119 else if (mask_mode == USE_MASKING)
1120 DrawGraphicThruMask(x, y, graphic);
1122 DrawGraphic(x, y, graphic);
1125 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1126 int cut_mode, int mask_mode)
1128 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1129 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1130 cut_mode, mask_mode);
1133 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1136 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1139 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1142 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1145 void DrawScreenElementThruMask(int x, int y, int element)
1147 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1150 void DrawLevelElementThruMask(int x, int y, int element)
1152 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1155 void DrawLevelFieldThruMask(int x, int y)
1157 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1160 void ErdreichAnbroeckeln(int x, int y)
1162 int i, width, height, cx,cy;
1163 int ux = LEVELX(x), uy = LEVELY(y);
1164 int element, graphic;
1166 static int xy[4][2] =
1174 if (!IN_LEV_FIELD(ux, uy))
1177 element = Feld[ux][uy];
1179 if (element == EL_ERDREICH)
1181 if (!IN_SCR_FIELD(x, y))
1184 graphic = GFX_ERDENRAND;
1190 uxx = ux + xy[i][0];
1191 uyy = uy + xy[i][1];
1192 if (!IN_LEV_FIELD(uxx, uyy))
1195 element = Feld[uxx][uyy];
1197 if (element == EL_ERDREICH)
1200 if (i == 1 || i == 2)
1204 cx = (i == 2 ? TILEX - snip : 0);
1212 cy = (i == 3 ? TILEY - snip : 0);
1215 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1216 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1217 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1218 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1221 MarkTileDirty(x, y);
1225 graphic = GFX_ERDENRAND;
1229 int xx, yy, uxx, uyy;
1233 uxx = ux + xy[i][0];
1234 uyy = uy + xy[i][1];
1236 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1237 !IN_SCR_FIELD(xx, yy))
1240 if (i == 1 || i == 2)
1244 cx = (i == 1 ? TILEX - snip : 0);
1252 cy = (i==0 ? TILEY-snip : 0);
1255 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1256 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1257 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1258 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1260 MarkTileDirty(xx, yy);
1265 void DrawScreenElement(int x, int y, int element)
1267 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1268 ErdreichAnbroeckeln(x, y);
1271 void DrawLevelElement(int x, int y, int element)
1273 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1274 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1277 void DrawScreenField(int x, int y)
1279 int ux = LEVELX(x), uy = LEVELY(y);
1282 if (!IN_LEV_FIELD(ux, uy))
1284 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1285 element = EL_LEERRAUM;
1287 element = BorderElement;
1289 DrawScreenElement(x, y, element);
1293 element = Feld[ux][uy];
1295 if (IS_MOVING(ux, uy))
1297 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1298 boolean cut_mode = NO_CUTTING;
1300 if (Store[ux][uy] == EL_MORAST_LEER ||
1301 Store[ux][uy] == EL_SIEB_LEER ||
1302 Store[ux][uy] == EL_SIEB2_LEER ||
1303 Store[ux][uy] == EL_AMOEBE_NASS)
1304 cut_mode = CUT_ABOVE;
1305 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1306 Store[ux][uy] == EL_SIEB_VOLL ||
1307 Store[ux][uy] == EL_SIEB2_VOLL)
1308 cut_mode = CUT_BELOW;
1310 if (cut_mode == CUT_ABOVE)
1311 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1313 DrawScreenElement(x, y, EL_LEERRAUM);
1316 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1318 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1320 if (Store[ux][uy] == EL_SALZSAEURE)
1321 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1323 else if (IS_BLOCKED(ux, uy))
1328 boolean cut_mode = NO_CUTTING;
1330 Blocked2Moving(ux, uy, &oldx, &oldy);
1333 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1334 MovDir[oldx][oldy] == MV_RIGHT);
1336 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1337 Store[oldx][oldy] == EL_SIEB_LEER ||
1338 Store[oldx][oldy] == EL_SIEB2_LEER ||
1339 Store[oldx][oldy] == EL_AMOEBE_NASS)
1340 cut_mode = CUT_ABOVE;
1342 DrawScreenElement(x, y, EL_LEERRAUM);
1343 element = Feld[oldx][oldy];
1346 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1348 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1350 else if (IS_DRAWABLE(element))
1351 DrawScreenElement(x, y, element);
1353 DrawScreenElement(x, y, EL_LEERRAUM);
1356 void DrawLevelField(int x, int y)
1358 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1359 DrawScreenField(SCREENX(x), SCREENY(y));
1360 else if (IS_MOVING(x, y))
1364 Moving2Blocked(x, y, &newx, &newy);
1365 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1366 DrawScreenField(SCREENX(newx), SCREENY(newy));
1368 else if (IS_BLOCKED(x, y))
1372 Blocked2Moving(x, y, &oldx, &oldy);
1373 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1374 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1378 void DrawMiniElement(int x, int y, int element)
1384 DrawMiniGraphic(x, y, -1);
1388 graphic = el2gfx(element);
1389 DrawMiniGraphic(x, y, graphic);
1392 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1394 int x = sx + scroll_x, y = sy + scroll_y;
1396 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1397 DrawMiniElement(sx, sy, EL_LEERRAUM);
1398 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1399 DrawMiniElement(sx, sy, Feld[x][y]);
1402 int steel_type, steel_position;
1405 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1406 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1407 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1408 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1409 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1410 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1413 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1414 steel_position = (x == -1 && y == -1 ? 0 :
1415 x == lev_fieldx && y == -1 ? 1 :
1416 x == -1 && y == lev_fieldy ? 2 :
1417 x == lev_fieldx && y == lev_fieldy ? 3 :
1418 x == -1 || x == lev_fieldx ? 4 :
1419 y == -1 || y == lev_fieldy ? 5 : -1);
1421 if (steel_position != -1)
1422 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1426 if (x == -1 && y == -1)
1427 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_LEFT);
1428 else if (x == lev_fieldx && y == -1)
1429 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_RIGHT);
1430 else if (x == -1 && y == lev_fieldy)
1431 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_LEFT);
1432 else if (x == lev_fieldx && y == lev_fieldy)
1433 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_RIGHT);
1434 else if (x == -1 || x == lev_fieldx)
1435 DrawMiniGraphic(sx, sy, GFX_STEEL_VERTICAL);
1436 else if (y == -1 || y == lev_fieldy)
1437 DrawMiniGraphic(sx, sy, GFX_STEEL_HORIZONTAL);
1444 void DrawMicroElement(int xpos, int ypos, int element)
1448 if (element == EL_LEERRAUM)
1451 graphic = el2gfx(element);
1453 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1455 graphic -= GFX_START_ROCKSMORE;
1456 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1457 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1458 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1459 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1462 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1463 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1464 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1465 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1474 for(x=BX1; x<=BX2; x++)
1475 for(y=BY1; y<=BY2; y++)
1476 DrawScreenField(x, y);
1478 if (setup.soft_scrolling)
1479 XCopyArea(display, fieldbuffer, backbuffer, gc,
1480 FX, FY, SXSIZE, SYSIZE, SX, SY);
1482 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1485 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1489 for(x=0; x<size_x; x++)
1490 for(y=0; y<size_y; y++)
1491 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1493 redraw_mask |= REDRAW_FIELD;
1496 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1500 /* determine border element for this level */
1503 XFillRectangle(display, drawto, gc,
1504 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1506 if (lev_fieldx < STD_LEV_FIELDX)
1507 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1508 if (lev_fieldy < STD_LEV_FIELDY)
1509 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1511 xpos += MICRO_TILEX;
1512 ypos += MICRO_TILEY;
1514 for(x=-1; x<=STD_LEV_FIELDX; x++)
1516 for(y=-1; y<=STD_LEV_FIELDY; y++)
1518 int lx = from_x + x, ly = from_y + y;
1520 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1521 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1523 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1524 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1529 redraw_mask |= REDRAW_MICROLEVEL;
1532 static void DrawMicroLevelLabelExt(int mode)
1534 char label_text[100];
1536 XFillRectangle(display, drawto,gc,
1537 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1539 strcpy(label_text, (mode == 1 ? level.name :
1540 mode == 2 ? "created by" :
1541 mode == 3 ? level.author : ""));
1543 if (strlen(label_text) > 0)
1545 int size, lxpos, lypos;
1547 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1549 size = strlen(label_text);
1550 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1551 lypos = MICROLABEL_YPOS;
1553 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1556 redraw_mask |= REDRAW_MICROLEVEL;
1559 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1561 static unsigned long scroll_delay = 0;
1562 static unsigned long label_delay = 0;
1563 static int from_x, from_y, scroll_direction;
1564 static int label_state, label_counter;
1568 from_x = from_y = 0;
1569 scroll_direction = MV_RIGHT;
1573 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1574 DrawMicroLevelLabelExt(label_state);
1576 /* initialize delay counters */
1577 DelayReached(&scroll_delay, 0);
1578 DelayReached(&label_delay, 0);
1583 /* scroll micro level, if needed */
1584 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1585 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1587 switch (scroll_direction)
1593 scroll_direction = MV_UP;
1597 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1600 scroll_direction = MV_DOWN;
1607 scroll_direction = MV_RIGHT;
1611 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1614 scroll_direction = MV_LEFT;
1621 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1624 /* redraw micro level label, if needed */
1625 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1626 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1627 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1628 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1630 label_counter = (label_counter + 1) % 23;
1631 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1632 label_counter >= 9 && label_counter <= 12 ? 2 :
1633 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1634 DrawMicroLevelLabelExt(label_state);
1638 int REQ_in_range(int x, int y)
1640 if (y > DY+249 && y < DY+278)
1642 if (x > DX+1 && x < DX+48)
1644 else if (x > DX+51 && x < DX+98)
1650 boolean Request(char *text, unsigned int req_state)
1652 int mx, my, ty, result = -1;
1653 unsigned int old_door_state;
1656 /* pause network game while waiting for request to answer */
1657 if (options.network &&
1658 game_status == PLAYING &&
1659 req_state & REQUEST_WAIT_FOR)
1660 SendToServer_PausePlaying();
1663 old_door_state = GetDoorState();
1667 CloseDoor(DOOR_CLOSE_1);
1669 /* save old door content */
1670 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1671 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1672 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1674 /* clear door drawing field */
1676 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1677 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1679 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1682 /* write text for request */
1683 for(ty=0; ty<13; ty++)
1691 for(tl=0,tx=0; tx<7; tl++,tx++)
1694 if (!tc || tc == 32)
1706 DrawTextExt(pix[PIX_DB_DOOR], gc,
1707 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1708 txt, FS_SMALL, FC_YELLOW);
1710 DrawTextExt(drawto, gc,
1711 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1712 txt, FS_SMALL, FC_YELLOW);
1714 text += tl + (tc == 32 ? 1 : 0);
1718 if (req_state & REQ_ASK)
1720 DrawYesNoButton(BUTTON_OK, DB_INIT);
1721 DrawYesNoButton(BUTTON_NO, DB_INIT);
1723 else if (req_state & REQ_CONFIRM)
1725 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1727 else if (req_state & REQ_PLAYER)
1729 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1730 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1731 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1732 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1736 if (req_state & REQ_ASK)
1738 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1739 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1741 else if (req_state & REQ_CONFIRM)
1743 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1745 else if (req_state & REQ_PLAYER)
1747 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1748 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1749 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1750 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1753 /* copy request gadgets to door backbuffer */
1754 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1755 DX, DY, DXSIZE, DYSIZE,
1756 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1760 OpenDoor(DOOR_OPEN_1);
1763 if (!(req_state & REQUEST_WAIT_FOR))
1766 if (game_status != MAINMENU)
1769 button_status = MB_RELEASED;
1771 request_gadget_id = -1;
1775 if (XPending(display))
1779 XNextEvent(display, &event);
1792 if (event.type == MotionNotify)
1799 if (!XQueryPointer(display, window, &root, &child,
1800 &root_x, &root_y, &win_x, &win_y, &mask))
1806 motion_status = TRUE;
1807 mx = ((XMotionEvent *) &event)->x;
1808 my = ((XMotionEvent *) &event)->y;
1812 motion_status = FALSE;
1813 mx = ((XButtonEvent *) &event)->x;
1814 my = ((XButtonEvent *) &event)->y;
1815 if (event.type==ButtonPress)
1816 button_status = ((XButtonEvent *) &event)->button;
1818 button_status = MB_RELEASED;
1824 if (req_state & REQ_ASK)
1825 choice = CheckYesNoButtons(mx,my,button_status);
1826 else if (req_state & REQ_CONFIRM)
1827 choice = CheckConfirmButton(mx,my,button_status);
1829 choice = CheckPlayerButtons(mx,my,button_status);
1839 case BUTTON_CONFIRM:
1840 result = TRUE | FALSE;
1843 case BUTTON_PLAYER_1:
1846 case BUTTON_PLAYER_2:
1849 case BUTTON_PLAYER_3:
1852 case BUTTON_PLAYER_4:
1861 /* this sets 'request_gadget_id' */
1862 HandleGadgets(mx, my, button_status);
1864 switch(request_gadget_id)
1866 case TOOL_CTRL_ID_YES:
1869 case TOOL_CTRL_ID_NO:
1872 case TOOL_CTRL_ID_CONFIRM:
1873 result = TRUE | FALSE;
1876 case TOOL_CTRL_ID_PLAYER_1:
1879 case TOOL_CTRL_ID_PLAYER_2:
1882 case TOOL_CTRL_ID_PLAYER_3:
1885 case TOOL_CTRL_ID_PLAYER_4:
1898 switch(XLookupKeysym((XKeyEvent *)&event,
1899 ((XKeyEvent *)&event)->state))
1912 if (req_state & REQ_PLAYER)
1917 key_joystick_mapping = 0;
1921 HandleOtherEvents(&event);
1925 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1927 int joy = AnyJoystick();
1929 if (joy & JOY_BUTTON_1)
1931 else if (joy & JOY_BUTTON_2)
1937 /* don't eat all CPU time */
1941 if (game_status != MAINMENU)
1946 if (!(req_state & REQ_STAY_OPEN))
1948 CloseDoor(DOOR_CLOSE_1);
1950 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1952 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1953 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1954 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1955 OpenDoor(DOOR_OPEN_1);
1962 /* continue network game after request */
1963 if (options.network &&
1964 game_status == PLAYING &&
1965 req_state & REQUEST_WAIT_FOR)
1966 SendToServer_ContinuePlaying();
1972 unsigned int OpenDoor(unsigned int door_state)
1974 unsigned int new_door_state;
1976 if (door_state & DOOR_COPY_BACK)
1978 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1979 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1980 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1981 door_state &= ~DOOR_COPY_BACK;
1984 new_door_state = MoveDoor(door_state);
1986 return(new_door_state);
1989 unsigned int CloseDoor(unsigned int door_state)
1991 unsigned int new_door_state;
1993 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1994 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1995 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1996 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1998 new_door_state = MoveDoor(door_state);
2000 return(new_door_state);
2003 unsigned int GetDoorState()
2005 return(MoveDoor(DOOR_GET_STATE));
2008 unsigned int MoveDoor(unsigned int door_state)
2010 static int door1 = DOOR_OPEN_1;
2011 static int door2 = DOOR_CLOSE_2;
2012 static unsigned long door_delay = 0;
2013 int x, start, stepsize = 2;
2014 unsigned long door_delay_value = stepsize * 5;
2016 if (door_state == DOOR_GET_STATE)
2017 return(door1 | door2);
2019 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2020 door_state &= ~DOOR_OPEN_1;
2021 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2022 door_state &= ~DOOR_CLOSE_1;
2023 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2024 door_state &= ~DOOR_OPEN_2;
2025 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2026 door_state &= ~DOOR_CLOSE_2;
2028 if (setup.quick_doors)
2031 door_delay_value = 0;
2032 StopSound(SND_OEFFNEN);
2035 if (door_state & DOOR_ACTION)
2037 if (!(door_state & DOOR_NO_DELAY))
2038 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2040 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2042 for(x=start; x<=DXSIZE; x+=stepsize)
2044 WaitUntilDelayReached(&door_delay, door_delay_value);
2046 if (door_state & DOOR_ACTION_1)
2048 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2049 int j = (DXSIZE - i) / 3;
2051 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2052 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2053 DXSIZE,DYSIZE - i/2, DX, DY);
2055 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2057 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2058 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2059 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2060 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2061 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2062 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2064 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2065 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2066 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2067 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2068 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2069 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2071 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2072 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2074 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2075 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2077 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2078 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2079 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2080 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2081 DX + DXSIZE - i, DY + 77 + j);
2082 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2083 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2084 DX + DXSIZE - i, DY + 203 + j);
2086 redraw_mask |= REDRAW_DOOR_1;
2089 if (door_state & DOOR_ACTION_2)
2091 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2092 int j = (VXSIZE - i) / 3;
2094 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2095 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2096 VXSIZE, VYSIZE - i/2, VX, VY);
2098 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2100 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2101 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2102 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2103 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2104 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2105 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2106 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2107 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2109 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2110 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2111 VX, VY + VYSIZE / 2 - j);
2112 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2113 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2114 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2115 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2116 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2118 redraw_mask |= REDRAW_DOOR_2;
2126 XCopyArea(display, drawto, window, gc, DX, DY, DXSIZE, DYSIZE, DX, DY);
2131 if (game_status == MAINMENU)
2136 if (setup.quick_doors)
2137 StopSound(SND_OEFFNEN);
2139 if (door_state & DOOR_ACTION_1)
2140 door1 = door_state & DOOR_ACTION_1;
2141 if (door_state & DOOR_ACTION_2)
2142 door2 = door_state & DOOR_ACTION_2;
2144 return(door1 | door2);
2147 int ReadPixel(Drawable d, int x, int y)
2149 XImage *pixel_image;
2150 unsigned long pixel_value;
2152 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2153 pixel_value = XGetPixel(pixel_image, 0, 0);
2155 XDestroyImage(pixel_image);
2160 /* ---------- new tool button stuff ---------------------------------------- */
2162 /* graphic position values for tool buttons */
2163 #define TOOL_BUTTON_YES_XPOS 2
2164 #define TOOL_BUTTON_YES_YPOS 250
2165 #define TOOL_BUTTON_YES_GFX_YPOS 0
2166 #define TOOL_BUTTON_YES_XSIZE 46
2167 #define TOOL_BUTTON_YES_YSIZE 28
2168 #define TOOL_BUTTON_NO_XPOS 52
2169 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2170 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2171 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2172 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2173 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2174 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2175 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2176 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2177 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2178 #define TOOL_BUTTON_PLAYER_XSIZE 30
2179 #define TOOL_BUTTON_PLAYER_YSIZE 30
2180 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2181 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2182 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2183 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2184 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2185 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2186 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2187 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2188 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2189 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2190 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2191 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2192 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2193 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2194 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2195 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2196 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2197 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2198 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2199 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2208 } toolbutton_info[NUM_TOOL_BUTTONS] =
2211 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2212 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2213 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2218 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2219 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2220 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2225 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2226 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2227 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2228 TOOL_CTRL_ID_CONFIRM,
2232 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2233 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2234 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2235 TOOL_CTRL_ID_PLAYER_1,
2239 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2240 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2241 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2242 TOOL_CTRL_ID_PLAYER_2,
2246 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2247 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2248 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2249 TOOL_CTRL_ID_PLAYER_3,
2253 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2254 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2255 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2256 TOOL_CTRL_ID_PLAYER_4,
2261 void CreateToolButtons()
2265 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2267 Pixmap gd_pixmap = pix[PIX_DOOR];
2268 Pixmap deco_pixmap = 0;
2269 int deco_x, deco_y, deco_xpos, deco_ypos;
2270 struct GadgetInfo *gi;
2271 unsigned long event_mask;
2272 int gd_xoffset, gd_yoffset;
2273 int gd_x1, gd_x2, gd_y;
2276 event_mask = GD_EVENT_RELEASED;
2278 gd_xoffset = toolbutton_info[i].xpos;
2279 gd_yoffset = toolbutton_info[i].ypos;
2280 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2281 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2282 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2284 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2286 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2287 &deco_pixmap, &deco_x, &deco_y);
2288 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2289 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2292 gi = CreateGadget(GDI_CUSTOM_ID, id,
2293 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2294 GDI_X, DX + toolbutton_info[i].x,
2295 GDI_Y, DY + toolbutton_info[i].y,
2296 GDI_WIDTH, toolbutton_info[i].width,
2297 GDI_HEIGHT, toolbutton_info[i].height,
2298 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2299 GDI_STATE, GD_BUTTON_UNPRESSED,
2300 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2301 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2302 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2303 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2304 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2305 GDI_DECORATION_SHIFTING, 1, 1,
2306 GDI_EVENT_MASK, event_mask,
2307 GDI_CALLBACK_ACTION, HandleToolButtons,
2311 Error(ERR_EXIT, "cannot create gadget");
2313 tool_gadget[id] = gi;
2317 static void UnmapToolButtons()
2321 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2322 UnmapGadget(tool_gadget[i]);
2325 static void HandleToolButtons(struct GadgetInfo *gi)
2327 request_gadget_id = gi->custom_id;
2331 int id = gi->custom_id;
2333 if (game_status != PLAYING)
2338 case GAME_CTRL_ID_STOP:
2341 CloseDoor(DOOR_CLOSE_1);
2342 game_status = MAINMENU;
2347 if (Request("Do you really want to quit the game ?",
2348 REQ_ASK | REQ_STAY_CLOSED))
2351 if (options.network)
2352 SendToServer_StopPlaying();
2356 game_status = MAINMENU;
2361 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2364 case GAME_CTRL_ID_PAUSE:
2365 if (options.network)
2369 SendToServer_ContinuePlaying();
2371 SendToServer_PausePlaying();
2378 case GAME_CTRL_ID_PLAY:
2382 if (options.network)
2383 SendToServer_ContinuePlaying();
2387 tape.pausing = FALSE;
2388 DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2393 case SOUND_CTRL_ID_MUSIC:
2394 if (setup.sound_music)
2396 setup.sound_music = FALSE;
2397 FadeSound(background_loop[level_nr % num_bg_loops]);
2399 else if (sound_loops_allowed)
2401 setup.sound = setup.sound_music = TRUE;
2402 PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
2406 case SOUND_CTRL_ID_LOOPS:
2407 if (setup.sound_loops)
2408 setup.sound_loops = FALSE;
2409 else if (sound_loops_allowed)
2410 setup.sound = setup.sound_loops = TRUE;
2413 case SOUND_CTRL_ID_SIMPLE:
2414 if (setup.sound_simple)
2415 setup.sound_simple = FALSE;
2416 else if (sound_status==SOUND_AVAILABLE)
2417 setup.sound = setup.sound_simple = TRUE;
2429 int el2gfx(int element)
2433 case EL_LEERRAUM: return -1;
2434 case EL_ERDREICH: return GFX_ERDREICH;
2435 case EL_MAUERWERK: return GFX_MAUERWERK;
2436 case EL_FELSBODEN: return GFX_FELSBODEN;
2437 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2438 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2439 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2440 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2441 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2442 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2443 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2444 case EL_SPIELER1: return GFX_SPIELER1;
2445 case EL_SPIELER2: return GFX_SPIELER2;
2446 case EL_SPIELER3: return GFX_SPIELER3;
2447 case EL_SPIELER4: return GFX_SPIELER4;
2448 case EL_KAEFER: return GFX_KAEFER;
2449 case EL_KAEFER_R: return GFX_KAEFER_R;
2450 case EL_KAEFER_O: return GFX_KAEFER_O;
2451 case EL_KAEFER_L: return GFX_KAEFER_L;
2452 case EL_KAEFER_U: return GFX_KAEFER_U;
2453 case EL_FLIEGER: return GFX_FLIEGER;
2454 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2455 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2456 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2457 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2458 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2459 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2460 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2461 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2462 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2463 case EL_FIREFLY: return GFX_FIREFLY;
2464 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2465 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2466 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2467 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2468 case EL_MAMPFER: return GFX_MAMPFER;
2469 case EL_ROBOT: return GFX_ROBOT;
2470 case EL_BETON: return GFX_BETON;
2471 case EL_DIAMANT: return GFX_DIAMANT;
2472 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2473 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2474 case EL_TROPFEN: return GFX_TROPFEN;
2475 case EL_BOMBE: return GFX_BOMBE;
2476 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2477 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2478 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2479 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2480 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2481 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2482 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2483 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2484 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2485 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2486 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2487 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2488 case EL_LIFE: return GFX_LIFE;
2489 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2490 case EL_DYNAMIT: return GFX_DYNAMIT;
2491 case EL_BADEWANNE: return GFX_BADEWANNE;
2492 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2493 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2494 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2495 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2496 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2497 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2498 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2499 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2500 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2501 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2502 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2503 case EL_PFORTE1: return GFX_PFORTE1;
2504 case EL_PFORTE2: return GFX_PFORTE2;
2505 case EL_PFORTE3: return GFX_PFORTE3;
2506 case EL_PFORTE4: return GFX_PFORTE4;
2507 case EL_PFORTE1X: return GFX_PFORTE1X;
2508 case EL_PFORTE2X: return GFX_PFORTE2X;
2509 case EL_PFORTE3X: return GFX_PFORTE3X;
2510 case EL_PFORTE4X: return GFX_PFORTE4X;
2511 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2512 case EL_PACMAN: return GFX_PACMAN;
2513 case EL_PACMAN_R: return GFX_PACMAN_R;
2514 case EL_PACMAN_O: return GFX_PACMAN_O;
2515 case EL_PACMAN_L: return GFX_PACMAN_L;
2516 case EL_PACMAN_U: return GFX_PACMAN_U;
2517 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2518 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2519 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2520 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2521 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2522 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2523 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2524 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2525 case EL_MAUER_X: return GFX_MAUER_X;
2526 case EL_MAUER_Y: return GFX_MAUER_Y;
2527 case EL_MAUER_XY: return GFX_MAUER_XY;
2528 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2529 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2530 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2531 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2532 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2533 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2534 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2535 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2536 case EL_MAMPFER2: return GFX_MAMPFER2;
2537 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2538 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2539 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2540 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2541 case EL_DYNABOMB: return GFX_DYNABOMB;
2542 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2543 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2544 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2545 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2546 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2547 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2548 case EL_MAULWURF: return GFX_MAULWURF;
2549 case EL_PINGUIN: return GFX_PINGUIN;
2550 case EL_SCHWEIN: return GFX_SCHWEIN;
2551 case EL_DRACHE: return GFX_DRACHE;
2552 case EL_SONDE: return GFX_SONDE;
2553 case EL_PFEIL_L: return GFX_PFEIL_L;
2554 case EL_PFEIL_R: return GFX_PFEIL_R;
2555 case EL_PFEIL_O: return GFX_PFEIL_O;
2556 case EL_PFEIL_U: return GFX_PFEIL_U;
2557 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2558 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2559 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2560 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2564 if (IS_CHAR(element))
2565 return GFX_CHAR_START + (element - EL_CHAR_START);
2566 else if (element >= EL_SP_START && element <= EL_SP_END)
2568 int nr_element = element - EL_SP_START;
2569 int gfx_per_line = 8;
2571 (nr_element / gfx_per_line) * MORE_PER_LINE +
2572 (nr_element % gfx_per_line);
2574 return GFX_START_ROCKSMORE + nr_graphic;