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;
98 if (redraw_mask & REDRAW_FIELD ||
99 (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING))
100 redraw_mask &= ~REDRAW_TILES;
106 /* synchronize X11 graphics at this point; if we would synchronize the
107 display immediately after the buffer switching (after the XFlush),
108 this could mean that we have to wait for the graphics to complete,
109 although we could go on doing calculations for the next frame */
111 XSync(display, FALSE);
115 wait_for_vsync = TRUE;
119 if (redraw_mask & REDRAW_ALL)
121 XCopyArea(display, backbuffer, window, gc,
122 0, 0, WIN_XSIZE, WIN_YSIZE,
127 if (redraw_mask & REDRAW_FIELD)
129 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
131 XCopyArea(display, backbuffer, window, gc,
132 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
137 int fx = FX, fy = FY;
139 if (setup.soft_scrolling)
141 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
142 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
145 if (setup.soft_scrolling ||
146 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
147 ABS(ScreenMovPos) == ScrollStepSize ||
148 redraw_tiles > REDRAWTILES_THRESHOLD)
150 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
154 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
156 (setup.soft_scrolling ?
157 "setup.soft_scrolling" :
158 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
159 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
160 ABS(ScreenGfxPos) == ScrollStepSize ?
161 "ABS(ScreenGfxPos) == ScrollStepSize" :
162 "redraw_tiles > REDRAWTILES_THRESHOLD"));
167 redraw_mask &= ~REDRAW_MAIN;
170 if (redraw_mask & REDRAW_DOORS)
172 if (redraw_mask & REDRAW_DOOR_1)
173 XCopyArea(display, backbuffer, window, gc,
174 DX, DY, DXSIZE, DYSIZE,
176 if (redraw_mask & REDRAW_DOOR_2)
178 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
179 XCopyArea(display,backbuffer,window,gc,
180 VX,VY, VXSIZE,VYSIZE,
184 if (redraw_mask & REDRAW_VIDEO_1)
185 XCopyArea(display,backbuffer,window,gc,
186 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
187 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
188 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
189 if (redraw_mask & REDRAW_VIDEO_2)
190 XCopyArea(display,backbuffer,window,gc,
191 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
192 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
193 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
194 if (redraw_mask & REDRAW_VIDEO_3)
195 XCopyArea(display,backbuffer,window,gc,
196 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
197 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
198 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
201 if (redraw_mask & REDRAW_DOOR_3)
202 XCopyArea(display, backbuffer, window, gc,
203 EX, EY, EXSIZE, EYSIZE,
205 redraw_mask &= ~REDRAW_DOORS;
208 if (redraw_mask & REDRAW_MICROLEVEL)
210 XCopyArea(display,backbuffer,window,gc,
211 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
212 MICROLEV_XPOS, MICROLEV_YPOS);
213 XCopyArea(display,backbuffer,window,gc,
214 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
215 SX, MICROLABEL_YPOS);
216 redraw_mask &= ~REDRAW_MICROLEVEL;
219 if (redraw_mask & REDRAW_TILES)
221 for(x=0; x<SCR_FIELDX; x++)
222 for(y=0; y<SCR_FIELDY; y++)
223 if (redraw[redraw_x1 + x][redraw_y1 + y])
224 XCopyArea(display, buffer, window, gc,
225 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
226 SX + x * TILEX, SY + y * TILEY);
231 for(x=0; x<MAX_BUF_XSIZE; x++)
232 for(y=0; y<MAX_BUF_YSIZE; y++)
241 long fading_delay = 300;
243 if (setup.fading && (redraw_mask & REDRAW_FIELD))
250 XFillRectangle(display,window,gc,
251 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
254 for(i=0;i<2*FULL_SYSIZE;i++)
256 for(y=0;y<FULL_SYSIZE;y++)
258 XCopyArea(display,backbuffer,window,gc,
259 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
267 for(i=1;i<FULL_SYSIZE;i+=2)
268 XCopyArea(display,backbuffer,window,gc,
269 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
275 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
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,-1);
282 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
283 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
287 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
288 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
289 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
293 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
294 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
295 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
299 redraw_mask &= ~REDRAW_MAIN;
308 XFillRectangle(display, backbuffer, gc,
309 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
311 if (setup.soft_scrolling && game_status == PLAYING)
313 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
314 SetDrawtoField(DRAW_BUFFERED);
317 SetDrawtoField(DRAW_BACKBUFFER);
319 if (setup.direct_draw && game_status == PLAYING)
321 XFillRectangle(display, window, gc,
322 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
323 SetDrawtoField(DRAW_DIRECT);
326 redraw_mask |= REDRAW_FIELD;
329 void DrawTextFCentered(int y, int font_type, char *format, ...)
331 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
335 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
336 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
338 va_start(ap, format);
339 vsprintf(buffer, format, ap);
342 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
343 buffer, FS_SMALL, font_type);
346 void DrawTextF(int x, int y, int font_type, char *format, ...)
348 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
351 va_start(ap, format);
352 vsprintf(buffer, format, ap);
355 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
358 void DrawText(int x, int y, char *text, int font_size, int font_type)
360 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
363 redraw_mask |= REDRAW_FIELD;
365 redraw_mask |= REDRAW_DOOR_1;
368 void DrawTextExt(Drawable d, GC gc, int x, int y,
369 char *text, int font_size, int font_type)
371 int font_width, font_height, font_start;
373 boolean print_inverse = FALSE;
375 if (font_size != FS_SMALL && font_size != FS_BIG)
376 font_size = FS_SMALL;
377 if (font_type < FC_RED || font_type > FC_SPECIAL2)
380 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
381 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
382 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
383 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
384 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
385 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
386 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
387 FONT_LINES_PER_FONT);
393 if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
395 print_inverse = TRUE;
399 if (c >= 'a' && c <= 'z')
401 else if (c == 'ä' || c == 'Ä')
403 else if (c == 'ö' || c == 'Ö')
405 else if (c == 'ü' || c == 'Ü')
408 if (c >= 32 && c <= 95)
410 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
411 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
412 int dest_x = x, dest_y = y;
416 XCopyArea(display, pix[font_pixmap], d, gc,
417 FONT_CHARS_PER_LINE * font_width,
418 3 * font_height + font_start,
419 font_width, font_height, x, y);
421 XSetClipOrigin(display, clip_gc[font_pixmap],
422 dest_x - src_x, dest_y - src_y);
423 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
424 0, 0, font_width, font_height, dest_x, dest_y);
427 XCopyArea(display, pix[font_pixmap], d, gc,
428 src_x, src_y, font_width, font_height, dest_x, dest_y);
435 void DrawAllPlayers()
439 for(i=0; i<MAX_PLAYERS; i++)
440 if (stored_player[i].active)
441 DrawPlayer(&stored_player[i]);
444 void DrawPlayerField(int x, int y)
449 DrawPlayer(PLAYERINFO(x,y));
452 void DrawPlayer(struct PlayerInfo *player)
454 int jx = player->jx, jy = player->jy;
455 int last_jx = player->last_jx, last_jy = player->last_jy;
456 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
457 int sx = SCREENX(jx), sy = SCREENY(jy);
458 int sxx = 0, syy = 0;
459 int element = Feld[jx][jy];
462 if (!player->active || player->gone ||
463 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
467 if (!IN_LEV_FIELD(jx,jy))
469 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
470 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
471 printf("DrawPlayerField(): This should never happen!\n");
476 if (element == EL_EXPLODING)
479 /* draw things in the field the player is leaving, if needed */
481 if (last_jx != jx || last_jy != jy)
483 if (Store[last_jx][last_jy] && IS_DRAWABLE(Feld[last_jx][last_jy]))
485 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
486 DrawLevelFieldThruMask(last_jx, last_jy);
488 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
489 DrawDynamite(last_jx, last_jy);
491 DrawLevelField(last_jx, last_jy);
493 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
497 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
498 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
500 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
503 DrawLevelField(next_jx, next_jy);
507 if (!IN_SCR_FIELD(sx, sy))
510 if (setup.direct_draw)
511 SetDrawtoField(DRAW_BUFFERED);
513 /* draw things behind the player, if needed */
516 DrawLevelElement(jx, jy, Store[jx][jy]);
517 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
518 DrawLevelField(jx, jy);
520 /* draw player himself */
522 if (game_emulation == EMU_SUPAPLEX)
524 static int last_dir = MV_LEFT;
525 boolean action_moving =
526 ((player->action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
527 !(player->action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)));
529 graphic = GFX_SP_MURPHY;
533 if (player->MovDir == MV_LEFT)
534 graphic = GFX_MURPHY_PUSH_LEFT;
535 else if (player->MovDir == MV_RIGHT)
536 graphic = GFX_MURPHY_PUSH_RIGHT;
537 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
538 graphic = GFX_MURPHY_PUSH_LEFT;
539 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
540 graphic = GFX_MURPHY_PUSH_RIGHT;
542 else if (player->snapped)
544 if (player->MovDir == MV_LEFT)
545 graphic = GFX_MURPHY_SNAP_LEFT;
546 else if (player->MovDir == MV_RIGHT)
547 graphic = GFX_MURPHY_SNAP_RIGHT;
548 else if (player->MovDir == MV_UP)
549 graphic = GFX_MURPHY_SNAP_UP;
550 else if (player->MovDir == MV_DOWN)
551 graphic = GFX_MURPHY_SNAP_DOWN;
553 else if (action_moving)
555 if (player->MovDir == MV_LEFT)
556 graphic = GFX_MURPHY_ANY_LEFT;
557 else if (player->MovDir == MV_RIGHT)
558 graphic = GFX_MURPHY_ANY_RIGHT;
559 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
560 graphic = GFX_MURPHY_ANY_LEFT;
561 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
562 graphic = GFX_MURPHY_ANY_RIGHT;
564 graphic -= getGraphicAnimationPhase(2, 4, ANIM_NORMAL);
567 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
568 last_dir = player->MovDir;
572 if (player->MovDir == MV_LEFT)
574 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
575 else if (player->MovDir == MV_RIGHT)
577 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
578 else if (player->MovDir == MV_UP)
579 graphic = GFX_SPIELER1_UP;
580 else /* MV_DOWN || MV_NO_MOVING */
581 graphic = GFX_SPIELER1_DOWN;
583 graphic += player->index_nr * 3 * HEROES_PER_LINE;
584 graphic += player->Frame;
589 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
590 sxx = player->GfxPos;
592 syy = player->GfxPos;
595 if (!setup.soft_scrolling && ScreenMovPos)
598 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
600 if (player->Pushing && player->GfxPos)
602 int px = SCREENX(next_jx), py = SCREENY(next_jy);
604 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
605 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
606 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
610 int element = Feld[next_jx][next_jy];
611 int graphic = el2gfx(element);
613 if (element == EL_FELSBROCKEN && sxx)
615 int phase = (player->GfxPos / (TILEX / 4));
617 if (player->MovDir == MV_LEFT)
620 graphic += (phase + 4) % 4;
622 else if (element == EL_SP_ZONK && sxx)
624 int phase = (player->GfxPos / (TILEX / 4));
626 graphic = GFX2_SP_ZONK;
628 if (player->MovDir == MV_LEFT)
631 graphic += (phase + 4) % 4;
634 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
638 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
640 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
642 graphic = el2gfx(element);
644 if (element == EL_DYNAMIT)
646 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
651 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
655 if (game_emulation == EMU_SUPAPLEX)
656 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
658 DrawGraphicThruMask(sx, sy, graphic + phase);
661 if ((last_jx != jx || last_jy != jy) &&
662 Feld[last_jx][last_jy] == EL_EXPLODING)
664 int phase = Frame[last_jx][last_jy];
668 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
669 GFX_EXPLOSION + ((phase - 1) / delay - 1));
672 if (setup.direct_draw)
674 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
675 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
676 int x_size = TILEX * (1 + ABS(jx - last_jx));
677 int y_size = TILEY * (1 + ABS(jy - last_jy));
679 XCopyArea(display, drawto_field, window, gc,
680 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
681 SetDrawtoField(DRAW_DIRECT);
684 MarkTileDirty(sx,sy);
687 static int getGraphicAnimationPhase(int frames, int delay, int mode)
691 if (mode == ANIM_OSCILLATE)
693 int max_anim_frames = 2 * frames - 2;
694 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
695 phase = (phase < frames ? phase : max_anim_frames - phase);
698 phase = (FrameCounter % (delay * frames)) / delay;
700 if (mode == ANIM_REVERSE)
706 void DrawGraphicAnimationExt(int x, int y, int graphic,
707 int frames, int delay, int mode, int mask_mode)
709 int phase = getGraphicAnimationPhase(frames, delay, mode);
711 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
713 if (mask_mode == USE_MASKING)
714 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
716 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
720 void DrawGraphicAnimation(int x, int y, int graphic,
721 int frames, int delay, int mode)
723 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
726 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
727 int frames, int delay, int mode)
729 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
732 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
734 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
736 graphic -= GFX_START_ROCKSSCREEN;
737 *pixmap_nr = PIX_BACK;
738 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
739 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
741 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
743 graphic -= GFX_START_ROCKSMORE;
744 *pixmap_nr = PIX_MORE;
745 *x = (graphic % MORE_PER_LINE) * TILEX;
746 *y = (graphic / MORE_PER_LINE) * TILEY;
748 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
750 graphic -= GFX_START_ROCKSHEROES;
751 *pixmap_nr = PIX_HEROES;
752 *x = (graphic % HEROES_PER_LINE) * TILEX;
753 *y = (graphic / HEROES_PER_LINE) * TILEY;
755 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
757 graphic -= GFX_START_ROCKSFONT;
758 *pixmap_nr = PIX_BIGFONT;
759 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
760 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
761 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
765 *pixmap_nr = PIX_MORE;
771 void DrawGraphic(int x, int y, int graphic)
774 if (!IN_SCR_FIELD(x,y))
776 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
777 printf("DrawGraphic(): This should never happen!\n");
782 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
786 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
794 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
795 XCopyArea(display, pix[pixmap_nr], d, gc,
796 src_x, src_y, TILEX, TILEY, x, y);
800 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
802 graphic -= GFX_START_ROCKSSCREEN;
803 XCopyArea(display, pix[PIX_BACK], d, gc,
804 SX + (graphic % GFX_PER_LINE) * TILEX,
805 SY + (graphic / GFX_PER_LINE) * TILEY,
808 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
810 graphic -= GFX_START_ROCKSMORE;
811 XCopyArea(display, pix[PIX_MORE], d, gc,
812 (graphic % MORE_PER_LINE) * TILEX,
813 (graphic / MORE_PER_LINE) * TILEY,
816 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
818 graphic -= GFX_START_ROCKSHEROES;
819 XCopyArea(display, pix[PIX_HEROES], d, gc,
820 (graphic % HEROES_PER_LINE) * TILEX,
821 (graphic / HEROES_PER_LINE) * TILEY,
824 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
826 graphic -= GFX_START_ROCKSFONT;
827 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
828 (graphic % FONT_CHARS_PER_LINE) * TILEX,
829 (graphic / FONT_CHARS_PER_LINE) * TILEY +
830 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
834 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
840 void DrawGraphicThruMask(int x, int y, int graphic)
843 if (!IN_SCR_FIELD(x,y))
845 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
846 printf("DrawGraphicThruMask(): This should never happen!\n");
851 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
855 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
866 if (graphic == GFX_LEERRAUM)
869 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
870 src_pixmap = pix[pixmap_nr];
871 drawing_gc = clip_gc[pixmap_nr];
880 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
882 src_pixmap = pix[PIX_BACK];
883 drawing_gc = clip_gc[PIX_BACK];
884 graphic -= GFX_START_ROCKSSCREEN;
885 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
886 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
888 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
890 src_pixmap = pix[PIX_MORE];
891 drawing_gc = clip_gc[PIX_MORE];
892 graphic -= GFX_START_ROCKSMORE;
893 src_x = (graphic % MORE_PER_LINE) * TILEX;
894 src_y = (graphic / MORE_PER_LINE) * TILEY;
896 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
898 src_pixmap = pix[PIX_HEROES];
899 drawing_gc = clip_gc[PIX_HEROES];
900 graphic -= GFX_START_ROCKSHEROES;
901 src_x = (graphic % HEROES_PER_LINE) * TILEX;
902 src_y = (graphic / HEROES_PER_LINE) * TILEY;
906 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
913 if (tile_clipmask[tile] != None)
915 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
916 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
917 XCopyArea(display, src_pixmap, d, tile_clip_gc,
918 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
923 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
926 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
927 XCopyArea(display, src_pixmap, d, drawing_gc,
928 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
932 void DrawMiniGraphic(int x, int y, int graphic)
934 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
935 MarkTileDirty(x/2, y/2);
938 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
940 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
942 graphic -= GFX_START_ROCKSSCREEN;
943 *pixmap = pix[PIX_BACK];
944 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
945 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
947 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
949 graphic -= GFX_START_ROCKSMORE;
950 *pixmap = pix[PIX_MORE];
951 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
952 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
954 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
956 graphic -= GFX_START_ROCKSFONT;
957 *pixmap = pix[PIX_SMALLFONT];
958 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
959 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
960 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
964 *pixmap = pix[PIX_MORE];
965 *x = MINI_MORE_STARTX;
966 *y = MINI_MORE_STARTY;
970 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
978 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
979 XCopyArea(display, pixmap, d, gc,
980 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
984 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
986 graphic -= GFX_START_ROCKSSCREEN;
987 XCopyArea(display, pix[PIX_BACK], d, gc,
988 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
989 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
990 MINI_TILEX, MINI_TILEY, x, y);
992 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
994 graphic -= GFX_START_ROCKSMORE;
995 XCopyArea(display, pix[PIX_MORE], d, gc,
996 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
997 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
998 MINI_TILEX, MINI_TILEY, x, y);
1000 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1002 graphic -= GFX_START_ROCKSFONT;
1003 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
1004 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
1005 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
1006 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
1007 MINI_TILEX, MINI_TILEY, x, y);
1010 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
1016 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1017 int cut_mode, int mask_mode)
1019 int width = TILEX, height = TILEY;
1021 int src_x, src_y, dest_x, dest_y;
1028 DrawGraphic(x, y, graphic);
1032 if (dx || dy) /* Verschiebung der Grafik? */
1034 if (x < BX1) /* Element kommt von links ins Bild */
1041 else if (x > BX2) /* Element kommt von rechts ins Bild */
1047 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1053 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1055 else if (dx) /* allg. Bewegung in x-Richtung */
1056 MarkTileDirty(x + SIGN(dx), y);
1058 if (y < BY1) /* Element kommt von oben ins Bild */
1060 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1068 else if (y > BY2) /* Element kommt von unten ins Bild */
1074 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1080 else if (dy > 0 && cut_mode == CUT_ABOVE)
1082 if (y == BY2) /* Element unterhalb des Bildes */
1088 MarkTileDirty(x, y + 1);
1089 } /* Element verläßt unten das Bild */
1090 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1092 else if (dy) /* allg. Bewegung in y-Richtung */
1093 MarkTileDirty(x, y + SIGN(dy));
1096 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
1098 src_pixmap = pix[PIX_BACK];
1099 drawing_gc = clip_gc[PIX_BACK];
1100 graphic -= GFX_START_ROCKSSCREEN;
1101 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
1102 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
1104 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1106 src_pixmap = pix[PIX_MORE];
1107 drawing_gc = clip_gc[PIX_MORE];
1108 graphic -= GFX_START_ROCKSMORE;
1109 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
1110 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
1112 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
1114 src_pixmap = pix[PIX_HEROES];
1115 drawing_gc = clip_gc[PIX_HEROES];
1116 graphic -= GFX_START_ROCKSHEROES;
1117 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
1118 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
1120 else /* big font graphics currently not allowed (and not needed) */
1123 dest_x = FX + x * TILEX + dx;
1124 dest_y = FY + y * TILEY + dy;
1127 if (!IN_SCR_FIELD(x,y))
1129 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1130 printf("DrawGraphicShifted(): This should never happen!\n");
1135 if (mask_mode == USE_MASKING)
1137 if (tile_clipmask[tile] != None)
1139 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1140 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1141 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1142 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1147 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1150 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1151 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1152 src_x, src_y, width, height, dest_x, dest_y);
1156 XCopyArea(display, src_pixmap, drawto_field, gc,
1157 src_x, src_y, width, height, dest_x, dest_y);
1162 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1165 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1168 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1169 int cut_mode, int mask_mode)
1171 int ux = LEVELX(x), uy = LEVELY(y);
1172 int graphic = el2gfx(element);
1173 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1174 int phase4 = phase8 / 2;
1175 int phase2 = phase8 / 4;
1176 int dir = MovDir[ux][uy];
1178 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1180 graphic += 4 * !phase2;
1184 else if (dir == MV_LEFT)
1186 else if (dir == MV_DOWN)
1189 else if (element == EL_SP_SNIKSNAK)
1192 graphic = GFX_SP_SNIKSNAK_LEFT;
1193 else if (dir == MV_RIGHT)
1194 graphic = GFX_SP_SNIKSNAK_RIGHT;
1195 else if (dir == MV_UP)
1196 graphic = GFX_SP_SNIKSNAK_UP;
1198 graphic = GFX_SP_SNIKSNAK_DOWN;
1200 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1202 else if (element == EL_SP_ELECTRON)
1204 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1206 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1207 element == EL_SCHWEIN || element == EL_DRACHE)
1210 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1211 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1212 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1213 else if (dir == MV_RIGHT)
1214 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1215 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1216 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1217 else if (dir == MV_UP)
1218 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1219 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1220 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1222 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1223 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1224 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1228 else if (element == EL_SONDE)
1230 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1232 else if (element == EL_SALZSAEURE)
1234 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1236 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1240 else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
1241 IS_GEM(element)) && !cut_mode)
1243 if (element == EL_SP_ZONK)
1246 graphic = GFX2_SP_ZONK + phase2 * 2;
1250 printf("-> %d\n", phase4);
1253 graphic = GFX2_SP_ZONK;
1256 graphic += (4 - phase4) % 4;
1257 else if (dir == MV_RIGHT)
1260 graphic += phase2 * 2;
1262 else if (element != EL_SP_INFOTRON)
1263 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1265 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1266 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1268 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1270 else if (IS_AMOEBOID(element))
1272 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1273 graphic += (x + 2 * y + 4) % 4;
1275 else if (element == EL_MAUER_LEBT)
1277 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1279 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1280 links_massiv = TRUE;
1281 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1282 rechts_massiv = TRUE;
1284 if (links_massiv && rechts_massiv)
1285 graphic = GFX_MAUERWERK;
1286 else if (links_massiv)
1287 graphic = GFX_MAUER_R;
1288 else if (rechts_massiv)
1289 graphic = GFX_MAUER_L;
1293 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1294 else if (mask_mode == USE_MASKING)
1295 DrawGraphicThruMask(x, y, graphic);
1297 DrawGraphic(x, y, graphic);
1300 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1301 int cut_mode, int mask_mode)
1303 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1304 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1305 cut_mode, mask_mode);
1308 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1311 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1314 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1317 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1320 void DrawScreenElementThruMask(int x, int y, int element)
1322 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1325 void DrawLevelElementThruMask(int x, int y, int element)
1327 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1330 void DrawLevelFieldThruMask(int x, int y)
1332 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1335 void ErdreichAnbroeckeln(int x, int y)
1337 int i, width, height, cx,cy;
1338 int ux = LEVELX(x), uy = LEVELY(y);
1339 int element, graphic;
1341 static int xy[4][2] =
1349 if (!IN_LEV_FIELD(ux, uy))
1352 element = Feld[ux][uy];
1354 if (element == EL_ERDREICH)
1356 if (!IN_SCR_FIELD(x, y))
1359 graphic = GFX_ERDENRAND;
1365 uxx = ux + xy[i][0];
1366 uyy = uy + xy[i][1];
1367 if (!IN_LEV_FIELD(uxx, uyy))
1370 element = Feld[uxx][uyy];
1372 if (element == EL_ERDREICH)
1375 if (i == 1 || i == 2)
1379 cx = (i == 2 ? TILEX - snip : 0);
1387 cy = (i == 3 ? TILEY - snip : 0);
1390 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1391 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1392 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1393 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1396 MarkTileDirty(x, y);
1400 graphic = GFX_ERDENRAND;
1404 int xx, yy, uxx, uyy;
1408 uxx = ux + xy[i][0];
1409 uyy = uy + xy[i][1];
1411 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1412 !IN_SCR_FIELD(xx, yy))
1415 if (i == 1 || i == 2)
1419 cx = (i == 1 ? TILEX - snip : 0);
1427 cy = (i==0 ? TILEY-snip : 0);
1430 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1431 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1432 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1433 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1435 MarkTileDirty(xx, yy);
1440 void DrawScreenElement(int x, int y, int element)
1442 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1443 ErdreichAnbroeckeln(x, y);
1446 void DrawLevelElement(int x, int y, int element)
1448 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1449 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1452 void DrawScreenField(int x, int y)
1454 int ux = LEVELX(x), uy = LEVELY(y);
1457 if (!IN_LEV_FIELD(ux, uy))
1459 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1460 element = EL_LEERRAUM;
1462 element = BorderElement;
1464 DrawScreenElement(x, y, element);
1468 element = Feld[ux][uy];
1470 if (IS_MOVING(ux, uy))
1472 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1473 boolean cut_mode = NO_CUTTING;
1475 if (Store[ux][uy] == EL_MORAST_LEER ||
1476 Store[ux][uy] == EL_SIEB_LEER ||
1477 Store[ux][uy] == EL_SIEB2_LEER ||
1478 Store[ux][uy] == EL_AMOEBE_NASS)
1479 cut_mode = CUT_ABOVE;
1480 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1481 Store[ux][uy] == EL_SIEB_VOLL ||
1482 Store[ux][uy] == EL_SIEB2_VOLL)
1483 cut_mode = CUT_BELOW;
1485 if (cut_mode == CUT_ABOVE)
1486 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1488 DrawScreenElement(x, y, EL_LEERRAUM);
1491 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1493 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1495 if (Store[ux][uy] == EL_SALZSAEURE)
1496 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1498 else if (IS_BLOCKED(ux, uy))
1503 boolean cut_mode = NO_CUTTING;
1505 Blocked2Moving(ux, uy, &oldx, &oldy);
1508 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1509 MovDir[oldx][oldy] == MV_RIGHT);
1511 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1512 Store[oldx][oldy] == EL_SIEB_LEER ||
1513 Store[oldx][oldy] == EL_SIEB2_LEER ||
1514 Store[oldx][oldy] == EL_AMOEBE_NASS)
1515 cut_mode = CUT_ABOVE;
1517 DrawScreenElement(x, y, EL_LEERRAUM);
1518 element = Feld[oldx][oldy];
1521 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1523 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1525 else if (IS_DRAWABLE(element))
1526 DrawScreenElement(x, y, element);
1528 DrawScreenElement(x, y, EL_LEERRAUM);
1531 void DrawLevelField(int x, int y)
1533 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1534 DrawScreenField(SCREENX(x), SCREENY(y));
1535 else if (IS_MOVING(x, y))
1539 Moving2Blocked(x, y, &newx, &newy);
1540 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1541 DrawScreenField(SCREENX(newx), SCREENY(newy));
1543 else if (IS_BLOCKED(x, y))
1547 Blocked2Moving(x, y, &oldx, &oldy);
1548 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1549 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1553 void DrawMiniElement(int x, int y, int element)
1559 DrawMiniGraphic(x, y, -1);
1563 graphic = el2gfx(element);
1564 DrawMiniGraphic(x, y, graphic);
1567 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1569 int x = sx + scroll_x, y = sy + scroll_y;
1571 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1572 DrawMiniElement(sx, sy, EL_LEERRAUM);
1573 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1574 DrawMiniElement(sx, sy, Feld[x][y]);
1577 int steel_type, steel_position;
1580 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1581 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1582 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1583 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1584 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1585 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1588 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1589 steel_position = (x == -1 && y == -1 ? 0 :
1590 x == lev_fieldx && y == -1 ? 1 :
1591 x == -1 && y == lev_fieldy ? 2 :
1592 x == lev_fieldx && y == lev_fieldy ? 3 :
1593 x == -1 || x == lev_fieldx ? 4 :
1594 y == -1 || y == lev_fieldy ? 5 : -1);
1596 if (steel_position != -1)
1597 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1601 if (x == -1 && y == -1)
1602 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_LEFT);
1603 else if (x == lev_fieldx && y == -1)
1604 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_RIGHT);
1605 else if (x == -1 && y == lev_fieldy)
1606 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_LEFT);
1607 else if (x == lev_fieldx && y == lev_fieldy)
1608 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_RIGHT);
1609 else if (x == -1 || x == lev_fieldx)
1610 DrawMiniGraphic(sx, sy, GFX_STEEL_VERTICAL);
1611 else if (y == -1 || y == lev_fieldy)
1612 DrawMiniGraphic(sx, sy, GFX_STEEL_HORIZONTAL);
1619 void DrawMicroElement(int xpos, int ypos, int element)
1623 if (element == EL_LEERRAUM)
1626 graphic = el2gfx(element);
1628 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1630 graphic -= GFX_START_ROCKSMORE;
1631 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1632 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1633 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1634 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1637 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1638 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1639 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1640 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1649 for(x=BX1; x<=BX2; x++)
1650 for(y=BY1; y<=BY2; y++)
1651 DrawScreenField(x, y);
1653 if (setup.soft_scrolling)
1654 XCopyArea(display, fieldbuffer, backbuffer, gc,
1655 FX, FY, SXSIZE, SYSIZE, SX, SY);
1657 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1660 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1664 for(x=0; x<size_x; x++)
1665 for(y=0; y<size_y; y++)
1666 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1668 redraw_mask |= REDRAW_FIELD;
1671 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1675 /* determine border element for this level */
1678 XFillRectangle(display, drawto, gc,
1679 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1681 if (lev_fieldx < STD_LEV_FIELDX)
1682 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1683 if (lev_fieldy < STD_LEV_FIELDY)
1684 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1686 xpos += MICRO_TILEX;
1687 ypos += MICRO_TILEY;
1689 for(x=-1; x<=STD_LEV_FIELDX; x++)
1691 for(y=-1; y<=STD_LEV_FIELDY; y++)
1693 int lx = from_x + x, ly = from_y + y;
1695 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1696 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1698 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1699 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1704 redraw_mask |= REDRAW_MICROLEVEL;
1707 static void DrawMicroLevelLabelExt(int mode)
1709 char label_text[100];
1711 XFillRectangle(display, drawto,gc,
1712 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1714 strcpy(label_text, (mode == 1 ? level.name :
1715 mode == 2 ? "created by" :
1716 mode == 3 ? level.author : ""));
1718 if (strlen(label_text) > 0)
1720 int size, lxpos, lypos;
1722 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1724 size = strlen(label_text);
1725 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1726 lypos = MICROLABEL_YPOS;
1728 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1731 redraw_mask |= REDRAW_MICROLEVEL;
1734 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1736 static unsigned long scroll_delay = 0;
1737 static unsigned long label_delay = 0;
1738 static int from_x, from_y, scroll_direction;
1739 static int label_state, label_counter;
1743 from_x = from_y = 0;
1744 scroll_direction = MV_RIGHT;
1748 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1749 DrawMicroLevelLabelExt(label_state);
1751 /* initialize delay counters */
1752 DelayReached(&scroll_delay, 0);
1753 DelayReached(&label_delay, 0);
1758 /* scroll micro level, if needed */
1759 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1760 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1762 switch (scroll_direction)
1768 scroll_direction = MV_UP;
1772 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1775 scroll_direction = MV_DOWN;
1782 scroll_direction = MV_RIGHT;
1786 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1789 scroll_direction = MV_LEFT;
1796 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1799 /* redraw micro level label, if needed */
1800 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1801 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1802 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1803 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1805 label_counter = (label_counter + 1) % 23;
1806 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1807 label_counter >= 9 && label_counter <= 12 ? 2 :
1808 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1809 DrawMicroLevelLabelExt(label_state);
1813 int REQ_in_range(int x, int y)
1815 if (y > DY+249 && y < DY+278)
1817 if (x > DX+1 && x < DX+48)
1819 else if (x > DX+51 && x < DX+98)
1825 boolean Request(char *text, unsigned int req_state)
1827 int mx, my, ty, result = -1;
1828 unsigned int old_door_state;
1831 /* pause network game while waiting for request to answer */
1832 if (options.network &&
1833 game_status == PLAYING &&
1834 req_state & REQUEST_WAIT_FOR)
1835 SendToServer_PausePlaying();
1838 old_door_state = GetDoorState();
1842 CloseDoor(DOOR_CLOSE_1);
1844 /* save old door content */
1845 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1846 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1847 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1849 /* clear door drawing field */
1851 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1852 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1854 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1857 /* write text for request */
1858 for(ty=0; ty<13; ty++)
1866 for(tl=0,tx=0; tx<7; tl++,tx++)
1869 if (!tc || tc == 32)
1881 DrawTextExt(pix[PIX_DB_DOOR], gc,
1882 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1883 txt, FS_SMALL, FC_YELLOW);
1885 DrawTextExt(drawto, gc,
1886 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1887 txt, FS_SMALL, FC_YELLOW);
1889 text += tl + (tc == 32 ? 1 : 0);
1893 if (req_state & REQ_ASK)
1895 DrawYesNoButton(BUTTON_OK, DB_INIT);
1896 DrawYesNoButton(BUTTON_NO, DB_INIT);
1898 else if (req_state & REQ_CONFIRM)
1900 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1902 else if (req_state & REQ_PLAYER)
1904 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1905 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1906 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1907 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1911 if (req_state & REQ_ASK)
1913 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1914 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1916 else if (req_state & REQ_CONFIRM)
1918 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1920 else if (req_state & REQ_PLAYER)
1922 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1923 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1924 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1925 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1928 /* copy request gadgets to door backbuffer */
1929 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1930 DX, DY, DXSIZE, DYSIZE,
1931 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1935 OpenDoor(DOOR_OPEN_1);
1938 if (!(req_state & REQUEST_WAIT_FOR))
1941 if (game_status != MAINMENU)
1944 button_status = MB_RELEASED;
1946 request_gadget_id = -1;
1950 if (XPending(display))
1954 XNextEvent(display, &event);
1967 if (event.type == MotionNotify)
1974 if (!XQueryPointer(display, window, &root, &child,
1975 &root_x, &root_y, &win_x, &win_y, &mask))
1981 motion_status = TRUE;
1982 mx = ((XMotionEvent *) &event)->x;
1983 my = ((XMotionEvent *) &event)->y;
1987 motion_status = FALSE;
1988 mx = ((XButtonEvent *) &event)->x;
1989 my = ((XButtonEvent *) &event)->y;
1990 if (event.type==ButtonPress)
1991 button_status = ((XButtonEvent *) &event)->button;
1993 button_status = MB_RELEASED;
1999 if (req_state & REQ_ASK)
2000 choice = CheckYesNoButtons(mx,my,button_status);
2001 else if (req_state & REQ_CONFIRM)
2002 choice = CheckConfirmButton(mx,my,button_status);
2004 choice = CheckPlayerButtons(mx,my,button_status);
2014 case BUTTON_CONFIRM:
2015 result = TRUE | FALSE;
2018 case BUTTON_PLAYER_1:
2021 case BUTTON_PLAYER_2:
2024 case BUTTON_PLAYER_3:
2027 case BUTTON_PLAYER_4:
2036 /* this sets 'request_gadget_id' */
2037 HandleGadgets(mx, my, button_status);
2039 switch(request_gadget_id)
2041 case TOOL_CTRL_ID_YES:
2044 case TOOL_CTRL_ID_NO:
2047 case TOOL_CTRL_ID_CONFIRM:
2048 result = TRUE | FALSE;
2051 case TOOL_CTRL_ID_PLAYER_1:
2054 case TOOL_CTRL_ID_PLAYER_2:
2057 case TOOL_CTRL_ID_PLAYER_3:
2060 case TOOL_CTRL_ID_PLAYER_4:
2073 switch(XLookupKeysym((XKeyEvent *)&event,
2074 ((XKeyEvent *)&event)->state))
2087 if (req_state & REQ_PLAYER)
2092 key_joystick_mapping = 0;
2096 HandleOtherEvents(&event);
2100 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2102 int joy = AnyJoystick();
2104 if (joy & JOY_BUTTON_1)
2106 else if (joy & JOY_BUTTON_2)
2112 /* don't eat all CPU time */
2116 if (game_status != MAINMENU)
2121 if (!(req_state & REQ_STAY_OPEN))
2123 CloseDoor(DOOR_CLOSE_1);
2125 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2127 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
2128 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2129 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2130 OpenDoor(DOOR_OPEN_1);
2137 /* continue network game after request */
2138 if (options.network &&
2139 game_status == PLAYING &&
2140 req_state & REQUEST_WAIT_FOR)
2141 SendToServer_ContinuePlaying();
2147 unsigned int OpenDoor(unsigned int door_state)
2149 unsigned int new_door_state;
2151 if (door_state & DOOR_COPY_BACK)
2153 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
2154 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2155 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2156 door_state &= ~DOOR_COPY_BACK;
2159 new_door_state = MoveDoor(door_state);
2161 return(new_door_state);
2164 unsigned int CloseDoor(unsigned int door_state)
2166 unsigned int new_door_state;
2168 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2169 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2170 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2171 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2173 new_door_state = MoveDoor(door_state);
2175 return(new_door_state);
2178 unsigned int GetDoorState()
2180 return(MoveDoor(DOOR_GET_STATE));
2183 unsigned int MoveDoor(unsigned int door_state)
2185 static int door1 = DOOR_OPEN_1;
2186 static int door2 = DOOR_CLOSE_2;
2187 static unsigned long door_delay = 0;
2188 int x, start, stepsize = 2;
2189 unsigned long door_delay_value = stepsize * 5;
2191 if (door_state == DOOR_GET_STATE)
2192 return(door1 | door2);
2194 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2195 door_state &= ~DOOR_OPEN_1;
2196 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2197 door_state &= ~DOOR_CLOSE_1;
2198 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2199 door_state &= ~DOOR_OPEN_2;
2200 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2201 door_state &= ~DOOR_CLOSE_2;
2203 if (setup.quick_doors)
2206 door_delay_value = 0;
2207 StopSound(SND_OEFFNEN);
2210 if (door_state & DOOR_ACTION)
2212 if (!(door_state & DOOR_NO_DELAY))
2213 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2215 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2217 for(x=start; x<=DXSIZE; x+=stepsize)
2219 WaitUntilDelayReached(&door_delay, door_delay_value);
2221 if (door_state & DOOR_ACTION_1)
2223 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2224 int j = (DXSIZE - i) / 3;
2226 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2227 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2228 DXSIZE,DYSIZE - i/2, DX, DY);
2230 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2232 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2233 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2234 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2235 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2236 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2237 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2239 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2240 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2241 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2242 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2243 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2244 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2246 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2247 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2249 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2250 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2252 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2253 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2254 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2255 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2256 DX + DXSIZE - i, DY + 77 + j);
2257 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2258 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2259 DX + DXSIZE - i, DY + 203 + j);
2261 redraw_mask |= REDRAW_DOOR_1;
2264 if (door_state & DOOR_ACTION_2)
2266 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2267 int j = (VXSIZE - i) / 3;
2269 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2270 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2271 VXSIZE, VYSIZE - i/2, VX, VY);
2273 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2275 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2276 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2277 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2278 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2279 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2280 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2281 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2282 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2284 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2285 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2286 VX, VY + VYSIZE / 2 - j);
2287 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2288 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2289 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2290 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2291 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2293 redraw_mask |= REDRAW_DOOR_2;
2301 XCopyArea(display, drawto, window, gc, DX, DY, DXSIZE, DYSIZE, DX, DY);
2306 if (game_status == MAINMENU)
2311 if (setup.quick_doors)
2312 StopSound(SND_OEFFNEN);
2314 if (door_state & DOOR_ACTION_1)
2315 door1 = door_state & DOOR_ACTION_1;
2316 if (door_state & DOOR_ACTION_2)
2317 door2 = door_state & DOOR_ACTION_2;
2319 return(door1 | door2);
2322 int ReadPixel(Drawable d, int x, int y)
2324 XImage *pixel_image;
2325 unsigned long pixel_value;
2327 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2328 pixel_value = XGetPixel(pixel_image, 0, 0);
2330 XDestroyImage(pixel_image);
2335 /* ---------- new tool button stuff ---------------------------------------- */
2337 /* graphic position values for tool buttons */
2338 #define TOOL_BUTTON_YES_XPOS 2
2339 #define TOOL_BUTTON_YES_YPOS 250
2340 #define TOOL_BUTTON_YES_GFX_YPOS 0
2341 #define TOOL_BUTTON_YES_XSIZE 46
2342 #define TOOL_BUTTON_YES_YSIZE 28
2343 #define TOOL_BUTTON_NO_XPOS 52
2344 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2345 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2346 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2347 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2348 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2349 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2350 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2351 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2352 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2353 #define TOOL_BUTTON_PLAYER_XSIZE 30
2354 #define TOOL_BUTTON_PLAYER_YSIZE 30
2355 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2356 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2357 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2358 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2359 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2360 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2361 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2362 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2363 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2364 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2365 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2366 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2367 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2368 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2369 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2370 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2371 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2372 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2373 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2374 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2383 } toolbutton_info[NUM_TOOL_BUTTONS] =
2386 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2387 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2388 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2393 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2394 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2395 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2400 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2401 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2402 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2403 TOOL_CTRL_ID_CONFIRM,
2407 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2408 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2409 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2410 TOOL_CTRL_ID_PLAYER_1,
2414 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2415 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2416 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2417 TOOL_CTRL_ID_PLAYER_2,
2421 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2422 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2423 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2424 TOOL_CTRL_ID_PLAYER_3,
2428 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2429 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2430 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2431 TOOL_CTRL_ID_PLAYER_4,
2436 void CreateToolButtons()
2440 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2442 Pixmap gd_pixmap = pix[PIX_DOOR];
2443 Pixmap deco_pixmap = None;
2444 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2445 struct GadgetInfo *gi;
2446 unsigned long event_mask;
2447 int gd_xoffset, gd_yoffset;
2448 int gd_x1, gd_x2, gd_y;
2451 event_mask = GD_EVENT_RELEASED;
2453 gd_xoffset = toolbutton_info[i].xpos;
2454 gd_yoffset = toolbutton_info[i].ypos;
2455 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2456 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2457 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2459 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2461 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2462 &deco_pixmap, &deco_x, &deco_y);
2463 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2464 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2467 gi = CreateGadget(GDI_CUSTOM_ID, id,
2468 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2469 GDI_X, DX + toolbutton_info[i].x,
2470 GDI_Y, DY + toolbutton_info[i].y,
2471 GDI_WIDTH, toolbutton_info[i].width,
2472 GDI_HEIGHT, toolbutton_info[i].height,
2473 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2474 GDI_STATE, GD_BUTTON_UNPRESSED,
2475 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2476 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2477 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2478 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2479 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2480 GDI_DECORATION_SHIFTING, 1, 1,
2481 GDI_EVENT_MASK, event_mask,
2482 GDI_CALLBACK_ACTION, HandleToolButtons,
2486 Error(ERR_EXIT, "cannot create gadget");
2488 tool_gadget[id] = gi;
2492 static void UnmapToolButtons()
2496 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2497 UnmapGadget(tool_gadget[i]);
2500 static void HandleToolButtons(struct GadgetInfo *gi)
2502 request_gadget_id = gi->custom_id;
2506 int id = gi->custom_id;
2508 if (game_status != PLAYING)
2513 case GAME_CTRL_ID_STOP:
2516 CloseDoor(DOOR_CLOSE_1);
2517 game_status = MAINMENU;
2522 if (Request("Do you really want to quit the game ?",
2523 REQ_ASK | REQ_STAY_CLOSED))
2526 if (options.network)
2527 SendToServer_StopPlaying();
2531 game_status = MAINMENU;
2536 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2539 case GAME_CTRL_ID_PAUSE:
2540 if (options.network)
2544 SendToServer_ContinuePlaying();
2546 SendToServer_PausePlaying();
2553 case GAME_CTRL_ID_PLAY:
2557 if (options.network)
2558 SendToServer_ContinuePlaying();
2562 tape.pausing = FALSE;
2563 DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2568 case SOUND_CTRL_ID_MUSIC:
2569 if (setup.sound_music)
2571 setup.sound_music = FALSE;
2572 FadeSound(background_loop[level_nr % num_bg_loops]);
2574 else if (sound_loops_allowed)
2576 setup.sound = setup.sound_music = TRUE;
2577 PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
2581 case SOUND_CTRL_ID_LOOPS:
2582 if (setup.sound_loops)
2583 setup.sound_loops = FALSE;
2584 else if (sound_loops_allowed)
2585 setup.sound = setup.sound_loops = TRUE;
2588 case SOUND_CTRL_ID_SIMPLE:
2589 if (setup.sound_simple)
2590 setup.sound_simple = FALSE;
2591 else if (sound_status==SOUND_AVAILABLE)
2592 setup.sound = setup.sound_simple = TRUE;
2604 int el2gfx(int element)
2608 case EL_LEERRAUM: return -1;
2609 case EL_ERDREICH: return GFX_ERDREICH;
2610 case EL_MAUERWERK: return GFX_MAUERWERK;
2611 case EL_FELSBODEN: return GFX_FELSBODEN;
2612 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2613 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2614 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2615 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2616 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2617 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2618 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2619 case EL_SPIELER1: return GFX_SPIELER1;
2620 case EL_SPIELER2: return GFX_SPIELER2;
2621 case EL_SPIELER3: return GFX_SPIELER3;
2622 case EL_SPIELER4: return GFX_SPIELER4;
2623 case EL_KAEFER: return GFX_KAEFER;
2624 case EL_KAEFER_R: return GFX_KAEFER_R;
2625 case EL_KAEFER_O: return GFX_KAEFER_O;
2626 case EL_KAEFER_L: return GFX_KAEFER_L;
2627 case EL_KAEFER_U: return GFX_KAEFER_U;
2628 case EL_FLIEGER: return GFX_FLIEGER;
2629 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2630 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2631 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2632 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2633 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2634 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2635 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2636 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2637 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2638 case EL_FIREFLY: return GFX_FIREFLY;
2639 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2640 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2641 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2642 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2643 case EL_MAMPFER: return GFX_MAMPFER;
2644 case EL_ROBOT: return GFX_ROBOT;
2645 case EL_BETON: return GFX_BETON;
2646 case EL_DIAMANT: return GFX_DIAMANT;
2647 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2648 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2649 case EL_TROPFEN: return GFX_TROPFEN;
2650 case EL_BOMBE: return GFX_BOMBE;
2651 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2652 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2653 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2654 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2655 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2656 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2657 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2658 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2659 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2660 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2661 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2662 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2663 case EL_LIFE: return GFX_LIFE;
2664 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2665 case EL_DYNAMIT: return GFX_DYNAMIT;
2666 case EL_BADEWANNE: return GFX_BADEWANNE;
2667 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2668 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2669 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2670 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2671 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2672 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2673 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2674 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2675 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2676 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2677 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2678 case EL_PFORTE1: return GFX_PFORTE1;
2679 case EL_PFORTE2: return GFX_PFORTE2;
2680 case EL_PFORTE3: return GFX_PFORTE3;
2681 case EL_PFORTE4: return GFX_PFORTE4;
2682 case EL_PFORTE1X: return GFX_PFORTE1X;
2683 case EL_PFORTE2X: return GFX_PFORTE2X;
2684 case EL_PFORTE3X: return GFX_PFORTE3X;
2685 case EL_PFORTE4X: return GFX_PFORTE4X;
2686 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2687 case EL_PACMAN: return GFX_PACMAN;
2688 case EL_PACMAN_R: return GFX_PACMAN_R;
2689 case EL_PACMAN_O: return GFX_PACMAN_O;
2690 case EL_PACMAN_L: return GFX_PACMAN_L;
2691 case EL_PACMAN_U: return GFX_PACMAN_U;
2692 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2693 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2694 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2695 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2696 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2697 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2698 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2699 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2700 case EL_MAUER_X: return GFX_MAUER_X;
2701 case EL_MAUER_Y: return GFX_MAUER_Y;
2702 case EL_MAUER_XY: return GFX_MAUER_XY;
2703 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2704 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2705 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2706 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2707 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2708 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2709 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2710 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2711 case EL_MAMPFER2: return GFX_MAMPFER2;
2712 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2713 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2714 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2715 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2716 case EL_DYNABOMB: return GFX_DYNABOMB;
2717 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2718 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2719 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2720 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2721 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2722 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2723 case EL_MAULWURF: return GFX_MAULWURF;
2724 case EL_PINGUIN: return GFX_PINGUIN;
2725 case EL_SCHWEIN: return GFX_SCHWEIN;
2726 case EL_DRACHE: return GFX_DRACHE;
2727 case EL_SONDE: return GFX_SONDE;
2728 case EL_PFEIL_L: return GFX_PFEIL_L;
2729 case EL_PFEIL_R: return GFX_PFEIL_R;
2730 case EL_PFEIL_O: return GFX_PFEIL_O;
2731 case EL_PFEIL_U: return GFX_PFEIL_U;
2732 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2733 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2734 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2735 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2736 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2740 if (IS_CHAR(element))
2741 return GFX_CHAR_START + (element - EL_CHAR_START);
2742 else if (element >= EL_SP_START && element <= EL_SP_END)
2744 int nr_element = element - EL_SP_START;
2745 int gfx_per_line = 8;
2747 (nr_element / gfx_per_line) * MORE_PER_LINE +
2748 (nr_element % gfx_per_line);
2750 return GFX_START_ROCKSMORE + nr_graphic;