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;
835 dest_x = FX + x * TILEX + dx;
836 dest_y = FY + y * TILEY + dy;
839 if (!IN_SCR_FIELD(x,y))
841 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
842 printf("DrawGraphicShifted(): This should never happen!\n");
847 if (mask_mode == USE_MASKING)
849 if (tile_clipmask[tile] != None)
851 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
852 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
853 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
854 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
859 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
862 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
863 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
864 src_x, src_y, width, height, dest_x, dest_y);
868 XCopyArea(display, src_pixmap, drawto_field, gc,
869 src_x, src_y, width, height, dest_x, dest_y);
874 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
877 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
880 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
881 int cut_mode, int mask_mode)
883 int ux = LEVELX(x), uy = LEVELY(y);
884 int graphic = el2gfx(element);
885 int phase4 = ABS(MovPos[ux][uy]) / (TILEX / 4);
886 int phase = phase4 / 2;
887 int dir = MovDir[ux][uy];
889 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
895 else if (dir == MV_LEFT)
897 else if (dir == MV_DOWN)
900 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
901 element == EL_SCHWEIN || element == EL_DRACHE)
904 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
905 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
906 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
907 else if (dir == MV_RIGHT)
908 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
909 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
910 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
911 else if (dir == MV_UP)
912 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
913 element == EL_PINGUIN ? GFX_PINGUIN_UP :
914 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
916 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
917 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
918 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
922 else if (element == EL_SONDE)
924 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
926 else if (element == EL_SALZSAEURE)
928 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
930 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
934 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
936 graphic += phase * (element == EL_FELSBROCKEN ? 2 : 1);
938 else if ((element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
939 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL) && SiebAktiv)
941 graphic += 3 - (SiebAktiv % 8) / 2;
943 else if (IS_AMOEBOID(element))
945 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
946 graphic += (x + 2 * y + 4) % 4;
948 else if (element == EL_MAUER_LEBT)
950 boolean links_massiv = FALSE, rechts_massiv = FALSE;
952 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
954 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
955 rechts_massiv = TRUE;
957 if (links_massiv && rechts_massiv)
958 graphic = GFX_MAUERWERK;
959 else if (links_massiv)
960 graphic = GFX_MAUER_R;
961 else if (rechts_massiv)
962 graphic = GFX_MAUER_L;
966 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
967 else if (mask_mode == USE_MASKING)
968 DrawGraphicThruMask(x, y, graphic);
970 DrawGraphic(x, y, graphic);
973 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
974 int cut_mode, int mask_mode)
976 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
977 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
978 cut_mode, mask_mode);
981 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
984 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
987 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
990 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
993 void DrawScreenElementThruMask(int x, int y, int element)
995 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
998 void DrawLevelElementThruMask(int x, int y, int element)
1000 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1003 void DrawLevelFieldThruMask(int x, int y)
1005 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1008 void ErdreichAnbroeckeln(int x, int y)
1010 int i, width, height, cx,cy;
1011 int ux = LEVELX(x), uy = LEVELY(y);
1012 int element, graphic;
1014 static int xy[4][2] =
1022 if (!IN_LEV_FIELD(ux, uy))
1025 element = Feld[ux][uy];
1027 if (element == EL_ERDREICH)
1029 if (!IN_SCR_FIELD(x, y))
1032 graphic = GFX_ERDENRAND;
1038 uxx = ux + xy[i][0];
1039 uyy = uy + xy[i][1];
1040 if (!IN_LEV_FIELD(uxx, uyy))
1043 element = Feld[uxx][uyy];
1045 if (element == EL_ERDREICH)
1048 if (i == 1 || i == 2)
1052 cx = (i == 2 ? TILEX - snip : 0);
1060 cy = (i == 3 ? TILEY - snip : 0);
1063 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1064 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1065 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1066 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1069 MarkTileDirty(x, y);
1073 graphic = GFX_ERDENRAND;
1077 int xx, yy, uxx, uyy;
1081 uxx = ux + xy[i][0];
1082 uyy = uy + xy[i][1];
1084 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1085 !IN_SCR_FIELD(xx, yy))
1088 if (i == 1 || i == 2)
1092 cx = (i == 1 ? TILEX - snip : 0);
1100 cy = (i==0 ? TILEY-snip : 0);
1103 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1104 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1105 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1106 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1108 MarkTileDirty(xx, yy);
1113 void DrawScreenElement(int x, int y, int element)
1115 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1116 ErdreichAnbroeckeln(x, y);
1119 void DrawLevelElement(int x, int y, int element)
1121 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1122 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1125 void DrawScreenField(int x, int y)
1127 int ux = LEVELX(x), uy = LEVELY(y);
1130 if (!IN_LEV_FIELD(ux, uy))
1132 DrawScreenElement(x, y, EL_BETON);
1136 element = Feld[ux][uy];
1138 if (IS_MOVING(ux, uy))
1140 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1141 boolean cut_mode = NO_CUTTING;
1143 if (Store[ux][uy] == EL_MORAST_LEER ||
1144 Store[ux][uy] == EL_SIEB_LEER ||
1145 Store[ux][uy] == EL_SIEB2_LEER ||
1146 Store[ux][uy] == EL_AMOEBE_NASS)
1147 cut_mode = CUT_ABOVE;
1148 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1149 Store[ux][uy] == EL_SIEB_VOLL ||
1150 Store[ux][uy] == EL_SIEB2_VOLL)
1151 cut_mode = CUT_BELOW;
1153 if (cut_mode == CUT_ABOVE)
1154 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1156 DrawScreenElement(x, y, EL_LEERRAUM);
1159 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1161 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1163 if (Store[ux][uy] == EL_SALZSAEURE)
1164 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1166 else if (IS_BLOCKED(ux, uy))
1171 boolean cut_mode = NO_CUTTING;
1173 Blocked2Moving(ux, uy, &oldx, &oldy);
1176 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1177 MovDir[oldx][oldy] == MV_RIGHT);
1179 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1180 Store[oldx][oldy] == EL_SIEB_LEER ||
1181 Store[oldx][oldy] == EL_SIEB2_LEER ||
1182 Store[oldx][oldy] == EL_AMOEBE_NASS)
1183 cut_mode = CUT_ABOVE;
1185 DrawScreenElement(x, y, EL_LEERRAUM);
1186 element = Feld[oldx][oldy];
1189 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1191 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1193 else if (IS_DRAWABLE(element))
1194 DrawScreenElement(x, y, element);
1196 DrawScreenElement(x, y, EL_LEERRAUM);
1199 void DrawLevelField(int x, int y)
1201 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1202 DrawScreenField(SCREENX(x), SCREENY(y));
1203 else if (IS_MOVING(x, y))
1207 Moving2Blocked(x, y, &newx, &newy);
1208 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1209 DrawScreenField(SCREENX(newx), SCREENY(newy));
1211 else if (IS_BLOCKED(x, y))
1215 Blocked2Moving(x, y, &oldx, &oldy);
1216 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1217 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1221 void DrawMiniElement(int x, int y, int element)
1227 DrawMiniGraphic(x, y, -1);
1231 graphic = el2gfx(element);
1232 DrawMiniGraphic(x, y, graphic);
1235 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1237 int x = sx + scroll_x, y = sy + scroll_y;
1239 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1240 DrawMiniElement(sx, sy, EL_LEERRAUM);
1241 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1242 DrawMiniElement(sx, sy, EL_BETON);
1244 DrawMiniElement(sx, sy, Feld[x][y]);
1247 void DrawMicroElement(int xpos, int ypos, int element)
1251 if (element == EL_LEERRAUM)
1254 graphic = el2gfx(element);
1256 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1257 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1258 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1259 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1268 for(x=BX1; x<=BX2; x++)
1269 for(y=BY1; y<=BY2; y++)
1270 DrawScreenField(x, y);
1272 if (setup.soft_scrolling)
1273 XCopyArea(display, fieldbuffer, backbuffer, gc,
1274 FX, FY, SXSIZE, SYSIZE, SX, SY);
1276 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1279 void DrawMiniLevel(int scroll_x, int scroll_y)
1285 for(x=0; x<2*SCR_FIELDX; x++)
1286 for(y=0; y<2*SCR_FIELDY; y++)
1287 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1289 redraw_mask |= REDRAW_FIELD;
1292 void DrawMicroLevel(int xpos, int ypos)
1296 XFillRectangle(display, drawto, gc,
1297 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1298 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1299 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1300 if (lev_fieldx < STD_LEV_FIELDX)
1301 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1302 if (lev_fieldy < STD_LEV_FIELDY)
1303 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1305 for(x=-1; x<=STD_LEV_FIELDX; x++)
1306 for(y=-1; y<=STD_LEV_FIELDY; y++)
1307 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1308 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1310 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1311 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1314 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1318 int len = strlen(level.name);
1319 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1320 int lypos = MICROLABEL_YPOS;
1322 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1325 redraw_mask |= REDRAW_MICROLEV;
1328 int REQ_in_range(int x, int y)
1330 if (y > DY+249 && y < DY+278)
1332 if (x > DX+1 && x < DX+48)
1334 else if (x > DX+51 && x < DX+98)
1340 boolean Request(char *text, unsigned int req_state)
1342 int mx, my, ty, result = -1;
1343 unsigned int old_door_state;
1346 /* pause network game while waiting for request to answer */
1347 if (options.network &&
1348 game_status == PLAYING &&
1349 req_state & REQUEST_WAIT_FOR)
1350 SendToServer_PausePlaying();
1353 old_door_state = GetDoorState();
1355 CloseDoor(DOOR_CLOSE_1);
1357 /* Alten Türinhalt sichern */
1358 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1359 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1360 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1362 /* Fragetext schreiben */
1363 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1364 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1366 for(ty=0; ty<13; ty++)
1374 for(tl=0,tx=0; tx<7; tl++,tx++)
1377 if (!tc || tc == 32)
1388 DrawTextExt(pix[PIX_DB_DOOR], gc,
1389 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1390 txt, FS_SMALL, FC_YELLOW);
1391 text += tl + (tc == 32 ? 1 : 0);
1394 if (req_state & REQ_ASK)
1396 DrawYesNoButton(BUTTON_OK, DB_INIT);
1397 DrawYesNoButton(BUTTON_NO, DB_INIT);
1399 else if (req_state & REQ_CONFIRM)
1401 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1403 else if (req_state & REQ_PLAYER)
1405 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1406 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1407 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1408 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1411 OpenDoor(DOOR_OPEN_1);
1414 if (!(req_state & REQUEST_WAIT_FOR))
1417 if (game_status != MAINMENU)
1420 button_status = MB_RELEASED;
1424 if (XPending(display))
1428 XNextEvent(display, &event);
1438 if (event.type == MotionNotify)
1440 motion_status = TRUE;
1441 mx = ((XMotionEvent *) &event)->x;
1442 my = ((XMotionEvent *) &event)->y;
1446 motion_status = FALSE;
1447 mx = ((XButtonEvent *) &event)->x;
1448 my = ((XButtonEvent *) &event)->y;
1449 if (event.type==ButtonPress)
1450 button_status = ((XButtonEvent *) &event)->button;
1452 button_status = MB_RELEASED;
1455 if (req_state & REQ_ASK)
1456 choice = CheckYesNoButtons(mx,my,button_status);
1457 else if (req_state & REQ_CONFIRM)
1458 choice = CheckConfirmButton(mx,my,button_status);
1460 choice = CheckPlayerButtons(mx,my,button_status);
1470 case BUTTON_CONFIRM:
1471 result = TRUE | FALSE;
1474 case BUTTON_PLAYER_1:
1477 case BUTTON_PLAYER_2:
1480 case BUTTON_PLAYER_3:
1483 case BUTTON_PLAYER_4:
1494 switch(XLookupKeysym((XKeyEvent *)&event,
1495 ((XKeyEvent *)&event)->state))
1508 if (req_state & REQ_PLAYER)
1513 key_joystick_mapping = 0;
1517 HandleOtherEvents(&event);
1521 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1523 int joy = AnyJoystick();
1525 if (joy & JOY_BUTTON_1)
1527 else if (joy & JOY_BUTTON_2)
1533 /* don't eat all CPU time */
1537 if (game_status != MAINMENU)
1540 if (!(req_state & REQ_STAY_OPEN))
1542 CloseDoor(DOOR_CLOSE_1);
1544 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1546 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1547 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1548 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1549 OpenDoor(DOOR_OPEN_1);
1554 /* continue network game after request */
1555 if (options.network &&
1556 game_status == PLAYING &&
1557 req_state & REQUEST_WAIT_FOR)
1558 SendToServer_ContinuePlaying();
1564 unsigned int OpenDoor(unsigned int door_state)
1566 unsigned int new_door_state;
1568 if (door_state & DOOR_COPY_BACK)
1570 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1571 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1572 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1573 door_state &= ~DOOR_COPY_BACK;
1576 new_door_state = MoveDoor(door_state);
1578 return(new_door_state);
1581 unsigned int CloseDoor(unsigned int door_state)
1583 unsigned int new_door_state;
1585 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1586 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1587 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1588 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1590 new_door_state = MoveDoor(door_state);
1592 return(new_door_state);
1595 unsigned int GetDoorState()
1597 return(MoveDoor(DOOR_GET_STATE));
1600 unsigned int MoveDoor(unsigned int door_state)
1602 static unsigned int door1 = DOOR_OPEN_1;
1603 static unsigned int door2 = DOOR_CLOSE_2;
1604 static long door_delay = 0;
1605 int x, start, stepsize = 2;
1606 long door_delay_value = stepsize * 5;
1608 if (door_state == DOOR_GET_STATE)
1609 return(door1 | door2);
1611 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1612 door_state &= ~DOOR_OPEN_1;
1613 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1614 door_state &= ~DOOR_CLOSE_1;
1615 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1616 door_state &= ~DOOR_OPEN_2;
1617 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1618 door_state &= ~DOOR_CLOSE_2;
1620 if (setup.quick_doors)
1623 door_delay_value = 0;
1624 StopSound(SND_OEFFNEN);
1627 if (door_state & DOOR_ACTION)
1629 if (!(door_state & DOOR_NO_DELAY))
1630 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1632 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1634 for(x=start; x<=DXSIZE; x+=stepsize)
1636 WaitUntilDelayReached(&door_delay, door_delay_value);
1638 if (door_state & DOOR_ACTION_1)
1640 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1641 int j = (DXSIZE - i) / 3;
1643 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1644 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1645 DXSIZE,DYSIZE - i/2, DX, DY);
1647 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1649 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1650 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1651 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1652 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1653 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1654 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1656 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1657 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1658 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1659 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1660 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1661 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1663 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1664 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1666 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1667 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1669 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1670 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1671 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1672 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1673 DX + DXSIZE - i, DY + 77 + j);
1674 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1675 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1676 DX + DXSIZE - i, DY + 203 + j);
1678 redraw_mask |= REDRAW_DOOR_1;
1681 if (door_state & DOOR_ACTION_2)
1683 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1684 int j = (VXSIZE - i) / 3;
1686 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1687 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1688 VXSIZE, VYSIZE - i/2, VX, VY);
1690 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1692 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1693 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1694 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1695 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1696 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1697 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1698 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1699 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1701 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1702 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1703 VX, VY + VYSIZE / 2 - j);
1704 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1705 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1706 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1707 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1708 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1710 redraw_mask |= REDRAW_DOOR_2;
1715 if (game_status == MAINMENU)
1720 if (setup.quick_doors)
1721 StopSound(SND_OEFFNEN);
1723 if (door_state & DOOR_ACTION_1)
1724 door1 = door_state & DOOR_ACTION_1;
1725 if (door_state & DOOR_ACTION_2)
1726 door2 = door_state & DOOR_ACTION_2;
1728 return(door1 | door2);
1731 int ReadPixel(Drawable d, int x, int y)
1733 static XImage *pixelimage;
1735 pixelimage = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1736 return(XGetPixel(pixelimage, 0, 0));
1739 int el2gfx(int element)
1743 case EL_LEERRAUM: return -1;
1744 case EL_ERDREICH: return GFX_ERDREICH;
1745 case EL_MAUERWERK: return GFX_MAUERWERK;
1746 case EL_FELSBODEN: return GFX_FELSBODEN;
1747 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1748 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1749 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1750 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1751 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1752 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1753 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1754 case EL_SPIELER1: return GFX_SPIELER1;
1755 case EL_SPIELER2: return GFX_SPIELER2;
1756 case EL_SPIELER3: return GFX_SPIELER3;
1757 case EL_SPIELER4: return GFX_SPIELER4;
1758 case EL_KAEFER: return GFX_KAEFER;
1759 case EL_KAEFER_R: return GFX_KAEFER_R;
1760 case EL_KAEFER_O: return GFX_KAEFER_O;
1761 case EL_KAEFER_L: return GFX_KAEFER_L;
1762 case EL_KAEFER_U: return GFX_KAEFER_U;
1763 case EL_FLIEGER: return GFX_FLIEGER;
1764 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1765 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1766 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1767 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1768 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1769 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1770 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1771 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1772 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1773 case EL_FIREFLY: return GFX_FIREFLY;
1774 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1775 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1776 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1777 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1778 case EL_MAMPFER: return GFX_MAMPFER;
1779 case EL_ROBOT: return GFX_ROBOT;
1780 case EL_BETON: return GFX_BETON;
1781 case EL_DIAMANT: return GFX_DIAMANT;
1782 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1783 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1784 case EL_TROPFEN: return GFX_TROPFEN;
1785 case EL_BOMBE: return GFX_BOMBE;
1786 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1787 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1788 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1789 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1790 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1791 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1792 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1793 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1794 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1795 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1796 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1797 case EL_LIFE: return GFX_LIFE;
1798 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1799 case EL_DYNAMIT: return GFX_DYNAMIT;
1800 case EL_BADEWANNE: return GFX_BADEWANNE;
1801 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1802 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1803 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1804 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1805 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1806 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1807 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1808 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1809 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1810 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1811 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1812 case EL_PFORTE1: return GFX_PFORTE1;
1813 case EL_PFORTE2: return GFX_PFORTE2;
1814 case EL_PFORTE3: return GFX_PFORTE3;
1815 case EL_PFORTE4: return GFX_PFORTE4;
1816 case EL_PFORTE1X: return GFX_PFORTE1X;
1817 case EL_PFORTE2X: return GFX_PFORTE2X;
1818 case EL_PFORTE3X: return GFX_PFORTE3X;
1819 case EL_PFORTE4X: return GFX_PFORTE4X;
1820 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1821 case EL_PACMAN: return GFX_PACMAN;
1822 case EL_PACMAN_R: return GFX_PACMAN_R;
1823 case EL_PACMAN_O: return GFX_PACMAN_O;
1824 case EL_PACMAN_L: return GFX_PACMAN_L;
1825 case EL_PACMAN_U: return GFX_PACMAN_U;
1826 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1827 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1828 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1829 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1830 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1831 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1832 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1833 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1834 case EL_MAUER_X: return GFX_MAUER_X;
1835 case EL_MAUER_Y: return GFX_MAUER_Y;
1836 case EL_MAUER_XY: return GFX_MAUER_XY;
1837 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1838 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1839 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1840 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1841 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1842 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1843 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1844 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1845 case EL_MAMPFER2: return GFX_MAMPFER2;
1846 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1847 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1848 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1849 case EL_DYNABOMB: return GFX_DYNABOMB;
1850 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1851 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1852 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1853 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1854 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1855 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1856 case EL_MAULWURF: return GFX_MAULWURF;
1857 case EL_PINGUIN: return GFX_PINGUIN;
1858 case EL_SCHWEIN: return GFX_SCHWEIN;
1859 case EL_DRACHE: return GFX_DRACHE;
1860 case EL_SONDE: return GFX_SONDE;
1861 case EL_PFEIL_L: return GFX_PFEIL_L;
1862 case EL_PFEIL_R: return GFX_PFEIL_R;
1863 case EL_PFEIL_O: return GFX_PFEIL_O;
1864 case EL_PFEIL_U: return GFX_PFEIL_U;
1867 if (IS_CHAR(element))
1868 return GFX_CHAR_START + (element - EL_CHAR_START);