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 ***********************************************************/
15 #include <machine/joystick.h>
31 extern boolean wait_for_vsync;
34 void SetDrawtoField(int mode)
36 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
47 drawto_field = fieldbuffer;
49 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
60 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
67 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
69 if (setup.direct_draw && game_status == PLAYING)
70 redraw_mask &= ~REDRAW_MAIN;
72 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
73 redraw_mask |= REDRAW_FIELD;
75 if (redraw_mask & REDRAW_FIELD)
76 redraw_mask &= ~REDRAW_TILES;
79 if (redraw_mask & REDRAW_FIELD ||
80 (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING))
81 redraw_mask &= ~REDRAW_TILES;
87 /* synchronize X11 graphics at this point; if we would synchronize the
88 display immediately after the buffer switching (after the XFlush),
89 this could mean that we have to wait for the graphics to complete,
90 although we could go on doing calculations for the next frame */
95 wait_for_vsync = TRUE;
98 if (redraw_mask & REDRAW_ALL)
100 XCopyArea(display,backbuffer,window,gc,
101 0,0, WIN_XSIZE,WIN_YSIZE,
106 if (redraw_mask & REDRAW_FIELD)
108 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
109 XCopyArea(display,backbuffer,window,gc,
110 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
114 int fx = FX, fy = FY;
116 if (setup.soft_scrolling)
118 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
119 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
122 XCopyArea(display,buffer,window,gc,
123 fx,fy, SXSIZE,SYSIZE,
126 redraw_mask &= ~REDRAW_MAIN;
129 if (redraw_mask & REDRAW_DOORS)
131 if (redraw_mask & REDRAW_DOOR_1)
132 XCopyArea(display,backbuffer,window,gc,
133 DX,DY, DXSIZE,DYSIZE,
135 if (redraw_mask & REDRAW_DOOR_2)
137 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
138 XCopyArea(display,backbuffer,window,gc,
139 VX,VY, VXSIZE,VYSIZE,
143 if (redraw_mask & REDRAW_VIDEO_1)
144 XCopyArea(display,backbuffer,window,gc,
145 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
146 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
147 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
148 if (redraw_mask & REDRAW_VIDEO_2)
149 XCopyArea(display,backbuffer,window,gc,
150 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
151 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
152 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
153 if (redraw_mask & REDRAW_VIDEO_3)
154 XCopyArea(display,backbuffer,window,gc,
155 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
156 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
157 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
160 redraw_mask &= ~REDRAW_DOORS;
163 if (redraw_mask & REDRAW_MICROLEV)
165 XCopyArea(display,backbuffer,window,gc,
166 MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
167 MICROLEV_XPOS,MICROLEV_YPOS);
168 XCopyArea(display,backbuffer,window,gc,
169 SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
171 redraw_mask &= ~REDRAW_MICROLEV;
174 if (redraw_mask & REDRAW_TILES)
176 for(x=0; x<SCR_FIELDX; x++)
177 for(y=0; y<SCR_FIELDY; y++)
178 if (redraw[redraw_x1 + x][redraw_y1 + y])
179 XCopyArea(display,buffer,window,gc,
180 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
181 SX+x*TILEX,SY+y*TILEY);
186 for(x=0; x<MAX_BUF_XSIZE; x++)
187 for(y=0; y<MAX_BUF_YSIZE; y++)
196 long fading_delay = 300;
198 if (setup.fading && (redraw_mask & REDRAW_FIELD))
205 XFillRectangle(display,window,gc,
206 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
209 for(i=0;i<2*FULL_SYSIZE;i++)
211 for(y=0;y<FULL_SYSIZE;y++)
213 XCopyArea(display,backbuffer,window,gc,
214 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
222 for(i=1;i<FULL_SYSIZE;i+=2)
223 XCopyArea(display,backbuffer,window,gc,
224 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
230 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
231 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
232 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
236 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
237 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
238 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
242 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
243 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
244 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
248 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
249 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
250 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
254 redraw_mask &= ~REDRAW_MAIN;
263 XFillRectangle(display, backbuffer, gc,
264 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
266 if (setup.soft_scrolling && game_status == PLAYING)
268 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
269 SetDrawtoField(DRAW_BUFFERED);
272 SetDrawtoField(DRAW_BACKBUFFER);
274 if (setup.direct_draw && game_status == PLAYING)
276 XFillRectangle(display, window, gc,
277 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
278 SetDrawtoField(DRAW_DIRECT);
281 redraw_mask |= REDRAW_FIELD;
284 void DrawText(int x, int y, char *text, int font, int col)
286 DrawTextExt(drawto, gc, x, y, text, font, col);
288 redraw_mask |= REDRAW_FIELD;
290 redraw_mask |= REDRAW_DOOR_1;
293 void DrawTextExt(Drawable d, GC gc, int x, int y,
294 char *text, int font, int font_color)
296 int font_width, font_height, font_start;
299 if (font != FS_SMALL && font != FS_BIG)
301 if (font_color < FC_RED || font_color > FC_SPECIAL2)
304 font_width = (font == FS_BIG ? FONT1_XSIZE :
305 font_color < FC_SPECIAL1 ? FONT2_XSIZE :
306 font_color < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
307 font_height = (font == FS_BIG ? FONT1_XSIZE :
308 font_color < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
309 font_pixmap = (font == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
310 font_start = (font_color * (font == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
311 FONT_LINES_PER_FONT);
317 if (c >= 'a' && c <= 'z')
319 else if (c == 'ä' || c == 'Ä')
321 else if (c == 'ö' || c == 'Ö')
323 else if (c == 'ü' || c == 'Ü')
326 if (c >= 32 && c <= 95)
327 XCopyArea(display, pix[font_pixmap], d, gc,
328 ((c - 32) % FONT_CHARS_PER_LINE) * font_width,
329 ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start,
330 font_width, font_height, x, y);
336 void DrawAllPlayers()
340 for(i=0; i<MAX_PLAYERS; i++)
341 if (stored_player[i].active)
342 DrawPlayer(&stored_player[i]);
345 void DrawPlayerField(int x, int y)
350 DrawPlayer(PLAYERINFO(x,y));
353 void DrawPlayer(struct PlayerInfo *player)
355 int jx = player->jx, jy = player->jy;
356 int last_jx = player->last_jx, last_jy = player->last_jy;
357 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
358 int sx = SCREENX(jx), sy = SCREENY(jy);
359 int sxx = 0, syy = 0;
360 int element = Feld[jx][jy];
363 if (!player->active || player->gone ||
364 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
368 if (!IN_LEV_FIELD(jx,jy))
370 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
371 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
372 printf("DrawPlayerField(): This should never happen!\n");
377 if (element == EL_EXPLODING)
380 /* draw things in the field the player is leaving, if needed */
382 if (last_jx != jx || last_jy != jy)
384 if (Store[last_jx][last_jy])
386 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
387 DrawLevelFieldThruMask(last_jx, last_jy);
389 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
390 DrawDynamite(last_jx, last_jy);
392 DrawLevelField(last_jx, last_jy);
394 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
398 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
399 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
401 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
404 DrawLevelField(next_jx, next_jy);
408 if (!IN_SCR_FIELD(sx, sy))
411 if (setup.direct_draw)
412 SetDrawtoField(DRAW_BUFFERED);
414 /* draw things behind the player, if needed */
417 DrawLevelElement(jx, jy, Store[jx][jy]);
418 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
419 DrawLevelField(jx, jy);
421 /* draw player himself */
423 if (player->MovDir == MV_LEFT)
424 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
425 else if (player->MovDir == MV_RIGHT)
426 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
427 else if (player->MovDir == MV_UP)
428 graphic = GFX_SPIELER1_UP;
429 else /* MV_DOWN || MV_NO_MOVING */
430 graphic = GFX_SPIELER1_DOWN;
432 graphic += player->index_nr * 3*HEROES_PER_LINE;
433 graphic += player->Frame;
437 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
438 sxx = player->GfxPos;
440 syy = player->GfxPos;
443 if (!setup.soft_scrolling && ScreenMovPos)
446 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
448 if (player->Pushing && player->GfxPos)
450 int px = SCREENX(next_jx), py = SCREENY(next_jy);
452 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
453 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
454 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
458 int element = Feld[next_jx][next_jy];
459 int graphic = el2gfx(element);
461 if (element == EL_FELSBROCKEN && sxx)
463 int phase = (player->GfxPos / (TILEX/4));
465 if (player->MovDir == MV_LEFT)
468 graphic += (phase+4)%4;
471 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
475 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
477 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
479 graphic = el2gfx(element);
481 if (element == EL_DYNAMIT)
483 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
488 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
492 DrawGraphicThruMask(sx, sy, graphic + phase);
495 if ((last_jx != jx || last_jy != jy) &&
496 Feld[last_jx][last_jy] == EL_EXPLODING)
498 int phase = Frame[last_jx][last_jy];
502 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
503 GFX_EXPLOSION + ((phase - 1) / delay - 1));
506 if (setup.direct_draw)
508 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
509 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
510 int x_size = TILEX * (1 + ABS(jx - last_jx));
511 int y_size = TILEY * (1 + ABS(jy - last_jy));
513 XCopyArea(display, drawto_field, window, gc,
514 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
515 SetDrawtoField(DRAW_DIRECT);
518 MarkTileDirty(sx,sy);
521 static int getGraphicAnimationPhase(int frames, int delay, int mode)
525 if (mode == ANIM_OSCILLATE)
527 int max_anim_frames = 2 * frames - 2;
528 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
529 phase = (phase < frames ? phase : max_anim_frames - phase);
532 phase = (FrameCounter % (delay * frames)) / delay;
534 if (mode == ANIM_REVERSE)
540 void DrawGraphicAnimationExt(int x, int y, int graphic,
541 int frames, int delay, int mode, int mask_mode)
543 int phase = getGraphicAnimationPhase(frames, delay, mode);
545 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
547 if (mask_mode == USE_MASKING)
548 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
550 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
554 void DrawGraphicAnimation(int x, int y, int graphic,
555 int frames, int delay, int mode)
557 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
560 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
561 int frames, int delay, int mode)
563 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
566 void DrawGraphic(int x, int y, int graphic)
569 if (!IN_SCR_FIELD(x,y))
571 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
572 printf("DrawGraphic(): This should never happen!\n");
577 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
581 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
583 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
585 graphic -= GFX_START_ROCKSSCREEN;
586 XCopyArea(display, pix[PIX_BACK], d, gc,
587 SX + (graphic % GFX_PER_LINE) * TILEX,
588 SY + (graphic / GFX_PER_LINE) * TILEY,
591 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
593 graphic -= GFX_START_ROCKSHEROES;
594 XCopyArea(display, pix[PIX_HEROES], d, gc,
595 (graphic % HEROES_PER_LINE) * TILEX,
596 (graphic / HEROES_PER_LINE) * TILEY,
599 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
601 graphic -= GFX_START_ROCKSFONT;
602 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
603 (graphic % FONT_CHARS_PER_LINE) * TILEX,
604 (graphic / FONT_CHARS_PER_LINE) * TILEY +
605 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
609 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
612 void DrawGraphicThruMask(int x, int y, int graphic)
615 if (!IN_SCR_FIELD(x,y))
617 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
618 printf("DrawGraphicThruMask(): This should never happen!\n");
623 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
627 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
634 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
636 src_pixmap = pix[PIX_BACK];
637 drawing_gc = clip_gc[PIX_BACK];
638 graphic -= GFX_START_ROCKSSCREEN;
639 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
640 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
642 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
644 src_pixmap = pix[PIX_HEROES];
645 drawing_gc = clip_gc[PIX_HEROES];
646 graphic -= GFX_START_ROCKSHEROES;
647 src_x = (graphic % HEROES_PER_LINE) * TILEX;
648 src_y = (graphic / HEROES_PER_LINE) * TILEY;
652 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
656 if (tile_clipmask[tile] != None)
658 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
659 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
660 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
661 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
666 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
669 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
670 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
671 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
675 void DrawMiniGraphic(int x, int y, int graphic)
677 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
678 MarkTileDirty(x/2, y/2);
681 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
683 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
685 graphic -= GFX_START_ROCKSSCREEN;
686 XCopyArea(display, pix[PIX_BACK], d, gc,
687 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
688 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
689 MINI_TILEX, MINI_TILEY, x, y);
691 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
693 graphic -= GFX_START_ROCKSFONT;
694 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
695 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
696 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
697 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
698 MINI_TILEX, MINI_TILEY, x, y);
701 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
704 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
705 int cut_mode, int mask_mode)
707 int width = TILEX, height = TILEY;
709 int src_x, src_y, dest_x, dest_y;
716 DrawGraphic(x, y, graphic);
720 if (dx || dy) /* Verschiebung der Grafik? */
722 if (x < BX1) /* Element kommt von links ins Bild */
729 else if (x > BX2) /* Element kommt von rechts ins Bild */
735 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
741 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
743 else if (dx) /* allg. Bewegung in x-Richtung */
744 MarkTileDirty(x + SIGN(dx), y);
746 if (y < BY1) /* Element kommt von oben ins Bild */
748 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
756 else if (y > BY2) /* Element kommt von unten ins Bild */
762 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
768 else if (dy > 0 && cut_mode == CUT_ABOVE)
770 if (y == BY2) /* Element unterhalb des Bildes */
776 MarkTileDirty(x, y + 1);
777 } /* Element verläßt unten das Bild */
778 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
780 else if (dy) /* allg. Bewegung in y-Richtung */
781 MarkTileDirty(x, y + SIGN(dy));
784 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
786 src_pixmap = pix[PIX_BACK];
787 drawing_gc = clip_gc[PIX_BACK];
788 graphic -= GFX_START_ROCKSSCREEN;
789 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
790 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
792 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
794 src_pixmap = pix[PIX_HEROES];
795 drawing_gc = clip_gc[PIX_HEROES];
796 graphic -= GFX_START_ROCKSHEROES;
797 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
798 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
801 dest_x = FX + x * TILEX + dx;
802 dest_y = FY + y * TILEY + dy;
805 if (!IN_SCR_FIELD(x,y))
807 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
808 printf("DrawGraphicShifted(): This should never happen!\n");
813 if (mask_mode == USE_MASKING)
815 if (tile_clipmask[tile] != None)
817 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
818 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
819 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
820 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
825 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
828 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
829 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
830 src_x, src_y, width, height, dest_x, dest_y);
834 XCopyArea(display, src_pixmap, drawto_field, gc,
835 src_x, src_y, width, height, dest_x, dest_y);
840 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
843 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
846 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
847 int cut_mode, int mask_mode)
849 int ux = LEVELX(x), uy = LEVELY(y);
850 int graphic = el2gfx(element);
851 int phase4 = ABS(MovPos[ux][uy]) / (TILEX / 4);
852 int phase = phase4 / 2;
853 int dir = MovDir[ux][uy];
855 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
861 else if (dir == MV_LEFT)
863 else if (dir == MV_DOWN)
866 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
867 element == EL_SCHWEIN || element == EL_DRACHE)
870 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
871 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
872 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
873 else if (dir == MV_RIGHT)
874 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
875 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
876 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
877 else if (dir == MV_UP)
878 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
879 element == EL_PINGUIN ? GFX_PINGUIN_UP :
880 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
882 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
883 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
884 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
888 else if (element == EL_SONDE)
890 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
892 else if (element == EL_SALZSAEURE)
894 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
896 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
900 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
902 graphic += phase * (element == EL_FELSBROCKEN ? 2 : 1);
904 else if ((element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
905 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL) && SiebAktiv)
907 graphic += 3 - (SiebAktiv % 8) / 2;
909 else if (IS_AMOEBOID(element))
911 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
912 graphic += (x + 2 * y + 4) % 4;
914 else if (element == EL_MAUER_LEBT)
916 boolean links_massiv = FALSE, rechts_massiv = FALSE;
918 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
920 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
921 rechts_massiv = TRUE;
923 if (links_massiv && rechts_massiv)
924 graphic = GFX_MAUERWERK;
925 else if (links_massiv)
926 graphic = GFX_MAUER_R;
927 else if (rechts_massiv)
928 graphic = GFX_MAUER_L;
932 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
933 else if (mask_mode == USE_MASKING)
934 DrawGraphicThruMask(x, y, graphic);
936 DrawGraphic(x, y, graphic);
939 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
940 int cut_mode, int mask_mode)
942 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
943 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
944 cut_mode, mask_mode);
947 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
950 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
953 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
956 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
959 void DrawScreenElementThruMask(int x, int y, int element)
961 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
964 void DrawLevelElementThruMask(int x, int y, int element)
966 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
969 void DrawLevelFieldThruMask(int x, int y)
971 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
974 void ErdreichAnbroeckeln(int x, int y)
976 int i, width, height, cx,cy;
977 int ux = LEVELX(x), uy = LEVELY(y);
978 int element, graphic;
980 static int xy[4][2] =
988 if (!IN_LEV_FIELD(ux, uy))
991 element = Feld[ux][uy];
993 if (element == EL_ERDREICH)
995 if (!IN_SCR_FIELD(x, y))
998 graphic = GFX_ERDENRAND;
1004 uxx = ux + xy[i][0];
1005 uyy = uy + xy[i][1];
1006 if (!IN_LEV_FIELD(uxx, uyy))
1009 element = Feld[uxx][uyy];
1011 if (element == EL_ERDREICH)
1014 if (i == 1 || i == 2)
1018 cx = (i == 2 ? TILEX - snip : 0);
1026 cy = (i == 3 ? TILEY - snip : 0);
1029 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1030 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1031 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1032 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1035 MarkTileDirty(x, y);
1039 graphic = GFX_ERDENRAND;
1043 int xx, yy, uxx, uyy;
1047 uxx = ux + xy[i][0];
1048 uyy = uy + xy[i][1];
1050 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1051 !IN_SCR_FIELD(xx, yy))
1054 if (i == 1 || i == 2)
1058 cx = (i == 1 ? TILEX - snip : 0);
1066 cy = (i==0 ? TILEY-snip : 0);
1069 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1070 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1071 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1072 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1074 MarkTileDirty(xx, yy);
1079 void DrawScreenElement(int x, int y, int element)
1081 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1082 ErdreichAnbroeckeln(x, y);
1085 void DrawLevelElement(int x, int y, int element)
1087 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1088 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1091 void DrawScreenField(int x, int y)
1093 int ux = LEVELX(x), uy = LEVELY(y);
1096 if (!IN_LEV_FIELD(ux, uy))
1098 DrawScreenElement(x, y, EL_BETON);
1102 element = Feld[ux][uy];
1104 if (IS_MOVING(ux, uy))
1106 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1107 boolean cut_mode = NO_CUTTING;
1109 if (Store[ux][uy] == EL_MORAST_LEER ||
1110 Store[ux][uy] == EL_SIEB_LEER ||
1111 Store[ux][uy] == EL_SIEB2_LEER ||
1112 Store[ux][uy] == EL_AMOEBE_NASS)
1113 cut_mode = CUT_ABOVE;
1114 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1115 Store[ux][uy] == EL_SIEB_VOLL ||
1116 Store[ux][uy] == EL_SIEB2_VOLL)
1117 cut_mode = CUT_BELOW;
1119 if (cut_mode == CUT_ABOVE)
1120 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1122 DrawScreenElement(x, y, EL_LEERRAUM);
1125 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1127 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1129 if (Store[ux][uy] == EL_SALZSAEURE)
1130 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1132 else if (IS_BLOCKED(ux, uy))
1137 boolean cut_mode = NO_CUTTING;
1139 Blocked2Moving(ux, uy, &oldx, &oldy);
1142 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1143 MovDir[oldx][oldy] == MV_RIGHT);
1145 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1146 Store[oldx][oldy] == EL_SIEB_LEER ||
1147 Store[oldx][oldy] == EL_SIEB2_LEER ||
1148 Store[oldx][oldy] == EL_AMOEBE_NASS)
1149 cut_mode = CUT_ABOVE;
1151 DrawScreenElement(x, y, EL_LEERRAUM);
1152 element = Feld[oldx][oldy];
1155 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1157 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1159 else if (IS_DRAWABLE(element))
1160 DrawScreenElement(x, y, element);
1162 DrawScreenElement(x, y, EL_LEERRAUM);
1165 void DrawLevelField(int x, int y)
1167 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1168 DrawScreenField(SCREENX(x), SCREENY(y));
1169 else if (IS_MOVING(x, y))
1173 Moving2Blocked(x, y, &newx, &newy);
1174 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1175 DrawScreenField(SCREENX(newx), SCREENY(newy));
1177 else if (IS_BLOCKED(x, y))
1181 Blocked2Moving(x, y, &oldx, &oldy);
1182 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1183 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1187 void DrawMiniElement(int x, int y, int element)
1193 DrawMiniGraphic(x, y, -1);
1197 graphic = el2gfx(element);
1198 DrawMiniGraphic(x, y, graphic);
1201 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1203 int x = sx + scroll_x, y = sy + scroll_y;
1205 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1206 DrawMiniElement(sx, sy, EL_LEERRAUM);
1207 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1208 DrawMiniElement(sx, sy, EL_BETON);
1210 DrawMiniElement(sx, sy, Feld[x][y]);
1213 void DrawMicroElement(int xpos, int ypos, int element)
1217 if (element == EL_LEERRAUM)
1220 graphic = el2gfx(element);
1222 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1223 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1224 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1225 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1234 for(x=BX1; x<=BX2; x++)
1235 for(y=BY1; y<=BY2; y++)
1236 DrawScreenField(x, y);
1238 if (setup.soft_scrolling)
1239 XCopyArea(display, fieldbuffer, backbuffer, gc,
1240 FX, FY, SXSIZE, SYSIZE, SX, SY);
1242 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1245 void DrawMiniLevel(int scroll_x, int scroll_y)
1251 for(x=0; x<2*SCR_FIELDX; x++)
1252 for(y=0; y<2*SCR_FIELDY; y++)
1253 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1255 redraw_mask |= REDRAW_FIELD;
1258 void DrawMicroLevel(int xpos, int ypos)
1262 XFillRectangle(display, drawto, gc,
1263 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1264 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1265 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1266 if (lev_fieldx < STD_LEV_FIELDX)
1267 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1268 if (lev_fieldy < STD_LEV_FIELDY)
1269 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1271 for(x=-1; x<=STD_LEV_FIELDX; x++)
1272 for(y=-1; y<=STD_LEV_FIELDY; y++)
1273 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1274 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1276 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1277 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1280 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1284 int len = strlen(level.name);
1285 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1286 int lypos = MICROLABEL_YPOS;
1288 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1291 redraw_mask |= REDRAW_MICROLEV;
1294 int REQ_in_range(int x, int y)
1296 if (y > DY+249 && y < DY+278)
1298 if (x > DX+1 && x < DX+48)
1300 else if (x > DX+51 && x < DX+98)
1306 boolean Request(char *text, unsigned int req_state)
1308 int mx, my, ty, result = -1;
1309 unsigned int old_door_state;
1311 /* pause network game while waiting for request to answer */
1312 if (options.network &&
1313 game_status == PLAYING &&
1314 req_state & REQUEST_WAIT_FOR)
1315 SendToServer_PausePlaying();
1317 old_door_state = GetDoorState();
1319 CloseDoor(DOOR_CLOSE_1);
1321 /* Alten Türinhalt sichern */
1322 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1323 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1324 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1326 /* Fragetext schreiben */
1327 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1328 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1330 for(ty=0; ty<13; ty++)
1338 for(tl=0,tx=0; tx<7; tl++,tx++)
1341 if (!tc || tc == 32)
1352 DrawTextExt(pix[PIX_DB_DOOR], gc,
1353 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1354 txt, FS_SMALL, FC_YELLOW);
1355 text += tl + (tc == 32 ? 1 : 0);
1358 if (req_state & REQ_ASK)
1360 DrawYesNoButton(BUTTON_OK, DB_INIT);
1361 DrawYesNoButton(BUTTON_NO, DB_INIT);
1363 else if (req_state & REQ_CONFIRM)
1365 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1367 else if (req_state & REQ_PLAYER)
1369 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1370 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1371 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1372 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1375 OpenDoor(DOOR_OPEN_1);
1378 if (!(req_state & REQUEST_WAIT_FOR))
1381 if (game_status != MAINMENU)
1384 button_status = MB_RELEASED;
1388 if (XPending(display))
1392 XNextEvent(display, &event);
1402 if (event.type == MotionNotify)
1404 motion_status = TRUE;
1405 mx = ((XMotionEvent *) &event)->x;
1406 my = ((XMotionEvent *) &event)->y;
1410 motion_status = FALSE;
1411 mx = ((XButtonEvent *) &event)->x;
1412 my = ((XButtonEvent *) &event)->y;
1413 if (event.type==ButtonPress)
1414 button_status = ((XButtonEvent *) &event)->button;
1416 button_status = MB_RELEASED;
1419 if (req_state & REQ_ASK)
1420 choice = CheckYesNoButtons(mx,my,button_status);
1421 else if (req_state & REQ_CONFIRM)
1422 choice = CheckConfirmButton(mx,my,button_status);
1424 choice = CheckPlayerButtons(mx,my,button_status);
1434 case BUTTON_CONFIRM:
1435 result = TRUE | FALSE;
1438 case BUTTON_PLAYER_1:
1441 case BUTTON_PLAYER_2:
1444 case BUTTON_PLAYER_3:
1447 case BUTTON_PLAYER_4:
1458 switch(XLookupKeysym((XKeyEvent *)&event,
1459 ((XKeyEvent *)&event)->state))
1472 if (req_state & REQ_PLAYER)
1477 key_joystick_mapping = 0;
1481 HandleOtherEvents(&event);
1485 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1487 int joy = AnyJoystick();
1489 if (joy & JOY_BUTTON_1)
1491 else if (joy & JOY_BUTTON_2)
1497 /* don't eat all CPU time */
1501 if (game_status != MAINMENU)
1504 if (!(req_state & REQ_STAY_OPEN))
1506 CloseDoor(DOOR_CLOSE_1);
1508 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1510 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1511 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1512 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1513 OpenDoor(DOOR_OPEN_1);
1517 /* continue network game after request */
1518 if (options.network &&
1519 game_status == PLAYING &&
1520 req_state & REQUEST_WAIT_FOR)
1521 SendToServer_ContinuePlaying();
1526 unsigned int OpenDoor(unsigned int door_state)
1528 unsigned int new_door_state;
1530 if (door_state & DOOR_COPY_BACK)
1532 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1533 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1534 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1535 door_state &= ~DOOR_COPY_BACK;
1538 new_door_state = MoveDoor(door_state);
1540 return(new_door_state);
1543 unsigned int CloseDoor(unsigned int door_state)
1545 unsigned int new_door_state;
1547 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1548 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1549 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1550 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1552 new_door_state = MoveDoor(door_state);
1554 return(new_door_state);
1557 unsigned int GetDoorState()
1559 return(MoveDoor(DOOR_GET_STATE));
1562 unsigned int MoveDoor(unsigned int door_state)
1564 static unsigned int door1 = DOOR_OPEN_1;
1565 static unsigned int door2 = DOOR_CLOSE_2;
1566 static long door_delay = 0;
1567 int x, start, stepsize = 2;
1568 long door_delay_value = stepsize * 5;
1570 if (door_state == DOOR_GET_STATE)
1571 return(door1 | door2);
1573 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1574 door_state &= ~DOOR_OPEN_1;
1575 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1576 door_state &= ~DOOR_CLOSE_1;
1577 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1578 door_state &= ~DOOR_OPEN_2;
1579 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1580 door_state &= ~DOOR_CLOSE_2;
1582 if (setup.quick_doors)
1585 door_delay_value = 0;
1586 StopSound(SND_OEFFNEN);
1589 if (door_state & DOOR_ACTION)
1591 if (!(door_state & DOOR_NO_DELAY))
1592 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1594 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1596 for(x=start; x<=DXSIZE; x+=stepsize)
1598 WaitUntilDelayReached(&door_delay, door_delay_value);
1600 if (door_state & DOOR_ACTION_1)
1602 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1603 int j = (DXSIZE - i) / 3;
1605 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1606 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1607 DXSIZE,DYSIZE - i/2, DX, DY);
1609 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1611 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1612 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1613 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1614 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1615 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1616 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1618 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1619 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1620 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1621 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1622 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1623 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1625 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1626 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1628 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1629 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1631 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1632 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1633 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1634 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1635 DX + DXSIZE - i, DY + 77 + j);
1636 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1637 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1638 DX + DXSIZE - i, DY + 203 + j);
1640 redraw_mask |= REDRAW_DOOR_1;
1643 if (door_state & DOOR_ACTION_2)
1645 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1646 int j = (VXSIZE - i) / 3;
1648 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1649 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1650 VXSIZE, VYSIZE - i/2, VX, VY);
1652 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1654 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1655 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1656 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1657 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1658 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1659 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1660 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1661 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1663 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1664 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1665 VX, VY + VYSIZE / 2 - j);
1666 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1667 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1668 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1669 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1670 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1672 redraw_mask |= REDRAW_DOOR_2;
1677 if (game_status == MAINMENU)
1682 if (setup.quick_doors)
1683 StopSound(SND_OEFFNEN);
1685 if (door_state & DOOR_ACTION_1)
1686 door1 = door_state & DOOR_ACTION_1;
1687 if (door_state & DOOR_ACTION_2)
1688 door2 = door_state & DOOR_ACTION_2;
1690 return(door1 | door2);
1693 int ReadPixel(Drawable d, int x, int y)
1695 static XImage *pixelimage;
1697 pixelimage = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1698 return(XGetPixel(pixelimage, 0, 0));
1701 int el2gfx(int element)
1705 case EL_LEERRAUM: return -1;
1706 case EL_ERDREICH: return GFX_ERDREICH;
1707 case EL_MAUERWERK: return GFX_MAUERWERK;
1708 case EL_FELSBODEN: return GFX_FELSBODEN;
1709 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1710 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1711 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1712 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1713 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1714 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1715 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1716 case EL_SPIELER1: return GFX_SPIELER1;
1717 case EL_SPIELER2: return GFX_SPIELER2;
1718 case EL_SPIELER3: return GFX_SPIELER3;
1719 case EL_SPIELER4: return GFX_SPIELER4;
1720 case EL_KAEFER: return GFX_KAEFER;
1721 case EL_KAEFER_R: return GFX_KAEFER_R;
1722 case EL_KAEFER_O: return GFX_KAEFER_O;
1723 case EL_KAEFER_L: return GFX_KAEFER_L;
1724 case EL_KAEFER_U: return GFX_KAEFER_U;
1725 case EL_FLIEGER: return GFX_FLIEGER;
1726 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1727 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1728 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1729 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1730 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1731 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1732 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1733 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1734 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1735 case EL_FIREFLY: return GFX_FIREFLY;
1736 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1737 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1738 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1739 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1740 case EL_MAMPFER: return GFX_MAMPFER;
1741 case EL_ROBOT: return GFX_ROBOT;
1742 case EL_BETON: return GFX_BETON;
1743 case EL_DIAMANT: return GFX_DIAMANT;
1744 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1745 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1746 case EL_TROPFEN: return GFX_TROPFEN;
1747 case EL_BOMBE: return GFX_BOMBE;
1748 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1749 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1750 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1751 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1752 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1753 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1754 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1755 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1756 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1757 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1758 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1759 case EL_LIFE: return GFX_LIFE;
1760 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1761 case EL_DYNAMIT: return GFX_DYNAMIT;
1762 case EL_BADEWANNE: return GFX_BADEWANNE;
1763 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1764 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1765 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1766 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1767 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1768 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1769 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1770 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1771 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1772 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1773 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1774 case EL_PFORTE1: return GFX_PFORTE1;
1775 case EL_PFORTE2: return GFX_PFORTE2;
1776 case EL_PFORTE3: return GFX_PFORTE3;
1777 case EL_PFORTE4: return GFX_PFORTE4;
1778 case EL_PFORTE1X: return GFX_PFORTE1X;
1779 case EL_PFORTE2X: return GFX_PFORTE2X;
1780 case EL_PFORTE3X: return GFX_PFORTE3X;
1781 case EL_PFORTE4X: return GFX_PFORTE4X;
1782 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1783 case EL_PACMAN: return GFX_PACMAN;
1784 case EL_PACMAN_R: return GFX_PACMAN_R;
1785 case EL_PACMAN_O: return GFX_PACMAN_O;
1786 case EL_PACMAN_L: return GFX_PACMAN_L;
1787 case EL_PACMAN_U: return GFX_PACMAN_U;
1788 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1789 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1790 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1791 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1792 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1793 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1794 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1795 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1796 case EL_MAUER_X: return GFX_MAUER_X;
1797 case EL_MAUER_Y: return GFX_MAUER_Y;
1798 case EL_MAUER_XY: return GFX_MAUER_XY;
1799 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1800 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1801 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1802 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1803 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1804 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1805 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1806 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1807 case EL_MAMPFER2: return GFX_MAMPFER2;
1808 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1809 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1810 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1811 case EL_DYNABOMB: return GFX_DYNABOMB;
1812 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1813 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1814 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1815 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1816 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1817 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1818 case EL_MAULWURF: return GFX_MAULWURF;
1819 case EL_PINGUIN: return GFX_PINGUIN;
1820 case EL_SCHWEIN: return GFX_SCHWEIN;
1821 case EL_DRACHE: return GFX_DRACHE;
1822 case EL_SONDE: return GFX_SONDE;
1823 case EL_PFEIL_L: return GFX_PFEIL_L;
1824 case EL_PFEIL_R: return GFX_PFEIL_R;
1825 case EL_PFEIL_O: return GFX_PFEIL_O;
1826 case EL_PFEIL_U: return GFX_PFEIL_U;
1829 if (IS_CHAR(element))
1830 return GFX_CHAR_START + (element - EL_CHAR_START);