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 */
92 XSync(display, FALSE);
96 wait_for_vsync = TRUE;
100 if (redraw_mask & REDRAW_ALL)
102 XCopyArea(display,backbuffer,window,gc,
103 0,0, WIN_XSIZE,WIN_YSIZE,
108 if (redraw_mask & REDRAW_FIELD)
110 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
111 XCopyArea(display,backbuffer,window,gc,
112 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
116 int fx = FX, fy = FY;
118 if (setup.soft_scrolling)
120 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
121 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
124 if (setup.soft_scrolling ||
125 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ||
126 ABS(ScreenGfxPos) == ScrollStepSize ||
127 redraw_tiles > REDRAWTILES_THRESHOLD)
128 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
130 redraw_mask &= ~REDRAW_MAIN;
133 if (redraw_mask & REDRAW_DOORS)
135 if (redraw_mask & REDRAW_DOOR_1)
136 XCopyArea(display,backbuffer,window,gc,
137 DX,DY, DXSIZE,DYSIZE,
139 if (redraw_mask & REDRAW_DOOR_2)
141 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
142 XCopyArea(display,backbuffer,window,gc,
143 VX,VY, VXSIZE,VYSIZE,
147 if (redraw_mask & REDRAW_VIDEO_1)
148 XCopyArea(display,backbuffer,window,gc,
149 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
150 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
151 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
152 if (redraw_mask & REDRAW_VIDEO_2)
153 XCopyArea(display,backbuffer,window,gc,
154 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
155 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
156 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
157 if (redraw_mask & REDRAW_VIDEO_3)
158 XCopyArea(display,backbuffer,window,gc,
159 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
160 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
161 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
164 if (redraw_mask & REDRAW_DOOR_3)
165 XCopyArea(display, backbuffer, window, gc,
166 EX, EY, EXSIZE, EYSIZE,
168 redraw_mask &= ~REDRAW_DOORS;
171 if (redraw_mask & REDRAW_MICROLEV)
173 XCopyArea(display,backbuffer,window,gc,
174 MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
175 MICROLEV_XPOS,MICROLEV_YPOS);
176 XCopyArea(display,backbuffer,window,gc,
177 SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
179 redraw_mask &= ~REDRAW_MICROLEV;
182 if (redraw_mask & REDRAW_TILES)
184 for(x=0; x<SCR_FIELDX; x++)
185 for(y=0; y<SCR_FIELDY; y++)
186 if (redraw[redraw_x1 + x][redraw_y1 + y])
187 XCopyArea(display,buffer,window,gc,
188 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
189 SX+x*TILEX,SY+y*TILEY);
194 for(x=0; x<MAX_BUF_XSIZE; x++)
195 for(y=0; y<MAX_BUF_YSIZE; y++)
204 long fading_delay = 300;
206 if (setup.fading && (redraw_mask & REDRAW_FIELD))
213 XFillRectangle(display,window,gc,
214 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
217 for(i=0;i<2*FULL_SYSIZE;i++)
219 for(y=0;y<FULL_SYSIZE;y++)
221 XCopyArea(display,backbuffer,window,gc,
222 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
230 for(i=1;i<FULL_SYSIZE;i+=2)
231 XCopyArea(display,backbuffer,window,gc,
232 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
238 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
239 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
240 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
244 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
245 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
246 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
250 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
251 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
252 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
256 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
257 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
258 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
262 redraw_mask &= ~REDRAW_MAIN;
271 XFillRectangle(display, backbuffer, gc,
272 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
274 if (setup.soft_scrolling && game_status == PLAYING)
276 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
277 SetDrawtoField(DRAW_BUFFERED);
280 SetDrawtoField(DRAW_BACKBUFFER);
282 if (setup.direct_draw && game_status == PLAYING)
284 XFillRectangle(display, window, gc,
285 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
286 SetDrawtoField(DRAW_DIRECT);
289 redraw_mask |= REDRAW_FIELD;
292 void DrawTextFCentered(int y, int font_type, char *format, ...)
294 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
298 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
299 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
301 va_start(ap, format);
302 vsprintf(buffer, format, ap);
305 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
306 buffer, FS_SMALL, font_type);
309 void DrawTextF(int x, int y, int font_type, char *format, ...)
311 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
314 va_start(ap, format);
315 vsprintf(buffer, format, ap);
318 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
321 void DrawText(int x, int y, char *text, int font_size, int font_type)
323 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
326 redraw_mask |= REDRAW_FIELD;
328 redraw_mask |= REDRAW_DOOR_1;
331 void DrawTextExt(Drawable d, GC gc, int x, int y,
332 char *text, int font_size, int font_type)
334 int font_width, font_height, font_start;
337 if (font_size != FS_SMALL && font_size != FS_BIG)
338 font_size = FS_SMALL;
339 if (font_type < FC_RED || font_type > FC_SPECIAL2)
342 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
343 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
344 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
345 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
346 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
347 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
348 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
349 FONT_LINES_PER_FONT);
355 if (c >= 'a' && c <= 'z')
357 else if (c == 'ä' || c == 'Ä')
359 else if (c == 'ö' || c == 'Ö')
361 else if (c == 'ü' || c == 'Ü')
364 if (c >= 32 && c <= 95)
365 XCopyArea(display, pix[font_pixmap], d, gc,
366 ((c - 32) % FONT_CHARS_PER_LINE) * font_width,
367 ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start,
368 font_width, font_height, x, y);
374 void DrawAllPlayers()
378 for(i=0; i<MAX_PLAYERS; i++)
379 if (stored_player[i].active)
380 DrawPlayer(&stored_player[i]);
383 void DrawPlayerField(int x, int y)
388 DrawPlayer(PLAYERINFO(x,y));
391 void DrawPlayer(struct PlayerInfo *player)
393 int jx = player->jx, jy = player->jy;
394 int last_jx = player->last_jx, last_jy = player->last_jy;
395 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
396 int sx = SCREENX(jx), sy = SCREENY(jy);
397 int sxx = 0, syy = 0;
398 int element = Feld[jx][jy];
401 if (!player->active || player->gone ||
402 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
406 if (!IN_LEV_FIELD(jx,jy))
408 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
409 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
410 printf("DrawPlayerField(): This should never happen!\n");
415 if (element == EL_EXPLODING)
418 /* draw things in the field the player is leaving, if needed */
420 if (last_jx != jx || last_jy != jy)
422 if (Store[last_jx][last_jy])
424 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
425 DrawLevelFieldThruMask(last_jx, last_jy);
427 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
428 DrawDynamite(last_jx, last_jy);
430 DrawLevelField(last_jx, last_jy);
432 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
436 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
437 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
439 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
442 DrawLevelField(next_jx, next_jy);
446 if (!IN_SCR_FIELD(sx, sy))
449 if (setup.direct_draw)
450 SetDrawtoField(DRAW_BUFFERED);
452 /* draw things behind the player, if needed */
455 DrawLevelElement(jx, jy, Store[jx][jy]);
456 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
457 DrawLevelField(jx, jy);
459 /* draw player himself */
461 if (player->MovDir == MV_LEFT)
462 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
463 else if (player->MovDir == MV_RIGHT)
464 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
465 else if (player->MovDir == MV_UP)
466 graphic = GFX_SPIELER1_UP;
467 else /* MV_DOWN || MV_NO_MOVING */
468 graphic = GFX_SPIELER1_DOWN;
470 graphic += player->index_nr * 3*HEROES_PER_LINE;
471 graphic += player->Frame;
475 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
476 sxx = player->GfxPos;
478 syy = player->GfxPos;
481 if (!setup.soft_scrolling && ScreenMovPos)
484 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
486 if (player->Pushing && player->GfxPos)
488 int px = SCREENX(next_jx), py = SCREENY(next_jy);
490 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
491 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
492 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
496 int element = Feld[next_jx][next_jy];
497 int graphic = el2gfx(element);
499 if (element == EL_FELSBROCKEN && sxx)
501 int phase = (player->GfxPos / (TILEX/4));
503 if (player->MovDir == MV_LEFT)
506 graphic += (phase+4)%4;
509 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
513 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
515 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
517 graphic = el2gfx(element);
519 if (element == EL_DYNAMIT)
521 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
526 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
530 DrawGraphicThruMask(sx, sy, graphic + phase);
533 if ((last_jx != jx || last_jy != jy) &&
534 Feld[last_jx][last_jy] == EL_EXPLODING)
536 int phase = Frame[last_jx][last_jy];
540 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
541 GFX_EXPLOSION + ((phase - 1) / delay - 1));
544 if (setup.direct_draw)
546 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
547 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
548 int x_size = TILEX * (1 + ABS(jx - last_jx));
549 int y_size = TILEY * (1 + ABS(jy - last_jy));
551 XCopyArea(display, drawto_field, window, gc,
552 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
553 SetDrawtoField(DRAW_DIRECT);
556 MarkTileDirty(sx,sy);
559 static int getGraphicAnimationPhase(int frames, int delay, int mode)
563 if (mode == ANIM_OSCILLATE)
565 int max_anim_frames = 2 * frames - 2;
566 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
567 phase = (phase < frames ? phase : max_anim_frames - phase);
570 phase = (FrameCounter % (delay * frames)) / delay;
572 if (mode == ANIM_REVERSE)
578 void DrawGraphicAnimationExt(int x, int y, int graphic,
579 int frames, int delay, int mode, int mask_mode)
581 int phase = getGraphicAnimationPhase(frames, delay, mode);
583 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
585 if (mask_mode == USE_MASKING)
586 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
588 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
592 void DrawGraphicAnimation(int x, int y, int graphic,
593 int frames, int delay, int mode)
595 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
598 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
599 int frames, int delay, int mode)
601 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
604 void DrawGraphic(int x, int y, int graphic)
607 if (!IN_SCR_FIELD(x,y))
609 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
610 printf("DrawGraphic(): This should never happen!\n");
615 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
619 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
621 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
623 graphic -= GFX_START_ROCKSSCREEN;
624 XCopyArea(display, pix[PIX_BACK], d, gc,
625 SX + (graphic % GFX_PER_LINE) * TILEX,
626 SY + (graphic / GFX_PER_LINE) * TILEY,
629 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
631 graphic -= GFX_START_ROCKSHEROES;
632 XCopyArea(display, pix[PIX_HEROES], d, gc,
633 (graphic % HEROES_PER_LINE) * TILEX,
634 (graphic / HEROES_PER_LINE) * TILEY,
637 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
639 graphic -= GFX_START_ROCKSFONT;
640 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
641 (graphic % FONT_CHARS_PER_LINE) * TILEX,
642 (graphic / FONT_CHARS_PER_LINE) * TILEY +
643 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
647 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
650 void DrawGraphicThruMask(int x, int y, int graphic)
653 if (!IN_SCR_FIELD(x,y))
655 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
656 printf("DrawGraphicThruMask(): This should never happen!\n");
661 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
665 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
672 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
674 src_pixmap = pix[PIX_BACK];
675 drawing_gc = clip_gc[PIX_BACK];
676 graphic -= GFX_START_ROCKSSCREEN;
677 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
678 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
680 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
682 src_pixmap = pix[PIX_HEROES];
683 drawing_gc = clip_gc[PIX_HEROES];
684 graphic -= GFX_START_ROCKSHEROES;
685 src_x = (graphic % HEROES_PER_LINE) * TILEX;
686 src_y = (graphic / HEROES_PER_LINE) * TILEY;
690 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
694 if (tile_clipmask[tile] != None)
696 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
697 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
698 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
699 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
704 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
707 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
708 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
709 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
713 void DrawMiniGraphic(int x, int y, int graphic)
715 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
716 MarkTileDirty(x/2, y/2);
719 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
721 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
723 graphic -= GFX_START_ROCKSSCREEN;
724 XCopyArea(display, pix[PIX_BACK], d, gc,
725 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
726 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
727 MINI_TILEX, MINI_TILEY, x, y);
729 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
731 graphic -= GFX_START_ROCKSFONT;
732 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
733 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
734 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
735 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
736 MINI_TILEX, MINI_TILEY, x, y);
739 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
742 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
743 int cut_mode, int mask_mode)
745 int width = TILEX, height = TILEY;
747 int src_x, src_y, dest_x, dest_y;
754 DrawGraphic(x, y, graphic);
758 if (dx || dy) /* Verschiebung der Grafik? */
760 if (x < BX1) /* Element kommt von links ins Bild */
767 else if (x > BX2) /* Element kommt von rechts ins Bild */
773 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
779 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
781 else if (dx) /* allg. Bewegung in x-Richtung */
782 MarkTileDirty(x + SIGN(dx), y);
784 if (y < BY1) /* Element kommt von oben ins Bild */
786 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
794 else if (y > BY2) /* Element kommt von unten ins Bild */
800 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
806 else if (dy > 0 && cut_mode == CUT_ABOVE)
808 if (y == BY2) /* Element unterhalb des Bildes */
814 MarkTileDirty(x, y + 1);
815 } /* Element verläßt unten das Bild */
816 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
818 else if (dy) /* allg. Bewegung in y-Richtung */
819 MarkTileDirty(x, y + SIGN(dy));
822 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
824 src_pixmap = pix[PIX_BACK];
825 drawing_gc = clip_gc[PIX_BACK];
826 graphic -= GFX_START_ROCKSSCREEN;
827 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
828 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
830 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
832 src_pixmap = pix[PIX_HEROES];
833 drawing_gc = clip_gc[PIX_HEROES];
834 graphic -= GFX_START_ROCKSHEROES;
835 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
836 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
838 else /* big font graphics currently not allowed (and not needed) */
841 dest_x = FX + x * TILEX + dx;
842 dest_y = FY + y * TILEY + dy;
845 if (!IN_SCR_FIELD(x,y))
847 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
848 printf("DrawGraphicShifted(): This should never happen!\n");
853 if (mask_mode == USE_MASKING)
855 if (tile_clipmask[tile] != None)
857 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
858 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
859 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
860 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
865 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
868 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
869 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
870 src_x, src_y, width, height, dest_x, dest_y);
874 XCopyArea(display, src_pixmap, drawto_field, gc,
875 src_x, src_y, width, height, dest_x, dest_y);
880 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
883 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
886 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
887 int cut_mode, int mask_mode)
889 int ux = LEVELX(x), uy = LEVELY(y);
890 int graphic = el2gfx(element);
891 int phase4 = ABS(MovPos[ux][uy]) / (TILEX / 4);
892 int phase = phase4 / 2;
893 int dir = MovDir[ux][uy];
895 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
901 else if (dir == MV_LEFT)
903 else if (dir == MV_DOWN)
906 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
907 element == EL_SCHWEIN || element == EL_DRACHE)
910 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
911 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
912 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
913 else if (dir == MV_RIGHT)
914 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
915 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
916 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
917 else if (dir == MV_UP)
918 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
919 element == EL_PINGUIN ? GFX_PINGUIN_UP :
920 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
922 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
923 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
924 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
928 else if (element == EL_SONDE)
930 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
932 else if (element == EL_SALZSAEURE)
934 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
936 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
940 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
942 graphic += phase * (element == EL_FELSBROCKEN ? 2 : 1);
944 else if ((element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
945 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL) && SiebAktiv)
947 graphic += 3 - (SiebAktiv % 8) / 2;
949 else if (IS_AMOEBOID(element))
951 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
952 graphic += (x + 2 * y + 4) % 4;
954 else if (element == EL_MAUER_LEBT)
956 boolean links_massiv = FALSE, rechts_massiv = FALSE;
958 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
960 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
961 rechts_massiv = TRUE;
963 if (links_massiv && rechts_massiv)
964 graphic = GFX_MAUERWERK;
965 else if (links_massiv)
966 graphic = GFX_MAUER_R;
967 else if (rechts_massiv)
968 graphic = GFX_MAUER_L;
972 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
973 else if (mask_mode == USE_MASKING)
974 DrawGraphicThruMask(x, y, graphic);
976 DrawGraphic(x, y, graphic);
979 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
980 int cut_mode, int mask_mode)
982 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
983 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
984 cut_mode, mask_mode);
987 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
990 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
993 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
996 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
999 void DrawScreenElementThruMask(int x, int y, int element)
1001 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1004 void DrawLevelElementThruMask(int x, int y, int element)
1006 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1009 void DrawLevelFieldThruMask(int x, int y)
1011 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1014 void ErdreichAnbroeckeln(int x, int y)
1016 int i, width, height, cx,cy;
1017 int ux = LEVELX(x), uy = LEVELY(y);
1018 int element, graphic;
1020 static int xy[4][2] =
1028 if (!IN_LEV_FIELD(ux, uy))
1031 element = Feld[ux][uy];
1033 if (element == EL_ERDREICH)
1035 if (!IN_SCR_FIELD(x, y))
1038 graphic = GFX_ERDENRAND;
1044 uxx = ux + xy[i][0];
1045 uyy = uy + xy[i][1];
1046 if (!IN_LEV_FIELD(uxx, uyy))
1049 element = Feld[uxx][uyy];
1051 if (element == EL_ERDREICH)
1054 if (i == 1 || i == 2)
1058 cx = (i == 2 ? TILEX - snip : 0);
1066 cy = (i == 3 ? TILEY - snip : 0);
1069 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1070 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1071 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1072 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1075 MarkTileDirty(x, y);
1079 graphic = GFX_ERDENRAND;
1083 int xx, yy, uxx, uyy;
1087 uxx = ux + xy[i][0];
1088 uyy = uy + xy[i][1];
1090 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1091 !IN_SCR_FIELD(xx, yy))
1094 if (i == 1 || i == 2)
1098 cx = (i == 1 ? TILEX - snip : 0);
1106 cy = (i==0 ? TILEY-snip : 0);
1109 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1110 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1111 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1112 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1114 MarkTileDirty(xx, yy);
1119 void DrawScreenElement(int x, int y, int element)
1121 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1122 ErdreichAnbroeckeln(x, y);
1125 void DrawLevelElement(int x, int y, int element)
1127 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1128 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1131 void DrawScreenField(int x, int y)
1133 int ux = LEVELX(x), uy = LEVELY(y);
1136 if (!IN_LEV_FIELD(ux, uy))
1138 DrawScreenElement(x, y, EL_BETON);
1142 element = Feld[ux][uy];
1144 if (IS_MOVING(ux, uy))
1146 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1147 boolean cut_mode = NO_CUTTING;
1149 if (Store[ux][uy] == EL_MORAST_LEER ||
1150 Store[ux][uy] == EL_SIEB_LEER ||
1151 Store[ux][uy] == EL_SIEB2_LEER ||
1152 Store[ux][uy] == EL_AMOEBE_NASS)
1153 cut_mode = CUT_ABOVE;
1154 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1155 Store[ux][uy] == EL_SIEB_VOLL ||
1156 Store[ux][uy] == EL_SIEB2_VOLL)
1157 cut_mode = CUT_BELOW;
1159 if (cut_mode == CUT_ABOVE)
1160 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1162 DrawScreenElement(x, y, EL_LEERRAUM);
1165 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1167 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1169 if (Store[ux][uy] == EL_SALZSAEURE)
1170 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1172 else if (IS_BLOCKED(ux, uy))
1177 boolean cut_mode = NO_CUTTING;
1179 Blocked2Moving(ux, uy, &oldx, &oldy);
1182 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1183 MovDir[oldx][oldy] == MV_RIGHT);
1185 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1186 Store[oldx][oldy] == EL_SIEB_LEER ||
1187 Store[oldx][oldy] == EL_SIEB2_LEER ||
1188 Store[oldx][oldy] == EL_AMOEBE_NASS)
1189 cut_mode = CUT_ABOVE;
1191 DrawScreenElement(x, y, EL_LEERRAUM);
1192 element = Feld[oldx][oldy];
1195 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1197 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1199 else if (IS_DRAWABLE(element))
1200 DrawScreenElement(x, y, element);
1202 DrawScreenElement(x, y, EL_LEERRAUM);
1205 void DrawLevelField(int x, int y)
1207 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1208 DrawScreenField(SCREENX(x), SCREENY(y));
1209 else if (IS_MOVING(x, y))
1213 Moving2Blocked(x, y, &newx, &newy);
1214 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1215 DrawScreenField(SCREENX(newx), SCREENY(newy));
1217 else if (IS_BLOCKED(x, y))
1221 Blocked2Moving(x, y, &oldx, &oldy);
1222 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1223 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1227 void DrawMiniElement(int x, int y, int element)
1233 DrawMiniGraphic(x, y, -1);
1237 graphic = el2gfx(element);
1238 DrawMiniGraphic(x, y, graphic);
1241 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1243 int x = sx + scroll_x, y = sy + scroll_y;
1245 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1246 DrawMiniElement(sx, sy, EL_LEERRAUM);
1247 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1248 DrawMiniElement(sx, sy, EL_BETON);
1250 DrawMiniElement(sx, sy, Feld[x][y]);
1253 void DrawMicroElement(int xpos, int ypos, int element)
1257 if (element == EL_LEERRAUM)
1260 graphic = el2gfx(element);
1262 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1263 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1264 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1265 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1274 for(x=BX1; x<=BX2; x++)
1275 for(y=BY1; y<=BY2; y++)
1276 DrawScreenField(x, y);
1278 if (setup.soft_scrolling)
1279 XCopyArea(display, fieldbuffer, backbuffer, gc,
1280 FX, FY, SXSIZE, SYSIZE, SX, SY);
1282 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1285 void DrawMiniLevel(int scroll_x, int scroll_y)
1291 for(x=0; x<2*SCR_FIELDX; x++)
1292 for(y=0; y<2*SCR_FIELDY; y++)
1293 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1295 redraw_mask |= REDRAW_FIELD;
1298 void DrawMicroLevel(int xpos, int ypos)
1302 XFillRectangle(display, drawto, gc,
1303 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1304 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1305 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1306 if (lev_fieldx < STD_LEV_FIELDX)
1307 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1308 if (lev_fieldy < STD_LEV_FIELDY)
1309 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1311 for(x=-1; x<=STD_LEV_FIELDX; x++)
1312 for(y=-1; y<=STD_LEV_FIELDY; y++)
1313 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1314 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1316 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1317 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1320 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1324 int len = strlen(level.name);
1325 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1326 int lypos = MICROLABEL_YPOS;
1328 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1331 redraw_mask |= REDRAW_MICROLEV;
1334 int REQ_in_range(int x, int y)
1336 if (y > DY+249 && y < DY+278)
1338 if (x > DX+1 && x < DX+48)
1340 else if (x > DX+51 && x < DX+98)
1346 boolean Request(char *text, unsigned int req_state)
1348 int mx, my, ty, result = -1;
1349 unsigned int old_door_state;
1352 /* pause network game while waiting for request to answer */
1353 if (options.network &&
1354 game_status == PLAYING &&
1355 req_state & REQUEST_WAIT_FOR)
1356 SendToServer_PausePlaying();
1359 old_door_state = GetDoorState();
1361 CloseDoor(DOOR_CLOSE_1);
1363 /* Alten Türinhalt sichern */
1364 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1365 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1366 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1368 /* Fragetext schreiben */
1369 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1370 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1372 for(ty=0; ty<13; ty++)
1380 for(tl=0,tx=0; tx<7; tl++,tx++)
1383 if (!tc || tc == 32)
1394 DrawTextExt(pix[PIX_DB_DOOR], gc,
1395 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1396 txt, FS_SMALL, FC_YELLOW);
1397 text += tl + (tc == 32 ? 1 : 0);
1400 if (req_state & REQ_ASK)
1402 DrawYesNoButton(BUTTON_OK, DB_INIT);
1403 DrawYesNoButton(BUTTON_NO, DB_INIT);
1405 else if (req_state & REQ_CONFIRM)
1407 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1409 else if (req_state & REQ_PLAYER)
1411 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1412 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1413 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1414 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1417 OpenDoor(DOOR_OPEN_1);
1420 if (!(req_state & REQUEST_WAIT_FOR))
1423 if (game_status != MAINMENU)
1426 button_status = MB_RELEASED;
1430 if (XPending(display))
1434 XNextEvent(display, &event);
1444 if (event.type == MotionNotify)
1446 motion_status = TRUE;
1447 mx = ((XMotionEvent *) &event)->x;
1448 my = ((XMotionEvent *) &event)->y;
1452 motion_status = FALSE;
1453 mx = ((XButtonEvent *) &event)->x;
1454 my = ((XButtonEvent *) &event)->y;
1455 if (event.type==ButtonPress)
1456 button_status = ((XButtonEvent *) &event)->button;
1458 button_status = MB_RELEASED;
1461 if (req_state & REQ_ASK)
1462 choice = CheckYesNoButtons(mx,my,button_status);
1463 else if (req_state & REQ_CONFIRM)
1464 choice = CheckConfirmButton(mx,my,button_status);
1466 choice = CheckPlayerButtons(mx,my,button_status);
1476 case BUTTON_CONFIRM:
1477 result = TRUE | FALSE;
1480 case BUTTON_PLAYER_1:
1483 case BUTTON_PLAYER_2:
1486 case BUTTON_PLAYER_3:
1489 case BUTTON_PLAYER_4:
1500 switch(XLookupKeysym((XKeyEvent *)&event,
1501 ((XKeyEvent *)&event)->state))
1514 if (req_state & REQ_PLAYER)
1519 key_joystick_mapping = 0;
1523 HandleOtherEvents(&event);
1527 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1529 int joy = AnyJoystick();
1531 if (joy & JOY_BUTTON_1)
1533 else if (joy & JOY_BUTTON_2)
1539 /* don't eat all CPU time */
1543 if (game_status != MAINMENU)
1546 if (!(req_state & REQ_STAY_OPEN))
1548 CloseDoor(DOOR_CLOSE_1);
1550 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1552 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1553 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1554 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1555 OpenDoor(DOOR_OPEN_1);
1560 /* continue network game after request */
1561 if (options.network &&
1562 game_status == PLAYING &&
1563 req_state & REQUEST_WAIT_FOR)
1564 SendToServer_ContinuePlaying();
1570 unsigned int OpenDoor(unsigned int door_state)
1572 unsigned int new_door_state;
1574 if (door_state & DOOR_COPY_BACK)
1576 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1577 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1578 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1579 door_state &= ~DOOR_COPY_BACK;
1582 new_door_state = MoveDoor(door_state);
1584 return(new_door_state);
1587 unsigned int CloseDoor(unsigned int door_state)
1589 unsigned int new_door_state;
1591 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1592 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1593 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1594 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1596 new_door_state = MoveDoor(door_state);
1598 return(new_door_state);
1601 unsigned int GetDoorState()
1603 return(MoveDoor(DOOR_GET_STATE));
1606 unsigned int MoveDoor(unsigned int door_state)
1608 static int door1 = DOOR_OPEN_1;
1609 static int door2 = DOOR_CLOSE_2;
1610 static unsigned long door_delay = 0;
1611 int x, start, stepsize = 2;
1612 unsigned long door_delay_value = stepsize * 5;
1614 if (door_state == DOOR_GET_STATE)
1615 return(door1 | door2);
1617 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1618 door_state &= ~DOOR_OPEN_1;
1619 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1620 door_state &= ~DOOR_CLOSE_1;
1621 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1622 door_state &= ~DOOR_OPEN_2;
1623 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1624 door_state &= ~DOOR_CLOSE_2;
1626 if (setup.quick_doors)
1629 door_delay_value = 0;
1630 StopSound(SND_OEFFNEN);
1633 if (door_state & DOOR_ACTION)
1635 if (!(door_state & DOOR_NO_DELAY))
1636 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1638 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1640 for(x=start; x<=DXSIZE; x+=stepsize)
1642 WaitUntilDelayReached(&door_delay, door_delay_value);
1644 if (door_state & DOOR_ACTION_1)
1646 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1647 int j = (DXSIZE - i) / 3;
1649 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1650 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1651 DXSIZE,DYSIZE - i/2, DX, DY);
1653 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1655 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1656 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1657 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1658 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1659 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1660 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1662 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1663 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1664 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1665 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1666 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1667 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1669 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1670 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1672 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1673 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1675 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1676 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1677 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1678 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1679 DX + DXSIZE - i, DY + 77 + j);
1680 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1681 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1682 DX + DXSIZE - i, DY + 203 + j);
1684 redraw_mask |= REDRAW_DOOR_1;
1687 if (door_state & DOOR_ACTION_2)
1689 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1690 int j = (VXSIZE - i) / 3;
1692 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1693 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1694 VXSIZE, VYSIZE - i/2, VX, VY);
1696 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1698 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1699 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1700 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1701 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1702 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1703 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1704 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1705 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1707 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1708 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1709 VX, VY + VYSIZE / 2 - j);
1710 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1711 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1712 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1713 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1714 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1716 redraw_mask |= REDRAW_DOOR_2;
1721 if (game_status == MAINMENU)
1726 if (setup.quick_doors)
1727 StopSound(SND_OEFFNEN);
1729 if (door_state & DOOR_ACTION_1)
1730 door1 = door_state & DOOR_ACTION_1;
1731 if (door_state & DOOR_ACTION_2)
1732 door2 = door_state & DOOR_ACTION_2;
1734 return(door1 | door2);
1737 int ReadPixel(Drawable d, int x, int y)
1739 XImage *pixel_image;
1740 unsigned long pixel_value;
1742 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1743 pixel_value = XGetPixel(pixel_image, 0, 0);
1745 XDestroyImage(pixel_image);
1750 int el2gfx(int element)
1754 case EL_LEERRAUM: return -1;
1755 case EL_ERDREICH: return GFX_ERDREICH;
1756 case EL_MAUERWERK: return GFX_MAUERWERK;
1757 case EL_FELSBODEN: return GFX_FELSBODEN;
1758 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1759 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1760 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1761 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1762 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1763 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1764 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1765 case EL_SPIELER1: return GFX_SPIELER1;
1766 case EL_SPIELER2: return GFX_SPIELER2;
1767 case EL_SPIELER3: return GFX_SPIELER3;
1768 case EL_SPIELER4: return GFX_SPIELER4;
1769 case EL_KAEFER: return GFX_KAEFER;
1770 case EL_KAEFER_R: return GFX_KAEFER_R;
1771 case EL_KAEFER_O: return GFX_KAEFER_O;
1772 case EL_KAEFER_L: return GFX_KAEFER_L;
1773 case EL_KAEFER_U: return GFX_KAEFER_U;
1774 case EL_FLIEGER: return GFX_FLIEGER;
1775 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1776 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1777 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1778 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1779 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1780 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1781 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1782 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1783 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1784 case EL_FIREFLY: return GFX_FIREFLY;
1785 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1786 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1787 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1788 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1789 case EL_MAMPFER: return GFX_MAMPFER;
1790 case EL_ROBOT: return GFX_ROBOT;
1791 case EL_BETON: return GFX_BETON;
1792 case EL_DIAMANT: return GFX_DIAMANT;
1793 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1794 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1795 case EL_TROPFEN: return GFX_TROPFEN;
1796 case EL_BOMBE: return GFX_BOMBE;
1797 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1798 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1799 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1800 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1801 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1802 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1803 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1804 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1805 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1806 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1807 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1808 case EL_LIFE: return GFX_LIFE;
1809 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1810 case EL_DYNAMIT: return GFX_DYNAMIT;
1811 case EL_BADEWANNE: return GFX_BADEWANNE;
1812 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1813 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1814 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1815 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1816 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1817 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1818 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1819 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1820 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1821 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1822 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1823 case EL_PFORTE1: return GFX_PFORTE1;
1824 case EL_PFORTE2: return GFX_PFORTE2;
1825 case EL_PFORTE3: return GFX_PFORTE3;
1826 case EL_PFORTE4: return GFX_PFORTE4;
1827 case EL_PFORTE1X: return GFX_PFORTE1X;
1828 case EL_PFORTE2X: return GFX_PFORTE2X;
1829 case EL_PFORTE3X: return GFX_PFORTE3X;
1830 case EL_PFORTE4X: return GFX_PFORTE4X;
1831 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1832 case EL_PACMAN: return GFX_PACMAN;
1833 case EL_PACMAN_R: return GFX_PACMAN_R;
1834 case EL_PACMAN_O: return GFX_PACMAN_O;
1835 case EL_PACMAN_L: return GFX_PACMAN_L;
1836 case EL_PACMAN_U: return GFX_PACMAN_U;
1837 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1838 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1839 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1840 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1841 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1842 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1843 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1844 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1845 case EL_MAUER_X: return GFX_MAUER_X;
1846 case EL_MAUER_Y: return GFX_MAUER_Y;
1847 case EL_MAUER_XY: return GFX_MAUER_XY;
1848 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1849 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1850 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1851 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1852 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1853 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1854 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1855 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1856 case EL_MAMPFER2: return GFX_MAMPFER2;
1857 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1858 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1859 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1860 case EL_DYNABOMB: return GFX_DYNABOMB;
1861 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1862 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1863 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1864 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1865 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1866 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1867 case EL_MAULWURF: return GFX_MAULWURF;
1868 case EL_PINGUIN: return GFX_PINGUIN;
1869 case EL_SCHWEIN: return GFX_SCHWEIN;
1870 case EL_DRACHE: return GFX_DRACHE;
1871 case EL_SONDE: return GFX_SONDE;
1872 case EL_PFEIL_L: return GFX_PFEIL_L;
1873 case EL_PFEIL_R: return GFX_PFEIL_R;
1874 case EL_PFEIL_O: return GFX_PFEIL_O;
1875 case EL_PFEIL_U: return GFX_PFEIL_U;
1878 if (IS_CHAR(element))
1879 return GFX_CHAR_START + (element - EL_CHAR_START);