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 ? drawto_field : backbuffer);
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 || 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)
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 && (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 && game_status==PLAYING)
262 XFillRectangle(display,fieldbuffer,gc,
264 SetDrawtoField(DRAW_BUFFERED);
267 SetDrawtoField(DRAW_BACKBUFFER);
269 if (setup.direct_draw && 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];
360 if (!player->active || player->gone ||
361 !IN_SCR_FIELD(SCREENX(last_jx),SCREENY(last_jy)))
365 if (!IN_LEV_FIELD(jx,jy))
367 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
368 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
369 printf("DrawPlayerField(): This should never happen!\n");
374 if (element == EL_EXPLODING)
377 /* draw things in the field the player is leaving, if needed */
379 if (last_jx != jx || last_jy != jy)
381 if (Store[last_jx][last_jy])
383 DrawLevelElement(last_jx,last_jy, Store[last_jx][last_jy]);
384 DrawLevelFieldThruMask(last_jx,last_jy);
386 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
387 DrawDynamite(last_jx,last_jy);
389 DrawLevelField(last_jx,last_jy);
391 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx),SCREENY(next_jy)))
395 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
396 DrawLevelElement(next_jx,next_jy, EL_SOKOBAN_FELD_LEER);
398 DrawLevelElement(next_jx,next_jy, EL_LEERRAUM);
401 DrawLevelField(next_jx,next_jy);
405 if (!IN_SCR_FIELD(sx,sy))
408 if (setup.direct_draw)
409 SetDrawtoField(DRAW_BUFFERED);
411 /* draw things behind the player, if needed */
414 DrawLevelElement(jx,jy, Store[jx][jy]);
415 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
416 DrawLevelField(jx,jy);
418 /* draw player himself */
420 if (player->MovDir==MV_LEFT)
421 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
422 else if (player->MovDir==MV_RIGHT)
423 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
424 else if (player->MovDir==MV_UP)
425 graphic = GFX_SPIELER1_UP;
426 else /* MV_DOWN || MV_NO_MOVING */
427 graphic = GFX_SPIELER1_DOWN;
429 graphic += player->index_nr * 3*HEROES_PER_LINE;
430 graphic += player->Frame;
434 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
435 sxx = player->GfxPos;
437 syy = player->GfxPos;
440 if (!setup.soft_scrolling && ScreenMovPos)
443 DrawGraphicShiftedThruMask(sx,sy, sxx,syy, graphic, NO_CUTTING);
445 if (player->Pushing && player->GfxPos)
447 int px = SCREENX(next_jx), py = SCREENY(next_jy);
449 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
450 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
451 DrawGraphicShiftedThruMask(px,py,sxx,syy, GFX_SOKOBAN_OBJEKT,NO_CUTTING);
454 int element = Feld[next_jx][next_jy];
455 int graphic = el2gfx(element);
457 if (element == EL_FELSBROCKEN && sxx)
459 int phase = (player->GfxPos / (TILEX/4));
461 if (player->MovDir == MV_LEFT)
464 graphic += (phase+4)%4;
467 DrawGraphicShifted(px,py, sxx,syy, graphic, NO_CUTTING, NO_MASKING);
471 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
473 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
475 graphic = el2gfx(element);
477 if (element == EL_DYNAMIT)
479 if ((phase = (96-MovDelay[jx][jy])/12) > 6)
484 if ((phase = ((96-MovDelay[jx][jy])/6) % 8) > 3)
488 DrawGraphicThruMask(sx,sy, graphic + phase);
491 if ((last_jx != jx || last_jy != jy) && Feld[last_jx][last_jy]==EL_EXPLODING)
493 int phase = Frame[last_jx][last_jy];
497 DrawGraphicThruMask(SCREENX(last_jx),SCREENY(last_jy),
498 GFX_EXPLOSION + ((phase-1)/delay-1));
501 if (setup.direct_draw)
503 int dest_x = SX + SCREENX(MIN(jx,last_jx))*TILEX;
504 int dest_y = SY + SCREENY(MIN(jy,last_jy))*TILEY;
505 int x_size = TILEX * (1 + ABS(jx - last_jx));
506 int y_size = TILEY * (1 + ABS(jy - last_jy));
508 XCopyArea(display,drawto_field,window,gc,
509 dest_x,dest_y, x_size,y_size, dest_x,dest_y);
510 SetDrawtoField(DRAW_DIRECT);
513 MarkTileDirty(sx,sy);
516 static int getGraphicAnimationPhase(int frames, int delay, int mode)
520 if (mode == ANIM_OSCILLATE)
522 int max_anim_frames = frames*2 - 2;
523 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
524 phase = (phase < frames ? phase : max_anim_frames - phase);
527 phase = (FrameCounter % (delay * frames)) / delay;
529 if (mode == ANIM_REVERSE)
535 void DrawGraphicAnimationExt(int x, int y, int graphic,
536 int frames, int delay, int mode, int mask_mode)
538 int phase = getGraphicAnimationPhase(frames, delay, mode);
540 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
542 if (mask_mode == USE_MASKING)
543 DrawGraphicThruMask(SCREENX(x),SCREENY(y), graphic + phase);
545 DrawGraphic(SCREENX(x),SCREENY(y), graphic + phase);
549 void DrawGraphicAnimation(int x, int y, int graphic,
550 int frames, int delay, int mode)
552 DrawGraphicAnimationExt(x,y, graphic, frames,delay,mode, NO_MASKING);
555 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
556 int frames, int delay, int mode)
558 DrawGraphicAnimationExt(x,y, graphic, frames,delay,mode, USE_MASKING);
561 void DrawGraphic(int x, int y, int graphic)
564 if (!IN_SCR_FIELD(x,y))
566 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
567 printf("DrawGraphic(): This should never happen!\n");
572 DrawGraphicExt(drawto_field, gc, FX+x*TILEX, FY+y*TILEY, graphic);
576 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
578 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
580 graphic -= GFX_START_ROCKSSCREEN;
581 XCopyArea(display,pix[PIX_BACK],d,gc,
582 SX + (graphic % GFX_PER_LINE) * TILEX,
583 SY + (graphic / GFX_PER_LINE) * TILEY,
586 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
588 graphic -= GFX_START_ROCKSHEROES;
589 XCopyArea(display,pix[PIX_HEROES],d,gc,
590 (graphic % HEROES_PER_LINE) * TILEX,
591 (graphic / HEROES_PER_LINE) * TILEY,
594 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
596 graphic -= GFX_START_ROCKSFONT;
597 XCopyArea(display,pix[PIX_BIGFONT],d,gc,
598 (graphic % FONT_CHARS_PER_LINE) * TILEX,
599 (graphic / FONT_CHARS_PER_LINE) * TILEY +
600 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
604 XFillRectangle(display,d,gc, x,y, TILEX,TILEY);
607 void DrawGraphicThruMask(int x, int y, int graphic)
610 if (!IN_SCR_FIELD(x,y))
612 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
613 printf("DrawGraphicThruMask(): This should never happen!\n");
618 DrawGraphicThruMaskExt(drawto_field, FX+x*TILEX, FY+y*TILEY, graphic);
622 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
629 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
631 src_pixmap = pix[PIX_BACK];
632 drawing_gc = clip_gc[PIX_BACK];
633 graphic -= GFX_START_ROCKSSCREEN;
634 src_x = SX+(graphic % GFX_PER_LINE)*TILEX;
635 src_y = SY+(graphic / GFX_PER_LINE)*TILEY;
637 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
639 src_pixmap = pix[PIX_HEROES];
640 drawing_gc = clip_gc[PIX_HEROES];
641 graphic -= GFX_START_ROCKSHEROES;
642 src_x = (graphic % HEROES_PER_LINE)*TILEX;
643 src_y = (graphic / HEROES_PER_LINE)*TILEY;
647 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
651 if (tile_clipmask[tile] != None)
653 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
654 XSetClipOrigin(display, tile_clip_gc, dest_x,dest_y);
655 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
656 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
661 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
664 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
665 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
666 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
670 void DrawMiniGraphic(int x, int y, int graphic)
672 DrawMiniGraphicExt(drawto,gc, SX+x*MINI_TILEX,SY+y*MINI_TILEY, graphic);
673 MarkTileDirty(x/2, y/2);
676 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
678 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
680 graphic -= GFX_START_ROCKSSCREEN;
681 XCopyArea(display,pix[PIX_BACK],d,gc,
682 MINI_GFX_STARTX+(graphic % MINI_GFX_PER_LINE)*MINI_TILEX,
683 MINI_GFX_STARTY+(graphic / MINI_GFX_PER_LINE)*MINI_TILEY,
684 MINI_TILEX,MINI_TILEY, x,y);
686 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
688 graphic -= GFX_START_ROCKSFONT;
689 XCopyArea(display,pix[PIX_SMALLFONT],d,gc,
690 (graphic % FONT_CHARS_PER_LINE)*FONT4_XSIZE,
691 (graphic / FONT_CHARS_PER_LINE)*FONT4_YSIZE +
692 FC_SPECIAL2*FONT2_YSIZE*FONT_LINES_PER_FONT,
693 MINI_TILEX,MINI_TILEY, x,y);
696 XFillRectangle(display,d,gc, x,y, MINI_TILEX,MINI_TILEY);
699 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
700 int cut_mode, int mask_mode)
702 int width = TILEX, height = TILEY;
704 int src_x,src_y, dest_x,dest_y;
711 DrawGraphic(x,y,graphic);
715 if (dx || dy) /* Verschiebung der Grafik? */
717 if (x < BX1) /* Element kommt von links ins Bild */
724 else if (x > BX2) /* Element kommt von rechts ins Bild */
730 else if (x==BX1 && dx<0) /* Element verläßt links das Bild */
736 else if (x==BX2 && dx>0) /* Element verläßt rechts das Bild */
738 else if (dx) /* allg. Bewegung in x-Richtung */
739 MarkTileDirty(x + SIGN(dx), y);
741 if (y < BY1) /* Element kommt von oben ins Bild */
743 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
751 else if (y > BY2) /* Element kommt von unten ins Bild */
757 else if (y==BY1 && dy<0) /* Element verläßt oben das Bild */
763 else if (dy > 0 && cut_mode==CUT_ABOVE)
765 if (y == BY2) /* Element unterhalb des Bildes */
771 MarkTileDirty(x, y + 1);
772 } /* Element verläßt unten das Bild */
773 else if (dy > 0 && (y == BY2 || cut_mode==CUT_BELOW))
775 else if (dy) /* allg. Bewegung in y-Richtung */
776 MarkTileDirty(x, y + SIGN(dy));
779 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
781 src_pixmap = pix[PIX_BACK];
782 drawing_gc = clip_gc[PIX_BACK];
783 graphic -= GFX_START_ROCKSSCREEN;
784 src_x = SX+(graphic % GFX_PER_LINE)*TILEX+cx;
785 src_y = SY+(graphic / GFX_PER_LINE)*TILEY+cy;
787 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
789 src_pixmap = pix[PIX_HEROES];
790 drawing_gc = clip_gc[PIX_HEROES];
791 graphic -= GFX_START_ROCKSHEROES;
792 src_x = (graphic % HEROES_PER_LINE)*TILEX+cx;
793 src_y = (graphic / HEROES_PER_LINE)*TILEY+cy;
796 dest_x = FX + x*TILEX + dx;
797 dest_y = FY + y*TILEY + dy;
800 if (!IN_SCR_FIELD(x,y))
802 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
803 printf("DrawGraphicShifted(): This should never happen!\n");
808 if (mask_mode == USE_MASKING)
810 if (tile_clipmask[tile] != None)
812 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
813 XSetClipOrigin(display, tile_clip_gc, dest_x,dest_y);
814 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
815 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
820 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
823 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
824 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
825 src_x,src_y, width,height, dest_x,dest_y);
829 XCopyArea(display, src_pixmap, drawto_field, gc,
830 src_x,src_y, width,height, dest_x,dest_y);
835 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
838 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
841 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
842 int cut_mode, int mask_mode)
844 int ux = LEVELX(x), uy = LEVELY(y);
845 int graphic = el2gfx(element);
846 int phase4 = ABS(MovPos[ux][uy])/(TILEX/4);
847 int phase = phase4 / 2;
848 int dir = MovDir[ux][uy];
850 if (element==EL_PACMAN || element==EL_KAEFER || element==EL_FLIEGER)
856 else if (dir == MV_LEFT)
858 else if (dir == MV_DOWN)
861 else if (element==EL_MAULWURF || element==EL_PINGUIN ||
862 element==EL_SCHWEIN || element==EL_DRACHE)
865 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_LEFT :
866 element==EL_PINGUIN ? GFX_PINGUIN_LEFT :
867 element==EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
868 else if (dir==MV_RIGHT)
869 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_RIGHT :
870 element==EL_PINGUIN ? GFX_PINGUIN_RIGHT :
871 element==EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
873 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_UP :
874 element==EL_PINGUIN ? GFX_PINGUIN_UP :
875 element==EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
877 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_DOWN :
878 element==EL_PINGUIN ? GFX_PINGUIN_DOWN :
879 element==EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
883 else if (element==EL_SONDE)
885 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
887 else if (element==EL_SALZSAEURE)
889 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
891 else if (element==EL_BUTTERFLY || element==EL_FIREFLY)
895 else if ((element==EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
897 graphic += phase * (element==EL_FELSBROCKEN ? 2 : 1);
899 else if ((element==EL_SIEB_LEER || element==EL_SIEB2_LEER ||
900 element==EL_SIEB_VOLL || element==EL_SIEB2_VOLL) && SiebAktiv)
902 graphic += 3-(SiebAktiv%8)/2;
904 else if (IS_AMOEBOID(element))
906 graphic = (element==EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
907 graphic += (x+2*y) % 4;
909 else if (element==EL_MAUER_LEBT)
911 boolean links_massiv = FALSE, rechts_massiv = FALSE;
913 if (!IN_LEV_FIELD(ux-1,uy) || IS_MAUER(Feld[ux-1][uy]))
915 if (!IN_LEV_FIELD(ux+1,uy) || IS_MAUER(Feld[ux+1][uy]))
916 rechts_massiv = TRUE;
918 if (links_massiv && rechts_massiv)
919 graphic = GFX_MAUERWERK;
920 else if (links_massiv)
921 graphic = GFX_MAUER_R;
922 else if (rechts_massiv)
923 graphic = GFX_MAUER_L;
927 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, mask_mode);
928 else if (mask_mode == USE_MASKING)
929 DrawGraphicThruMask(x,y, graphic);
931 DrawGraphic(x,y, graphic);
934 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
935 int cut_mode, int mask_mode)
937 if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
938 DrawScreenElementExt(SCREENX(x),SCREENY(y), dx,dy, element,
939 cut_mode, mask_mode);
942 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
945 DrawScreenElementExt(x,y, dx,dy, element, cut_mode, NO_MASKING);
948 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
951 DrawLevelElementExt(x,y, dx,dy, element, cut_mode, NO_MASKING);
954 void DrawScreenElementThruMask(int x, int y, int element)
956 DrawScreenElementExt(x,y, 0,0, element, NO_CUTTING, USE_MASKING);
959 void DrawLevelElementThruMask(int x, int y, int element)
961 DrawLevelElementExt(x,y, 0,0, element, NO_CUTTING, USE_MASKING);
964 void DrawLevelFieldThruMask(int x, int y)
966 DrawLevelElementExt(x,y, 0,0, Feld[x][y], NO_CUTTING, USE_MASKING);
969 void ErdreichAnbroeckeln(int x, int y)
971 int i, width, height, cx,cy;
972 int ux = LEVELX(x), uy = LEVELY(y);
973 int element, graphic;
975 static int xy[4][2] =
983 if (!IN_LEV_FIELD(ux,uy))
986 element = Feld[ux][uy];
988 if (element==EL_ERDREICH)
990 if (!IN_SCR_FIELD(x,y))
993 graphic = GFX_ERDENRAND;
1001 if (!IN_LEV_FIELD(uxx,uyy))
1004 element = Feld[uxx][uyy];
1006 if (element==EL_ERDREICH)
1013 cx = (i==2 ? TILEX-snip : 0);
1021 cy = (i==3 ? TILEY-snip : 0);
1024 XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
1025 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
1026 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
1027 width,height, FX+x*TILEX+cx,FY+y*TILEY+cy);
1034 graphic = GFX_ERDENRAND;
1045 if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
1046 !IN_SCR_FIELD(xx,yy))
1053 cx = (i==1 ? TILEX-snip : 0);
1061 cy = (i==0 ? TILEY-snip : 0);
1064 XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
1065 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
1066 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
1067 width,height, FX+xx*TILEX+cx,FY+yy*TILEY+cy);
1069 MarkTileDirty(xx,yy);
1074 void DrawScreenElement(int x, int y, int element)
1076 DrawScreenElementExt(x,y, 0,0, element, NO_CUTTING, NO_MASKING);
1077 ErdreichAnbroeckeln(x,y);
1080 void DrawLevelElement(int x, int y, int element)
1082 if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
1083 DrawScreenElement(SCREENX(x),SCREENY(y),element);
1086 void DrawScreenField(int x, int y)
1088 int ux = LEVELX(x), uy = LEVELY(y);
1091 if (!IN_LEV_FIELD(ux,uy))
1093 DrawScreenElement(x,y,EL_BETON);
1097 element = Feld[ux][uy];
1099 if (IS_MOVING(ux,uy))
1101 int horiz_move = (MovDir[ux][uy]==MV_LEFT || MovDir[ux][uy]==MV_RIGHT);
1102 boolean cut_mode = NO_CUTTING;
1104 if (Store[ux][uy]==EL_MORAST_LEER ||
1105 Store[ux][uy]==EL_SIEB_LEER ||
1106 Store[ux][uy]==EL_SIEB2_LEER ||
1107 Store[ux][uy]==EL_AMOEBE_NASS)
1108 cut_mode = CUT_ABOVE;
1109 else if (Store[ux][uy]==EL_MORAST_VOLL ||
1110 Store[ux][uy]==EL_SIEB_VOLL ||
1111 Store[ux][uy]==EL_SIEB2_VOLL)
1112 cut_mode = CUT_BELOW;
1114 if (cut_mode==CUT_ABOVE)
1115 DrawScreenElementShifted(x,y, 0,0, Store[ux][uy], NO_CUTTING);
1117 DrawScreenElement(x,y,EL_LEERRAUM);
1120 DrawScreenElementShifted(x,y, MovPos[ux][uy],0, element, NO_CUTTING);
1122 DrawScreenElementShifted(x,y, 0,MovPos[ux][uy], element, cut_mode);
1124 if (Store[ux][uy] == EL_SALZSAEURE)
1125 DrawLevelElementThruMask(ux,uy+1, EL_SALZSAEURE);
1127 else if (IS_BLOCKED(ux,uy))
1132 boolean cut_mode = NO_CUTTING;
1134 Blocked2Moving(ux,uy,&oldx,&oldy);
1137 horiz_move = (MovDir[oldx][oldy]==MV_LEFT || MovDir[oldx][oldy]==MV_RIGHT);
1139 if (Store[oldx][oldy]==EL_MORAST_LEER ||
1140 Store[oldx][oldy]==EL_SIEB_LEER ||
1141 Store[oldx][oldy]==EL_SIEB2_LEER ||
1142 Store[oldx][oldy]==EL_AMOEBE_NASS)
1143 cut_mode = CUT_ABOVE;
1145 DrawScreenElement(x,y,EL_LEERRAUM);
1146 element = Feld[oldx][oldy];
1149 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1151 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1153 else if (IS_DRAWABLE(element))
1154 DrawScreenElement(x,y,element);
1156 DrawScreenElement(x,y,EL_LEERRAUM);
1159 void DrawLevelField(int x, int y)
1161 if (IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
1162 DrawScreenField(SCREENX(x),SCREENY(y));
1163 else if (IS_MOVING(x,y))
1167 Moving2Blocked(x,y,&newx,&newy);
1168 if (IN_SCR_FIELD(SCREENX(newx),SCREENY(newy)))
1169 DrawScreenField(SCREENX(newx),SCREENY(newy));
1171 else if (IS_BLOCKED(x,y))
1175 Blocked2Moving(x,y,&oldx,&oldy);
1176 if (IN_SCR_FIELD(SCREENX(oldx),SCREENY(oldy)))
1177 DrawScreenField(SCREENX(oldx),SCREENY(oldy));
1181 void DrawMiniElement(int x, int y, int element)
1187 DrawMiniGraphic(x,y,-1);
1191 graphic = el2gfx(element);
1192 DrawMiniGraphic(x,y,graphic);
1195 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1197 int x = sx + scroll_x, y = sy + scroll_y;
1199 if (x<-1 || x>lev_fieldx || y<-1 || y>lev_fieldy)
1200 DrawMiniElement(sx,sy,EL_LEERRAUM);
1201 else if (x==-1 || x==lev_fieldx || y==-1 || y==lev_fieldy)
1202 DrawMiniElement(sx,sy,EL_BETON);
1204 DrawMiniElement(sx,sy,Feld[x][y]);
1207 void DrawMicroElement(int xpos, int ypos, int element)
1211 if (element==EL_LEERRAUM)
1214 graphic = el2gfx(element);
1216 XCopyArea(display,pix[PIX_BACK],drawto,gc,
1217 MICRO_GFX_STARTX+(graphic % MICRO_GFX_PER_LINE)*MICRO_TILEX,
1218 MICRO_GFX_STARTY+(graphic / MICRO_GFX_PER_LINE)*MICRO_TILEY,
1219 MICRO_TILEX,MICRO_TILEY, xpos,ypos);
1228 for(x=BX1; x<=BX2; x++)
1229 for(y=BY1; y<=BY2; y++)
1230 DrawScreenField(x,y);
1232 if (setup.soft_scrolling)
1233 XCopyArea(display,fieldbuffer,backbuffer,gc,
1234 FX,FY, SXSIZE,SYSIZE,
1237 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1240 void DrawMiniLevel(int scroll_x, int scroll_y)
1246 for(x=0;x<2*SCR_FIELDX;x++)
1247 for(y=0;y<2*SCR_FIELDY;y++)
1248 DrawMiniElementOrWall(x,y,scroll_x,scroll_y);
1250 redraw_mask |= REDRAW_FIELD;
1253 void DrawMicroLevel(int xpos, int ypos)
1257 XFillRectangle(display,drawto,gc,
1258 xpos-MICRO_TILEX,ypos-MICRO_TILEY,
1259 MICRO_TILEX*(STD_LEV_FIELDX+2),
1260 MICRO_TILEY*(STD_LEV_FIELDY+2));
1261 if (lev_fieldx < STD_LEV_FIELDX)
1262 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1263 if (lev_fieldy < STD_LEV_FIELDY)
1264 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1266 for(x=-1;x<=STD_LEV_FIELDX;x++)
1267 for(y=-1;y<=STD_LEV_FIELDY;y++)
1268 if (x>=0 && x<lev_fieldx && y>=0 && y<lev_fieldy)
1269 DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
1270 Feld[x][y]=Ur[x][y]);
1271 else if (x>=-1 && x<lev_fieldx+1 && y>=-1 && y<lev_fieldy+1)
1272 DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
1275 XFillRectangle(display,drawto,gc, SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE);
1279 int len = strlen(level.name);
1280 int lxpos = SX+(SXSIZE-len*FONT4_XSIZE)/2;
1281 int lypos = MICROLABEL_YPOS;
1283 DrawText(lxpos,lypos,level.name,FS_SMALL,FC_SPECIAL2);
1286 redraw_mask |= REDRAW_MICROLEV;
1289 int REQ_in_range(int x, int y)
1291 if (y>DY+249 && y<DY+278)
1293 if (x>DX+1 && x<DX+48)
1295 else if (x>DX+51 && x<DX+98)
1301 boolean Request(char *text, unsigned int req_state)
1303 int mx,my, ty, result = -1;
1304 unsigned int old_door_state;
1306 /* pause network game while waiting for request to answer */
1307 if (options.network &&
1308 game_status == PLAYING &&
1309 req_state & REQUEST_WAIT_FOR)
1310 SendToServer_PausePlaying();
1312 old_door_state = GetDoorState();
1314 CloseDoor(DOOR_CLOSE_1);
1316 /* Alten Türinhalt sichern */
1317 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1318 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1319 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1);
1321 /* Fragetext schreiben */
1322 XFillRectangle(display,pix[PIX_DB_DOOR],gc,
1323 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1,DXSIZE,DYSIZE);
1325 for(ty=0;ty<13;ty++)
1332 for(tl=0,tx=0;tx<7;tl++,tx++)
1346 DrawTextExt(pix[PIX_DB_DOOR],gc,
1347 DOOR_GFX_PAGEX1+51-(tl*14)/2,SY+ty*16,txt,FS_SMALL,FC_YELLOW);
1348 text+=(tl+(tc==32));
1351 if (req_state & REQ_ASK)
1353 DrawYesNoButton(BUTTON_OK, DB_INIT);
1354 DrawYesNoButton(BUTTON_NO, DB_INIT);
1356 else if (req_state & REQ_CONFIRM)
1358 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1360 else if (req_state & REQ_PLAYER)
1362 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1363 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1364 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1365 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1368 OpenDoor(DOOR_OPEN_1);
1371 if (!(req_state & REQUEST_WAIT_FOR))
1374 if (game_status != MAINMENU)
1377 button_status = MB_RELEASED;
1381 if (XPending(display))
1385 XNextEvent(display, &event);
1395 if (event.type == MotionNotify)
1397 motion_status = TRUE;
1398 mx = ((XMotionEvent *) &event)->x;
1399 my = ((XMotionEvent *) &event)->y;
1403 motion_status = FALSE;
1404 mx = ((XButtonEvent *) &event)->x;
1405 my = ((XButtonEvent *) &event)->y;
1406 if (event.type==ButtonPress)
1407 button_status = ((XButtonEvent *) &event)->button;
1409 button_status = MB_RELEASED;
1412 if (req_state & REQ_ASK)
1413 choice = CheckYesNoButtons(mx,my,button_status);
1414 else if (req_state & REQ_CONFIRM)
1415 choice = CheckConfirmButton(mx,my,button_status);
1417 choice = CheckPlayerButtons(mx,my,button_status);
1427 case BUTTON_CONFIRM:
1428 result = TRUE | FALSE;
1431 case BUTTON_PLAYER_1:
1434 case BUTTON_PLAYER_2:
1437 case BUTTON_PLAYER_3:
1440 case BUTTON_PLAYER_4:
1451 switch(XLookupKeysym((XKeyEvent *)&event,
1452 ((XKeyEvent *)&event)->state))
1465 if (req_state & REQ_PLAYER)
1470 key_joystick_mapping = 0;
1474 HandleOtherEvents(&event);
1478 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1480 int joy = AnyJoystick();
1482 if (joy & JOY_BUTTON_1)
1484 else if (joy & JOY_BUTTON_2)
1490 /* don't eat all CPU time */
1494 if (game_status != MAINMENU)
1497 if (!(req_state & REQ_STAY_OPEN))
1499 CloseDoor(DOOR_CLOSE_1);
1501 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1503 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1504 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1505 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1506 OpenDoor(DOOR_OPEN_1);
1510 /* continue network game after request */
1511 if (options.network &&
1512 game_status == PLAYING &&
1513 req_state & REQUEST_WAIT_FOR)
1514 SendToServer_ContinuePlaying();
1519 unsigned int OpenDoor(unsigned int door_state)
1521 unsigned int new_door_state;
1523 if (door_state & DOOR_COPY_BACK)
1525 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1526 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE+VYSIZE,
1527 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1528 door_state &= ~DOOR_COPY_BACK;
1531 new_door_state = MoveDoor(door_state);
1533 return(new_door_state);
1536 unsigned int CloseDoor(unsigned int door_state)
1538 unsigned int new_door_state;
1540 XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1541 DX,DY, DXSIZE,DYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1542 XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1543 VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1545 new_door_state = MoveDoor(door_state);
1547 return(new_door_state);
1550 unsigned int GetDoorState()
1552 return(MoveDoor(DOOR_GET_STATE));
1555 unsigned int MoveDoor(unsigned int door_state)
1557 static unsigned int door1 = DOOR_OPEN_1;
1558 static unsigned int door2 = DOOR_CLOSE_2;
1559 static long door_delay = 0;
1560 int x, start, stepsize = 2;
1561 long door_delay_value = stepsize * 5;
1563 if (door_state == DOOR_GET_STATE)
1564 return(door1 | door2);
1566 if (door1==DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1567 door_state &= ~DOOR_OPEN_1;
1568 else if (door1==DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1569 door_state &= ~DOOR_CLOSE_1;
1570 if (door2==DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1571 door_state &= ~DOOR_OPEN_2;
1572 else if (door2==DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1573 door_state &= ~DOOR_CLOSE_2;
1575 if (setup.quick_doors)
1578 door_delay_value = 0;
1579 StopSound(SND_OEFFNEN);
1582 if (door_state & DOOR_ACTION)
1584 if (!(door_state & DOOR_NO_DELAY))
1585 PlaySoundStereo(SND_OEFFNEN,PSND_MAX_RIGHT);
1587 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1589 for(x=start; x<=DXSIZE; x+=stepsize)
1591 WaitUntilDelayReached(&door_delay, door_delay_value);
1593 if (door_state & DOOR_ACTION_1)
1595 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1596 int j = (DXSIZE - i)/3;
1598 XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1599 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1+i/2,
1600 DXSIZE,DYSIZE-i/2, DX,DY);
1602 XFillRectangle(display,drawto,gc,DX,DY+DYSIZE-i/2,DXSIZE,i/2);
1604 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1605 DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1606 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1607 DXSIZE,DOOR_GFX_PAGEY1, i,77, DX+DXSIZE-i,DY+j);
1608 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1609 DXSIZE,DOOR_GFX_PAGEY1+140, i,63, DX+DXSIZE-i,DY+140+j);
1610 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1611 DX-DXSIZE+i,DY-(DOOR_GFX_PAGEY1+j));
1612 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1613 DXSIZE-i,DOOR_GFX_PAGEY1+j, i,77-j, DX,DY);
1614 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1615 DXSIZE-i,DOOR_GFX_PAGEY1+140, i,63, DX,DY+140-j);
1617 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1618 DXSIZE-i,DOOR_GFX_PAGEY1+77, i,63,
1620 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1621 DXSIZE-i,DOOR_GFX_PAGEY1+203, i,77,
1623 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1624 DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1625 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1626 DXSIZE,DOOR_GFX_PAGEY1+77, i,63,
1627 DX+DXSIZE-i,DY+77+j);
1628 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1629 DXSIZE,DOOR_GFX_PAGEY1+203, i,77-j,
1630 DX+DXSIZE-i,DY+203+j);
1632 redraw_mask |= REDRAW_DOOR_1;
1635 if (door_state & DOOR_ACTION_2)
1637 int i = (door_state & DOOR_OPEN_2 ? VXSIZE-x : x);
1638 int j = (VXSIZE - i)/3;
1640 XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1641 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2+i/2,
1642 VXSIZE,VYSIZE-i/2, VX,VY);
1644 XFillRectangle(display,drawto,gc,VX,VY+VYSIZE-i/2,VXSIZE,i/2);
1646 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1647 VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1648 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1649 VXSIZE,DOOR_GFX_PAGEY2, i,VYSIZE/2, VX+VXSIZE-i,VY+j);
1650 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1651 VX-VXSIZE+i,VY-(DOOR_GFX_PAGEY2+j));
1652 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1653 VXSIZE-i,DOOR_GFX_PAGEY2+j, i,VYSIZE/2-j, VX,VY);
1655 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1656 VXSIZE-i,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2,
1658 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1659 VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1660 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1661 VXSIZE,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2-j,
1662 VX+VXSIZE-i,VY+VYSIZE/2+j);
1664 redraw_mask |= REDRAW_DOOR_2;
1669 if (game_status == MAINMENU)
1674 if (setup.quick_doors)
1675 StopSound(SND_OEFFNEN);
1677 if (door_state & DOOR_ACTION_1)
1678 door1 = door_state & DOOR_ACTION_1;
1679 if (door_state & DOOR_ACTION_2)
1680 door2 = door_state & DOOR_ACTION_2;
1682 return(door1 | door2);
1685 int ReadPixel(Drawable d, int x, int y)
1687 static XImage *pixelimage;
1689 pixelimage = XGetImage(display, d, x,y, 1,1, AllPlanes, ZPixmap);
1690 return(XGetPixel(pixelimage,0,0));
1693 int el2gfx(int element)
1697 case EL_LEERRAUM: return(-1);
1698 case EL_ERDREICH: return(GFX_ERDREICH);
1699 case EL_MAUERWERK: return(GFX_MAUERWERK);
1700 case EL_FELSBODEN: return(GFX_FELSBODEN);
1701 case EL_FELSBROCKEN: return(GFX_FELSBROCKEN);
1702 case EL_SCHLUESSEL: return(GFX_SCHLUESSEL);
1703 case EL_EDELSTEIN: return(GFX_EDELSTEIN);
1704 case EL_AUSGANG_ZU: return(GFX_AUSGANG_ZU);
1705 case EL_AUSGANG_ACT: return(GFX_AUSGANG_ACT);
1706 case EL_AUSGANG_AUF: return(GFX_AUSGANG_AUF);
1707 case EL_SPIELFIGUR: return(GFX_SPIELFIGUR);
1708 case EL_SPIELER1: return(GFX_SPIELER1);
1709 case EL_SPIELER2: return(GFX_SPIELER2);
1710 case EL_SPIELER3: return(GFX_SPIELER3);
1711 case EL_SPIELER4: return(GFX_SPIELER4);
1712 case EL_KAEFER: return(GFX_KAEFER);
1713 case EL_KAEFER_R: return(GFX_KAEFER_R);
1714 case EL_KAEFER_O: return(GFX_KAEFER_O);
1715 case EL_KAEFER_L: return(GFX_KAEFER_L);
1716 case EL_KAEFER_U: return(GFX_KAEFER_U);
1717 case EL_FLIEGER: return(GFX_FLIEGER);
1718 case EL_FLIEGER_R: return(GFX_FLIEGER_R);
1719 case EL_FLIEGER_O: return(GFX_FLIEGER_O);
1720 case EL_FLIEGER_L: return(GFX_FLIEGER_L);
1721 case EL_FLIEGER_U: return(GFX_FLIEGER_U);
1722 case EL_BUTTERFLY: return(GFX_BUTTERFLY);
1723 case EL_BUTTERFLY_R: return(GFX_BUTTERFLY_R);
1724 case EL_BUTTERFLY_O: return(GFX_BUTTERFLY_O);
1725 case EL_BUTTERFLY_L: return(GFX_BUTTERFLY_L);
1726 case EL_BUTTERFLY_U: return(GFX_BUTTERFLY_U);
1727 case EL_FIREFLY: return(GFX_FIREFLY);
1728 case EL_FIREFLY_R: return(GFX_FIREFLY_R);
1729 case EL_FIREFLY_O: return(GFX_FIREFLY_O);
1730 case EL_FIREFLY_L: return(GFX_FIREFLY_L);
1731 case EL_FIREFLY_U: return(GFX_FIREFLY_U);
1732 case EL_MAMPFER: return(GFX_MAMPFER);
1733 case EL_ROBOT: return(GFX_ROBOT);
1734 case EL_BETON: return(GFX_BETON);
1735 case EL_DIAMANT: return(GFX_DIAMANT);
1736 case EL_MORAST_LEER: return(GFX_MORAST_LEER);
1737 case EL_MORAST_VOLL: return(GFX_MORAST_VOLL);
1738 case EL_TROPFEN: return(GFX_TROPFEN);
1739 case EL_BOMBE: return(GFX_BOMBE);
1740 case EL_SIEB_LEER: return(GFX_SIEB_LEER);
1741 case EL_SIEB_VOLL: return(GFX_SIEB_VOLL);
1742 case EL_SIEB_TOT: return(GFX_SIEB_TOT);
1743 case EL_SALZSAEURE: return(GFX_SALZSAEURE);
1744 case EL_AMOEBE_TOT: return(GFX_AMOEBE_TOT);
1745 case EL_AMOEBE_NASS: return(GFX_AMOEBE_NASS);
1746 case EL_AMOEBE_NORM: return(GFX_AMOEBE_NORM);
1747 case EL_AMOEBE_VOLL: return(GFX_AMOEBE_VOLL);
1748 case EL_AMOEBE_BD: return(GFX_AMOEBE_BD);
1749 case EL_AMOEBA2DIAM: return(GFX_AMOEBA2DIAM);
1750 case EL_KOKOSNUSS: return(GFX_KOKOSNUSS);
1751 case EL_LIFE: return(GFX_LIFE);
1752 case EL_LIFE_ASYNC: return(GFX_LIFE_ASYNC);
1753 case EL_DYNAMIT: return(GFX_DYNAMIT);
1754 case EL_BADEWANNE: return(GFX_BADEWANNE);
1755 case EL_BADEWANNE1: return(GFX_BADEWANNE1);
1756 case EL_BADEWANNE2: return(GFX_BADEWANNE2);
1757 case EL_BADEWANNE3: return(GFX_BADEWANNE3);
1758 case EL_BADEWANNE4: return(GFX_BADEWANNE4);
1759 case EL_BADEWANNE5: return(GFX_BADEWANNE5);
1760 case EL_ABLENK_AUS: return(GFX_ABLENK_AUS);
1761 case EL_ABLENK_EIN: return(GFX_ABLENK_EIN);
1762 case EL_SCHLUESSEL1: return(GFX_SCHLUESSEL1);
1763 case EL_SCHLUESSEL2: return(GFX_SCHLUESSEL2);
1764 case EL_SCHLUESSEL3: return(GFX_SCHLUESSEL3);
1765 case EL_SCHLUESSEL4: return(GFX_SCHLUESSEL4);
1766 case EL_PFORTE1: return(GFX_PFORTE1);
1767 case EL_PFORTE2: return(GFX_PFORTE2);
1768 case EL_PFORTE3: return(GFX_PFORTE3);
1769 case EL_PFORTE4: return(GFX_PFORTE4);
1770 case EL_PFORTE1X: return(GFX_PFORTE1X);
1771 case EL_PFORTE2X: return(GFX_PFORTE2X);
1772 case EL_PFORTE3X: return(GFX_PFORTE3X);
1773 case EL_PFORTE4X: return(GFX_PFORTE4X);
1774 case EL_DYNAMIT_AUS: return(GFX_DYNAMIT_AUS);
1775 case EL_PACMAN: return(GFX_PACMAN);
1776 case EL_PACMAN_R: return(GFX_PACMAN_R);
1777 case EL_PACMAN_O: return(GFX_PACMAN_O);
1778 case EL_PACMAN_L: return(GFX_PACMAN_L);
1779 case EL_PACMAN_U: return(GFX_PACMAN_U);
1780 case EL_UNSICHTBAR: return(GFX_UNSICHTBAR);
1781 case EL_ERZ_EDEL: return(GFX_ERZ_EDEL);
1782 case EL_ERZ_DIAM: return(GFX_ERZ_DIAM);
1783 case EL_BIRNE_AUS: return(GFX_BIRNE_AUS);
1784 case EL_BIRNE_EIN: return(GFX_BIRNE_EIN);
1785 case EL_ZEIT_VOLL: return(GFX_ZEIT_VOLL);
1786 case EL_ZEIT_LEER: return(GFX_ZEIT_LEER);
1787 case EL_MAUER_LEBT: return(GFX_MAUER_LEBT);
1788 case EL_MAUER_X: return(GFX_MAUER_X);
1789 case EL_MAUER_Y: return(GFX_MAUER_Y);
1790 case EL_MAUER_XY: return(GFX_MAUER_XY);
1791 case EL_EDELSTEIN_BD: return(GFX_EDELSTEIN_BD);
1792 case EL_EDELSTEIN_GELB: return(GFX_EDELSTEIN_GELB);
1793 case EL_EDELSTEIN_ROT: return(GFX_EDELSTEIN_ROT);
1794 case EL_EDELSTEIN_LILA: return(GFX_EDELSTEIN_LILA);
1795 case EL_ERZ_EDEL_BD: return(GFX_ERZ_EDEL_BD);
1796 case EL_ERZ_EDEL_GELB: return(GFX_ERZ_EDEL_GELB);
1797 case EL_ERZ_EDEL_ROT: return(GFX_ERZ_EDEL_ROT);
1798 case EL_ERZ_EDEL_LILA: return(GFX_ERZ_EDEL_LILA);
1799 case EL_MAMPFER2: return(GFX_MAMPFER2);
1800 case EL_SIEB2_LEER: return(GFX_SIEB2_LEER);
1801 case EL_SIEB2_VOLL: return(GFX_SIEB2_VOLL);
1802 case EL_SIEB2_TOT: return(GFX_SIEB2_TOT);
1803 case EL_DYNABOMB: return(GFX_DYNABOMB);
1804 case EL_DYNABOMB_NR: return(GFX_DYNABOMB_NR);
1805 case EL_DYNABOMB_SZ: return(GFX_DYNABOMB_SZ);
1806 case EL_DYNABOMB_XL: return(GFX_DYNABOMB_XL);
1807 case EL_SOKOBAN_OBJEKT: return(GFX_SOKOBAN_OBJEKT);
1808 case EL_SOKOBAN_FELD_LEER: return(GFX_SOKOBAN_FELD_LEER);
1809 case EL_SOKOBAN_FELD_VOLL: return(GFX_SOKOBAN_FELD_VOLL);
1810 case EL_MAULWURF: return(GFX_MAULWURF);
1811 case EL_PINGUIN: return(GFX_PINGUIN);
1812 case EL_SCHWEIN: return(GFX_SCHWEIN);
1813 case EL_DRACHE: return(GFX_DRACHE);
1814 case EL_SONDE: return(GFX_SONDE);
1815 case EL_PFEIL_L: return(GFX_PFEIL_L);
1816 case EL_PFEIL_R: return(GFX_PFEIL_R);
1817 case EL_PFEIL_O: return(GFX_PFEIL_O);
1818 case EL_PFEIL_U: return(GFX_PFEIL_U);
1821 if (IS_CHAR(element))
1822 return(GFX_CHAR_START + (element-EL_CHAR_START));