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 redraw_mask &= ~REDRAW_DOORS;
167 if (redraw_mask & REDRAW_MICROLEV)
169 XCopyArea(display,backbuffer,window,gc,
170 MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
171 MICROLEV_XPOS,MICROLEV_YPOS);
172 XCopyArea(display,backbuffer,window,gc,
173 SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
175 redraw_mask &= ~REDRAW_MICROLEV;
178 if (redraw_mask & REDRAW_TILES)
180 for(x=0; x<SCR_FIELDX; x++)
181 for(y=0; y<SCR_FIELDY; y++)
182 if (redraw[redraw_x1 + x][redraw_y1 + y])
183 XCopyArea(display,buffer,window,gc,
184 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
185 SX+x*TILEX,SY+y*TILEY);
190 for(x=0; x<MAX_BUF_XSIZE; x++)
191 for(y=0; y<MAX_BUF_YSIZE; y++)
200 long fading_delay = 300;
202 if (setup.fading && (redraw_mask & REDRAW_FIELD))
209 XFillRectangle(display,window,gc,
210 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
213 for(i=0;i<2*FULL_SYSIZE;i++)
215 for(y=0;y<FULL_SYSIZE;y++)
217 XCopyArea(display,backbuffer,window,gc,
218 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
226 for(i=1;i<FULL_SYSIZE;i+=2)
227 XCopyArea(display,backbuffer,window,gc,
228 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
234 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
235 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
236 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
240 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
241 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
242 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
246 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
247 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
248 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
252 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
253 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
254 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
258 redraw_mask &= ~REDRAW_MAIN;
267 XFillRectangle(display, backbuffer, gc,
268 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
270 if (setup.soft_scrolling && game_status == PLAYING)
272 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
273 SetDrawtoField(DRAW_BUFFERED);
276 SetDrawtoField(DRAW_BACKBUFFER);
278 if (setup.direct_draw && game_status == PLAYING)
280 XFillRectangle(display, window, gc,
281 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
282 SetDrawtoField(DRAW_DIRECT);
285 redraw_mask |= REDRAW_FIELD;
288 void DrawTextFCentered(int y, int font_type, char *format, ...)
290 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
294 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
295 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
297 va_start(ap, format);
298 vsprintf(buffer, format, ap);
301 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
302 buffer, FS_SMALL, font_type);
305 void DrawTextF(int x, int y, int font_type, char *format, ...)
307 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
310 va_start(ap, format);
311 vsprintf(buffer, format, ap);
314 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
317 void DrawText(int x, int y, char *text, int font_size, int font_type)
319 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
322 redraw_mask |= REDRAW_FIELD;
324 redraw_mask |= REDRAW_DOOR_1;
327 void DrawTextExt(Drawable d, GC gc, int x, int y,
328 char *text, int font_size, int font_type)
330 int font_width, font_height, font_start;
333 if (font_size != FS_SMALL && font_size != FS_BIG)
334 font_size = FS_SMALL;
335 if (font_type < FC_RED || font_type > FC_SPECIAL2)
338 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
339 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
340 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
341 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
342 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
343 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
344 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
345 FONT_LINES_PER_FONT);
351 if (c >= 'a' && c <= 'z')
353 else if (c == 'ä' || c == 'Ä')
355 else if (c == 'ö' || c == 'Ö')
357 else if (c == 'ü' || c == 'Ü')
360 if (c >= 32 && c <= 95)
361 XCopyArea(display, pix[font_pixmap], d, gc,
362 ((c - 32) % FONT_CHARS_PER_LINE) * font_width,
363 ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start,
364 font_width, font_height, x, y);
370 void DrawAllPlayers()
374 for(i=0; i<MAX_PLAYERS; i++)
375 if (stored_player[i].active)
376 DrawPlayer(&stored_player[i]);
379 void DrawPlayerField(int x, int y)
384 DrawPlayer(PLAYERINFO(x,y));
387 void DrawPlayer(struct PlayerInfo *player)
389 int jx = player->jx, jy = player->jy;
390 int last_jx = player->last_jx, last_jy = player->last_jy;
391 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
392 int sx = SCREENX(jx), sy = SCREENY(jy);
393 int sxx = 0, syy = 0;
394 int element = Feld[jx][jy];
397 if (!player->active || player->gone ||
398 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
402 if (!IN_LEV_FIELD(jx,jy))
404 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
405 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
406 printf("DrawPlayerField(): This should never happen!\n");
411 if (element == EL_EXPLODING)
414 /* draw things in the field the player is leaving, if needed */
416 if (last_jx != jx || last_jy != jy)
418 if (Store[last_jx][last_jy])
420 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
421 DrawLevelFieldThruMask(last_jx, last_jy);
423 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
424 DrawDynamite(last_jx, last_jy);
426 DrawLevelField(last_jx, last_jy);
428 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
432 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
433 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
435 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
438 DrawLevelField(next_jx, next_jy);
442 if (!IN_SCR_FIELD(sx, sy))
445 if (setup.direct_draw)
446 SetDrawtoField(DRAW_BUFFERED);
448 /* draw things behind the player, if needed */
451 DrawLevelElement(jx, jy, Store[jx][jy]);
452 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
453 DrawLevelField(jx, jy);
455 /* draw player himself */
457 if (player->MovDir == MV_LEFT)
458 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
459 else if (player->MovDir == MV_RIGHT)
460 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
461 else if (player->MovDir == MV_UP)
462 graphic = GFX_SPIELER1_UP;
463 else /* MV_DOWN || MV_NO_MOVING */
464 graphic = GFX_SPIELER1_DOWN;
466 graphic += player->index_nr * 3*HEROES_PER_LINE;
467 graphic += player->Frame;
471 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
472 sxx = player->GfxPos;
474 syy = player->GfxPos;
477 if (!setup.soft_scrolling && ScreenMovPos)
480 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
482 if (player->Pushing && player->GfxPos)
484 int px = SCREENX(next_jx), py = SCREENY(next_jy);
486 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
487 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
488 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
492 int element = Feld[next_jx][next_jy];
493 int graphic = el2gfx(element);
495 if (element == EL_FELSBROCKEN && sxx)
497 int phase = (player->GfxPos / (TILEX/4));
499 if (player->MovDir == MV_LEFT)
502 graphic += (phase+4)%4;
505 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
509 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
511 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
513 graphic = el2gfx(element);
515 if (element == EL_DYNAMIT)
517 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
522 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
526 DrawGraphicThruMask(sx, sy, graphic + phase);
529 if ((last_jx != jx || last_jy != jy) &&
530 Feld[last_jx][last_jy] == EL_EXPLODING)
532 int phase = Frame[last_jx][last_jy];
536 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
537 GFX_EXPLOSION + ((phase - 1) / delay - 1));
540 if (setup.direct_draw)
542 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
543 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
544 int x_size = TILEX * (1 + ABS(jx - last_jx));
545 int y_size = TILEY * (1 + ABS(jy - last_jy));
547 XCopyArea(display, drawto_field, window, gc,
548 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
549 SetDrawtoField(DRAW_DIRECT);
552 MarkTileDirty(sx,sy);
555 static int getGraphicAnimationPhase(int frames, int delay, int mode)
559 if (mode == ANIM_OSCILLATE)
561 int max_anim_frames = 2 * frames - 2;
562 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
563 phase = (phase < frames ? phase : max_anim_frames - phase);
566 phase = (FrameCounter % (delay * frames)) / delay;
568 if (mode == ANIM_REVERSE)
574 void DrawGraphicAnimationExt(int x, int y, int graphic,
575 int frames, int delay, int mode, int mask_mode)
577 int phase = getGraphicAnimationPhase(frames, delay, mode);
579 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
581 if (mask_mode == USE_MASKING)
582 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
584 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
588 void DrawGraphicAnimation(int x, int y, int graphic,
589 int frames, int delay, int mode)
591 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
594 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
595 int frames, int delay, int mode)
597 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
600 void DrawGraphic(int x, int y, int graphic)
603 if (!IN_SCR_FIELD(x,y))
605 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
606 printf("DrawGraphic(): This should never happen!\n");
611 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
615 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
617 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
619 graphic -= GFX_START_ROCKSSCREEN;
620 XCopyArea(display, pix[PIX_BACK], d, gc,
621 SX + (graphic % GFX_PER_LINE) * TILEX,
622 SY + (graphic / GFX_PER_LINE) * TILEY,
625 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
627 graphic -= GFX_START_ROCKSHEROES;
628 XCopyArea(display, pix[PIX_HEROES], d, gc,
629 (graphic % HEROES_PER_LINE) * TILEX,
630 (graphic / HEROES_PER_LINE) * TILEY,
633 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
635 graphic -= GFX_START_ROCKSFONT;
636 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
637 (graphic % FONT_CHARS_PER_LINE) * TILEX,
638 (graphic / FONT_CHARS_PER_LINE) * TILEY +
639 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
643 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
646 void DrawGraphicThruMask(int x, int y, int graphic)
649 if (!IN_SCR_FIELD(x,y))
651 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
652 printf("DrawGraphicThruMask(): This should never happen!\n");
657 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
661 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
668 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
670 src_pixmap = pix[PIX_BACK];
671 drawing_gc = clip_gc[PIX_BACK];
672 graphic -= GFX_START_ROCKSSCREEN;
673 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
674 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
676 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
678 src_pixmap = pix[PIX_HEROES];
679 drawing_gc = clip_gc[PIX_HEROES];
680 graphic -= GFX_START_ROCKSHEROES;
681 src_x = (graphic % HEROES_PER_LINE) * TILEX;
682 src_y = (graphic / HEROES_PER_LINE) * TILEY;
686 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
690 if (tile_clipmask[tile] != None)
692 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
693 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
694 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
695 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
700 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
703 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
704 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
705 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
709 void DrawMiniGraphic(int x, int y, int graphic)
711 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
712 MarkTileDirty(x/2, y/2);
715 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
717 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
719 graphic -= GFX_START_ROCKSSCREEN;
720 XCopyArea(display, pix[PIX_BACK], d, gc,
721 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
722 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
723 MINI_TILEX, MINI_TILEY, x, y);
725 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
727 graphic -= GFX_START_ROCKSFONT;
728 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
729 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
730 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
731 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
732 MINI_TILEX, MINI_TILEY, x, y);
735 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
738 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
739 int cut_mode, int mask_mode)
741 int width = TILEX, height = TILEY;
743 int src_x, src_y, dest_x, dest_y;
750 DrawGraphic(x, y, graphic);
754 if (dx || dy) /* Verschiebung der Grafik? */
756 if (x < BX1) /* Element kommt von links ins Bild */
763 else if (x > BX2) /* Element kommt von rechts ins Bild */
769 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
775 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
777 else if (dx) /* allg. Bewegung in x-Richtung */
778 MarkTileDirty(x + SIGN(dx), y);
780 if (y < BY1) /* Element kommt von oben ins Bild */
782 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
790 else if (y > BY2) /* Element kommt von unten ins Bild */
796 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
802 else if (dy > 0 && cut_mode == CUT_ABOVE)
804 if (y == BY2) /* Element unterhalb des Bildes */
810 MarkTileDirty(x, y + 1);
811 } /* Element verläßt unten das Bild */
812 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
814 else if (dy) /* allg. Bewegung in y-Richtung */
815 MarkTileDirty(x, y + SIGN(dy));
818 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
820 src_pixmap = pix[PIX_BACK];
821 drawing_gc = clip_gc[PIX_BACK];
822 graphic -= GFX_START_ROCKSSCREEN;
823 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
824 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
826 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
828 src_pixmap = pix[PIX_HEROES];
829 drawing_gc = clip_gc[PIX_HEROES];
830 graphic -= GFX_START_ROCKSHEROES;
831 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
832 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
834 else /* big font graphics currently not allowed (and not needed) */
837 dest_x = FX + x * TILEX + dx;
838 dest_y = FY + y * TILEY + dy;
841 if (!IN_SCR_FIELD(x,y))
843 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
844 printf("DrawGraphicShifted(): This should never happen!\n");
849 if (mask_mode == USE_MASKING)
851 if (tile_clipmask[tile] != None)
853 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
854 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
855 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
856 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
861 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
864 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
865 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
866 src_x, src_y, width, height, dest_x, dest_y);
870 XCopyArea(display, src_pixmap, drawto_field, gc,
871 src_x, src_y, width, height, dest_x, dest_y);
876 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
879 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
882 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
883 int cut_mode, int mask_mode)
885 int ux = LEVELX(x), uy = LEVELY(y);
886 int graphic = el2gfx(element);
887 int phase4 = ABS(MovPos[ux][uy]) / (TILEX / 4);
888 int phase = phase4 / 2;
889 int dir = MovDir[ux][uy];
891 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
897 else if (dir == MV_LEFT)
899 else if (dir == MV_DOWN)
902 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
903 element == EL_SCHWEIN || element == EL_DRACHE)
906 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
907 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
908 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
909 else if (dir == MV_RIGHT)
910 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
911 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
912 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
913 else if (dir == MV_UP)
914 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
915 element == EL_PINGUIN ? GFX_PINGUIN_UP :
916 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
918 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
919 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
920 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
924 else if (element == EL_SONDE)
926 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
928 else if (element == EL_SALZSAEURE)
930 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
932 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
936 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
938 graphic += phase * (element == EL_FELSBROCKEN ? 2 : 1);
940 else if ((element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
941 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL) && SiebAktiv)
943 graphic += 3 - (SiebAktiv % 8) / 2;
945 else if (IS_AMOEBOID(element))
947 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
948 graphic += (x + 2 * y + 4) % 4;
950 else if (element == EL_MAUER_LEBT)
952 boolean links_massiv = FALSE, rechts_massiv = FALSE;
954 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
956 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
957 rechts_massiv = TRUE;
959 if (links_massiv && rechts_massiv)
960 graphic = GFX_MAUERWERK;
961 else if (links_massiv)
962 graphic = GFX_MAUER_R;
963 else if (rechts_massiv)
964 graphic = GFX_MAUER_L;
968 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
969 else if (mask_mode == USE_MASKING)
970 DrawGraphicThruMask(x, y, graphic);
972 DrawGraphic(x, y, graphic);
975 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
976 int cut_mode, int mask_mode)
978 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
979 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
980 cut_mode, mask_mode);
983 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
986 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
989 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
992 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
995 void DrawScreenElementThruMask(int x, int y, int element)
997 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1000 void DrawLevelElementThruMask(int x, int y, int element)
1002 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1005 void DrawLevelFieldThruMask(int x, int y)
1007 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1010 void ErdreichAnbroeckeln(int x, int y)
1012 int i, width, height, cx,cy;
1013 int ux = LEVELX(x), uy = LEVELY(y);
1014 int element, graphic;
1016 static int xy[4][2] =
1024 if (!IN_LEV_FIELD(ux, uy))
1027 element = Feld[ux][uy];
1029 if (element == EL_ERDREICH)
1031 if (!IN_SCR_FIELD(x, y))
1034 graphic = GFX_ERDENRAND;
1040 uxx = ux + xy[i][0];
1041 uyy = uy + xy[i][1];
1042 if (!IN_LEV_FIELD(uxx, uyy))
1045 element = Feld[uxx][uyy];
1047 if (element == EL_ERDREICH)
1050 if (i == 1 || i == 2)
1054 cx = (i == 2 ? TILEX - snip : 0);
1062 cy = (i == 3 ? TILEY - snip : 0);
1065 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1066 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1067 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1068 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1071 MarkTileDirty(x, y);
1075 graphic = GFX_ERDENRAND;
1079 int xx, yy, uxx, uyy;
1083 uxx = ux + xy[i][0];
1084 uyy = uy + xy[i][1];
1086 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1087 !IN_SCR_FIELD(xx, yy))
1090 if (i == 1 || i == 2)
1094 cx = (i == 1 ? TILEX - snip : 0);
1102 cy = (i==0 ? TILEY-snip : 0);
1105 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1106 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1107 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1108 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1110 MarkTileDirty(xx, yy);
1115 void DrawScreenElement(int x, int y, int element)
1117 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1118 ErdreichAnbroeckeln(x, y);
1121 void DrawLevelElement(int x, int y, int element)
1123 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1124 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1127 void DrawScreenField(int x, int y)
1129 int ux = LEVELX(x), uy = LEVELY(y);
1132 if (!IN_LEV_FIELD(ux, uy))
1134 DrawScreenElement(x, y, EL_BETON);
1138 element = Feld[ux][uy];
1140 if (IS_MOVING(ux, uy))
1142 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1143 boolean cut_mode = NO_CUTTING;
1145 if (Store[ux][uy] == EL_MORAST_LEER ||
1146 Store[ux][uy] == EL_SIEB_LEER ||
1147 Store[ux][uy] == EL_SIEB2_LEER ||
1148 Store[ux][uy] == EL_AMOEBE_NASS)
1149 cut_mode = CUT_ABOVE;
1150 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1151 Store[ux][uy] == EL_SIEB_VOLL ||
1152 Store[ux][uy] == EL_SIEB2_VOLL)
1153 cut_mode = CUT_BELOW;
1155 if (cut_mode == CUT_ABOVE)
1156 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1158 DrawScreenElement(x, y, EL_LEERRAUM);
1161 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1163 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1165 if (Store[ux][uy] == EL_SALZSAEURE)
1166 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1168 else if (IS_BLOCKED(ux, uy))
1173 boolean cut_mode = NO_CUTTING;
1175 Blocked2Moving(ux, uy, &oldx, &oldy);
1178 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1179 MovDir[oldx][oldy] == MV_RIGHT);
1181 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1182 Store[oldx][oldy] == EL_SIEB_LEER ||
1183 Store[oldx][oldy] == EL_SIEB2_LEER ||
1184 Store[oldx][oldy] == EL_AMOEBE_NASS)
1185 cut_mode = CUT_ABOVE;
1187 DrawScreenElement(x, y, EL_LEERRAUM);
1188 element = Feld[oldx][oldy];
1191 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1193 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1195 else if (IS_DRAWABLE(element))
1196 DrawScreenElement(x, y, element);
1198 DrawScreenElement(x, y, EL_LEERRAUM);
1201 void DrawLevelField(int x, int y)
1203 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1204 DrawScreenField(SCREENX(x), SCREENY(y));
1205 else if (IS_MOVING(x, y))
1209 Moving2Blocked(x, y, &newx, &newy);
1210 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1211 DrawScreenField(SCREENX(newx), SCREENY(newy));
1213 else if (IS_BLOCKED(x, y))
1217 Blocked2Moving(x, y, &oldx, &oldy);
1218 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1219 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1223 void DrawMiniElement(int x, int y, int element)
1229 DrawMiniGraphic(x, y, -1);
1233 graphic = el2gfx(element);
1234 DrawMiniGraphic(x, y, graphic);
1237 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1239 int x = sx + scroll_x, y = sy + scroll_y;
1241 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1242 DrawMiniElement(sx, sy, EL_LEERRAUM);
1243 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1244 DrawMiniElement(sx, sy, EL_BETON);
1246 DrawMiniElement(sx, sy, Feld[x][y]);
1249 void DrawMicroElement(int xpos, int ypos, int element)
1253 if (element == EL_LEERRAUM)
1256 graphic = el2gfx(element);
1258 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1259 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1260 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1261 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1270 for(x=BX1; x<=BX2; x++)
1271 for(y=BY1; y<=BY2; y++)
1272 DrawScreenField(x, y);
1274 if (setup.soft_scrolling)
1275 XCopyArea(display, fieldbuffer, backbuffer, gc,
1276 FX, FY, SXSIZE, SYSIZE, SX, SY);
1278 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1281 void DrawMiniLevel(int scroll_x, int scroll_y)
1287 for(x=0; x<2*SCR_FIELDX; x++)
1288 for(y=0; y<2*SCR_FIELDY; y++)
1289 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1291 redraw_mask |= REDRAW_FIELD;
1294 void DrawMicroLevel(int xpos, int ypos)
1298 XFillRectangle(display, drawto, gc,
1299 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1300 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1301 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1302 if (lev_fieldx < STD_LEV_FIELDX)
1303 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1304 if (lev_fieldy < STD_LEV_FIELDY)
1305 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1307 for(x=-1; x<=STD_LEV_FIELDX; x++)
1308 for(y=-1; y<=STD_LEV_FIELDY; y++)
1309 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1310 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1312 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1313 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1316 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1320 int len = strlen(level.name);
1321 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1322 int lypos = MICROLABEL_YPOS;
1324 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1327 redraw_mask |= REDRAW_MICROLEV;
1330 int REQ_in_range(int x, int y)
1332 if (y > DY+249 && y < DY+278)
1334 if (x > DX+1 && x < DX+48)
1336 else if (x > DX+51 && x < DX+98)
1342 boolean Request(char *text, unsigned int req_state)
1344 int mx, my, ty, result = -1;
1345 unsigned int old_door_state;
1348 /* pause network game while waiting for request to answer */
1349 if (options.network &&
1350 game_status == PLAYING &&
1351 req_state & REQUEST_WAIT_FOR)
1352 SendToServer_PausePlaying();
1355 old_door_state = GetDoorState();
1357 CloseDoor(DOOR_CLOSE_1);
1359 /* Alten Türinhalt sichern */
1360 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1361 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1362 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1364 /* Fragetext schreiben */
1365 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1366 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1368 for(ty=0; ty<13; ty++)
1376 for(tl=0,tx=0; tx<7; tl++,tx++)
1379 if (!tc || tc == 32)
1390 DrawTextExt(pix[PIX_DB_DOOR], gc,
1391 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1392 txt, FS_SMALL, FC_YELLOW);
1393 text += tl + (tc == 32 ? 1 : 0);
1396 if (req_state & REQ_ASK)
1398 DrawYesNoButton(BUTTON_OK, DB_INIT);
1399 DrawYesNoButton(BUTTON_NO, DB_INIT);
1401 else if (req_state & REQ_CONFIRM)
1403 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1405 else if (req_state & REQ_PLAYER)
1407 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1408 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1409 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1410 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1413 OpenDoor(DOOR_OPEN_1);
1416 if (!(req_state & REQUEST_WAIT_FOR))
1419 if (game_status != MAINMENU)
1422 button_status = MB_RELEASED;
1426 if (XPending(display))
1430 XNextEvent(display, &event);
1440 if (event.type == MotionNotify)
1442 motion_status = TRUE;
1443 mx = ((XMotionEvent *) &event)->x;
1444 my = ((XMotionEvent *) &event)->y;
1448 motion_status = FALSE;
1449 mx = ((XButtonEvent *) &event)->x;
1450 my = ((XButtonEvent *) &event)->y;
1451 if (event.type==ButtonPress)
1452 button_status = ((XButtonEvent *) &event)->button;
1454 button_status = MB_RELEASED;
1457 if (req_state & REQ_ASK)
1458 choice = CheckYesNoButtons(mx,my,button_status);
1459 else if (req_state & REQ_CONFIRM)
1460 choice = CheckConfirmButton(mx,my,button_status);
1462 choice = CheckPlayerButtons(mx,my,button_status);
1472 case BUTTON_CONFIRM:
1473 result = TRUE | FALSE;
1476 case BUTTON_PLAYER_1:
1479 case BUTTON_PLAYER_2:
1482 case BUTTON_PLAYER_3:
1485 case BUTTON_PLAYER_4:
1496 switch(XLookupKeysym((XKeyEvent *)&event,
1497 ((XKeyEvent *)&event)->state))
1510 if (req_state & REQ_PLAYER)
1515 key_joystick_mapping = 0;
1519 HandleOtherEvents(&event);
1523 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1525 int joy = AnyJoystick();
1527 if (joy & JOY_BUTTON_1)
1529 else if (joy & JOY_BUTTON_2)
1535 /* don't eat all CPU time */
1539 if (game_status != MAINMENU)
1542 if (!(req_state & REQ_STAY_OPEN))
1544 CloseDoor(DOOR_CLOSE_1);
1546 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1548 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1549 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1550 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1551 OpenDoor(DOOR_OPEN_1);
1556 /* continue network game after request */
1557 if (options.network &&
1558 game_status == PLAYING &&
1559 req_state & REQUEST_WAIT_FOR)
1560 SendToServer_ContinuePlaying();
1566 unsigned int OpenDoor(unsigned int door_state)
1568 unsigned int new_door_state;
1570 if (door_state & DOOR_COPY_BACK)
1572 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1573 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1574 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1575 door_state &= ~DOOR_COPY_BACK;
1578 new_door_state = MoveDoor(door_state);
1580 return(new_door_state);
1583 unsigned int CloseDoor(unsigned int door_state)
1585 unsigned int new_door_state;
1587 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1588 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1589 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1590 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1592 new_door_state = MoveDoor(door_state);
1594 return(new_door_state);
1597 unsigned int GetDoorState()
1599 return(MoveDoor(DOOR_GET_STATE));
1602 unsigned int MoveDoor(unsigned int door_state)
1604 static int door1 = DOOR_OPEN_1;
1605 static int door2 = DOOR_CLOSE_2;
1606 static unsigned long door_delay = 0;
1607 int x, start, stepsize = 2;
1608 unsigned long door_delay_value = stepsize * 5;
1610 if (door_state == DOOR_GET_STATE)
1611 return(door1 | door2);
1613 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1614 door_state &= ~DOOR_OPEN_1;
1615 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1616 door_state &= ~DOOR_CLOSE_1;
1617 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1618 door_state &= ~DOOR_OPEN_2;
1619 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1620 door_state &= ~DOOR_CLOSE_2;
1622 if (setup.quick_doors)
1625 door_delay_value = 0;
1626 StopSound(SND_OEFFNEN);
1629 if (door_state & DOOR_ACTION)
1631 if (!(door_state & DOOR_NO_DELAY))
1632 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1634 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1636 for(x=start; x<=DXSIZE; x+=stepsize)
1638 WaitUntilDelayReached(&door_delay, door_delay_value);
1640 if (door_state & DOOR_ACTION_1)
1642 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1643 int j = (DXSIZE - i) / 3;
1645 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1646 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1647 DXSIZE,DYSIZE - i/2, DX, DY);
1649 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1651 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1652 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1653 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1654 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1655 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1656 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1658 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1659 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1660 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1661 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1662 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1663 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1665 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1666 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1668 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1669 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1671 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1672 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1673 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1674 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1675 DX + DXSIZE - i, DY + 77 + j);
1676 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1677 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1678 DX + DXSIZE - i, DY + 203 + j);
1680 redraw_mask |= REDRAW_DOOR_1;
1683 if (door_state & DOOR_ACTION_2)
1685 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1686 int j = (VXSIZE - i) / 3;
1688 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1689 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1690 VXSIZE, VYSIZE - i/2, VX, VY);
1692 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1694 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1695 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1696 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1697 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1698 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1699 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1700 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1701 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1703 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1704 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1705 VX, VY + VYSIZE / 2 - j);
1706 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1707 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1708 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1709 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1710 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1712 redraw_mask |= REDRAW_DOOR_2;
1717 if (game_status == MAINMENU)
1722 if (setup.quick_doors)
1723 StopSound(SND_OEFFNEN);
1725 if (door_state & DOOR_ACTION_1)
1726 door1 = door_state & DOOR_ACTION_1;
1727 if (door_state & DOOR_ACTION_2)
1728 door2 = door_state & DOOR_ACTION_2;
1730 return(door1 | door2);
1733 int ReadPixel(Drawable d, int x, int y)
1735 static XImage *pixelimage;
1737 pixelimage = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1738 return(XGetPixel(pixelimage, 0, 0));
1741 int el2gfx(int element)
1745 case EL_LEERRAUM: return -1;
1746 case EL_ERDREICH: return GFX_ERDREICH;
1747 case EL_MAUERWERK: return GFX_MAUERWERK;
1748 case EL_FELSBODEN: return GFX_FELSBODEN;
1749 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1750 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1751 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1752 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1753 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1754 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1755 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1756 case EL_SPIELER1: return GFX_SPIELER1;
1757 case EL_SPIELER2: return GFX_SPIELER2;
1758 case EL_SPIELER3: return GFX_SPIELER3;
1759 case EL_SPIELER4: return GFX_SPIELER4;
1760 case EL_KAEFER: return GFX_KAEFER;
1761 case EL_KAEFER_R: return GFX_KAEFER_R;
1762 case EL_KAEFER_O: return GFX_KAEFER_O;
1763 case EL_KAEFER_L: return GFX_KAEFER_L;
1764 case EL_KAEFER_U: return GFX_KAEFER_U;
1765 case EL_FLIEGER: return GFX_FLIEGER;
1766 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1767 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1768 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1769 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1770 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1771 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1772 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1773 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1774 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1775 case EL_FIREFLY: return GFX_FIREFLY;
1776 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1777 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1778 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1779 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1780 case EL_MAMPFER: return GFX_MAMPFER;
1781 case EL_ROBOT: return GFX_ROBOT;
1782 case EL_BETON: return GFX_BETON;
1783 case EL_DIAMANT: return GFX_DIAMANT;
1784 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1785 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1786 case EL_TROPFEN: return GFX_TROPFEN;
1787 case EL_BOMBE: return GFX_BOMBE;
1788 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1789 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1790 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1791 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1792 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1793 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1794 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1795 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1796 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1797 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1798 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1799 case EL_LIFE: return GFX_LIFE;
1800 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1801 case EL_DYNAMIT: return GFX_DYNAMIT;
1802 case EL_BADEWANNE: return GFX_BADEWANNE;
1803 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1804 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1805 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1806 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1807 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1808 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1809 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1810 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1811 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1812 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1813 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1814 case EL_PFORTE1: return GFX_PFORTE1;
1815 case EL_PFORTE2: return GFX_PFORTE2;
1816 case EL_PFORTE3: return GFX_PFORTE3;
1817 case EL_PFORTE4: return GFX_PFORTE4;
1818 case EL_PFORTE1X: return GFX_PFORTE1X;
1819 case EL_PFORTE2X: return GFX_PFORTE2X;
1820 case EL_PFORTE3X: return GFX_PFORTE3X;
1821 case EL_PFORTE4X: return GFX_PFORTE4X;
1822 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1823 case EL_PACMAN: return GFX_PACMAN;
1824 case EL_PACMAN_R: return GFX_PACMAN_R;
1825 case EL_PACMAN_O: return GFX_PACMAN_O;
1826 case EL_PACMAN_L: return GFX_PACMAN_L;
1827 case EL_PACMAN_U: return GFX_PACMAN_U;
1828 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1829 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1830 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1831 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1832 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1833 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1834 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1835 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1836 case EL_MAUER_X: return GFX_MAUER_X;
1837 case EL_MAUER_Y: return GFX_MAUER_Y;
1838 case EL_MAUER_XY: return GFX_MAUER_XY;
1839 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1840 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1841 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1842 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1843 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1844 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1845 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1846 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1847 case EL_MAMPFER2: return GFX_MAMPFER2;
1848 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1849 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1850 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1851 case EL_DYNABOMB: return GFX_DYNABOMB;
1852 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1853 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1854 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1855 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1856 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1857 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1858 case EL_MAULWURF: return GFX_MAULWURF;
1859 case EL_PINGUIN: return GFX_PINGUIN;
1860 case EL_SCHWEIN: return GFX_SCHWEIN;
1861 case EL_DRACHE: return GFX_DRACHE;
1862 case EL_SONDE: return GFX_SONDE;
1863 case EL_PFEIL_L: return GFX_PFEIL_L;
1864 case EL_PFEIL_R: return GFX_PFEIL_R;
1865 case EL_PFEIL_O: return GFX_PFEIL_O;
1866 case EL_PFEIL_U: return GFX_PFEIL_U;
1869 if (IS_CHAR(element))
1870 return GFX_CHAR_START + (element - EL_CHAR_START);