1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
17 #include <machine/joystick.h>
31 extern boolean wait_for_vsync;
34 void SetDrawtoField(int mode)
36 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
47 drawto_field = fieldbuffer;
49 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
60 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
67 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
69 if (setup.direct_draw && game_status == PLAYING)
70 redraw_mask &= ~REDRAW_MAIN;
72 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
73 redraw_mask |= REDRAW_FIELD;
75 if (redraw_mask & REDRAW_FIELD)
76 redraw_mask &= ~REDRAW_TILES;
79 if (redraw_mask & REDRAW_FIELD ||
80 (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING))
81 redraw_mask &= ~REDRAW_TILES;
87 /* synchronize X11 graphics at this point; if we would synchronize the
88 display immediately after the buffer switching (after the XFlush),
89 this could mean that we have to wait for the graphics to complete,
90 although we could go on doing calculations for the next frame */
95 wait_for_vsync = TRUE;
98 if (redraw_mask & REDRAW_ALL)
100 XCopyArea(display,backbuffer,window,gc,
101 0,0, WIN_XSIZE,WIN_YSIZE,
106 if (redraw_mask & REDRAW_FIELD)
108 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
109 XCopyArea(display,backbuffer,window,gc,
110 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
114 int fx = FX, fy = FY;
116 if (setup.soft_scrolling)
118 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
119 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
122 XCopyArea(display,buffer,window,gc,
123 fx,fy, SXSIZE,SYSIZE,
126 redraw_mask &= ~REDRAW_MAIN;
129 if (redraw_mask & REDRAW_DOORS)
131 if (redraw_mask & REDRAW_DOOR_1)
132 XCopyArea(display,backbuffer,window,gc,
133 DX,DY, DXSIZE,DYSIZE,
135 if (redraw_mask & REDRAW_DOOR_2)
137 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
138 XCopyArea(display,backbuffer,window,gc,
139 VX,VY, VXSIZE,VYSIZE,
143 if (redraw_mask & REDRAW_VIDEO_1)
144 XCopyArea(display,backbuffer,window,gc,
145 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
146 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
147 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
148 if (redraw_mask & REDRAW_VIDEO_2)
149 XCopyArea(display,backbuffer,window,gc,
150 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
151 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
152 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
153 if (redraw_mask & REDRAW_VIDEO_3)
154 XCopyArea(display,backbuffer,window,gc,
155 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
156 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
157 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
160 redraw_mask &= ~REDRAW_DOORS;
163 if (redraw_mask & REDRAW_MICROLEV)
165 XCopyArea(display,backbuffer,window,gc,
166 MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
167 MICROLEV_XPOS,MICROLEV_YPOS);
168 XCopyArea(display,backbuffer,window,gc,
169 SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
171 redraw_mask &= ~REDRAW_MICROLEV;
174 if (redraw_mask & REDRAW_TILES)
176 for(x=0; x<SCR_FIELDX; x++)
177 for(y=0; y<SCR_FIELDY; y++)
178 if (redraw[redraw_x1 + x][redraw_y1 + y])
179 XCopyArea(display,buffer,window,gc,
180 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
181 SX+x*TILEX,SY+y*TILEY);
186 for(x=0; x<MAX_BUF_XSIZE; x++)
187 for(y=0; y<MAX_BUF_YSIZE; y++)
196 long fading_delay = 300;
198 if (setup.fading && (redraw_mask & REDRAW_FIELD))
205 XFillRectangle(display,window,gc,
206 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
209 for(i=0;i<2*FULL_SYSIZE;i++)
211 for(y=0;y<FULL_SYSIZE;y++)
213 XCopyArea(display,backbuffer,window,gc,
214 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
222 for(i=1;i<FULL_SYSIZE;i+=2)
223 XCopyArea(display,backbuffer,window,gc,
224 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
230 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
231 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
232 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
236 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
237 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
238 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
242 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
243 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
244 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
248 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
249 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
250 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
254 redraw_mask &= ~REDRAW_MAIN;
263 XFillRectangle(display, backbuffer, gc,
264 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
266 if (setup.soft_scrolling && game_status == PLAYING)
268 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
269 SetDrawtoField(DRAW_BUFFERED);
272 SetDrawtoField(DRAW_BACKBUFFER);
274 if (setup.direct_draw && game_status == PLAYING)
276 XFillRectangle(display, window, gc,
277 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
278 SetDrawtoField(DRAW_DIRECT);
281 redraw_mask |= REDRAW_FIELD;
284 void DrawTextFCentered(int y, int font_type, char *format, ...)
286 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
290 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
291 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
293 va_start(ap, format);
294 vsprintf(buffer, format, ap);
297 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
298 buffer, FS_SMALL, font_type);
301 void DrawTextF(int x, int y, int font_type, char *format, ...)
303 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
306 va_start(ap, format);
307 vsprintf(buffer, format, ap);
310 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
313 void DrawText(int x, int y, char *text, int font_size, int font_type)
315 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
318 redraw_mask |= REDRAW_FIELD;
320 redraw_mask |= REDRAW_DOOR_1;
323 void DrawTextExt(Drawable d, GC gc, int x, int y,
324 char *text, int font_size, int font_type)
326 int font_width, font_height, font_start;
329 if (font_size != FS_SMALL && font_size != FS_BIG)
330 font_size = FS_SMALL;
331 if (font_type < FC_RED || font_type > FC_SPECIAL2)
334 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
335 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
336 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
337 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
338 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
339 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
340 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
341 FONT_LINES_PER_FONT);
347 if (c >= 'a' && c <= 'z')
349 else if (c == 'ä' || c == 'Ä')
351 else if (c == 'ö' || c == 'Ö')
353 else if (c == 'ü' || c == 'Ü')
356 if (c >= 32 && c <= 95)
357 XCopyArea(display, pix[font_pixmap], d, gc,
358 ((c - 32) % FONT_CHARS_PER_LINE) * font_width,
359 ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start,
360 font_width, font_height, x, y);
366 void DrawAllPlayers()
370 for(i=0; i<MAX_PLAYERS; i++)
371 if (stored_player[i].active)
372 DrawPlayer(&stored_player[i]);
375 void DrawPlayerField(int x, int y)
380 DrawPlayer(PLAYERINFO(x,y));
383 void DrawPlayer(struct PlayerInfo *player)
385 int jx = player->jx, jy = player->jy;
386 int last_jx = player->last_jx, last_jy = player->last_jy;
387 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
388 int sx = SCREENX(jx), sy = SCREENY(jy);
389 int sxx = 0, syy = 0;
390 int element = Feld[jx][jy];
393 if (!player->active || player->gone ||
394 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
398 if (!IN_LEV_FIELD(jx,jy))
400 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
401 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
402 printf("DrawPlayerField(): This should never happen!\n");
407 if (element == EL_EXPLODING)
410 /* draw things in the field the player is leaving, if needed */
412 if (last_jx != jx || last_jy != jy)
414 if (Store[last_jx][last_jy])
416 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
417 DrawLevelFieldThruMask(last_jx, last_jy);
419 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
420 DrawDynamite(last_jx, last_jy);
422 DrawLevelField(last_jx, last_jy);
424 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
428 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
429 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
431 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
434 DrawLevelField(next_jx, next_jy);
438 if (!IN_SCR_FIELD(sx, sy))
441 if (setup.direct_draw)
442 SetDrawtoField(DRAW_BUFFERED);
444 /* draw things behind the player, if needed */
447 DrawLevelElement(jx, jy, Store[jx][jy]);
448 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
449 DrawLevelField(jx, jy);
451 /* draw player himself */
453 if (player->MovDir == MV_LEFT)
454 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
455 else if (player->MovDir == MV_RIGHT)
456 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
457 else if (player->MovDir == MV_UP)
458 graphic = GFX_SPIELER1_UP;
459 else /* MV_DOWN || MV_NO_MOVING */
460 graphic = GFX_SPIELER1_DOWN;
462 graphic += player->index_nr * 3*HEROES_PER_LINE;
463 graphic += player->Frame;
467 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
468 sxx = player->GfxPos;
470 syy = player->GfxPos;
473 if (!setup.soft_scrolling && ScreenMovPos)
476 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
478 if (player->Pushing && player->GfxPos)
480 int px = SCREENX(next_jx), py = SCREENY(next_jy);
482 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
483 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
484 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
488 int element = Feld[next_jx][next_jy];
489 int graphic = el2gfx(element);
491 if (element == EL_FELSBROCKEN && sxx)
493 int phase = (player->GfxPos / (TILEX/4));
495 if (player->MovDir == MV_LEFT)
498 graphic += (phase+4)%4;
501 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
505 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
507 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
509 graphic = el2gfx(element);
511 if (element == EL_DYNAMIT)
513 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
518 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
522 DrawGraphicThruMask(sx, sy, graphic + phase);
525 if ((last_jx != jx || last_jy != jy) &&
526 Feld[last_jx][last_jy] == EL_EXPLODING)
528 int phase = Frame[last_jx][last_jy];
532 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
533 GFX_EXPLOSION + ((phase - 1) / delay - 1));
536 if (setup.direct_draw)
538 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
539 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
540 int x_size = TILEX * (1 + ABS(jx - last_jx));
541 int y_size = TILEY * (1 + ABS(jy - last_jy));
543 XCopyArea(display, drawto_field, window, gc,
544 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
545 SetDrawtoField(DRAW_DIRECT);
548 MarkTileDirty(sx,sy);
551 static int getGraphicAnimationPhase(int frames, int delay, int mode)
555 if (mode == ANIM_OSCILLATE)
557 int max_anim_frames = 2 * frames - 2;
558 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
559 phase = (phase < frames ? phase : max_anim_frames - phase);
562 phase = (FrameCounter % (delay * frames)) / delay;
564 if (mode == ANIM_REVERSE)
570 void DrawGraphicAnimationExt(int x, int y, int graphic,
571 int frames, int delay, int mode, int mask_mode)
573 int phase = getGraphicAnimationPhase(frames, delay, mode);
575 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
577 if (mask_mode == USE_MASKING)
578 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
580 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
584 void DrawGraphicAnimation(int x, int y, int graphic,
585 int frames, int delay, int mode)
587 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
590 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
591 int frames, int delay, int mode)
593 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
596 void DrawGraphic(int x, int y, int graphic)
599 if (!IN_SCR_FIELD(x,y))
601 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
602 printf("DrawGraphic(): This should never happen!\n");
607 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
611 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
613 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
615 graphic -= GFX_START_ROCKSSCREEN;
616 XCopyArea(display, pix[PIX_BACK], d, gc,
617 SX + (graphic % GFX_PER_LINE) * TILEX,
618 SY + (graphic / GFX_PER_LINE) * TILEY,
621 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
623 graphic -= GFX_START_ROCKSHEROES;
624 XCopyArea(display, pix[PIX_HEROES], d, gc,
625 (graphic % HEROES_PER_LINE) * TILEX,
626 (graphic / HEROES_PER_LINE) * TILEY,
629 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
631 graphic -= GFX_START_ROCKSFONT;
632 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
633 (graphic % FONT_CHARS_PER_LINE) * TILEX,
634 (graphic / FONT_CHARS_PER_LINE) * TILEY +
635 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
639 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
642 void DrawGraphicThruMask(int x, int y, int graphic)
645 if (!IN_SCR_FIELD(x,y))
647 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
648 printf("DrawGraphicThruMask(): This should never happen!\n");
653 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
657 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
664 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
666 src_pixmap = pix[PIX_BACK];
667 drawing_gc = clip_gc[PIX_BACK];
668 graphic -= GFX_START_ROCKSSCREEN;
669 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
670 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
672 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
674 src_pixmap = pix[PIX_HEROES];
675 drawing_gc = clip_gc[PIX_HEROES];
676 graphic -= GFX_START_ROCKSHEROES;
677 src_x = (graphic % HEROES_PER_LINE) * TILEX;
678 src_y = (graphic / HEROES_PER_LINE) * TILEY;
682 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
686 if (tile_clipmask[tile] != None)
688 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
689 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
690 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
691 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
696 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
699 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
700 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
701 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
705 void DrawMiniGraphic(int x, int y, int graphic)
707 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
708 MarkTileDirty(x/2, y/2);
711 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
713 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
715 graphic -= GFX_START_ROCKSSCREEN;
716 XCopyArea(display, pix[PIX_BACK], d, gc,
717 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
718 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
719 MINI_TILEX, MINI_TILEY, x, y);
721 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
723 graphic -= GFX_START_ROCKSFONT;
724 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
725 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
726 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
727 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
728 MINI_TILEX, MINI_TILEY, x, y);
731 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
734 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
735 int cut_mode, int mask_mode)
737 int width = TILEX, height = TILEY;
739 int src_x, src_y, dest_x, dest_y;
746 DrawGraphic(x, y, graphic);
750 if (dx || dy) /* Verschiebung der Grafik? */
752 if (x < BX1) /* Element kommt von links ins Bild */
759 else if (x > BX2) /* Element kommt von rechts ins Bild */
765 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
771 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
773 else if (dx) /* allg. Bewegung in x-Richtung */
774 MarkTileDirty(x + SIGN(dx), y);
776 if (y < BY1) /* Element kommt von oben ins Bild */
778 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
786 else if (y > BY2) /* Element kommt von unten ins Bild */
792 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
798 else if (dy > 0 && cut_mode == CUT_ABOVE)
800 if (y == BY2) /* Element unterhalb des Bildes */
806 MarkTileDirty(x, y + 1);
807 } /* Element verläßt unten das Bild */
808 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
810 else if (dy) /* allg. Bewegung in y-Richtung */
811 MarkTileDirty(x, y + SIGN(dy));
814 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
816 src_pixmap = pix[PIX_BACK];
817 drawing_gc = clip_gc[PIX_BACK];
818 graphic -= GFX_START_ROCKSSCREEN;
819 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
820 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
822 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
824 src_pixmap = pix[PIX_HEROES];
825 drawing_gc = clip_gc[PIX_HEROES];
826 graphic -= GFX_START_ROCKSHEROES;
827 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
828 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
831 dest_x = FX + x * TILEX + dx;
832 dest_y = FY + y * TILEY + dy;
835 if (!IN_SCR_FIELD(x,y))
837 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
838 printf("DrawGraphicShifted(): This should never happen!\n");
843 if (mask_mode == USE_MASKING)
845 if (tile_clipmask[tile] != None)
847 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
848 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
849 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
850 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
855 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
858 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
859 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
860 src_x, src_y, width, height, dest_x, dest_y);
864 XCopyArea(display, src_pixmap, drawto_field, gc,
865 src_x, src_y, width, height, dest_x, dest_y);
870 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
873 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
876 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
877 int cut_mode, int mask_mode)
879 int ux = LEVELX(x), uy = LEVELY(y);
880 int graphic = el2gfx(element);
881 int phase4 = ABS(MovPos[ux][uy]) / (TILEX / 4);
882 int phase = phase4 / 2;
883 int dir = MovDir[ux][uy];
885 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
891 else if (dir == MV_LEFT)
893 else if (dir == MV_DOWN)
896 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
897 element == EL_SCHWEIN || element == EL_DRACHE)
900 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
901 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
902 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
903 else if (dir == MV_RIGHT)
904 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
905 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
906 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
907 else if (dir == MV_UP)
908 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
909 element == EL_PINGUIN ? GFX_PINGUIN_UP :
910 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
912 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
913 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
914 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
918 else if (element == EL_SONDE)
920 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
922 else if (element == EL_SALZSAEURE)
924 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
926 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
930 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
932 graphic += phase * (element == EL_FELSBROCKEN ? 2 : 1);
934 else if ((element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
935 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL) && SiebAktiv)
937 graphic += 3 - (SiebAktiv % 8) / 2;
939 else if (IS_AMOEBOID(element))
941 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
942 graphic += (x + 2 * y + 4) % 4;
944 else if (element == EL_MAUER_LEBT)
946 boolean links_massiv = FALSE, rechts_massiv = FALSE;
948 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
950 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
951 rechts_massiv = TRUE;
953 if (links_massiv && rechts_massiv)
954 graphic = GFX_MAUERWERK;
955 else if (links_massiv)
956 graphic = GFX_MAUER_R;
957 else if (rechts_massiv)
958 graphic = GFX_MAUER_L;
962 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
963 else if (mask_mode == USE_MASKING)
964 DrawGraphicThruMask(x, y, graphic);
966 DrawGraphic(x, y, graphic);
969 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
970 int cut_mode, int mask_mode)
972 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
973 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
974 cut_mode, mask_mode);
977 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
980 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
983 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
986 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
989 void DrawScreenElementThruMask(int x, int y, int element)
991 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
994 void DrawLevelElementThruMask(int x, int y, int element)
996 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
999 void DrawLevelFieldThruMask(int x, int y)
1001 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1004 void ErdreichAnbroeckeln(int x, int y)
1006 int i, width, height, cx,cy;
1007 int ux = LEVELX(x), uy = LEVELY(y);
1008 int element, graphic;
1010 static int xy[4][2] =
1018 if (!IN_LEV_FIELD(ux, uy))
1021 element = Feld[ux][uy];
1023 if (element == EL_ERDREICH)
1025 if (!IN_SCR_FIELD(x, y))
1028 graphic = GFX_ERDENRAND;
1034 uxx = ux + xy[i][0];
1035 uyy = uy + xy[i][1];
1036 if (!IN_LEV_FIELD(uxx, uyy))
1039 element = Feld[uxx][uyy];
1041 if (element == EL_ERDREICH)
1044 if (i == 1 || i == 2)
1048 cx = (i == 2 ? TILEX - snip : 0);
1056 cy = (i == 3 ? TILEY - snip : 0);
1059 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1060 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1061 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1062 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1065 MarkTileDirty(x, y);
1069 graphic = GFX_ERDENRAND;
1073 int xx, yy, uxx, uyy;
1077 uxx = ux + xy[i][0];
1078 uyy = uy + xy[i][1];
1080 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1081 !IN_SCR_FIELD(xx, yy))
1084 if (i == 1 || i == 2)
1088 cx = (i == 1 ? TILEX - snip : 0);
1096 cy = (i==0 ? TILEY-snip : 0);
1099 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1100 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1101 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1102 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1104 MarkTileDirty(xx, yy);
1109 void DrawScreenElement(int x, int y, int element)
1111 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1112 ErdreichAnbroeckeln(x, y);
1115 void DrawLevelElement(int x, int y, int element)
1117 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1118 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1121 void DrawScreenField(int x, int y)
1123 int ux = LEVELX(x), uy = LEVELY(y);
1126 if (!IN_LEV_FIELD(ux, uy))
1128 DrawScreenElement(x, y, EL_BETON);
1132 element = Feld[ux][uy];
1134 if (IS_MOVING(ux, uy))
1136 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1137 boolean cut_mode = NO_CUTTING;
1139 if (Store[ux][uy] == EL_MORAST_LEER ||
1140 Store[ux][uy] == EL_SIEB_LEER ||
1141 Store[ux][uy] == EL_SIEB2_LEER ||
1142 Store[ux][uy] == EL_AMOEBE_NASS)
1143 cut_mode = CUT_ABOVE;
1144 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1145 Store[ux][uy] == EL_SIEB_VOLL ||
1146 Store[ux][uy] == EL_SIEB2_VOLL)
1147 cut_mode = CUT_BELOW;
1149 if (cut_mode == CUT_ABOVE)
1150 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1152 DrawScreenElement(x, y, EL_LEERRAUM);
1155 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1157 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1159 if (Store[ux][uy] == EL_SALZSAEURE)
1160 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1162 else if (IS_BLOCKED(ux, uy))
1167 boolean cut_mode = NO_CUTTING;
1169 Blocked2Moving(ux, uy, &oldx, &oldy);
1172 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1173 MovDir[oldx][oldy] == MV_RIGHT);
1175 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1176 Store[oldx][oldy] == EL_SIEB_LEER ||
1177 Store[oldx][oldy] == EL_SIEB2_LEER ||
1178 Store[oldx][oldy] == EL_AMOEBE_NASS)
1179 cut_mode = CUT_ABOVE;
1181 DrawScreenElement(x, y, EL_LEERRAUM);
1182 element = Feld[oldx][oldy];
1185 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1187 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1189 else if (IS_DRAWABLE(element))
1190 DrawScreenElement(x, y, element);
1192 DrawScreenElement(x, y, EL_LEERRAUM);
1195 void DrawLevelField(int x, int y)
1197 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1198 DrawScreenField(SCREENX(x), SCREENY(y));
1199 else if (IS_MOVING(x, y))
1203 Moving2Blocked(x, y, &newx, &newy);
1204 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1205 DrawScreenField(SCREENX(newx), SCREENY(newy));
1207 else if (IS_BLOCKED(x, y))
1211 Blocked2Moving(x, y, &oldx, &oldy);
1212 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1213 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1217 void DrawMiniElement(int x, int y, int element)
1223 DrawMiniGraphic(x, y, -1);
1227 graphic = el2gfx(element);
1228 DrawMiniGraphic(x, y, graphic);
1231 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1233 int x = sx + scroll_x, y = sy + scroll_y;
1235 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1236 DrawMiniElement(sx, sy, EL_LEERRAUM);
1237 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1238 DrawMiniElement(sx, sy, EL_BETON);
1240 DrawMiniElement(sx, sy, Feld[x][y]);
1243 void DrawMicroElement(int xpos, int ypos, int element)
1247 if (element == EL_LEERRAUM)
1250 graphic = el2gfx(element);
1252 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1253 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1254 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1255 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1264 for(x=BX1; x<=BX2; x++)
1265 for(y=BY1; y<=BY2; y++)
1266 DrawScreenField(x, y);
1268 if (setup.soft_scrolling)
1269 XCopyArea(display, fieldbuffer, backbuffer, gc,
1270 FX, FY, SXSIZE, SYSIZE, SX, SY);
1272 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1275 void DrawMiniLevel(int scroll_x, int scroll_y)
1281 for(x=0; x<2*SCR_FIELDX; x++)
1282 for(y=0; y<2*SCR_FIELDY; y++)
1283 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1285 redraw_mask |= REDRAW_FIELD;
1288 void DrawMicroLevel(int xpos, int ypos)
1292 XFillRectangle(display, drawto, gc,
1293 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1294 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1295 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1296 if (lev_fieldx < STD_LEV_FIELDX)
1297 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1298 if (lev_fieldy < STD_LEV_FIELDY)
1299 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1301 for(x=-1; x<=STD_LEV_FIELDX; x++)
1302 for(y=-1; y<=STD_LEV_FIELDY; y++)
1303 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1304 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1306 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1307 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1310 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1314 int len = strlen(level.name);
1315 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1316 int lypos = MICROLABEL_YPOS;
1318 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1321 redraw_mask |= REDRAW_MICROLEV;
1324 int REQ_in_range(int x, int y)
1326 if (y > DY+249 && y < DY+278)
1328 if (x > DX+1 && x < DX+48)
1330 else if (x > DX+51 && x < DX+98)
1336 boolean Request(char *text, unsigned int req_state)
1338 int mx, my, ty, result = -1;
1339 unsigned int old_door_state;
1341 /* pause network game while waiting for request to answer */
1342 if (options.network &&
1343 game_status == PLAYING &&
1344 req_state & REQUEST_WAIT_FOR)
1345 SendToServer_PausePlaying();
1347 old_door_state = GetDoorState();
1349 CloseDoor(DOOR_CLOSE_1);
1351 /* Alten Türinhalt sichern */
1352 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1353 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1354 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1356 /* Fragetext schreiben */
1357 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1358 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1360 for(ty=0; ty<13; ty++)
1368 for(tl=0,tx=0; tx<7; tl++,tx++)
1371 if (!tc || tc == 32)
1382 DrawTextExt(pix[PIX_DB_DOOR], gc,
1383 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1384 txt, FS_SMALL, FC_YELLOW);
1385 text += tl + (tc == 32 ? 1 : 0);
1388 if (req_state & REQ_ASK)
1390 DrawYesNoButton(BUTTON_OK, DB_INIT);
1391 DrawYesNoButton(BUTTON_NO, DB_INIT);
1393 else if (req_state & REQ_CONFIRM)
1395 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1397 else if (req_state & REQ_PLAYER)
1399 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1400 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1401 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1402 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1405 OpenDoor(DOOR_OPEN_1);
1408 if (!(req_state & REQUEST_WAIT_FOR))
1411 if (game_status != MAINMENU)
1414 button_status = MB_RELEASED;
1418 if (XPending(display))
1422 XNextEvent(display, &event);
1432 if (event.type == MotionNotify)
1434 motion_status = TRUE;
1435 mx = ((XMotionEvent *) &event)->x;
1436 my = ((XMotionEvent *) &event)->y;
1440 motion_status = FALSE;
1441 mx = ((XButtonEvent *) &event)->x;
1442 my = ((XButtonEvent *) &event)->y;
1443 if (event.type==ButtonPress)
1444 button_status = ((XButtonEvent *) &event)->button;
1446 button_status = MB_RELEASED;
1449 if (req_state & REQ_ASK)
1450 choice = CheckYesNoButtons(mx,my,button_status);
1451 else if (req_state & REQ_CONFIRM)
1452 choice = CheckConfirmButton(mx,my,button_status);
1454 choice = CheckPlayerButtons(mx,my,button_status);
1464 case BUTTON_CONFIRM:
1465 result = TRUE | FALSE;
1468 case BUTTON_PLAYER_1:
1471 case BUTTON_PLAYER_2:
1474 case BUTTON_PLAYER_3:
1477 case BUTTON_PLAYER_4:
1488 switch(XLookupKeysym((XKeyEvent *)&event,
1489 ((XKeyEvent *)&event)->state))
1502 if (req_state & REQ_PLAYER)
1507 key_joystick_mapping = 0;
1511 HandleOtherEvents(&event);
1515 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1517 int joy = AnyJoystick();
1519 if (joy & JOY_BUTTON_1)
1521 else if (joy & JOY_BUTTON_2)
1527 /* don't eat all CPU time */
1531 if (game_status != MAINMENU)
1534 if (!(req_state & REQ_STAY_OPEN))
1536 CloseDoor(DOOR_CLOSE_1);
1538 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1540 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1541 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1542 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1543 OpenDoor(DOOR_OPEN_1);
1547 /* continue network game after request */
1548 if (options.network &&
1549 game_status == PLAYING &&
1550 req_state & REQUEST_WAIT_FOR)
1551 SendToServer_ContinuePlaying();
1556 unsigned int OpenDoor(unsigned int door_state)
1558 unsigned int new_door_state;
1560 if (door_state & DOOR_COPY_BACK)
1562 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1563 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1564 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1565 door_state &= ~DOOR_COPY_BACK;
1568 new_door_state = MoveDoor(door_state);
1570 return(new_door_state);
1573 unsigned int CloseDoor(unsigned int door_state)
1575 unsigned int new_door_state;
1577 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1578 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1579 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1580 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1582 new_door_state = MoveDoor(door_state);
1584 return(new_door_state);
1587 unsigned int GetDoorState()
1589 return(MoveDoor(DOOR_GET_STATE));
1592 unsigned int MoveDoor(unsigned int door_state)
1594 static unsigned int door1 = DOOR_OPEN_1;
1595 static unsigned int door2 = DOOR_CLOSE_2;
1596 static long door_delay = 0;
1597 int x, start, stepsize = 2;
1598 long door_delay_value = stepsize * 5;
1600 if (door_state == DOOR_GET_STATE)
1601 return(door1 | door2);
1603 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1604 door_state &= ~DOOR_OPEN_1;
1605 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1606 door_state &= ~DOOR_CLOSE_1;
1607 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1608 door_state &= ~DOOR_OPEN_2;
1609 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1610 door_state &= ~DOOR_CLOSE_2;
1612 if (setup.quick_doors)
1615 door_delay_value = 0;
1616 StopSound(SND_OEFFNEN);
1619 if (door_state & DOOR_ACTION)
1621 if (!(door_state & DOOR_NO_DELAY))
1622 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1624 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1626 for(x=start; x<=DXSIZE; x+=stepsize)
1628 WaitUntilDelayReached(&door_delay, door_delay_value);
1630 if (door_state & DOOR_ACTION_1)
1632 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1633 int j = (DXSIZE - i) / 3;
1635 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1636 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1637 DXSIZE,DYSIZE - i/2, DX, DY);
1639 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1641 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1642 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1643 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1644 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1645 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1646 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1648 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1649 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1650 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1651 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1652 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1653 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1655 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1656 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1658 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1659 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1661 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1662 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1663 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1664 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1665 DX + DXSIZE - i, DY + 77 + j);
1666 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1667 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1668 DX + DXSIZE - i, DY + 203 + j);
1670 redraw_mask |= REDRAW_DOOR_1;
1673 if (door_state & DOOR_ACTION_2)
1675 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1676 int j = (VXSIZE - i) / 3;
1678 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1679 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1680 VXSIZE, VYSIZE - i/2, VX, VY);
1682 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1684 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1685 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1686 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1687 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1688 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1689 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1690 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1691 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1693 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1694 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1695 VX, VY + VYSIZE / 2 - j);
1696 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1697 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1698 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1699 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1700 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1702 redraw_mask |= REDRAW_DOOR_2;
1707 if (game_status == MAINMENU)
1712 if (setup.quick_doors)
1713 StopSound(SND_OEFFNEN);
1715 if (door_state & DOOR_ACTION_1)
1716 door1 = door_state & DOOR_ACTION_1;
1717 if (door_state & DOOR_ACTION_2)
1718 door2 = door_state & DOOR_ACTION_2;
1720 return(door1 | door2);
1723 int ReadPixel(Drawable d, int x, int y)
1725 static XImage *pixelimage;
1727 pixelimage = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1728 return(XGetPixel(pixelimage, 0, 0));
1731 int el2gfx(int element)
1735 case EL_LEERRAUM: return -1;
1736 case EL_ERDREICH: return GFX_ERDREICH;
1737 case EL_MAUERWERK: return GFX_MAUERWERK;
1738 case EL_FELSBODEN: return GFX_FELSBODEN;
1739 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1740 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1741 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1742 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1743 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1744 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1745 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1746 case EL_SPIELER1: return GFX_SPIELER1;
1747 case EL_SPIELER2: return GFX_SPIELER2;
1748 case EL_SPIELER3: return GFX_SPIELER3;
1749 case EL_SPIELER4: return GFX_SPIELER4;
1750 case EL_KAEFER: return GFX_KAEFER;
1751 case EL_KAEFER_R: return GFX_KAEFER_R;
1752 case EL_KAEFER_O: return GFX_KAEFER_O;
1753 case EL_KAEFER_L: return GFX_KAEFER_L;
1754 case EL_KAEFER_U: return GFX_KAEFER_U;
1755 case EL_FLIEGER: return GFX_FLIEGER;
1756 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1757 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1758 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1759 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1760 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1761 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1762 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1763 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1764 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1765 case EL_FIREFLY: return GFX_FIREFLY;
1766 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1767 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1768 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1769 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1770 case EL_MAMPFER: return GFX_MAMPFER;
1771 case EL_ROBOT: return GFX_ROBOT;
1772 case EL_BETON: return GFX_BETON;
1773 case EL_DIAMANT: return GFX_DIAMANT;
1774 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1775 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1776 case EL_TROPFEN: return GFX_TROPFEN;
1777 case EL_BOMBE: return GFX_BOMBE;
1778 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1779 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1780 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1781 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1782 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1783 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1784 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1785 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1786 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1787 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1788 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1789 case EL_LIFE: return GFX_LIFE;
1790 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1791 case EL_DYNAMIT: return GFX_DYNAMIT;
1792 case EL_BADEWANNE: return GFX_BADEWANNE;
1793 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1794 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1795 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1796 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1797 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1798 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1799 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1800 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1801 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1802 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1803 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1804 case EL_PFORTE1: return GFX_PFORTE1;
1805 case EL_PFORTE2: return GFX_PFORTE2;
1806 case EL_PFORTE3: return GFX_PFORTE3;
1807 case EL_PFORTE4: return GFX_PFORTE4;
1808 case EL_PFORTE1X: return GFX_PFORTE1X;
1809 case EL_PFORTE2X: return GFX_PFORTE2X;
1810 case EL_PFORTE3X: return GFX_PFORTE3X;
1811 case EL_PFORTE4X: return GFX_PFORTE4X;
1812 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1813 case EL_PACMAN: return GFX_PACMAN;
1814 case EL_PACMAN_R: return GFX_PACMAN_R;
1815 case EL_PACMAN_O: return GFX_PACMAN_O;
1816 case EL_PACMAN_L: return GFX_PACMAN_L;
1817 case EL_PACMAN_U: return GFX_PACMAN_U;
1818 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1819 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1820 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1821 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1822 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1823 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1824 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1825 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1826 case EL_MAUER_X: return GFX_MAUER_X;
1827 case EL_MAUER_Y: return GFX_MAUER_Y;
1828 case EL_MAUER_XY: return GFX_MAUER_XY;
1829 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1830 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1831 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1832 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1833 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1834 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1835 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1836 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1837 case EL_MAMPFER2: return GFX_MAMPFER2;
1838 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1839 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1840 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1841 case EL_DYNABOMB: return GFX_DYNABOMB;
1842 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1843 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1844 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1845 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1846 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1847 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1848 case EL_MAULWURF: return GFX_MAULWURF;
1849 case EL_PINGUIN: return GFX_PINGUIN;
1850 case EL_SCHWEIN: return GFX_SCHWEIN;
1851 case EL_DRACHE: return GFX_DRACHE;
1852 case EL_SONDE: return GFX_SONDE;
1853 case EL_PFEIL_L: return GFX_PFEIL_L;
1854 case EL_PFEIL_R: return GFX_PFEIL_R;
1855 case EL_PFEIL_O: return GFX_PFEIL_O;
1856 case EL_PFEIL_U: return GFX_PFEIL_U;
1859 if (IS_CHAR(element))
1860 return GFX_CHAR_START + (element - EL_CHAR_START);