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 XCopyArea(display,buffer,window,gc,
125 fx,fy, SXSIZE,SYSIZE,
128 redraw_mask &= ~REDRAW_MAIN;
131 if (redraw_mask & REDRAW_DOORS)
133 if (redraw_mask & REDRAW_DOOR_1)
134 XCopyArea(display,backbuffer,window,gc,
135 DX,DY, DXSIZE,DYSIZE,
137 if (redraw_mask & REDRAW_DOOR_2)
139 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
140 XCopyArea(display,backbuffer,window,gc,
141 VX,VY, VXSIZE,VYSIZE,
145 if (redraw_mask & REDRAW_VIDEO_1)
146 XCopyArea(display,backbuffer,window,gc,
147 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
148 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
149 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
150 if (redraw_mask & REDRAW_VIDEO_2)
151 XCopyArea(display,backbuffer,window,gc,
152 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
153 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
154 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
155 if (redraw_mask & REDRAW_VIDEO_3)
156 XCopyArea(display,backbuffer,window,gc,
157 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
158 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
159 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
162 redraw_mask &= ~REDRAW_DOORS;
165 if (redraw_mask & REDRAW_MICROLEV)
167 XCopyArea(display,backbuffer,window,gc,
168 MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
169 MICROLEV_XPOS,MICROLEV_YPOS);
170 XCopyArea(display,backbuffer,window,gc,
171 SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
173 redraw_mask &= ~REDRAW_MICROLEV;
176 if (redraw_mask & REDRAW_TILES)
178 for(x=0; x<SCR_FIELDX; x++)
179 for(y=0; y<SCR_FIELDY; y++)
180 if (redraw[redraw_x1 + x][redraw_y1 + y])
181 XCopyArea(display,buffer,window,gc,
182 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
183 SX+x*TILEX,SY+y*TILEY);
188 for(x=0; x<MAX_BUF_XSIZE; x++)
189 for(y=0; y<MAX_BUF_YSIZE; y++)
198 long fading_delay = 300;
200 if (setup.fading && (redraw_mask & REDRAW_FIELD))
207 XFillRectangle(display,window,gc,
208 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
211 for(i=0;i<2*FULL_SYSIZE;i++)
213 for(y=0;y<FULL_SYSIZE;y++)
215 XCopyArea(display,backbuffer,window,gc,
216 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
224 for(i=1;i<FULL_SYSIZE;i+=2)
225 XCopyArea(display,backbuffer,window,gc,
226 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
232 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
233 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
234 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
238 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
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],0,-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],-1,0);
251 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
252 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
256 redraw_mask &= ~REDRAW_MAIN;
265 XFillRectangle(display, backbuffer, gc,
266 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
268 if (setup.soft_scrolling && game_status == PLAYING)
270 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
271 SetDrawtoField(DRAW_BUFFERED);
274 SetDrawtoField(DRAW_BACKBUFFER);
276 if (setup.direct_draw && game_status == PLAYING)
278 XFillRectangle(display, window, gc,
279 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
280 SetDrawtoField(DRAW_DIRECT);
283 redraw_mask |= REDRAW_FIELD;
286 void DrawTextFCentered(int y, int font_type, char *format, ...)
288 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
292 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
293 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
295 va_start(ap, format);
296 vsprintf(buffer, format, ap);
299 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
300 buffer, FS_SMALL, font_type);
303 void DrawTextF(int x, int y, int font_type, char *format, ...)
305 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
308 va_start(ap, format);
309 vsprintf(buffer, format, ap);
312 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
315 void DrawText(int x, int y, char *text, int font_size, int font_type)
317 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
320 redraw_mask |= REDRAW_FIELD;
322 redraw_mask |= REDRAW_DOOR_1;
325 void DrawTextExt(Drawable d, GC gc, int x, int y,
326 char *text, int font_size, int font_type)
328 int font_width, font_height, font_start;
331 if (font_size != FS_SMALL && font_size != FS_BIG)
332 font_size = FS_SMALL;
333 if (font_type < FC_RED || font_type > FC_SPECIAL2)
336 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
337 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
338 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
339 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
340 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
341 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
342 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
343 FONT_LINES_PER_FONT);
349 if (c >= 'a' && c <= 'z')
351 else if (c == 'ä' || c == 'Ä')
353 else if (c == 'ö' || c == 'Ö')
355 else if (c == 'ü' || c == 'Ü')
358 if (c >= 32 && c <= 95)
359 XCopyArea(display, pix[font_pixmap], d, gc,
360 ((c - 32) % FONT_CHARS_PER_LINE) * font_width,
361 ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start,
362 font_width, font_height, x, y);
368 void DrawAllPlayers()
372 for(i=0; i<MAX_PLAYERS; i++)
373 if (stored_player[i].active)
374 DrawPlayer(&stored_player[i]);
377 void DrawPlayerField(int x, int y)
382 DrawPlayer(PLAYERINFO(x,y));
385 void DrawPlayer(struct PlayerInfo *player)
387 int jx = player->jx, jy = player->jy;
388 int last_jx = player->last_jx, last_jy = player->last_jy;
389 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
390 int sx = SCREENX(jx), sy = SCREENY(jy);
391 int sxx = 0, syy = 0;
392 int element = Feld[jx][jy];
395 if (!player->active || player->gone ||
396 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
400 if (!IN_LEV_FIELD(jx,jy))
402 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
403 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
404 printf("DrawPlayerField(): This should never happen!\n");
409 if (element == EL_EXPLODING)
412 /* draw things in the field the player is leaving, if needed */
414 if (last_jx != jx || last_jy != jy)
416 if (Store[last_jx][last_jy])
418 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
419 DrawLevelFieldThruMask(last_jx, last_jy);
421 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
422 DrawDynamite(last_jx, last_jy);
424 DrawLevelField(last_jx, last_jy);
426 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
430 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
431 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
433 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
436 DrawLevelField(next_jx, next_jy);
440 if (!IN_SCR_FIELD(sx, sy))
443 if (setup.direct_draw)
444 SetDrawtoField(DRAW_BUFFERED);
446 /* draw things behind the player, if needed */
449 DrawLevelElement(jx, jy, Store[jx][jy]);
450 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
451 DrawLevelField(jx, jy);
453 /* draw player himself */
455 if (player->MovDir == MV_LEFT)
456 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
457 else if (player->MovDir == MV_RIGHT)
458 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
459 else if (player->MovDir == MV_UP)
460 graphic = GFX_SPIELER1_UP;
461 else /* MV_DOWN || MV_NO_MOVING */
462 graphic = GFX_SPIELER1_DOWN;
464 graphic += player->index_nr * 3*HEROES_PER_LINE;
465 graphic += player->Frame;
469 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
470 sxx = player->GfxPos;
472 syy = player->GfxPos;
475 if (!setup.soft_scrolling && ScreenMovPos)
478 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
480 if (player->Pushing && player->GfxPos)
482 int px = SCREENX(next_jx), py = SCREENY(next_jy);
484 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
485 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
486 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
490 int element = Feld[next_jx][next_jy];
491 int graphic = el2gfx(element);
493 if (element == EL_FELSBROCKEN && sxx)
495 int phase = (player->GfxPos / (TILEX/4));
497 if (player->MovDir == MV_LEFT)
500 graphic += (phase+4)%4;
503 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
507 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
509 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
511 graphic = el2gfx(element);
513 if (element == EL_DYNAMIT)
515 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
520 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
524 DrawGraphicThruMask(sx, sy, graphic + phase);
527 if ((last_jx != jx || last_jy != jy) &&
528 Feld[last_jx][last_jy] == EL_EXPLODING)
530 int phase = Frame[last_jx][last_jy];
534 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
535 GFX_EXPLOSION + ((phase - 1) / delay - 1));
538 if (setup.direct_draw)
540 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
541 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
542 int x_size = TILEX * (1 + ABS(jx - last_jx));
543 int y_size = TILEY * (1 + ABS(jy - last_jy));
545 XCopyArea(display, drawto_field, window, gc,
546 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
547 SetDrawtoField(DRAW_DIRECT);
550 MarkTileDirty(sx,sy);
553 static int getGraphicAnimationPhase(int frames, int delay, int mode)
557 if (mode == ANIM_OSCILLATE)
559 int max_anim_frames = 2 * frames - 2;
560 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
561 phase = (phase < frames ? phase : max_anim_frames - phase);
564 phase = (FrameCounter % (delay * frames)) / delay;
566 if (mode == ANIM_REVERSE)
572 void DrawGraphicAnimationExt(int x, int y, int graphic,
573 int frames, int delay, int mode, int mask_mode)
575 int phase = getGraphicAnimationPhase(frames, delay, mode);
577 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
579 if (mask_mode == USE_MASKING)
580 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
582 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
586 void DrawGraphicAnimation(int x, int y, int graphic,
587 int frames, int delay, int mode)
589 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
592 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
593 int frames, int delay, int mode)
595 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
598 void DrawGraphic(int x, int y, int graphic)
601 if (!IN_SCR_FIELD(x,y))
603 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
604 printf("DrawGraphic(): This should never happen!\n");
609 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
613 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
615 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
617 graphic -= GFX_START_ROCKSSCREEN;
618 XCopyArea(display, pix[PIX_BACK], d, gc,
619 SX + (graphic % GFX_PER_LINE) * TILEX,
620 SY + (graphic / GFX_PER_LINE) * TILEY,
623 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
625 graphic -= GFX_START_ROCKSHEROES;
626 XCopyArea(display, pix[PIX_HEROES], d, gc,
627 (graphic % HEROES_PER_LINE) * TILEX,
628 (graphic / HEROES_PER_LINE) * TILEY,
631 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
633 graphic -= GFX_START_ROCKSFONT;
634 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
635 (graphic % FONT_CHARS_PER_LINE) * TILEX,
636 (graphic / FONT_CHARS_PER_LINE) * TILEY +
637 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
641 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
644 void DrawGraphicThruMask(int x, int y, int graphic)
647 if (!IN_SCR_FIELD(x,y))
649 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
650 printf("DrawGraphicThruMask(): This should never happen!\n");
655 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
659 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
666 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
668 src_pixmap = pix[PIX_BACK];
669 drawing_gc = clip_gc[PIX_BACK];
670 graphic -= GFX_START_ROCKSSCREEN;
671 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
672 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
674 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
676 src_pixmap = pix[PIX_HEROES];
677 drawing_gc = clip_gc[PIX_HEROES];
678 graphic -= GFX_START_ROCKSHEROES;
679 src_x = (graphic % HEROES_PER_LINE) * TILEX;
680 src_y = (graphic / HEROES_PER_LINE) * TILEY;
684 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
688 if (tile_clipmask[tile] != None)
690 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
691 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
692 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
693 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
698 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
701 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
702 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
703 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
707 void DrawMiniGraphic(int x, int y, int graphic)
709 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
710 MarkTileDirty(x/2, y/2);
713 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
715 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
717 graphic -= GFX_START_ROCKSSCREEN;
718 XCopyArea(display, pix[PIX_BACK], d, gc,
719 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
720 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
721 MINI_TILEX, MINI_TILEY, x, y);
723 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
725 graphic -= GFX_START_ROCKSFONT;
726 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
727 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
728 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
729 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
730 MINI_TILEX, MINI_TILEY, x, y);
733 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
736 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
737 int cut_mode, int mask_mode)
739 int width = TILEX, height = TILEY;
741 int src_x, src_y, dest_x, dest_y;
748 DrawGraphic(x, y, graphic);
752 if (dx || dy) /* Verschiebung der Grafik? */
754 if (x < BX1) /* Element kommt von links ins Bild */
761 else if (x > BX2) /* Element kommt von rechts ins Bild */
767 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
773 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
775 else if (dx) /* allg. Bewegung in x-Richtung */
776 MarkTileDirty(x + SIGN(dx), y);
778 if (y < BY1) /* Element kommt von oben ins Bild */
780 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
788 else if (y > BY2) /* Element kommt von unten ins Bild */
794 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
800 else if (dy > 0 && cut_mode == CUT_ABOVE)
802 if (y == BY2) /* Element unterhalb des Bildes */
808 MarkTileDirty(x, y + 1);
809 } /* Element verläßt unten das Bild */
810 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
812 else if (dy) /* allg. Bewegung in y-Richtung */
813 MarkTileDirty(x, y + SIGN(dy));
816 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
818 src_pixmap = pix[PIX_BACK];
819 drawing_gc = clip_gc[PIX_BACK];
820 graphic -= GFX_START_ROCKSSCREEN;
821 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
822 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
824 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
826 src_pixmap = pix[PIX_HEROES];
827 drawing_gc = clip_gc[PIX_HEROES];
828 graphic -= GFX_START_ROCKSHEROES;
829 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
830 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
833 dest_x = FX + x * TILEX + dx;
834 dest_y = FY + y * TILEY + dy;
837 if (!IN_SCR_FIELD(x,y))
839 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
840 printf("DrawGraphicShifted(): This should never happen!\n");
845 if (mask_mode == USE_MASKING)
847 if (tile_clipmask[tile] != None)
849 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
850 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
851 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
852 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
857 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
860 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
861 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
862 src_x, src_y, width, height, dest_x, dest_y);
866 XCopyArea(display, src_pixmap, drawto_field, gc,
867 src_x, src_y, width, height, dest_x, dest_y);
872 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
875 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
878 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
879 int cut_mode, int mask_mode)
881 int ux = LEVELX(x), uy = LEVELY(y);
882 int graphic = el2gfx(element);
883 int phase4 = ABS(MovPos[ux][uy]) / (TILEX / 4);
884 int phase = phase4 / 2;
885 int dir = MovDir[ux][uy];
887 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
893 else if (dir == MV_LEFT)
895 else if (dir == MV_DOWN)
898 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
899 element == EL_SCHWEIN || element == EL_DRACHE)
902 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
903 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
904 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
905 else if (dir == MV_RIGHT)
906 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
907 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
908 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
909 else if (dir == MV_UP)
910 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
911 element == EL_PINGUIN ? GFX_PINGUIN_UP :
912 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
914 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
915 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
916 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
920 else if (element == EL_SONDE)
922 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
924 else if (element == EL_SALZSAEURE)
926 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
928 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
932 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
934 graphic += phase * (element == EL_FELSBROCKEN ? 2 : 1);
936 else if ((element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
937 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL) && SiebAktiv)
939 graphic += 3 - (SiebAktiv % 8) / 2;
941 else if (IS_AMOEBOID(element))
943 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
944 graphic += (x + 2 * y + 4) % 4;
946 else if (element == EL_MAUER_LEBT)
948 boolean links_massiv = FALSE, rechts_massiv = FALSE;
950 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
952 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
953 rechts_massiv = TRUE;
955 if (links_massiv && rechts_massiv)
956 graphic = GFX_MAUERWERK;
957 else if (links_massiv)
958 graphic = GFX_MAUER_R;
959 else if (rechts_massiv)
960 graphic = GFX_MAUER_L;
964 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
965 else if (mask_mode == USE_MASKING)
966 DrawGraphicThruMask(x, y, graphic);
968 DrawGraphic(x, y, graphic);
971 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
972 int cut_mode, int mask_mode)
974 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
975 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
976 cut_mode, mask_mode);
979 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
982 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
985 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
988 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
991 void DrawScreenElementThruMask(int x, int y, int element)
993 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
996 void DrawLevelElementThruMask(int x, int y, int element)
998 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1001 void DrawLevelFieldThruMask(int x, int y)
1003 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1006 void ErdreichAnbroeckeln(int x, int y)
1008 int i, width, height, cx,cy;
1009 int ux = LEVELX(x), uy = LEVELY(y);
1010 int element, graphic;
1012 static int xy[4][2] =
1020 if (!IN_LEV_FIELD(ux, uy))
1023 element = Feld[ux][uy];
1025 if (element == EL_ERDREICH)
1027 if (!IN_SCR_FIELD(x, y))
1030 graphic = GFX_ERDENRAND;
1036 uxx = ux + xy[i][0];
1037 uyy = uy + xy[i][1];
1038 if (!IN_LEV_FIELD(uxx, uyy))
1041 element = Feld[uxx][uyy];
1043 if (element == EL_ERDREICH)
1046 if (i == 1 || i == 2)
1050 cx = (i == 2 ? TILEX - snip : 0);
1058 cy = (i == 3 ? TILEY - snip : 0);
1061 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1062 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1063 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1064 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1067 MarkTileDirty(x, y);
1071 graphic = GFX_ERDENRAND;
1075 int xx, yy, uxx, uyy;
1079 uxx = ux + xy[i][0];
1080 uyy = uy + xy[i][1];
1082 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1083 !IN_SCR_FIELD(xx, yy))
1086 if (i == 1 || i == 2)
1090 cx = (i == 1 ? TILEX - snip : 0);
1098 cy = (i==0 ? TILEY-snip : 0);
1101 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1102 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1103 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1104 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1106 MarkTileDirty(xx, yy);
1111 void DrawScreenElement(int x, int y, int element)
1113 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1114 ErdreichAnbroeckeln(x, y);
1117 void DrawLevelElement(int x, int y, int element)
1119 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1120 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1123 void DrawScreenField(int x, int y)
1125 int ux = LEVELX(x), uy = LEVELY(y);
1128 if (!IN_LEV_FIELD(ux, uy))
1130 DrawScreenElement(x, y, EL_BETON);
1134 element = Feld[ux][uy];
1136 if (IS_MOVING(ux, uy))
1138 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1139 boolean cut_mode = NO_CUTTING;
1141 if (Store[ux][uy] == EL_MORAST_LEER ||
1142 Store[ux][uy] == EL_SIEB_LEER ||
1143 Store[ux][uy] == EL_SIEB2_LEER ||
1144 Store[ux][uy] == EL_AMOEBE_NASS)
1145 cut_mode = CUT_ABOVE;
1146 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1147 Store[ux][uy] == EL_SIEB_VOLL ||
1148 Store[ux][uy] == EL_SIEB2_VOLL)
1149 cut_mode = CUT_BELOW;
1151 if (cut_mode == CUT_ABOVE)
1152 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1154 DrawScreenElement(x, y, EL_LEERRAUM);
1157 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1159 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1161 if (Store[ux][uy] == EL_SALZSAEURE)
1162 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1164 else if (IS_BLOCKED(ux, uy))
1169 boolean cut_mode = NO_CUTTING;
1171 Blocked2Moving(ux, uy, &oldx, &oldy);
1174 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1175 MovDir[oldx][oldy] == MV_RIGHT);
1177 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1178 Store[oldx][oldy] == EL_SIEB_LEER ||
1179 Store[oldx][oldy] == EL_SIEB2_LEER ||
1180 Store[oldx][oldy] == EL_AMOEBE_NASS)
1181 cut_mode = CUT_ABOVE;
1183 DrawScreenElement(x, y, EL_LEERRAUM);
1184 element = Feld[oldx][oldy];
1187 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1189 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1191 else if (IS_DRAWABLE(element))
1192 DrawScreenElement(x, y, element);
1194 DrawScreenElement(x, y, EL_LEERRAUM);
1197 void DrawLevelField(int x, int y)
1199 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1200 DrawScreenField(SCREENX(x), SCREENY(y));
1201 else if (IS_MOVING(x, y))
1205 Moving2Blocked(x, y, &newx, &newy);
1206 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1207 DrawScreenField(SCREENX(newx), SCREENY(newy));
1209 else if (IS_BLOCKED(x, y))
1213 Blocked2Moving(x, y, &oldx, &oldy);
1214 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1215 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1219 void DrawMiniElement(int x, int y, int element)
1225 DrawMiniGraphic(x, y, -1);
1229 graphic = el2gfx(element);
1230 DrawMiniGraphic(x, y, graphic);
1233 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1235 int x = sx + scroll_x, y = sy + scroll_y;
1237 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1238 DrawMiniElement(sx, sy, EL_LEERRAUM);
1239 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1240 DrawMiniElement(sx, sy, EL_BETON);
1242 DrawMiniElement(sx, sy, Feld[x][y]);
1245 void DrawMicroElement(int xpos, int ypos, int element)
1249 if (element == EL_LEERRAUM)
1252 graphic = el2gfx(element);
1254 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1255 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1256 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1257 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1266 for(x=BX1; x<=BX2; x++)
1267 for(y=BY1; y<=BY2; y++)
1268 DrawScreenField(x, y);
1270 if (setup.soft_scrolling)
1271 XCopyArea(display, fieldbuffer, backbuffer, gc,
1272 FX, FY, SXSIZE, SYSIZE, SX, SY);
1274 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1277 void DrawMiniLevel(int scroll_x, int scroll_y)
1283 for(x=0; x<2*SCR_FIELDX; x++)
1284 for(y=0; y<2*SCR_FIELDY; y++)
1285 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1287 redraw_mask |= REDRAW_FIELD;
1290 void DrawMicroLevel(int xpos, int ypos)
1294 XFillRectangle(display, drawto, gc,
1295 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1296 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1297 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1298 if (lev_fieldx < STD_LEV_FIELDX)
1299 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1300 if (lev_fieldy < STD_LEV_FIELDY)
1301 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1303 for(x=-1; x<=STD_LEV_FIELDX; x++)
1304 for(y=-1; y<=STD_LEV_FIELDY; y++)
1305 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1306 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1308 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1309 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1312 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1316 int len = strlen(level.name);
1317 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1318 int lypos = MICROLABEL_YPOS;
1320 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1323 redraw_mask |= REDRAW_MICROLEV;
1326 int REQ_in_range(int x, int y)
1328 if (y > DY+249 && y < DY+278)
1330 if (x > DX+1 && x < DX+48)
1332 else if (x > DX+51 && x < DX+98)
1338 boolean Request(char *text, unsigned int req_state)
1340 int mx, my, ty, result = -1;
1341 unsigned int old_door_state;
1344 /* pause network game while waiting for request to answer */
1345 if (options.network &&
1346 game_status == PLAYING &&
1347 req_state & REQUEST_WAIT_FOR)
1348 SendToServer_PausePlaying();
1351 old_door_state = GetDoorState();
1353 CloseDoor(DOOR_CLOSE_1);
1355 /* Alten Türinhalt sichern */
1356 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1357 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1358 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1360 /* Fragetext schreiben */
1361 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1362 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1364 for(ty=0; ty<13; ty++)
1372 for(tl=0,tx=0; tx<7; tl++,tx++)
1375 if (!tc || tc == 32)
1386 DrawTextExt(pix[PIX_DB_DOOR], gc,
1387 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1388 txt, FS_SMALL, FC_YELLOW);
1389 text += tl + (tc == 32 ? 1 : 0);
1392 if (req_state & REQ_ASK)
1394 DrawYesNoButton(BUTTON_OK, DB_INIT);
1395 DrawYesNoButton(BUTTON_NO, DB_INIT);
1397 else if (req_state & REQ_CONFIRM)
1399 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1401 else if (req_state & REQ_PLAYER)
1403 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1404 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1405 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1406 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1409 OpenDoor(DOOR_OPEN_1);
1412 if (!(req_state & REQUEST_WAIT_FOR))
1415 if (game_status != MAINMENU)
1418 button_status = MB_RELEASED;
1422 if (XPending(display))
1426 XNextEvent(display, &event);
1436 if (event.type == MotionNotify)
1438 motion_status = TRUE;
1439 mx = ((XMotionEvent *) &event)->x;
1440 my = ((XMotionEvent *) &event)->y;
1444 motion_status = FALSE;
1445 mx = ((XButtonEvent *) &event)->x;
1446 my = ((XButtonEvent *) &event)->y;
1447 if (event.type==ButtonPress)
1448 button_status = ((XButtonEvent *) &event)->button;
1450 button_status = MB_RELEASED;
1453 if (req_state & REQ_ASK)
1454 choice = CheckYesNoButtons(mx,my,button_status);
1455 else if (req_state & REQ_CONFIRM)
1456 choice = CheckConfirmButton(mx,my,button_status);
1458 choice = CheckPlayerButtons(mx,my,button_status);
1468 case BUTTON_CONFIRM:
1469 result = TRUE | FALSE;
1472 case BUTTON_PLAYER_1:
1475 case BUTTON_PLAYER_2:
1478 case BUTTON_PLAYER_3:
1481 case BUTTON_PLAYER_4:
1492 switch(XLookupKeysym((XKeyEvent *)&event,
1493 ((XKeyEvent *)&event)->state))
1506 if (req_state & REQ_PLAYER)
1511 key_joystick_mapping = 0;
1515 HandleOtherEvents(&event);
1519 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1521 int joy = AnyJoystick();
1523 if (joy & JOY_BUTTON_1)
1525 else if (joy & JOY_BUTTON_2)
1531 /* don't eat all CPU time */
1535 if (game_status != MAINMENU)
1538 if (!(req_state & REQ_STAY_OPEN))
1540 CloseDoor(DOOR_CLOSE_1);
1542 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1544 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1545 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1546 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1547 OpenDoor(DOOR_OPEN_1);
1552 /* continue network game after request */
1553 if (options.network &&
1554 game_status == PLAYING &&
1555 req_state & REQUEST_WAIT_FOR)
1556 SendToServer_ContinuePlaying();
1562 unsigned int OpenDoor(unsigned int door_state)
1564 unsigned int new_door_state;
1566 if (door_state & DOOR_COPY_BACK)
1568 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1569 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1570 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1571 door_state &= ~DOOR_COPY_BACK;
1574 new_door_state = MoveDoor(door_state);
1576 return(new_door_state);
1579 unsigned int CloseDoor(unsigned int door_state)
1581 unsigned int new_door_state;
1583 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1584 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1585 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1586 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1588 new_door_state = MoveDoor(door_state);
1590 return(new_door_state);
1593 unsigned int GetDoorState()
1595 return(MoveDoor(DOOR_GET_STATE));
1598 unsigned int MoveDoor(unsigned int door_state)
1600 static unsigned int door1 = DOOR_OPEN_1;
1601 static unsigned int door2 = DOOR_CLOSE_2;
1602 static long door_delay = 0;
1603 int x, start, stepsize = 2;
1604 long door_delay_value = stepsize * 5;
1606 if (door_state == DOOR_GET_STATE)
1607 return(door1 | door2);
1609 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1610 door_state &= ~DOOR_OPEN_1;
1611 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1612 door_state &= ~DOOR_CLOSE_1;
1613 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1614 door_state &= ~DOOR_OPEN_2;
1615 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1616 door_state &= ~DOOR_CLOSE_2;
1618 if (setup.quick_doors)
1621 door_delay_value = 0;
1622 StopSound(SND_OEFFNEN);
1625 if (door_state & DOOR_ACTION)
1627 if (!(door_state & DOOR_NO_DELAY))
1628 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1630 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1632 for(x=start; x<=DXSIZE; x+=stepsize)
1634 WaitUntilDelayReached(&door_delay, door_delay_value);
1636 if (door_state & DOOR_ACTION_1)
1638 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1639 int j = (DXSIZE - i) / 3;
1641 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1642 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1643 DXSIZE,DYSIZE - i/2, DX, DY);
1645 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1647 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1648 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1649 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1650 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1651 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1652 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1654 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1655 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1656 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1657 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1658 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1659 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1661 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1662 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1664 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1665 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1667 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1668 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1669 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1670 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1671 DX + DXSIZE - i, DY + 77 + j);
1672 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1673 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1674 DX + DXSIZE - i, DY + 203 + j);
1676 redraw_mask |= REDRAW_DOOR_1;
1679 if (door_state & DOOR_ACTION_2)
1681 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1682 int j = (VXSIZE - i) / 3;
1684 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1685 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1686 VXSIZE, VYSIZE - i/2, VX, VY);
1688 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1690 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1691 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1692 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1693 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1694 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1695 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1696 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1697 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1699 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1700 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1701 VX, VY + VYSIZE / 2 - j);
1702 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1703 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1704 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1705 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1706 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1708 redraw_mask |= REDRAW_DOOR_2;
1713 if (game_status == MAINMENU)
1718 if (setup.quick_doors)
1719 StopSound(SND_OEFFNEN);
1721 if (door_state & DOOR_ACTION_1)
1722 door1 = door_state & DOOR_ACTION_1;
1723 if (door_state & DOOR_ACTION_2)
1724 door2 = door_state & DOOR_ACTION_2;
1726 return(door1 | door2);
1729 int ReadPixel(Drawable d, int x, int y)
1731 static XImage *pixelimage;
1733 pixelimage = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1734 return(XGetPixel(pixelimage, 0, 0));
1737 int el2gfx(int element)
1741 case EL_LEERRAUM: return -1;
1742 case EL_ERDREICH: return GFX_ERDREICH;
1743 case EL_MAUERWERK: return GFX_MAUERWERK;
1744 case EL_FELSBODEN: return GFX_FELSBODEN;
1745 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1746 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1747 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1748 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1749 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1750 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1751 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1752 case EL_SPIELER1: return GFX_SPIELER1;
1753 case EL_SPIELER2: return GFX_SPIELER2;
1754 case EL_SPIELER3: return GFX_SPIELER3;
1755 case EL_SPIELER4: return GFX_SPIELER4;
1756 case EL_KAEFER: return GFX_KAEFER;
1757 case EL_KAEFER_R: return GFX_KAEFER_R;
1758 case EL_KAEFER_O: return GFX_KAEFER_O;
1759 case EL_KAEFER_L: return GFX_KAEFER_L;
1760 case EL_KAEFER_U: return GFX_KAEFER_U;
1761 case EL_FLIEGER: return GFX_FLIEGER;
1762 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1763 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1764 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1765 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1766 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1767 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1768 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1769 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1770 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1771 case EL_FIREFLY: return GFX_FIREFLY;
1772 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1773 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1774 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1775 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1776 case EL_MAMPFER: return GFX_MAMPFER;
1777 case EL_ROBOT: return GFX_ROBOT;
1778 case EL_BETON: return GFX_BETON;
1779 case EL_DIAMANT: return GFX_DIAMANT;
1780 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1781 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1782 case EL_TROPFEN: return GFX_TROPFEN;
1783 case EL_BOMBE: return GFX_BOMBE;
1784 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1785 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1786 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1787 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1788 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1789 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1790 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1791 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1792 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1793 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1794 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1795 case EL_LIFE: return GFX_LIFE;
1796 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1797 case EL_DYNAMIT: return GFX_DYNAMIT;
1798 case EL_BADEWANNE: return GFX_BADEWANNE;
1799 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1800 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1801 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1802 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1803 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1804 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1805 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1806 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1807 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1808 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1809 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1810 case EL_PFORTE1: return GFX_PFORTE1;
1811 case EL_PFORTE2: return GFX_PFORTE2;
1812 case EL_PFORTE3: return GFX_PFORTE3;
1813 case EL_PFORTE4: return GFX_PFORTE4;
1814 case EL_PFORTE1X: return GFX_PFORTE1X;
1815 case EL_PFORTE2X: return GFX_PFORTE2X;
1816 case EL_PFORTE3X: return GFX_PFORTE3X;
1817 case EL_PFORTE4X: return GFX_PFORTE4X;
1818 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1819 case EL_PACMAN: return GFX_PACMAN;
1820 case EL_PACMAN_R: return GFX_PACMAN_R;
1821 case EL_PACMAN_O: return GFX_PACMAN_O;
1822 case EL_PACMAN_L: return GFX_PACMAN_L;
1823 case EL_PACMAN_U: return GFX_PACMAN_U;
1824 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1825 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1826 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1827 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1828 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1829 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1830 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1831 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1832 case EL_MAUER_X: return GFX_MAUER_X;
1833 case EL_MAUER_Y: return GFX_MAUER_Y;
1834 case EL_MAUER_XY: return GFX_MAUER_XY;
1835 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1836 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1837 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1838 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1839 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1840 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1841 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1842 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1843 case EL_MAMPFER2: return GFX_MAMPFER2;
1844 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1845 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1846 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1847 case EL_DYNABOMB: return GFX_DYNABOMB;
1848 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1849 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1850 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1851 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1852 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1853 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1854 case EL_MAULWURF: return GFX_MAULWURF;
1855 case EL_PINGUIN: return GFX_PINGUIN;
1856 case EL_SCHWEIN: return GFX_SCHWEIN;
1857 case EL_DRACHE: return GFX_DRACHE;
1858 case EL_SONDE: return GFX_SONDE;
1859 case EL_PFEIL_L: return GFX_PFEIL_L;
1860 case EL_PFEIL_R: return GFX_PFEIL_R;
1861 case EL_PFEIL_O: return GFX_PFEIL_O;
1862 case EL_PFEIL_U: return GFX_PFEIL_U;
1865 if (IS_CHAR(element))
1866 return GFX_CHAR_START + (element - EL_CHAR_START);