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,
270 SetDrawtoField(DRAW_BUFFERED);
273 SetDrawtoField(DRAW_BACKBUFFER);
275 if (setup.direct_draw && game_status==PLAYING)
277 XFillRectangle(display,window,gc,
278 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
279 SetDrawtoField(DRAW_DIRECT);
282 redraw_mask |= REDRAW_FIELD;
285 void DrawText(int x, int y, char *text, int font, int col)
287 DrawTextExt(drawto, gc, x, y, text, font, col);
289 redraw_mask |= REDRAW_FIELD;
291 redraw_mask |= REDRAW_DOOR_1;
294 void DrawTextExt(Drawable d, GC gc, int x, int y,
295 char *text, int font, int font_color)
297 int font_width, font_height, font_start;
300 if (font!=FS_SMALL && font!=FS_BIG)
302 if (font_color<FC_RED || font_color>FC_SPECIAL2)
306 (font==FS_BIG ? FONT1_XSIZE :
307 font_color<FC_SPECIAL1 ? FONT2_XSIZE :
308 font_color<FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
310 (font==FS_BIG ? FONT1_XSIZE :
311 font_color<FC_SPECIAL2 ? FONT2_XSIZE: FONT4_XSIZE);
312 font_pixmap = (font==FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
314 font_color*(font==FS_BIG ? FONT1_YSIZE : FONT2_YSIZE)*FONT_LINES_PER_FONT;
320 if (c>='a' && c<='z')
322 else if (c=='ä' || c=='Ä')
324 else if (c=='ö' || c=='Ö')
326 else if (c=='ü' || c=='Ü')
330 XCopyArea(display,pix[font_pixmap],d,gc,
331 ((c-32) % FONT_CHARS_PER_LINE)*font_width,
332 ((c-32) / FONT_CHARS_PER_LINE)*font_height + font_start,
333 font_width,font_height, x,y);
339 void DrawAllPlayers()
343 for(i=0; i<MAX_PLAYERS; i++)
344 if (stored_player[i].active)
345 DrawPlayer(&stored_player[i]);
348 void DrawPlayerField(int x, int y)
353 DrawPlayer(PLAYERINFO(x,y));
356 void DrawPlayer(struct PlayerInfo *player)
358 int jx = player->jx, jy = player->jy;
359 int last_jx = player->last_jx, last_jy = player->last_jy;
360 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
361 int sx = SCREENX(jx), sy = SCREENY(jy);
362 int sxx = 0, syy = 0;
363 int element = Feld[jx][jy];
366 if (!player->active || player->gone ||
367 !IN_SCR_FIELD(SCREENX(last_jx),SCREENY(last_jy)))
371 if (!IN_LEV_FIELD(jx,jy))
373 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
374 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
375 printf("DrawPlayerField(): This should never happen!\n");
380 if (element == EL_EXPLODING)
383 /* draw things in the field the player is leaving, if needed */
385 if (last_jx != jx || last_jy != jy)
387 if (Store[last_jx][last_jy])
389 DrawLevelElement(last_jx,last_jy, Store[last_jx][last_jy]);
390 DrawLevelFieldThruMask(last_jx,last_jy);
392 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
393 DrawDynamite(last_jx,last_jy);
395 DrawLevelField(last_jx,last_jy);
397 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx),SCREENY(next_jy)))
401 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
402 DrawLevelElement(next_jx,next_jy, EL_SOKOBAN_FELD_LEER);
404 DrawLevelElement(next_jx,next_jy, EL_LEERRAUM);
407 DrawLevelField(next_jx,next_jy);
411 if (!IN_SCR_FIELD(sx,sy))
414 if (setup.direct_draw)
415 SetDrawtoField(DRAW_BUFFERED);
417 /* draw things behind the player, if needed */
420 DrawLevelElement(jx,jy, Store[jx][jy]);
421 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
422 DrawLevelField(jx,jy);
424 /* draw player himself */
426 if (player->MovDir==MV_LEFT)
427 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
428 else if (player->MovDir==MV_RIGHT)
429 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
430 else if (player->MovDir==MV_UP)
431 graphic = GFX_SPIELER1_UP;
432 else /* MV_DOWN || MV_NO_MOVING */
433 graphic = GFX_SPIELER1_DOWN;
435 graphic += player->index_nr * 3*HEROES_PER_LINE;
436 graphic += player->Frame;
440 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
441 sxx = player->GfxPos;
443 syy = player->GfxPos;
446 if (!setup.soft_scrolling && ScreenMovPos)
449 DrawGraphicShiftedThruMask(sx,sy, sxx,syy, graphic, NO_CUTTING);
451 if (player->Pushing && player->GfxPos)
453 int px = SCREENX(next_jx), py = SCREENY(next_jy);
455 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
456 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
457 DrawGraphicShiftedThruMask(px,py,sxx,syy, GFX_SOKOBAN_OBJEKT,NO_CUTTING);
460 int element = Feld[next_jx][next_jy];
461 int graphic = el2gfx(element);
463 if (element == EL_FELSBROCKEN && sxx)
465 int phase = (player->GfxPos / (TILEX/4));
467 if (player->MovDir == MV_LEFT)
470 graphic += (phase+4)%4;
473 DrawGraphicShifted(px,py, sxx,syy, graphic, NO_CUTTING, NO_MASKING);
477 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
479 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
481 graphic = el2gfx(element);
483 if (element == EL_DYNAMIT)
485 if ((phase = (96-MovDelay[jx][jy])/12) > 6)
490 if ((phase = ((96-MovDelay[jx][jy])/6) % 8) > 3)
494 DrawGraphicThruMask(sx,sy, graphic + phase);
497 if ((last_jx != jx || last_jy != jy) && Feld[last_jx][last_jy]==EL_EXPLODING)
499 int phase = Frame[last_jx][last_jy];
503 DrawGraphicThruMask(SCREENX(last_jx),SCREENY(last_jy),
504 GFX_EXPLOSION + ((phase-1)/delay-1));
507 if (setup.direct_draw)
509 int dest_x = SX + SCREENX(MIN(jx,last_jx))*TILEX;
510 int dest_y = SY + SCREENY(MIN(jy,last_jy))*TILEY;
511 int x_size = TILEX * (1 + ABS(jx - last_jx));
512 int y_size = TILEY * (1 + ABS(jy - last_jy));
514 XCopyArea(display,drawto_field,window,gc,
515 dest_x,dest_y, x_size,y_size, dest_x,dest_y);
516 SetDrawtoField(DRAW_DIRECT);
519 MarkTileDirty(sx,sy);
522 static int getGraphicAnimationPhase(int frames, int delay, int mode)
526 if (mode == ANIM_OSCILLATE)
528 int max_anim_frames = frames*2 - 2;
529 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
530 phase = (phase < frames ? phase : max_anim_frames - phase);
533 phase = (FrameCounter % (delay * frames)) / delay;
535 if (mode == ANIM_REVERSE)
541 void DrawGraphicAnimationExt(int x, int y, int graphic,
542 int frames, int delay, int mode, int mask_mode)
544 int phase = getGraphicAnimationPhase(frames, delay, mode);
546 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
548 if (mask_mode == USE_MASKING)
549 DrawGraphicThruMask(SCREENX(x),SCREENY(y), graphic + phase);
551 DrawGraphic(SCREENX(x),SCREENY(y), graphic + phase);
555 void DrawGraphicAnimation(int x, int y, int graphic,
556 int frames, int delay, int mode)
558 DrawGraphicAnimationExt(x,y, graphic, frames,delay,mode, NO_MASKING);
561 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
562 int frames, int delay, int mode)
564 DrawGraphicAnimationExt(x,y, graphic, frames,delay,mode, USE_MASKING);
567 void DrawGraphic(int x, int y, int graphic)
570 if (!IN_SCR_FIELD(x,y))
572 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
573 printf("DrawGraphic(): This should never happen!\n");
578 DrawGraphicExt(drawto_field, gc, FX+x*TILEX, FY+y*TILEY, graphic);
582 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
584 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
586 graphic -= GFX_START_ROCKSSCREEN;
587 XCopyArea(display,pix[PIX_BACK],d,gc,
588 SX + (graphic % GFX_PER_LINE) * TILEX,
589 SY + (graphic / GFX_PER_LINE) * TILEY,
592 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
594 graphic -= GFX_START_ROCKSHEROES;
595 XCopyArea(display,pix[PIX_HEROES],d,gc,
596 (graphic % HEROES_PER_LINE) * TILEX,
597 (graphic / HEROES_PER_LINE) * TILEY,
600 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
602 graphic -= GFX_START_ROCKSFONT;
603 XCopyArea(display,pix[PIX_BIGFONT],d,gc,
604 (graphic % FONT_CHARS_PER_LINE) * TILEX,
605 (graphic / FONT_CHARS_PER_LINE) * TILEY +
606 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
610 XFillRectangle(display,d,gc, x,y, TILEX,TILEY);
613 void DrawGraphicThruMask(int x, int y, int graphic)
616 if (!IN_SCR_FIELD(x,y))
618 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
619 printf("DrawGraphicThruMask(): This should never happen!\n");
624 DrawGraphicThruMaskExt(drawto_field, FX+x*TILEX, FY+y*TILEY, graphic);
628 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
635 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
637 src_pixmap = pix[PIX_BACK];
638 drawing_gc = clip_gc[PIX_BACK];
639 graphic -= GFX_START_ROCKSSCREEN;
640 src_x = SX+(graphic % GFX_PER_LINE)*TILEX;
641 src_y = SY+(graphic / GFX_PER_LINE)*TILEY;
643 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
645 src_pixmap = pix[PIX_HEROES];
646 drawing_gc = clip_gc[PIX_HEROES];
647 graphic -= GFX_START_ROCKSHEROES;
648 src_x = (graphic % HEROES_PER_LINE)*TILEX;
649 src_y = (graphic / HEROES_PER_LINE)*TILEY;
653 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
657 if (tile_clipmask[tile] != None)
659 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
660 XSetClipOrigin(display, tile_clip_gc, dest_x,dest_y);
661 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
662 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
667 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
670 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
671 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
672 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
676 void DrawMiniGraphic(int x, int y, int graphic)
678 DrawMiniGraphicExt(drawto,gc, SX+x*MINI_TILEX,SY+y*MINI_TILEY, graphic);
679 MarkTileDirty(x/2, y/2);
682 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
684 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
686 graphic -= GFX_START_ROCKSSCREEN;
687 XCopyArea(display,pix[PIX_BACK],d,gc,
688 MINI_GFX_STARTX+(graphic % MINI_GFX_PER_LINE)*MINI_TILEX,
689 MINI_GFX_STARTY+(graphic / MINI_GFX_PER_LINE)*MINI_TILEY,
690 MINI_TILEX,MINI_TILEY, x,y);
692 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
694 graphic -= GFX_START_ROCKSFONT;
695 XCopyArea(display,pix[PIX_SMALLFONT],d,gc,
696 (graphic % FONT_CHARS_PER_LINE)*FONT4_XSIZE,
697 (graphic / FONT_CHARS_PER_LINE)*FONT4_YSIZE +
698 FC_SPECIAL2*FONT2_YSIZE*FONT_LINES_PER_FONT,
699 MINI_TILEX,MINI_TILEY, x,y);
702 XFillRectangle(display,d,gc, x,y, MINI_TILEX,MINI_TILEY);
705 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
706 int cut_mode, int mask_mode)
708 int width = TILEX, height = TILEY;
710 int src_x,src_y, dest_x,dest_y;
717 DrawGraphic(x,y,graphic);
721 if (dx || dy) /* Verschiebung der Grafik? */
723 if (x < BX1) /* Element kommt von links ins Bild */
730 else if (x > BX2) /* Element kommt von rechts ins Bild */
736 else if (x==BX1 && dx<0) /* Element verläßt links das Bild */
742 else if (x==BX2 && dx>0) /* Element verläßt rechts das Bild */
744 else if (dx) /* allg. Bewegung in x-Richtung */
745 MarkTileDirty(x + SIGN(dx), y);
747 if (y < BY1) /* Element kommt von oben ins Bild */
749 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
757 else if (y > BY2) /* Element kommt von unten ins Bild */
763 else if (y==BY1 && dy<0) /* Element verläßt oben das Bild */
769 else if (dy > 0 && cut_mode==CUT_ABOVE)
771 if (y == BY2) /* Element unterhalb des Bildes */
777 MarkTileDirty(x, y + 1);
778 } /* Element verläßt unten das Bild */
779 else if (dy > 0 && (y == BY2 || cut_mode==CUT_BELOW))
781 else if (dy) /* allg. Bewegung in y-Richtung */
782 MarkTileDirty(x, y + SIGN(dy));
785 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
787 src_pixmap = pix[PIX_BACK];
788 drawing_gc = clip_gc[PIX_BACK];
789 graphic -= GFX_START_ROCKSSCREEN;
790 src_x = SX+(graphic % GFX_PER_LINE)*TILEX+cx;
791 src_y = SY+(graphic / GFX_PER_LINE)*TILEY+cy;
793 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
795 src_pixmap = pix[PIX_HEROES];
796 drawing_gc = clip_gc[PIX_HEROES];
797 graphic -= GFX_START_ROCKSHEROES;
798 src_x = (graphic % HEROES_PER_LINE)*TILEX+cx;
799 src_y = (graphic / HEROES_PER_LINE)*TILEY+cy;
802 dest_x = FX + x*TILEX + dx;
803 dest_y = FY + y*TILEY + dy;
806 if (!IN_SCR_FIELD(x,y))
808 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
809 printf("DrawGraphicShifted(): This should never happen!\n");
814 if (mask_mode == USE_MASKING)
816 if (tile_clipmask[tile] != None)
818 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
819 XSetClipOrigin(display, tile_clip_gc, dest_x,dest_y);
820 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
821 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
826 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
829 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
830 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
831 src_x,src_y, width,height, dest_x,dest_y);
835 XCopyArea(display, src_pixmap, drawto_field, gc,
836 src_x,src_y, width,height, dest_x,dest_y);
841 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
844 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
847 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
848 int cut_mode, int mask_mode)
850 int ux = LEVELX(x), uy = LEVELY(y);
851 int graphic = el2gfx(element);
852 int phase4 = ABS(MovPos[ux][uy])/(TILEX/4);
853 int phase = phase4 / 2;
854 int dir = MovDir[ux][uy];
856 if (element==EL_PACMAN || element==EL_KAEFER || element==EL_FLIEGER)
862 else if (dir == MV_LEFT)
864 else if (dir == MV_DOWN)
867 else if (element==EL_MAULWURF || element==EL_PINGUIN ||
868 element==EL_SCHWEIN || element==EL_DRACHE)
871 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_LEFT :
872 element==EL_PINGUIN ? GFX_PINGUIN_LEFT :
873 element==EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
874 else if (dir==MV_RIGHT)
875 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_RIGHT :
876 element==EL_PINGUIN ? GFX_PINGUIN_RIGHT :
877 element==EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
879 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_UP :
880 element==EL_PINGUIN ? GFX_PINGUIN_UP :
881 element==EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
883 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_DOWN :
884 element==EL_PINGUIN ? GFX_PINGUIN_DOWN :
885 element==EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
889 else if (element==EL_SONDE)
891 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
893 else if (element==EL_SALZSAEURE)
895 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
897 else if (element==EL_BUTTERFLY || element==EL_FIREFLY)
901 else if ((element==EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
903 graphic += phase * (element==EL_FELSBROCKEN ? 2 : 1);
905 else if ((element==EL_SIEB_LEER || element==EL_SIEB2_LEER ||
906 element==EL_SIEB_VOLL || element==EL_SIEB2_VOLL) && SiebAktiv)
908 graphic += 3-(SiebAktiv%8)/2;
910 else if (IS_AMOEBOID(element))
912 graphic = (element==EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
913 graphic += (x+2*y) % 4;
915 else if (element==EL_MAUER_LEBT)
917 boolean links_massiv = FALSE, rechts_massiv = FALSE;
919 if (!IN_LEV_FIELD(ux-1,uy) || IS_MAUER(Feld[ux-1][uy]))
921 if (!IN_LEV_FIELD(ux+1,uy) || IS_MAUER(Feld[ux+1][uy]))
922 rechts_massiv = TRUE;
924 if (links_massiv && rechts_massiv)
925 graphic = GFX_MAUERWERK;
926 else if (links_massiv)
927 graphic = GFX_MAUER_R;
928 else if (rechts_massiv)
929 graphic = GFX_MAUER_L;
933 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, mask_mode);
934 else if (mask_mode == USE_MASKING)
935 DrawGraphicThruMask(x,y, graphic);
937 DrawGraphic(x,y, graphic);
940 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
941 int cut_mode, int mask_mode)
943 if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
944 DrawScreenElementExt(SCREENX(x),SCREENY(y), dx,dy, element,
945 cut_mode, mask_mode);
948 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
951 DrawScreenElementExt(x,y, dx,dy, element, cut_mode, NO_MASKING);
954 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
957 DrawLevelElementExt(x,y, dx,dy, element, cut_mode, NO_MASKING);
960 void DrawScreenElementThruMask(int x, int y, int element)
962 DrawScreenElementExt(x,y, 0,0, element, NO_CUTTING, USE_MASKING);
965 void DrawLevelElementThruMask(int x, int y, int element)
967 DrawLevelElementExt(x,y, 0,0, element, NO_CUTTING, USE_MASKING);
970 void DrawLevelFieldThruMask(int x, int y)
972 DrawLevelElementExt(x,y, 0,0, Feld[x][y], NO_CUTTING, USE_MASKING);
975 void ErdreichAnbroeckeln(int x, int y)
977 int i, width, height, cx,cy;
978 int ux = LEVELX(x), uy = LEVELY(y);
979 int element, graphic;
981 static int xy[4][2] =
989 if (!IN_LEV_FIELD(ux,uy))
992 element = Feld[ux][uy];
994 if (element==EL_ERDREICH)
996 if (!IN_SCR_FIELD(x,y))
999 graphic = GFX_ERDENRAND;
1007 if (!IN_LEV_FIELD(uxx,uyy))
1010 element = Feld[uxx][uyy];
1012 if (element==EL_ERDREICH)
1019 cx = (i==2 ? TILEX-snip : 0);
1027 cy = (i==3 ? TILEY-snip : 0);
1030 XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
1031 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
1032 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
1033 width,height, FX+x*TILEX+cx,FY+y*TILEY+cy);
1040 graphic = GFX_ERDENRAND;
1051 if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
1052 !IN_SCR_FIELD(xx,yy))
1059 cx = (i==1 ? TILEX-snip : 0);
1067 cy = (i==0 ? TILEY-snip : 0);
1070 XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
1071 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
1072 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
1073 width,height, FX+xx*TILEX+cx,FY+yy*TILEY+cy);
1075 MarkTileDirty(xx,yy);
1080 void DrawScreenElement(int x, int y, int element)
1082 DrawScreenElementExt(x,y, 0,0, element, NO_CUTTING, NO_MASKING);
1083 ErdreichAnbroeckeln(x,y);
1086 void DrawLevelElement(int x, int y, int element)
1088 if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
1089 DrawScreenElement(SCREENX(x),SCREENY(y),element);
1092 void DrawScreenField(int x, int y)
1094 int ux = LEVELX(x), uy = LEVELY(y);
1097 if (!IN_LEV_FIELD(ux,uy))
1099 DrawScreenElement(x,y,EL_BETON);
1103 element = Feld[ux][uy];
1105 if (IS_MOVING(ux,uy))
1107 int horiz_move = (MovDir[ux][uy]==MV_LEFT || MovDir[ux][uy]==MV_RIGHT);
1108 boolean cut_mode = NO_CUTTING;
1110 if (Store[ux][uy]==EL_MORAST_LEER ||
1111 Store[ux][uy]==EL_SIEB_LEER ||
1112 Store[ux][uy]==EL_SIEB2_LEER ||
1113 Store[ux][uy]==EL_AMOEBE_NASS)
1114 cut_mode = CUT_ABOVE;
1115 else if (Store[ux][uy]==EL_MORAST_VOLL ||
1116 Store[ux][uy]==EL_SIEB_VOLL ||
1117 Store[ux][uy]==EL_SIEB2_VOLL)
1118 cut_mode = CUT_BELOW;
1120 if (cut_mode==CUT_ABOVE)
1121 DrawScreenElementShifted(x,y, 0,0, Store[ux][uy], NO_CUTTING);
1123 DrawScreenElement(x,y,EL_LEERRAUM);
1126 DrawScreenElementShifted(x,y, MovPos[ux][uy],0, element, NO_CUTTING);
1128 DrawScreenElementShifted(x,y, 0,MovPos[ux][uy], element, cut_mode);
1130 if (Store[ux][uy] == EL_SALZSAEURE)
1131 DrawLevelElementThruMask(ux,uy+1, EL_SALZSAEURE);
1133 else if (IS_BLOCKED(ux,uy))
1138 boolean cut_mode = NO_CUTTING;
1140 Blocked2Moving(ux,uy,&oldx,&oldy);
1143 horiz_move = (MovDir[oldx][oldy]==MV_LEFT || 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,
1243 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1246 void DrawMiniLevel(int scroll_x, int scroll_y)
1252 for(x=0;x<2*SCR_FIELDX;x++)
1253 for(y=0;y<2*SCR_FIELDY;y++)
1254 DrawMiniElementOrWall(x,y,scroll_x,scroll_y);
1256 redraw_mask |= REDRAW_FIELD;
1259 void DrawMicroLevel(int xpos, int ypos)
1263 XFillRectangle(display,drawto,gc,
1264 xpos-MICRO_TILEX,ypos-MICRO_TILEY,
1265 MICRO_TILEX*(STD_LEV_FIELDX+2),
1266 MICRO_TILEY*(STD_LEV_FIELDY+2));
1267 if (lev_fieldx < STD_LEV_FIELDX)
1268 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1269 if (lev_fieldy < STD_LEV_FIELDY)
1270 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1272 for(x=-1;x<=STD_LEV_FIELDX;x++)
1273 for(y=-1;y<=STD_LEV_FIELDY;y++)
1274 if (x>=0 && x<lev_fieldx && y>=0 && y<lev_fieldy)
1275 DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
1276 Feld[x][y]=Ur[x][y]);
1277 else if (x>=-1 && x<lev_fieldx+1 && y>=-1 && y<lev_fieldy+1)
1278 DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
1281 XFillRectangle(display,drawto,gc, SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE);
1285 int len = strlen(level.name);
1286 int lxpos = SX+(SXSIZE-len*FONT4_XSIZE)/2;
1287 int lypos = MICROLABEL_YPOS;
1289 DrawText(lxpos,lypos,level.name,FS_SMALL,FC_SPECIAL2);
1292 redraw_mask |= REDRAW_MICROLEV;
1295 int REQ_in_range(int x, int y)
1297 if (y>DY+249 && y<DY+278)
1299 if (x>DX+1 && x<DX+48)
1301 else if (x>DX+51 && x<DX+98)
1307 boolean Request(char *text, unsigned int req_state)
1309 int mx,my, ty, result = -1;
1310 unsigned int old_door_state;
1312 /* pause network game while waiting for request to answer */
1313 if (options.network &&
1314 game_status == PLAYING &&
1315 req_state & REQUEST_WAIT_FOR)
1316 SendToServer_PausePlaying();
1318 old_door_state = GetDoorState();
1320 CloseDoor(DOOR_CLOSE_1);
1322 /* Alten Türinhalt sichern */
1323 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1324 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1325 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1);
1327 /* Fragetext schreiben */
1328 XFillRectangle(display,pix[PIX_DB_DOOR],gc,
1329 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1,DXSIZE,DYSIZE);
1331 for(ty=0;ty<13;ty++)
1338 for(tl=0,tx=0;tx<7;tl++,tx++)
1352 DrawTextExt(pix[PIX_DB_DOOR],gc,
1353 DOOR_GFX_PAGEX1+51-(tl*14)/2,SY+ty*16,txt,FS_SMALL,FC_YELLOW);
1354 text+=(tl+(tc==32));
1357 if (req_state & REQ_ASK)
1359 DrawYesNoButton(BUTTON_OK, DB_INIT);
1360 DrawYesNoButton(BUTTON_NO, DB_INIT);
1362 else if (req_state & REQ_CONFIRM)
1364 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1366 else if (req_state & REQ_PLAYER)
1368 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1369 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1370 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1371 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1374 OpenDoor(DOOR_OPEN_1);
1377 if (!(req_state & REQUEST_WAIT_FOR))
1380 if (game_status != MAINMENU)
1383 button_status = MB_RELEASED;
1387 if (XPending(display))
1391 XNextEvent(display, &event);
1401 if (event.type == MotionNotify)
1403 motion_status = TRUE;
1404 mx = ((XMotionEvent *) &event)->x;
1405 my = ((XMotionEvent *) &event)->y;
1409 motion_status = FALSE;
1410 mx = ((XButtonEvent *) &event)->x;
1411 my = ((XButtonEvent *) &event)->y;
1412 if (event.type==ButtonPress)
1413 button_status = ((XButtonEvent *) &event)->button;
1415 button_status = MB_RELEASED;
1418 if (req_state & REQ_ASK)
1419 choice = CheckYesNoButtons(mx,my,button_status);
1420 else if (req_state & REQ_CONFIRM)
1421 choice = CheckConfirmButton(mx,my,button_status);
1423 choice = CheckPlayerButtons(mx,my,button_status);
1433 case BUTTON_CONFIRM:
1434 result = TRUE | FALSE;
1437 case BUTTON_PLAYER_1:
1440 case BUTTON_PLAYER_2:
1443 case BUTTON_PLAYER_3:
1446 case BUTTON_PLAYER_4:
1457 switch(XLookupKeysym((XKeyEvent *)&event,
1458 ((XKeyEvent *)&event)->state))
1471 if (req_state & REQ_PLAYER)
1476 key_joystick_mapping = 0;
1480 HandleOtherEvents(&event);
1484 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1486 int joy = AnyJoystick();
1488 if (joy & JOY_BUTTON_1)
1490 else if (joy & JOY_BUTTON_2)
1496 /* don't eat all CPU time */
1500 if (game_status != MAINMENU)
1503 if (!(req_state & REQ_STAY_OPEN))
1505 CloseDoor(DOOR_CLOSE_1);
1507 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1509 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1510 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1511 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1512 OpenDoor(DOOR_OPEN_1);
1516 /* continue network game after request */
1517 if (options.network &&
1518 game_status == PLAYING &&
1519 req_state & REQUEST_WAIT_FOR)
1520 SendToServer_ContinuePlaying();
1525 unsigned int OpenDoor(unsigned int door_state)
1527 unsigned int new_door_state;
1529 if (door_state & DOOR_COPY_BACK)
1531 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1532 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE+VYSIZE,
1533 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1534 door_state &= ~DOOR_COPY_BACK;
1537 new_door_state = MoveDoor(door_state);
1539 return(new_door_state);
1542 unsigned int CloseDoor(unsigned int door_state)
1544 unsigned int new_door_state;
1546 XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1547 DX,DY, DXSIZE,DYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1548 XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1549 VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1551 new_door_state = MoveDoor(door_state);
1553 return(new_door_state);
1556 unsigned int GetDoorState()
1558 return(MoveDoor(DOOR_GET_STATE));
1561 unsigned int MoveDoor(unsigned int door_state)
1563 static unsigned int door1 = DOOR_OPEN_1;
1564 static unsigned int door2 = DOOR_CLOSE_2;
1565 static long door_delay = 0;
1566 int x, start, stepsize = 2;
1567 long door_delay_value = stepsize * 5;
1569 if (door_state == DOOR_GET_STATE)
1570 return(door1 | door2);
1572 if (door1==DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1573 door_state &= ~DOOR_OPEN_1;
1574 else if (door1==DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1575 door_state &= ~DOOR_CLOSE_1;
1576 if (door2==DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1577 door_state &= ~DOOR_OPEN_2;
1578 else if (door2==DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1579 door_state &= ~DOOR_CLOSE_2;
1581 if (setup.quick_doors)
1584 door_delay_value = 0;
1585 StopSound(SND_OEFFNEN);
1588 if (door_state & DOOR_ACTION)
1590 if (!(door_state & DOOR_NO_DELAY))
1591 PlaySoundStereo(SND_OEFFNEN,PSND_MAX_RIGHT);
1593 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1595 for(x=start; x<=DXSIZE; x+=stepsize)
1597 WaitUntilDelayReached(&door_delay, door_delay_value);
1599 if (door_state & DOOR_ACTION_1)
1601 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1602 int j = (DXSIZE - i)/3;
1604 XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1605 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1+i/2,
1606 DXSIZE,DYSIZE-i/2, DX,DY);
1608 XFillRectangle(display,drawto,gc,DX,DY+DYSIZE-i/2,DXSIZE,i/2);
1610 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1611 DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1612 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1613 DXSIZE,DOOR_GFX_PAGEY1, i,77, DX+DXSIZE-i,DY+j);
1614 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1615 DXSIZE,DOOR_GFX_PAGEY1+140, i,63, DX+DXSIZE-i,DY+140+j);
1616 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1617 DX-DXSIZE+i,DY-(DOOR_GFX_PAGEY1+j));
1618 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1619 DXSIZE-i,DOOR_GFX_PAGEY1+j, i,77-j, DX,DY);
1620 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1621 DXSIZE-i,DOOR_GFX_PAGEY1+140, i,63, DX,DY+140-j);
1623 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1624 DXSIZE-i,DOOR_GFX_PAGEY1+77, i,63,
1626 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1627 DXSIZE-i,DOOR_GFX_PAGEY1+203, i,77,
1629 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1630 DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1631 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1632 DXSIZE,DOOR_GFX_PAGEY1+77, i,63,
1633 DX+DXSIZE-i,DY+77+j);
1634 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1635 DXSIZE,DOOR_GFX_PAGEY1+203, i,77-j,
1636 DX+DXSIZE-i,DY+203+j);
1638 redraw_mask |= REDRAW_DOOR_1;
1641 if (door_state & DOOR_ACTION_2)
1643 int i = (door_state & DOOR_OPEN_2 ? VXSIZE-x : x);
1644 int j = (VXSIZE - i)/3;
1646 XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1647 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2+i/2,
1648 VXSIZE,VYSIZE-i/2, VX,VY);
1650 XFillRectangle(display,drawto,gc,VX,VY+VYSIZE-i/2,VXSIZE,i/2);
1652 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1653 VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1654 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1655 VXSIZE,DOOR_GFX_PAGEY2, i,VYSIZE/2, VX+VXSIZE-i,VY+j);
1656 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1657 VX-VXSIZE+i,VY-(DOOR_GFX_PAGEY2+j));
1658 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1659 VXSIZE-i,DOOR_GFX_PAGEY2+j, i,VYSIZE/2-j, VX,VY);
1661 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1662 VXSIZE-i,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2,
1664 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1665 VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1666 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1667 VXSIZE,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2-j,
1668 VX+VXSIZE-i,VY+VYSIZE/2+j);
1670 redraw_mask |= REDRAW_DOOR_2;
1675 if (game_status == MAINMENU)
1680 if (setup.quick_doors)
1681 StopSound(SND_OEFFNEN);
1683 if (door_state & DOOR_ACTION_1)
1684 door1 = door_state & DOOR_ACTION_1;
1685 if (door_state & DOOR_ACTION_2)
1686 door2 = door_state & DOOR_ACTION_2;
1688 return(door1 | door2);
1691 int ReadPixel(Drawable d, int x, int y)
1693 static XImage *pixelimage;
1695 pixelimage = XGetImage(display, d, x,y, 1,1, AllPlanes, ZPixmap);
1696 return(XGetPixel(pixelimage,0,0));
1699 int el2gfx(int element)
1703 case EL_LEERRAUM: return(-1);
1704 case EL_ERDREICH: return(GFX_ERDREICH);
1705 case EL_MAUERWERK: return(GFX_MAUERWERK);
1706 case EL_FELSBODEN: return(GFX_FELSBODEN);
1707 case EL_FELSBROCKEN: return(GFX_FELSBROCKEN);
1708 case EL_SCHLUESSEL: return(GFX_SCHLUESSEL);
1709 case EL_EDELSTEIN: return(GFX_EDELSTEIN);
1710 case EL_AUSGANG_ZU: return(GFX_AUSGANG_ZU);
1711 case EL_AUSGANG_ACT: return(GFX_AUSGANG_ACT);
1712 case EL_AUSGANG_AUF: return(GFX_AUSGANG_AUF);
1713 case EL_SPIELFIGUR: return(GFX_SPIELFIGUR);
1714 case EL_SPIELER1: return(GFX_SPIELER1);
1715 case EL_SPIELER2: return(GFX_SPIELER2);
1716 case EL_SPIELER3: return(GFX_SPIELER3);
1717 case EL_SPIELER4: return(GFX_SPIELER4);
1718 case EL_KAEFER: return(GFX_KAEFER);
1719 case EL_KAEFER_R: return(GFX_KAEFER_R);
1720 case EL_KAEFER_O: return(GFX_KAEFER_O);
1721 case EL_KAEFER_L: return(GFX_KAEFER_L);
1722 case EL_KAEFER_U: return(GFX_KAEFER_U);
1723 case EL_FLIEGER: return(GFX_FLIEGER);
1724 case EL_FLIEGER_R: return(GFX_FLIEGER_R);
1725 case EL_FLIEGER_O: return(GFX_FLIEGER_O);
1726 case EL_FLIEGER_L: return(GFX_FLIEGER_L);
1727 case EL_FLIEGER_U: return(GFX_FLIEGER_U);
1728 case EL_BUTTERFLY: return(GFX_BUTTERFLY);
1729 case EL_BUTTERFLY_R: return(GFX_BUTTERFLY_R);
1730 case EL_BUTTERFLY_O: return(GFX_BUTTERFLY_O);
1731 case EL_BUTTERFLY_L: return(GFX_BUTTERFLY_L);
1732 case EL_BUTTERFLY_U: return(GFX_BUTTERFLY_U);
1733 case EL_FIREFLY: return(GFX_FIREFLY);
1734 case EL_FIREFLY_R: return(GFX_FIREFLY_R);
1735 case EL_FIREFLY_O: return(GFX_FIREFLY_O);
1736 case EL_FIREFLY_L: return(GFX_FIREFLY_L);
1737 case EL_FIREFLY_U: return(GFX_FIREFLY_U);
1738 case EL_MAMPFER: return(GFX_MAMPFER);
1739 case EL_ROBOT: return(GFX_ROBOT);
1740 case EL_BETON: return(GFX_BETON);
1741 case EL_DIAMANT: return(GFX_DIAMANT);
1742 case EL_MORAST_LEER: return(GFX_MORAST_LEER);
1743 case EL_MORAST_VOLL: return(GFX_MORAST_VOLL);
1744 case EL_TROPFEN: return(GFX_TROPFEN);
1745 case EL_BOMBE: return(GFX_BOMBE);
1746 case EL_SIEB_LEER: return(GFX_SIEB_LEER);
1747 case EL_SIEB_VOLL: return(GFX_SIEB_VOLL);
1748 case EL_SIEB_TOT: return(GFX_SIEB_TOT);
1749 case EL_SALZSAEURE: return(GFX_SALZSAEURE);
1750 case EL_AMOEBE_TOT: return(GFX_AMOEBE_TOT);
1751 case EL_AMOEBE_NASS: return(GFX_AMOEBE_NASS);
1752 case EL_AMOEBE_NORM: return(GFX_AMOEBE_NORM);
1753 case EL_AMOEBE_VOLL: return(GFX_AMOEBE_VOLL);
1754 case EL_AMOEBE_BD: return(GFX_AMOEBE_BD);
1755 case EL_AMOEBA2DIAM: return(GFX_AMOEBA2DIAM);
1756 case EL_KOKOSNUSS: return(GFX_KOKOSNUSS);
1757 case EL_LIFE: return(GFX_LIFE);
1758 case EL_LIFE_ASYNC: return(GFX_LIFE_ASYNC);
1759 case EL_DYNAMIT: return(GFX_DYNAMIT);
1760 case EL_BADEWANNE: return(GFX_BADEWANNE);
1761 case EL_BADEWANNE1: return(GFX_BADEWANNE1);
1762 case EL_BADEWANNE2: return(GFX_BADEWANNE2);
1763 case EL_BADEWANNE3: return(GFX_BADEWANNE3);
1764 case EL_BADEWANNE4: return(GFX_BADEWANNE4);
1765 case EL_BADEWANNE5: return(GFX_BADEWANNE5);
1766 case EL_ABLENK_AUS: return(GFX_ABLENK_AUS);
1767 case EL_ABLENK_EIN: return(GFX_ABLENK_EIN);
1768 case EL_SCHLUESSEL1: return(GFX_SCHLUESSEL1);
1769 case EL_SCHLUESSEL2: return(GFX_SCHLUESSEL2);
1770 case EL_SCHLUESSEL3: return(GFX_SCHLUESSEL3);
1771 case EL_SCHLUESSEL4: return(GFX_SCHLUESSEL4);
1772 case EL_PFORTE1: return(GFX_PFORTE1);
1773 case EL_PFORTE2: return(GFX_PFORTE2);
1774 case EL_PFORTE3: return(GFX_PFORTE3);
1775 case EL_PFORTE4: return(GFX_PFORTE4);
1776 case EL_PFORTE1X: return(GFX_PFORTE1X);
1777 case EL_PFORTE2X: return(GFX_PFORTE2X);
1778 case EL_PFORTE3X: return(GFX_PFORTE3X);
1779 case EL_PFORTE4X: return(GFX_PFORTE4X);
1780 case EL_DYNAMIT_AUS: return(GFX_DYNAMIT_AUS);
1781 case EL_PACMAN: return(GFX_PACMAN);
1782 case EL_PACMAN_R: return(GFX_PACMAN_R);
1783 case EL_PACMAN_O: return(GFX_PACMAN_O);
1784 case EL_PACMAN_L: return(GFX_PACMAN_L);
1785 case EL_PACMAN_U: return(GFX_PACMAN_U);
1786 case EL_UNSICHTBAR: return(GFX_UNSICHTBAR);
1787 case EL_ERZ_EDEL: return(GFX_ERZ_EDEL);
1788 case EL_ERZ_DIAM: return(GFX_ERZ_DIAM);
1789 case EL_BIRNE_AUS: return(GFX_BIRNE_AUS);
1790 case EL_BIRNE_EIN: return(GFX_BIRNE_EIN);
1791 case EL_ZEIT_VOLL: return(GFX_ZEIT_VOLL);
1792 case EL_ZEIT_LEER: return(GFX_ZEIT_LEER);
1793 case EL_MAUER_LEBT: return(GFX_MAUER_LEBT);
1794 case EL_MAUER_X: return(GFX_MAUER_X);
1795 case EL_MAUER_Y: return(GFX_MAUER_Y);
1796 case EL_MAUER_XY: return(GFX_MAUER_XY);
1797 case EL_EDELSTEIN_BD: return(GFX_EDELSTEIN_BD);
1798 case EL_EDELSTEIN_GELB: return(GFX_EDELSTEIN_GELB);
1799 case EL_EDELSTEIN_ROT: return(GFX_EDELSTEIN_ROT);
1800 case EL_EDELSTEIN_LILA: return(GFX_EDELSTEIN_LILA);
1801 case EL_ERZ_EDEL_BD: return(GFX_ERZ_EDEL_BD);
1802 case EL_ERZ_EDEL_GELB: return(GFX_ERZ_EDEL_GELB);
1803 case EL_ERZ_EDEL_ROT: return(GFX_ERZ_EDEL_ROT);
1804 case EL_ERZ_EDEL_LILA: return(GFX_ERZ_EDEL_LILA);
1805 case EL_MAMPFER2: return(GFX_MAMPFER2);
1806 case EL_SIEB2_LEER: return(GFX_SIEB2_LEER);
1807 case EL_SIEB2_VOLL: return(GFX_SIEB2_VOLL);
1808 case EL_SIEB2_TOT: return(GFX_SIEB2_TOT);
1809 case EL_DYNABOMB: return(GFX_DYNABOMB);
1810 case EL_DYNABOMB_NR: return(GFX_DYNABOMB_NR);
1811 case EL_DYNABOMB_SZ: return(GFX_DYNABOMB_SZ);
1812 case EL_DYNABOMB_XL: return(GFX_DYNABOMB_XL);
1813 case EL_SOKOBAN_OBJEKT: return(GFX_SOKOBAN_OBJEKT);
1814 case EL_SOKOBAN_FELD_LEER: return(GFX_SOKOBAN_FELD_LEER);
1815 case EL_SOKOBAN_FELD_VOLL: return(GFX_SOKOBAN_FELD_VOLL);
1816 case EL_MAULWURF: return(GFX_MAULWURF);
1817 case EL_PINGUIN: return(GFX_PINGUIN);
1818 case EL_SCHWEIN: return(GFX_SCHWEIN);
1819 case EL_DRACHE: return(GFX_DRACHE);
1820 case EL_SONDE: return(GFX_SONDE);
1821 case EL_PFEIL_L: return(GFX_PFEIL_L);
1822 case EL_PFEIL_R: return(GFX_PFEIL_R);
1823 case EL_PFEIL_O: return(GFX_PFEIL_O);
1824 case EL_PFEIL_U: return(GFX_PFEIL_U);
1827 if (IS_CHAR(element))
1828 return(GFX_CHAR_START + (element-EL_CHAR_START));