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_on)
47 drawto_field = fieldbuffer;
49 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
60 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
67 Drawable buffer = (drawto_field != window ? drawto_field : backbuffer);
69 if (setup.direct_draw_on && 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 || ScreenGfxPos)
76 redraw_mask &= ~REDRAW_TILES;
81 /* synchronize X11 graphics at this point; if we would synchronize the
82 display immediately after the buffer switching (after the XFlush),
83 this could mean that we have to wait for the graphics to complete,
84 although we could go on doing calculations for the next frame */
89 wait_for_vsync = TRUE;
92 if (redraw_mask & REDRAW_ALL)
94 XCopyArea(display,backbuffer,window,gc,
95 0,0, WIN_XSIZE,WIN_YSIZE,
100 if (redraw_mask & REDRAW_FIELD)
102 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
103 XCopyArea(display,backbuffer,window,gc,
104 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
108 int fx = FX, fy = FY;
110 if (setup.soft_scrolling_on)
112 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
113 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
116 XCopyArea(display,buffer,window,gc,
117 fx,fy, SXSIZE,SYSIZE,
120 redraw_mask &= ~REDRAW_MAIN;
123 if (redraw_mask & REDRAW_DOORS)
125 if (redraw_mask & REDRAW_DOOR_1)
126 XCopyArea(display,backbuffer,window,gc,
127 DX,DY, DXSIZE,DYSIZE,
129 if (redraw_mask & REDRAW_DOOR_2)
131 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
132 XCopyArea(display,backbuffer,window,gc,
133 VX,VY, VXSIZE,VYSIZE,
137 if (redraw_mask & REDRAW_VIDEO_1)
138 XCopyArea(display,backbuffer,window,gc,
139 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
140 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
141 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
142 if (redraw_mask & REDRAW_VIDEO_2)
143 XCopyArea(display,backbuffer,window,gc,
144 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
145 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
146 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
147 if (redraw_mask & REDRAW_VIDEO_3)
148 XCopyArea(display,backbuffer,window,gc,
149 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
150 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
151 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
154 redraw_mask &= ~REDRAW_DOORS;
157 if (redraw_mask & REDRAW_MICROLEV)
159 XCopyArea(display,backbuffer,window,gc,
160 MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
161 MICROLEV_XPOS,MICROLEV_YPOS);
162 XCopyArea(display,backbuffer,window,gc,
163 SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
165 redraw_mask &= ~REDRAW_MICROLEV;
168 if (redraw_mask & REDRAW_TILES)
170 for(x=0; x<SCR_FIELDX; x++)
171 for(y=0; y<SCR_FIELDY; y++)
172 if (redraw[redraw_x1 + x][redraw_y1 + y])
173 XCopyArea(display,buffer,window,gc,
174 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
175 SX+x*TILEX,SY+y*TILEY);
180 for(x=0; x<MAX_BUF_XSIZE; x++)
181 for(y=0; y<MAX_BUF_YSIZE; y++)
190 long fading_delay = 300;
192 if (setup.fading_on && (redraw_mask & REDRAW_FIELD))
199 XFillRectangle(display,window,gc,
200 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
203 for(i=0;i<2*FULL_SYSIZE;i++)
205 for(y=0;y<FULL_SYSIZE;y++)
207 XCopyArea(display,backbuffer,window,gc,
208 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
216 for(i=1;i<FULL_SYSIZE;i+=2)
217 XCopyArea(display,backbuffer,window,gc,
218 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
224 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
225 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
226 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
230 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
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],0,-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],-1,0);
243 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
244 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
248 redraw_mask &= ~REDRAW_MAIN;
257 XFillRectangle(display,backbuffer,gc,
258 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
260 if (setup.soft_scrolling_on && game_status==PLAYING)
262 XFillRectangle(display,fieldbuffer,gc,
264 SetDrawtoField(DRAW_BUFFERED);
267 SetDrawtoField(DRAW_BACKBUFFER);
269 if (setup.direct_draw_on && game_status==PLAYING)
271 XFillRectangle(display,window,gc,
272 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
273 SetDrawtoField(DRAW_DIRECT);
276 redraw_mask |= REDRAW_FIELD;
279 void DrawText(int x, int y, char *text, int font, int col)
281 DrawTextExt(drawto, gc, x, y, text, font, col);
283 redraw_mask |= REDRAW_FIELD;
285 redraw_mask |= REDRAW_DOOR_1;
288 void DrawTextExt(Drawable d, GC gc, int x, int y,
289 char *text, int font, int font_color)
291 int font_width, font_height, font_start;
294 if (font!=FS_SMALL && font!=FS_BIG)
296 if (font_color<FC_RED || font_color>FC_SPECIAL2)
300 (font==FS_BIG ? FONT1_XSIZE :
301 font_color<FC_SPECIAL1 ? FONT2_XSIZE :
302 font_color<FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
304 (font==FS_BIG ? FONT1_XSIZE :
305 font_color<FC_SPECIAL2 ? FONT2_XSIZE: FONT4_XSIZE);
306 font_pixmap = (font==FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
308 font_color*(font==FS_BIG ? FONT1_YSIZE : FONT2_YSIZE)*FONT_LINES_PER_FONT;
314 if (c>='a' && c<='z')
316 else if (c=='ä' || c=='Ä')
318 else if (c=='ö' || c=='Ö')
320 else if (c=='ü' || c=='Ü')
324 XCopyArea(display,pix[font_pixmap],d,gc,
325 ((c-32) % FONT_CHARS_PER_LINE)*font_width,
326 ((c-32) / FONT_CHARS_PER_LINE)*font_height + font_start,
327 font_width,font_height, x,y);
333 void DrawAllPlayers()
337 for(i=0; i<MAX_PLAYERS; i++)
338 if (stored_player[i].active)
339 DrawPlayer(&stored_player[i]);
342 void DrawPlayerField(int x, int y)
347 DrawPlayer(PLAYERINFO(x,y));
350 void DrawPlayer(struct PlayerInfo *player)
352 int jx = player->jx, jy = player->jy;
353 int last_jx = player->last_jx, last_jy = player->last_jy;
354 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
355 int sx = SCREENX(jx), sy = SCREENY(jy);
356 int sxx = 0, syy = 0;
357 int element = Feld[jx][jy];
361 if (!player->active || player->gone || !IN_SCR_FIELD(sx,sy))
365 if (!player->active || player->gone ||
366 !IN_SCR_FIELD(SCREENX(last_jx),SCREENY(last_jy)))
370 if (!IN_LEV_FIELD(jx,jy))
372 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
373 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
374 printf("DrawPlayerField(): This should never happen!\n");
379 if (element == EL_EXPLODING)
382 /* draw things in the field the player is leaving, if needed */
384 if (last_jx != jx || last_jy != jy)
386 if (Store[last_jx][last_jy])
388 DrawLevelElement(last_jx,last_jy, Store[last_jx][last_jy]);
389 DrawLevelFieldThruMask(last_jx,last_jy);
391 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
392 DrawDynamite(last_jx,last_jy);
394 DrawLevelField(last_jx,last_jy);
396 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx),SCREENY(next_jy)))
400 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
401 DrawLevelElement(next_jx,next_jy, EL_SOKOBAN_FELD_LEER);
403 DrawLevelElement(next_jx,next_jy, EL_LEERRAUM);
406 DrawLevelField(next_jx,next_jy);
410 if (!IN_SCR_FIELD(sx,sy))
413 if (setup.direct_draw_on)
414 SetDrawtoField(DRAW_BUFFERED);
416 /* draw things behind the player, if needed */
419 DrawLevelElement(jx,jy, Store[jx][jy]);
420 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
421 DrawLevelField(jx,jy);
423 /* draw player himself */
425 if (player->MovDir==MV_LEFT)
426 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
427 else if (player->MovDir==MV_RIGHT)
428 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
429 else if (player->MovDir==MV_UP)
430 graphic = GFX_SPIELER1_UP;
431 else /* MV_DOWN || MV_NO_MOVING */
432 graphic = GFX_SPIELER1_DOWN;
434 graphic += player->index_nr * 3*HEROES_PER_LINE;
435 graphic += player->Frame;
439 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
440 sxx = player->GfxPos;
442 syy = player->GfxPos;
445 if (!setup.soft_scrolling_on && ScreenMovPos)
448 DrawGraphicShiftedThruMask(sx,sy, sxx,syy, graphic, NO_CUTTING);
450 if (player->Pushing && player->GfxPos)
452 int px = SCREENX(next_jx), py = SCREENY(next_jy);
454 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
455 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
456 DrawGraphicShiftedThruMask(px,py,sxx,syy, GFX_SOKOBAN_OBJEKT,NO_CUTTING);
459 int element = Feld[next_jx][next_jy];
460 int graphic = el2gfx(element);
462 if (element == EL_FELSBROCKEN && sxx)
464 int phase = (player->GfxPos / (TILEX/4));
466 if (player->MovDir == MV_LEFT)
469 graphic += (phase+4)%4;
472 DrawGraphicShifted(px,py, sxx,syy, graphic, NO_CUTTING, NO_MASKING);
476 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
478 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
480 graphic = el2gfx(element);
482 if (element == EL_DYNAMIT)
484 if ((phase = (96-MovDelay[jx][jy])/12) > 6)
489 if ((phase = ((96-MovDelay[jx][jy])/6) % 8) > 3)
493 DrawGraphicThruMask(sx,sy, graphic + phase);
496 if ((last_jx != jx || last_jy != jy) && 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_on)
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 = frames*2 - 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);
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;
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;
1006 if (!IN_LEV_FIELD(uxx,uyy))
1009 element = Feld[uxx][uyy];
1011 if (element==EL_ERDREICH)
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);
1039 graphic = GFX_ERDENRAND;
1050 if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
1051 !IN_SCR_FIELD(xx,yy))
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 || MovDir[oldx][oldy]==MV_RIGHT);
1144 if (Store[oldx][oldy]==EL_MORAST_LEER ||
1145 Store[oldx][oldy]==EL_SIEB_LEER ||
1146 Store[oldx][oldy]==EL_SIEB2_LEER ||
1147 Store[oldx][oldy]==EL_AMOEBE_NASS)
1148 cut_mode = CUT_ABOVE;
1150 DrawScreenElement(x,y,EL_LEERRAUM);
1151 element = Feld[oldx][oldy];
1154 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1156 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1158 else if (IS_DRAWABLE(element))
1159 DrawScreenElement(x,y,element);
1161 DrawScreenElement(x,y,EL_LEERRAUM);
1164 void DrawLevelField(int x, int y)
1166 if (IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
1167 DrawScreenField(SCREENX(x),SCREENY(y));
1168 else if (IS_MOVING(x,y))
1172 Moving2Blocked(x,y,&newx,&newy);
1173 if (IN_SCR_FIELD(SCREENX(newx),SCREENY(newy)))
1174 DrawScreenField(SCREENX(newx),SCREENY(newy));
1176 else if (IS_BLOCKED(x,y))
1180 Blocked2Moving(x,y,&oldx,&oldy);
1181 if (IN_SCR_FIELD(SCREENX(oldx),SCREENY(oldy)))
1182 DrawScreenField(SCREENX(oldx),SCREENY(oldy));
1186 void DrawMiniElement(int x, int y, int element)
1192 DrawMiniGraphic(x,y,-1);
1196 graphic = el2gfx(element);
1197 DrawMiniGraphic(x,y,graphic);
1200 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1202 int x = sx + scroll_x, y = sy + scroll_y;
1204 if (x<-1 || x>lev_fieldx || y<-1 || y>lev_fieldy)
1205 DrawMiniElement(sx,sy,EL_LEERRAUM);
1206 else if (x==-1 || x==lev_fieldx || y==-1 || y==lev_fieldy)
1207 DrawMiniElement(sx,sy,EL_BETON);
1209 DrawMiniElement(sx,sy,Feld[x][y]);
1212 void DrawMicroElement(int xpos, int ypos, int element)
1216 if (element==EL_LEERRAUM)
1219 graphic = el2gfx(element);
1221 XCopyArea(display,pix[PIX_BACK],drawto,gc,
1222 MICRO_GFX_STARTX+(graphic % MICRO_GFX_PER_LINE)*MICRO_TILEX,
1223 MICRO_GFX_STARTY+(graphic / MICRO_GFX_PER_LINE)*MICRO_TILEY,
1224 MICRO_TILEX,MICRO_TILEY, xpos,ypos);
1233 for(x=BX1; x<=BX2; x++)
1234 for(y=BY1; y<=BY2; y++)
1235 DrawScreenField(x,y);
1237 if (setup.soft_scrolling_on)
1238 XCopyArea(display,fieldbuffer,backbuffer,gc,
1239 FX,FY, SXSIZE,SYSIZE,
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+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
1275 Feld[x][y]=Ur[x][y]);
1276 else if (x>=-1 && x<lev_fieldx+1 && y>=-1 && y<lev_fieldy+1)
1277 DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
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++)
1337 for(tl=0,tx=0;tx<7;tl++,tx++)
1351 DrawTextExt(pix[PIX_DB_DOOR],gc,
1352 DOOR_GFX_PAGEX1+51-(tl*14)/2,SY+ty*16,txt,FS_SMALL,FC_YELLOW);
1353 text+=(tl+(tc==32));
1356 if (req_state & REQ_ASK)
1358 DrawYesNoButton(BUTTON_OK, DB_INIT);
1359 DrawYesNoButton(BUTTON_NO, DB_INIT);
1361 else if (req_state & REQ_CONFIRM)
1363 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1365 else if (req_state & REQ_PLAYER)
1367 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1368 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1369 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1370 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1373 OpenDoor(DOOR_OPEN_1);
1376 if (!(req_state & REQUEST_WAIT_FOR))
1379 if (game_status != MAINMENU)
1382 button_status = MB_RELEASED;
1386 if (XPending(display))
1390 XNextEvent(display, &event);
1400 if (event.type == MotionNotify)
1402 motion_status = TRUE;
1403 mx = ((XMotionEvent *) &event)->x;
1404 my = ((XMotionEvent *) &event)->y;
1408 motion_status = FALSE;
1409 mx = ((XButtonEvent *) &event)->x;
1410 my = ((XButtonEvent *) &event)->y;
1411 if (event.type==ButtonPress)
1412 button_status = ((XButtonEvent *) &event)->button;
1414 button_status = MB_RELEASED;
1417 if (req_state & REQ_ASK)
1418 choice = CheckYesNoButtons(mx,my,button_status);
1419 else if (req_state & REQ_CONFIRM)
1420 choice = CheckConfirmButton(mx,my,button_status);
1422 choice = CheckPlayerButtons(mx,my,button_status);
1432 case BUTTON_CONFIRM:
1433 result = TRUE | FALSE;
1436 case BUTTON_PLAYER_1:
1439 case BUTTON_PLAYER_2:
1442 case BUTTON_PLAYER_3:
1445 case BUTTON_PLAYER_4:
1456 switch(XLookupKeysym((XKeyEvent *)&event,
1457 ((XKeyEvent *)&event)->state))
1470 if (req_state & REQ_PLAYER)
1475 key_joystick_mapping = 0;
1479 HandleOtherEvents(&event);
1483 else if (JoystickButton() == JOY_BUTTON_NEW_PRESSED)
1487 if (joy & JOY_BUTTON_1)
1489 else if (joy & JOY_BUTTON_2)
1495 /* don't eat all CPU time */
1499 if (game_status != MAINMENU)
1502 if (!(req_state & REQ_STAY_OPEN))
1504 CloseDoor(DOOR_CLOSE_1);
1506 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1508 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1509 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1510 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1511 OpenDoor(DOOR_OPEN_1);
1515 /* continue network game after request */
1516 if (options.network &&
1517 game_status == PLAYING &&
1518 req_state & REQUEST_WAIT_FOR)
1519 SendToServer_ContinuePlaying();
1524 unsigned int OpenDoor(unsigned int door_state)
1526 unsigned int new_door_state;
1528 if (door_state & DOOR_COPY_BACK)
1530 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1531 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE+VYSIZE,
1532 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1533 door_state &= ~DOOR_COPY_BACK;
1536 new_door_state = MoveDoor(door_state);
1538 return(new_door_state);
1541 unsigned int CloseDoor(unsigned int door_state)
1543 unsigned int new_door_state;
1545 XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1546 DX,DY, DXSIZE,DYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1547 XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1548 VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1550 new_door_state = MoveDoor(door_state);
1552 return(new_door_state);
1555 unsigned int GetDoorState()
1557 return(MoveDoor(DOOR_GET_STATE));
1560 unsigned int MoveDoor(unsigned int door_state)
1562 static unsigned int door1 = DOOR_OPEN_1;
1563 static unsigned int door2 = DOOR_CLOSE_2;
1564 static long door_delay = 0;
1565 int x, start, stepsize = 2;
1566 long door_delay_value = stepsize * 5;
1568 if (door_state == DOOR_GET_STATE)
1569 return(door1 | door2);
1571 if (door1==DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1572 door_state &= ~DOOR_OPEN_1;
1573 else if (door1==DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1574 door_state &= ~DOOR_CLOSE_1;
1575 if (door2==DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1576 door_state &= ~DOOR_OPEN_2;
1577 else if (door2==DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1578 door_state &= ~DOOR_CLOSE_2;
1580 if (setup.quick_doors)
1583 door_delay_value = 0;
1584 StopSound(SND_OEFFNEN);
1587 if (door_state & DOOR_ACTION)
1589 if (!(door_state & DOOR_NO_DELAY))
1590 PlaySoundStereo(SND_OEFFNEN,PSND_MAX_RIGHT);
1592 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1594 for(x=start; x<=DXSIZE; x+=stepsize)
1596 WaitUntilDelayReached(&door_delay, door_delay_value);
1598 if (door_state & DOOR_ACTION_1)
1600 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1601 int j = (DXSIZE - i)/3;
1603 XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1604 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1+i/2,
1605 DXSIZE,DYSIZE-i/2, DX,DY);
1607 XFillRectangle(display,drawto,gc,DX,DY+DYSIZE-i/2,DXSIZE,i/2);
1609 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1610 DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1611 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1612 DXSIZE,DOOR_GFX_PAGEY1, i,77, DX+DXSIZE-i,DY+j);
1613 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1614 DXSIZE,DOOR_GFX_PAGEY1+140, i,63, DX+DXSIZE-i,DY+140+j);
1615 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1616 DX-DXSIZE+i,DY-(DOOR_GFX_PAGEY1+j));
1617 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1618 DXSIZE-i,DOOR_GFX_PAGEY1+j, i,77-j, DX,DY);
1619 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1620 DXSIZE-i,DOOR_GFX_PAGEY1+140, i,63, DX,DY+140-j);
1622 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1623 DXSIZE-i,DOOR_GFX_PAGEY1+77, i,63,
1625 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1626 DXSIZE-i,DOOR_GFX_PAGEY1+203, i,77,
1628 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1629 DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1630 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1631 DXSIZE,DOOR_GFX_PAGEY1+77, i,63,
1632 DX+DXSIZE-i,DY+77+j);
1633 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1634 DXSIZE,DOOR_GFX_PAGEY1+203, i,77-j,
1635 DX+DXSIZE-i,DY+203+j);
1637 redraw_mask |= REDRAW_DOOR_1;
1640 if (door_state & DOOR_ACTION_2)
1642 int i = (door_state & DOOR_OPEN_2 ? VXSIZE-x : x);
1643 int j = (VXSIZE - i)/3;
1645 XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1646 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2+i/2,
1647 VXSIZE,VYSIZE-i/2, VX,VY);
1649 XFillRectangle(display,drawto,gc,VX,VY+VYSIZE-i/2,VXSIZE,i/2);
1651 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1652 VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1653 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1654 VXSIZE,DOOR_GFX_PAGEY2, i,VYSIZE/2, VX+VXSIZE-i,VY+j);
1655 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1656 VX-VXSIZE+i,VY-(DOOR_GFX_PAGEY2+j));
1657 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1658 VXSIZE-i,DOOR_GFX_PAGEY2+j, i,VYSIZE/2-j, VX,VY);
1660 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1661 VXSIZE-i,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2,
1663 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1664 VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1665 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1666 VXSIZE,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2-j,
1667 VX+VXSIZE-i,VY+VYSIZE/2+j);
1669 redraw_mask |= REDRAW_DOOR_2;
1674 if (game_status == MAINMENU)
1679 if (setup.quick_doors)
1680 StopSound(SND_OEFFNEN);
1682 if (door_state & DOOR_ACTION_1)
1683 door1 = door_state & DOOR_ACTION_1;
1684 if (door_state & DOOR_ACTION_2)
1685 door2 = door_state & DOOR_ACTION_2;
1687 return(door1 | door2);
1690 int ReadPixel(Drawable d, int x, int y)
1692 static XImage *pixelimage;
1694 pixelimage = XGetImage(display, d, x,y, 1,1, AllPlanes, ZPixmap);
1695 return(XGetPixel(pixelimage,0,0));
1698 int el2gfx(int element)
1702 case EL_LEERRAUM: return(-1);
1703 case EL_ERDREICH: return(GFX_ERDREICH);
1704 case EL_MAUERWERK: return(GFX_MAUERWERK);
1705 case EL_FELSBODEN: return(GFX_FELSBODEN);
1706 case EL_FELSBROCKEN: return(GFX_FELSBROCKEN);
1707 case EL_SCHLUESSEL: return(GFX_SCHLUESSEL);
1708 case EL_EDELSTEIN: return(GFX_EDELSTEIN);
1709 case EL_AUSGANG_ZU: return(GFX_AUSGANG_ZU);
1710 case EL_AUSGANG_ACT: return(GFX_AUSGANG_ACT);
1711 case EL_AUSGANG_AUF: return(GFX_AUSGANG_AUF);
1712 case EL_SPIELFIGUR: return(GFX_SPIELFIGUR);
1713 case EL_SPIELER1: return(GFX_SPIELER1);
1714 case EL_SPIELER2: return(GFX_SPIELER2);
1715 case EL_SPIELER3: return(GFX_SPIELER3);
1716 case EL_SPIELER4: return(GFX_SPIELER4);
1717 case EL_KAEFER: return(GFX_KAEFER);
1718 case EL_KAEFER_R: return(GFX_KAEFER_R);
1719 case EL_KAEFER_O: return(GFX_KAEFER_O);
1720 case EL_KAEFER_L: return(GFX_KAEFER_L);
1721 case EL_KAEFER_U: return(GFX_KAEFER_U);
1722 case EL_FLIEGER: return(GFX_FLIEGER);
1723 case EL_FLIEGER_R: return(GFX_FLIEGER_R);
1724 case EL_FLIEGER_O: return(GFX_FLIEGER_O);
1725 case EL_FLIEGER_L: return(GFX_FLIEGER_L);
1726 case EL_FLIEGER_U: return(GFX_FLIEGER_U);
1727 case EL_BUTTERFLY: return(GFX_BUTTERFLY);
1728 case EL_BUTTERFLY_R: return(GFX_BUTTERFLY_R);
1729 case EL_BUTTERFLY_O: return(GFX_BUTTERFLY_O);
1730 case EL_BUTTERFLY_L: return(GFX_BUTTERFLY_L);
1731 case EL_BUTTERFLY_U: return(GFX_BUTTERFLY_U);
1732 case EL_FIREFLY: return(GFX_FIREFLY);
1733 case EL_FIREFLY_R: return(GFX_FIREFLY_R);
1734 case EL_FIREFLY_O: return(GFX_FIREFLY_O);
1735 case EL_FIREFLY_L: return(GFX_FIREFLY_L);
1736 case EL_FIREFLY_U: return(GFX_FIREFLY_U);
1737 case EL_MAMPFER: return(GFX_MAMPFER);
1738 case EL_ROBOT: return(GFX_ROBOT);
1739 case EL_BETON: return(GFX_BETON);
1740 case EL_DIAMANT: return(GFX_DIAMANT);
1741 case EL_MORAST_LEER: return(GFX_MORAST_LEER);
1742 case EL_MORAST_VOLL: return(GFX_MORAST_VOLL);
1743 case EL_TROPFEN: return(GFX_TROPFEN);
1744 case EL_BOMBE: return(GFX_BOMBE);
1745 case EL_SIEB_LEER: return(GFX_SIEB_LEER);
1746 case EL_SIEB_VOLL: return(GFX_SIEB_VOLL);
1747 case EL_SIEB_TOT: return(GFX_SIEB_TOT);
1748 case EL_SALZSAEURE: return(GFX_SALZSAEURE);
1749 case EL_AMOEBE_TOT: return(GFX_AMOEBE_TOT);
1750 case EL_AMOEBE_NASS: return(GFX_AMOEBE_NASS);
1751 case EL_AMOEBE_NORM: return(GFX_AMOEBE_NORM);
1752 case EL_AMOEBE_VOLL: return(GFX_AMOEBE_VOLL);
1753 case EL_AMOEBE_BD: return(GFX_AMOEBE_BD);
1754 case EL_AMOEBA2DIAM: return(GFX_AMOEBA2DIAM);
1755 case EL_KOKOSNUSS: return(GFX_KOKOSNUSS);
1756 case EL_LIFE: return(GFX_LIFE);
1757 case EL_LIFE_ASYNC: return(GFX_LIFE_ASYNC);
1758 case EL_DYNAMIT: return(GFX_DYNAMIT);
1759 case EL_BADEWANNE: return(GFX_BADEWANNE);
1760 case EL_BADEWANNE1: return(GFX_BADEWANNE1);
1761 case EL_BADEWANNE2: return(GFX_BADEWANNE2);
1762 case EL_BADEWANNE3: return(GFX_BADEWANNE3);
1763 case EL_BADEWANNE4: return(GFX_BADEWANNE4);
1764 case EL_BADEWANNE5: return(GFX_BADEWANNE5);
1765 case EL_ABLENK_AUS: return(GFX_ABLENK_AUS);
1766 case EL_ABLENK_EIN: return(GFX_ABLENK_EIN);
1767 case EL_SCHLUESSEL1: return(GFX_SCHLUESSEL1);
1768 case EL_SCHLUESSEL2: return(GFX_SCHLUESSEL2);
1769 case EL_SCHLUESSEL3: return(GFX_SCHLUESSEL3);
1770 case EL_SCHLUESSEL4: return(GFX_SCHLUESSEL4);
1771 case EL_PFORTE1: return(GFX_PFORTE1);
1772 case EL_PFORTE2: return(GFX_PFORTE2);
1773 case EL_PFORTE3: return(GFX_PFORTE3);
1774 case EL_PFORTE4: return(GFX_PFORTE4);
1775 case EL_PFORTE1X: return(GFX_PFORTE1X);
1776 case EL_PFORTE2X: return(GFX_PFORTE2X);
1777 case EL_PFORTE3X: return(GFX_PFORTE3X);
1778 case EL_PFORTE4X: return(GFX_PFORTE4X);
1779 case EL_DYNAMIT_AUS: return(GFX_DYNAMIT_AUS);
1780 case EL_PACMAN: return(GFX_PACMAN);
1781 case EL_PACMAN_R: return(GFX_PACMAN_R);
1782 case EL_PACMAN_O: return(GFX_PACMAN_O);
1783 case EL_PACMAN_L: return(GFX_PACMAN_L);
1784 case EL_PACMAN_U: return(GFX_PACMAN_U);
1785 case EL_UNSICHTBAR: return(GFX_UNSICHTBAR);
1786 case EL_ERZ_EDEL: return(GFX_ERZ_EDEL);
1787 case EL_ERZ_DIAM: return(GFX_ERZ_DIAM);
1788 case EL_BIRNE_AUS: return(GFX_BIRNE_AUS);
1789 case EL_BIRNE_EIN: return(GFX_BIRNE_EIN);
1790 case EL_ZEIT_VOLL: return(GFX_ZEIT_VOLL);
1791 case EL_ZEIT_LEER: return(GFX_ZEIT_LEER);
1792 case EL_MAUER_LEBT: return(GFX_MAUER_LEBT);
1793 case EL_MAUER_X: return(GFX_MAUER_X);
1794 case EL_MAUER_Y: return(GFX_MAUER_Y);
1795 case EL_MAUER_XY: return(GFX_MAUER_XY);
1796 case EL_EDELSTEIN_BD: return(GFX_EDELSTEIN_BD);
1797 case EL_EDELSTEIN_GELB: return(GFX_EDELSTEIN_GELB);
1798 case EL_EDELSTEIN_ROT: return(GFX_EDELSTEIN_ROT);
1799 case EL_EDELSTEIN_LILA: return(GFX_EDELSTEIN_LILA);
1800 case EL_ERZ_EDEL_BD: return(GFX_ERZ_EDEL_BD);
1801 case EL_ERZ_EDEL_GELB: return(GFX_ERZ_EDEL_GELB);
1802 case EL_ERZ_EDEL_ROT: return(GFX_ERZ_EDEL_ROT);
1803 case EL_ERZ_EDEL_LILA: return(GFX_ERZ_EDEL_LILA);
1804 case EL_MAMPFER2: return(GFX_MAMPFER2);
1805 case EL_SIEB2_LEER: return(GFX_SIEB2_LEER);
1806 case EL_SIEB2_VOLL: return(GFX_SIEB2_VOLL);
1807 case EL_SIEB2_TOT: return(GFX_SIEB2_TOT);
1808 case EL_DYNABOMB: return(GFX_DYNABOMB);
1809 case EL_DYNABOMB_NR: return(GFX_DYNABOMB_NR);
1810 case EL_DYNABOMB_SZ: return(GFX_DYNABOMB_SZ);
1811 case EL_DYNABOMB_XL: return(GFX_DYNABOMB_XL);
1812 case EL_SOKOBAN_OBJEKT: return(GFX_SOKOBAN_OBJEKT);
1813 case EL_SOKOBAN_FELD_LEER: return(GFX_SOKOBAN_FELD_LEER);
1814 case EL_SOKOBAN_FELD_VOLL: return(GFX_SOKOBAN_FELD_VOLL);
1815 case EL_MAULWURF: return(GFX_MAULWURF);
1816 case EL_PINGUIN: return(GFX_PINGUIN);
1817 case EL_SCHWEIN: return(GFX_SCHWEIN);
1818 case EL_DRACHE: return(GFX_DRACHE);
1819 case EL_SONDE: return(GFX_SONDE);
1820 case EL_PFEIL_L: return(GFX_PFEIL_L);
1821 case EL_PFEIL_R: return(GFX_PFEIL_R);
1822 case EL_PFEIL_O: return(GFX_PFEIL_O);
1823 case EL_PFEIL_U: return(GFX_PFEIL_U);
1826 if (IS_CHAR(element))
1827 return(GFX_CHAR_START + (element-EL_CHAR_START));