1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
17 #include <machine/joystick.h>
31 extern boolean wait_for_vsync;
34 void SetDrawtoField(int mode)
36 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
47 drawto_field = fieldbuffer;
49 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
60 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
67 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
69 if (setup.direct_draw && game_status == PLAYING)
70 redraw_mask &= ~REDRAW_MAIN;
72 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
73 redraw_mask |= REDRAW_FIELD;
75 if (redraw_mask & REDRAW_FIELD)
76 redraw_mask &= ~REDRAW_TILES;
79 if (redraw_mask & REDRAW_FIELD ||
80 (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING))
81 redraw_mask &= ~REDRAW_TILES;
87 /* synchronize X11 graphics at this point; if we would synchronize the
88 display immediately after the buffer switching (after the XFlush),
89 this could mean that we have to wait for the graphics to complete,
90 although we could go on doing calculations for the next frame */
92 XSync(display, FALSE);
96 wait_for_vsync = TRUE;
100 if (redraw_mask & REDRAW_ALL)
102 XCopyArea(display,backbuffer,window,gc,
103 0,0, WIN_XSIZE,WIN_YSIZE,
108 if (redraw_mask & REDRAW_FIELD)
110 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
111 XCopyArea(display,backbuffer,window,gc,
112 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
116 int fx = FX, fy = FY;
118 if (setup.soft_scrolling)
120 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
121 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
124 if (setup.soft_scrolling ||
125 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ||
126 ABS(ScreenGfxPos) == ScrollStepSize ||
127 redraw_tiles > REDRAWTILES_THRESHOLD)
128 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
130 redraw_mask &= ~REDRAW_MAIN;
133 if (redraw_mask & REDRAW_DOORS)
135 if (redraw_mask & REDRAW_DOOR_1)
136 XCopyArea(display,backbuffer,window,gc,
137 DX,DY, DXSIZE,DYSIZE,
139 if (redraw_mask & REDRAW_DOOR_2)
141 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
142 XCopyArea(display,backbuffer,window,gc,
143 VX,VY, VXSIZE,VYSIZE,
147 if (redraw_mask & REDRAW_VIDEO_1)
148 XCopyArea(display,backbuffer,window,gc,
149 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
150 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
151 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
152 if (redraw_mask & REDRAW_VIDEO_2)
153 XCopyArea(display,backbuffer,window,gc,
154 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
155 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
156 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
157 if (redraw_mask & REDRAW_VIDEO_3)
158 XCopyArea(display,backbuffer,window,gc,
159 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
160 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
161 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
164 if (redraw_mask & REDRAW_DOOR_3)
165 XCopyArea(display, backbuffer, window, gc,
166 EX, EY, EXSIZE, EYSIZE,
168 redraw_mask &= ~REDRAW_DOORS;
171 if (redraw_mask & REDRAW_MICROLEV)
173 XCopyArea(display,backbuffer,window,gc,
174 MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
175 MICROLEV_XPOS,MICROLEV_YPOS);
176 XCopyArea(display,backbuffer,window,gc,
177 SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
179 redraw_mask &= ~REDRAW_MICROLEV;
182 if (redraw_mask & REDRAW_TILES)
184 for(x=0; x<SCR_FIELDX; x++)
185 for(y=0; y<SCR_FIELDY; y++)
186 if (redraw[redraw_x1 + x][redraw_y1 + y])
187 XCopyArea(display,buffer,window,gc,
188 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
189 SX+x*TILEX,SY+y*TILEY);
194 for(x=0; x<MAX_BUF_XSIZE; x++)
195 for(y=0; y<MAX_BUF_YSIZE; y++)
204 long fading_delay = 300;
206 if (setup.fading && (redraw_mask & REDRAW_FIELD))
213 XFillRectangle(display,window,gc,
214 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
217 for(i=0;i<2*FULL_SYSIZE;i++)
219 for(y=0;y<FULL_SYSIZE;y++)
221 XCopyArea(display,backbuffer,window,gc,
222 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
230 for(i=1;i<FULL_SYSIZE;i+=2)
231 XCopyArea(display,backbuffer,window,gc,
232 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
238 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
239 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
240 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
244 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
245 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
246 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
250 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
251 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
252 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
256 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
257 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
258 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
262 redraw_mask &= ~REDRAW_MAIN;
271 XFillRectangle(display, backbuffer, gc,
272 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
274 if (setup.soft_scrolling && game_status == PLAYING)
276 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
277 SetDrawtoField(DRAW_BUFFERED);
280 SetDrawtoField(DRAW_BACKBUFFER);
282 if (setup.direct_draw && game_status == PLAYING)
284 XFillRectangle(display, window, gc,
285 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
286 SetDrawtoField(DRAW_DIRECT);
289 redraw_mask |= REDRAW_FIELD;
292 void DrawTextFCentered(int y, int font_type, char *format, ...)
294 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
298 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
299 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
301 va_start(ap, format);
302 vsprintf(buffer, format, ap);
305 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
306 buffer, FS_SMALL, font_type);
309 void DrawTextF(int x, int y, int font_type, char *format, ...)
311 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
314 va_start(ap, format);
315 vsprintf(buffer, format, ap);
318 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
321 void DrawText(int x, int y, char *text, int font_size, int font_type)
323 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
326 redraw_mask |= REDRAW_FIELD;
328 redraw_mask |= REDRAW_DOOR_1;
331 void DrawTextExt(Drawable d, GC gc, int x, int y,
332 char *text, int font_size, int font_type)
334 int font_width, font_height, font_start;
337 if (font_size != FS_SMALL && font_size != FS_BIG)
338 font_size = FS_SMALL;
339 if (font_type < FC_RED || font_type > FC_SPECIAL2)
342 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
343 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
344 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
345 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
346 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
347 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
348 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
349 FONT_LINES_PER_FONT);
355 if (c >= 'a' && c <= 'z')
357 else if (c == 'ä' || c == 'Ä')
359 else if (c == 'ö' || c == 'Ö')
361 else if (c == 'ü' || c == 'Ü')
364 if (c >= 32 && c <= 95)
365 XCopyArea(display, pix[font_pixmap], d, gc,
366 ((c - 32) % FONT_CHARS_PER_LINE) * font_width,
367 ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start,
368 font_width, font_height, x, y);
374 void DrawAllPlayers()
378 for(i=0; i<MAX_PLAYERS; i++)
379 if (stored_player[i].active)
380 DrawPlayer(&stored_player[i]);
383 void DrawPlayerField(int x, int y)
388 DrawPlayer(PLAYERINFO(x,y));
391 void DrawPlayer(struct PlayerInfo *player)
393 int jx = player->jx, jy = player->jy;
394 int last_jx = player->last_jx, last_jy = player->last_jy;
395 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
396 int sx = SCREENX(jx), sy = SCREENY(jy);
397 int sxx = 0, syy = 0;
398 int element = Feld[jx][jy];
401 if (!player->active || player->gone ||
402 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
406 if (!IN_LEV_FIELD(jx,jy))
408 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
409 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
410 printf("DrawPlayerField(): This should never happen!\n");
415 if (element == EL_EXPLODING)
418 /* draw things in the field the player is leaving, if needed */
420 if (last_jx != jx || last_jy != jy)
422 if (Store[last_jx][last_jy])
424 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
425 DrawLevelFieldThruMask(last_jx, last_jy);
427 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
428 DrawDynamite(last_jx, last_jy);
430 DrawLevelField(last_jx, last_jy);
432 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
436 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
437 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
439 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
442 DrawLevelField(next_jx, next_jy);
446 if (!IN_SCR_FIELD(sx, sy))
449 if (setup.direct_draw)
450 SetDrawtoField(DRAW_BUFFERED);
452 /* draw things behind the player, if needed */
455 DrawLevelElement(jx, jy, Store[jx][jy]);
456 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
457 DrawLevelField(jx, jy);
459 /* draw player himself */
461 if (player->MovDir == MV_LEFT)
462 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
463 else if (player->MovDir == MV_RIGHT)
464 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
465 else if (player->MovDir == MV_UP)
466 graphic = GFX_SPIELER1_UP;
467 else /* MV_DOWN || MV_NO_MOVING */
468 graphic = GFX_SPIELER1_DOWN;
470 graphic += player->index_nr * 3*HEROES_PER_LINE;
471 graphic += player->Frame;
475 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
476 sxx = player->GfxPos;
478 syy = player->GfxPos;
481 if (!setup.soft_scrolling && ScreenMovPos)
484 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
486 if (player->Pushing && player->GfxPos)
488 int px = SCREENX(next_jx), py = SCREENY(next_jy);
490 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
491 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
492 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
496 int element = Feld[next_jx][next_jy];
497 int graphic = el2gfx(element);
499 if (element == EL_FELSBROCKEN && sxx)
501 int phase = (player->GfxPos / (TILEX/4));
503 if (player->MovDir == MV_LEFT)
506 graphic += (phase+4)%4;
509 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
513 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
515 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
517 graphic = el2gfx(element);
519 if (element == EL_DYNAMIT)
521 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
526 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
530 DrawGraphicThruMask(sx, sy, graphic + phase);
533 if ((last_jx != jx || last_jy != jy) &&
534 Feld[last_jx][last_jy] == EL_EXPLODING)
536 int phase = Frame[last_jx][last_jy];
540 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
541 GFX_EXPLOSION + ((phase - 1) / delay - 1));
544 if (setup.direct_draw)
546 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
547 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
548 int x_size = TILEX * (1 + ABS(jx - last_jx));
549 int y_size = TILEY * (1 + ABS(jy - last_jy));
551 XCopyArea(display, drawto_field, window, gc,
552 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
553 SetDrawtoField(DRAW_DIRECT);
556 MarkTileDirty(sx,sy);
559 static int getGraphicAnimationPhase(int frames, int delay, int mode)
563 if (mode == ANIM_OSCILLATE)
565 int max_anim_frames = 2 * frames - 2;
566 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
567 phase = (phase < frames ? phase : max_anim_frames - phase);
570 phase = (FrameCounter % (delay * frames)) / delay;
572 if (mode == ANIM_REVERSE)
578 void DrawGraphicAnimationExt(int x, int y, int graphic,
579 int frames, int delay, int mode, int mask_mode)
581 int phase = getGraphicAnimationPhase(frames, delay, mode);
583 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
585 if (mask_mode == USE_MASKING)
586 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
588 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
592 void DrawGraphicAnimation(int x, int y, int graphic,
593 int frames, int delay, int mode)
595 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
598 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
599 int frames, int delay, int mode)
601 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
604 void DrawGraphic(int x, int y, int graphic)
607 if (!IN_SCR_FIELD(x,y))
609 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
610 printf("DrawGraphic(): This should never happen!\n");
615 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
619 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
621 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
623 graphic -= GFX_START_ROCKSSCREEN;
624 XCopyArea(display, pix[PIX_BACK], d, gc,
625 SX + (graphic % GFX_PER_LINE) * TILEX,
626 SY + (graphic / GFX_PER_LINE) * TILEY,
629 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
631 graphic -= GFX_START_ROCKSMORE;
632 XCopyArea(display, pix[PIX_MORE], d, gc,
633 (graphic % MORE_PER_LINE) * TILEX,
634 (graphic / MORE_PER_LINE) * TILEY,
637 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
639 graphic -= GFX_START_ROCKSHEROES;
640 XCopyArea(display, pix[PIX_HEROES], d, gc,
641 (graphic % HEROES_PER_LINE) * TILEX,
642 (graphic / HEROES_PER_LINE) * TILEY,
645 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
647 graphic -= GFX_START_ROCKSFONT;
648 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
649 (graphic % FONT_CHARS_PER_LINE) * TILEX,
650 (graphic / FONT_CHARS_PER_LINE) * TILEY +
651 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
655 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
658 void DrawGraphicThruMask(int x, int y, int graphic)
661 if (!IN_SCR_FIELD(x,y))
663 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
664 printf("DrawGraphicThruMask(): This should never happen!\n");
669 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
673 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
680 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
682 src_pixmap = pix[PIX_BACK];
683 drawing_gc = clip_gc[PIX_BACK];
684 graphic -= GFX_START_ROCKSSCREEN;
685 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
686 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
688 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
690 src_pixmap = pix[PIX_MORE];
691 drawing_gc = clip_gc[PIX_MORE];
692 graphic -= GFX_START_ROCKSMORE;
693 src_x = (graphic % MORE_PER_LINE) * TILEX;
694 src_y = (graphic / MORE_PER_LINE) * TILEY;
696 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
698 src_pixmap = pix[PIX_HEROES];
699 drawing_gc = clip_gc[PIX_HEROES];
700 graphic -= GFX_START_ROCKSHEROES;
701 src_x = (graphic % HEROES_PER_LINE) * TILEX;
702 src_y = (graphic / HEROES_PER_LINE) * TILEY;
706 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
710 if (tile_clipmask[tile] != None)
712 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
713 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
714 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
715 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
720 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
723 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
724 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
725 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
729 void DrawMiniGraphic(int x, int y, int graphic)
731 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
732 MarkTileDirty(x/2, y/2);
735 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
737 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
739 graphic -= GFX_START_ROCKSSCREEN;
740 XCopyArea(display, pix[PIX_BACK], d, gc,
741 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
742 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
743 MINI_TILEX, MINI_TILEY, x, y);
745 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
747 graphic -= GFX_START_ROCKSMORE;
748 XCopyArea(display, pix[PIX_MORE], d, gc,
749 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
750 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
751 MINI_TILEX, MINI_TILEY, x, y);
753 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
755 graphic -= GFX_START_ROCKSFONT;
756 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
757 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
758 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
759 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
760 MINI_TILEX, MINI_TILEY, x, y);
763 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
766 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
767 int cut_mode, int mask_mode)
769 int width = TILEX, height = TILEY;
771 int src_x, src_y, dest_x, dest_y;
778 DrawGraphic(x, y, graphic);
782 if (dx || dy) /* Verschiebung der Grafik? */
784 if (x < BX1) /* Element kommt von links ins Bild */
791 else if (x > BX2) /* Element kommt von rechts ins Bild */
797 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
803 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
805 else if (dx) /* allg. Bewegung in x-Richtung */
806 MarkTileDirty(x + SIGN(dx), y);
808 if (y < BY1) /* Element kommt von oben ins Bild */
810 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
818 else if (y > BY2) /* Element kommt von unten ins Bild */
824 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
830 else if (dy > 0 && cut_mode == CUT_ABOVE)
832 if (y == BY2) /* Element unterhalb des Bildes */
838 MarkTileDirty(x, y + 1);
839 } /* Element verläßt unten das Bild */
840 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
842 else if (dy) /* allg. Bewegung in y-Richtung */
843 MarkTileDirty(x, y + SIGN(dy));
846 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
848 src_pixmap = pix[PIX_BACK];
849 drawing_gc = clip_gc[PIX_BACK];
850 graphic -= GFX_START_ROCKSSCREEN;
851 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
852 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
854 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
856 src_pixmap = pix[PIX_MORE];
857 drawing_gc = clip_gc[PIX_MORE];
858 graphic -= GFX_START_ROCKSMORE;
859 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
860 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
862 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
864 src_pixmap = pix[PIX_HEROES];
865 drawing_gc = clip_gc[PIX_HEROES];
866 graphic -= GFX_START_ROCKSHEROES;
867 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
868 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
870 else /* big font graphics currently not allowed (and not needed) */
873 dest_x = FX + x * TILEX + dx;
874 dest_y = FY + y * TILEY + dy;
877 if (!IN_SCR_FIELD(x,y))
879 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
880 printf("DrawGraphicShifted(): This should never happen!\n");
885 if (mask_mode == USE_MASKING)
887 if (tile_clipmask[tile] != None)
889 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
890 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
891 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
892 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
897 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
900 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
901 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
902 src_x, src_y, width, height, dest_x, dest_y);
906 XCopyArea(display, src_pixmap, drawto_field, gc,
907 src_x, src_y, width, height, dest_x, dest_y);
912 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
915 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
918 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
919 int cut_mode, int mask_mode)
921 int ux = LEVELX(x), uy = LEVELY(y);
922 int graphic = el2gfx(element);
923 int phase4 = ABS(MovPos[ux][uy]) / (TILEX / 4);
924 int phase = phase4 / 2;
925 int dir = MovDir[ux][uy];
927 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
933 else if (dir == MV_LEFT)
935 else if (dir == MV_DOWN)
938 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
939 element == EL_SCHWEIN || element == EL_DRACHE)
942 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
943 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
944 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
945 else if (dir == MV_RIGHT)
946 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
947 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
948 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
949 else if (dir == MV_UP)
950 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
951 element == EL_PINGUIN ? GFX_PINGUIN_UP :
952 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
954 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
955 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
956 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
960 else if (element == EL_SONDE)
962 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
964 else if (element == EL_SALZSAEURE)
966 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
968 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
972 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
974 graphic += phase * (element == EL_FELSBROCKEN ? 2 : 1);
976 else if ((element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
977 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL) && SiebAktiv)
979 graphic += 3 - (SiebAktiv % 8) / 2;
981 else if (IS_AMOEBOID(element))
983 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
984 graphic += (x + 2 * y + 4) % 4;
986 else if (element == EL_MAUER_LEBT)
988 boolean links_massiv = FALSE, rechts_massiv = FALSE;
990 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
992 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
993 rechts_massiv = TRUE;
995 if (links_massiv && rechts_massiv)
996 graphic = GFX_MAUERWERK;
997 else if (links_massiv)
998 graphic = GFX_MAUER_R;
999 else if (rechts_massiv)
1000 graphic = GFX_MAUER_L;
1004 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1005 else if (mask_mode == USE_MASKING)
1006 DrawGraphicThruMask(x, y, graphic);
1008 DrawGraphic(x, y, graphic);
1011 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1012 int cut_mode, int mask_mode)
1014 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1015 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1016 cut_mode, mask_mode);
1019 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1022 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1025 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1028 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1031 void DrawScreenElementThruMask(int x, int y, int element)
1033 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1036 void DrawLevelElementThruMask(int x, int y, int element)
1038 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1041 void DrawLevelFieldThruMask(int x, int y)
1043 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1046 void ErdreichAnbroeckeln(int x, int y)
1048 int i, width, height, cx,cy;
1049 int ux = LEVELX(x), uy = LEVELY(y);
1050 int element, graphic;
1052 static int xy[4][2] =
1060 if (!IN_LEV_FIELD(ux, uy))
1063 element = Feld[ux][uy];
1065 if (element == EL_ERDREICH)
1067 if (!IN_SCR_FIELD(x, y))
1070 graphic = GFX_ERDENRAND;
1076 uxx = ux + xy[i][0];
1077 uyy = uy + xy[i][1];
1078 if (!IN_LEV_FIELD(uxx, uyy))
1081 element = Feld[uxx][uyy];
1083 if (element == EL_ERDREICH)
1086 if (i == 1 || i == 2)
1090 cx = (i == 2 ? TILEX - snip : 0);
1098 cy = (i == 3 ? 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 + x * TILEX + cx, FY + y * TILEY + cy);
1107 MarkTileDirty(x, y);
1111 graphic = GFX_ERDENRAND;
1115 int xx, yy, uxx, uyy;
1119 uxx = ux + xy[i][0];
1120 uyy = uy + xy[i][1];
1122 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1123 !IN_SCR_FIELD(xx, yy))
1126 if (i == 1 || i == 2)
1130 cx = (i == 1 ? TILEX - snip : 0);
1138 cy = (i==0 ? TILEY-snip : 0);
1141 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1142 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1143 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1144 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1146 MarkTileDirty(xx, yy);
1151 void DrawScreenElement(int x, int y, int element)
1153 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1154 ErdreichAnbroeckeln(x, y);
1157 void DrawLevelElement(int x, int y, int element)
1159 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1160 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1163 void DrawScreenField(int x, int y)
1165 int ux = LEVELX(x), uy = LEVELY(y);
1168 if (!IN_LEV_FIELD(ux, uy))
1170 DrawScreenElement(x, y, EL_BETON);
1174 element = Feld[ux][uy];
1176 if (IS_MOVING(ux, uy))
1178 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1179 boolean cut_mode = NO_CUTTING;
1181 if (Store[ux][uy] == EL_MORAST_LEER ||
1182 Store[ux][uy] == EL_SIEB_LEER ||
1183 Store[ux][uy] == EL_SIEB2_LEER ||
1184 Store[ux][uy] == EL_AMOEBE_NASS)
1185 cut_mode = CUT_ABOVE;
1186 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1187 Store[ux][uy] == EL_SIEB_VOLL ||
1188 Store[ux][uy] == EL_SIEB2_VOLL)
1189 cut_mode = CUT_BELOW;
1191 if (cut_mode == CUT_ABOVE)
1192 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1194 DrawScreenElement(x, y, EL_LEERRAUM);
1197 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1199 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1201 if (Store[ux][uy] == EL_SALZSAEURE)
1202 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1204 else if (IS_BLOCKED(ux, uy))
1209 boolean cut_mode = NO_CUTTING;
1211 Blocked2Moving(ux, uy, &oldx, &oldy);
1214 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1215 MovDir[oldx][oldy] == MV_RIGHT);
1217 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1218 Store[oldx][oldy] == EL_SIEB_LEER ||
1219 Store[oldx][oldy] == EL_SIEB2_LEER ||
1220 Store[oldx][oldy] == EL_AMOEBE_NASS)
1221 cut_mode = CUT_ABOVE;
1223 DrawScreenElement(x, y, EL_LEERRAUM);
1224 element = Feld[oldx][oldy];
1227 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1229 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1231 else if (IS_DRAWABLE(element))
1232 DrawScreenElement(x, y, element);
1234 DrawScreenElement(x, y, EL_LEERRAUM);
1237 void DrawLevelField(int x, int y)
1239 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1240 DrawScreenField(SCREENX(x), SCREENY(y));
1241 else if (IS_MOVING(x, y))
1245 Moving2Blocked(x, y, &newx, &newy);
1246 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1247 DrawScreenField(SCREENX(newx), SCREENY(newy));
1249 else if (IS_BLOCKED(x, y))
1253 Blocked2Moving(x, y, &oldx, &oldy);
1254 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1255 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1259 void DrawMiniElement(int x, int y, int element)
1265 DrawMiniGraphic(x, y, -1);
1269 graphic = el2gfx(element);
1270 DrawMiniGraphic(x, y, graphic);
1273 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1275 int x = sx + scroll_x, y = sy + scroll_y;
1277 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1278 DrawMiniElement(sx, sy, EL_LEERRAUM);
1279 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1280 DrawMiniElement(sx, sy, EL_BETON);
1282 DrawMiniElement(sx, sy, Feld[x][y]);
1285 void DrawMicroElement(int xpos, int ypos, int element)
1289 if (element == EL_LEERRAUM)
1292 graphic = el2gfx(element);
1294 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1295 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1296 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1297 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1298 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1300 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1301 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1302 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1303 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1312 for(x=BX1; x<=BX2; x++)
1313 for(y=BY1; y<=BY2; y++)
1314 DrawScreenField(x, y);
1316 if (setup.soft_scrolling)
1317 XCopyArea(display, fieldbuffer, backbuffer, gc,
1318 FX, FY, SXSIZE, SYSIZE, SX, SY);
1320 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1323 void DrawMiniLevel(int scroll_x, int scroll_y)
1329 for(x=0; x<2*SCR_FIELDX; x++)
1330 for(y=0; y<2*SCR_FIELDY; y++)
1331 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1333 redraw_mask |= REDRAW_FIELD;
1336 void DrawMicroLevel(int xpos, int ypos)
1340 XFillRectangle(display, drawto, gc,
1341 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1342 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1343 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1344 if (lev_fieldx < STD_LEV_FIELDX)
1345 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1346 if (lev_fieldy < STD_LEV_FIELDY)
1347 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1349 for(x=-1; x<=STD_LEV_FIELDX; x++)
1350 for(y=-1; y<=STD_LEV_FIELDY; y++)
1351 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1352 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1354 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1355 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1358 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1362 int len = strlen(level.name);
1363 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1364 int lypos = MICROLABEL_YPOS;
1366 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1369 redraw_mask |= REDRAW_MICROLEV;
1372 int REQ_in_range(int x, int y)
1374 if (y > DY+249 && y < DY+278)
1376 if (x > DX+1 && x < DX+48)
1378 else if (x > DX+51 && x < DX+98)
1384 boolean Request(char *text, unsigned int req_state)
1386 int mx, my, ty, result = -1;
1387 unsigned int old_door_state;
1390 /* pause network game while waiting for request to answer */
1391 if (options.network &&
1392 game_status == PLAYING &&
1393 req_state & REQUEST_WAIT_FOR)
1394 SendToServer_PausePlaying();
1397 old_door_state = GetDoorState();
1399 CloseDoor(DOOR_CLOSE_1);
1401 /* Alten Türinhalt sichern */
1402 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1403 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1404 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1406 /* Fragetext schreiben */
1407 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1408 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1410 for(ty=0; ty<13; ty++)
1418 for(tl=0,tx=0; tx<7; tl++,tx++)
1421 if (!tc || tc == 32)
1432 DrawTextExt(pix[PIX_DB_DOOR], gc,
1433 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1434 txt, FS_SMALL, FC_YELLOW);
1435 text += tl + (tc == 32 ? 1 : 0);
1438 if (req_state & REQ_ASK)
1440 DrawYesNoButton(BUTTON_OK, DB_INIT);
1441 DrawYesNoButton(BUTTON_NO, DB_INIT);
1443 else if (req_state & REQ_CONFIRM)
1445 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1447 else if (req_state & REQ_PLAYER)
1449 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1450 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1451 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1452 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1455 OpenDoor(DOOR_OPEN_1);
1458 if (!(req_state & REQUEST_WAIT_FOR))
1461 if (game_status != MAINMENU)
1464 button_status = MB_RELEASED;
1468 if (XPending(display))
1472 XNextEvent(display, &event);
1482 if (event.type == MotionNotify)
1484 motion_status = TRUE;
1485 mx = ((XMotionEvent *) &event)->x;
1486 my = ((XMotionEvent *) &event)->y;
1490 motion_status = FALSE;
1491 mx = ((XButtonEvent *) &event)->x;
1492 my = ((XButtonEvent *) &event)->y;
1493 if (event.type==ButtonPress)
1494 button_status = ((XButtonEvent *) &event)->button;
1496 button_status = MB_RELEASED;
1499 if (req_state & REQ_ASK)
1500 choice = CheckYesNoButtons(mx,my,button_status);
1501 else if (req_state & REQ_CONFIRM)
1502 choice = CheckConfirmButton(mx,my,button_status);
1504 choice = CheckPlayerButtons(mx,my,button_status);
1514 case BUTTON_CONFIRM:
1515 result = TRUE | FALSE;
1518 case BUTTON_PLAYER_1:
1521 case BUTTON_PLAYER_2:
1524 case BUTTON_PLAYER_3:
1527 case BUTTON_PLAYER_4:
1538 switch(XLookupKeysym((XKeyEvent *)&event,
1539 ((XKeyEvent *)&event)->state))
1552 if (req_state & REQ_PLAYER)
1557 key_joystick_mapping = 0;
1561 HandleOtherEvents(&event);
1565 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1567 int joy = AnyJoystick();
1569 if (joy & JOY_BUTTON_1)
1571 else if (joy & JOY_BUTTON_2)
1577 /* don't eat all CPU time */
1581 if (game_status != MAINMENU)
1584 if (!(req_state & REQ_STAY_OPEN))
1586 CloseDoor(DOOR_CLOSE_1);
1588 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1590 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1591 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1592 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1593 OpenDoor(DOOR_OPEN_1);
1598 /* continue network game after request */
1599 if (options.network &&
1600 game_status == PLAYING &&
1601 req_state & REQUEST_WAIT_FOR)
1602 SendToServer_ContinuePlaying();
1608 unsigned int OpenDoor(unsigned int door_state)
1610 unsigned int new_door_state;
1612 if (door_state & DOOR_COPY_BACK)
1614 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1615 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1616 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1617 door_state &= ~DOOR_COPY_BACK;
1620 new_door_state = MoveDoor(door_state);
1622 return(new_door_state);
1625 unsigned int CloseDoor(unsigned int door_state)
1627 unsigned int new_door_state;
1629 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1630 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1631 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1632 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1634 new_door_state = MoveDoor(door_state);
1636 return(new_door_state);
1639 unsigned int GetDoorState()
1641 return(MoveDoor(DOOR_GET_STATE));
1644 unsigned int MoveDoor(unsigned int door_state)
1646 static int door1 = DOOR_OPEN_1;
1647 static int door2 = DOOR_CLOSE_2;
1648 static unsigned long door_delay = 0;
1649 int x, start, stepsize = 2;
1650 unsigned long door_delay_value = stepsize * 5;
1652 if (door_state == DOOR_GET_STATE)
1653 return(door1 | door2);
1655 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1656 door_state &= ~DOOR_OPEN_1;
1657 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1658 door_state &= ~DOOR_CLOSE_1;
1659 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1660 door_state &= ~DOOR_OPEN_2;
1661 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1662 door_state &= ~DOOR_CLOSE_2;
1664 if (setup.quick_doors)
1667 door_delay_value = 0;
1668 StopSound(SND_OEFFNEN);
1671 if (door_state & DOOR_ACTION)
1673 if (!(door_state & DOOR_NO_DELAY))
1674 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1676 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1678 for(x=start; x<=DXSIZE; x+=stepsize)
1680 WaitUntilDelayReached(&door_delay, door_delay_value);
1682 if (door_state & DOOR_ACTION_1)
1684 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1685 int j = (DXSIZE - i) / 3;
1687 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1688 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1689 DXSIZE,DYSIZE - i/2, DX, DY);
1691 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1693 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1694 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1695 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1696 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1697 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1698 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1700 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1701 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1702 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1703 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1704 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1705 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1707 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1708 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1710 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1711 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1713 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1714 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1715 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1716 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1717 DX + DXSIZE - i, DY + 77 + j);
1718 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1719 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1720 DX + DXSIZE - i, DY + 203 + j);
1722 redraw_mask |= REDRAW_DOOR_1;
1725 if (door_state & DOOR_ACTION_2)
1727 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1728 int j = (VXSIZE - i) / 3;
1730 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1731 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1732 VXSIZE, VYSIZE - i/2, VX, VY);
1734 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1736 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1737 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1738 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1739 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1740 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1741 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1742 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1743 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1745 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1746 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1747 VX, VY + VYSIZE / 2 - j);
1748 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1749 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1750 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1751 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1752 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1754 redraw_mask |= REDRAW_DOOR_2;
1759 if (game_status == MAINMENU)
1764 if (setup.quick_doors)
1765 StopSound(SND_OEFFNEN);
1767 if (door_state & DOOR_ACTION_1)
1768 door1 = door_state & DOOR_ACTION_1;
1769 if (door_state & DOOR_ACTION_2)
1770 door2 = door_state & DOOR_ACTION_2;
1772 return(door1 | door2);
1775 int ReadPixel(Drawable d, int x, int y)
1777 XImage *pixel_image;
1778 unsigned long pixel_value;
1780 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1781 pixel_value = XGetPixel(pixel_image, 0, 0);
1783 XDestroyImage(pixel_image);
1788 int el2gfx(int element)
1792 case EL_LEERRAUM: return -1;
1793 case EL_ERDREICH: return GFX_ERDREICH;
1794 case EL_MAUERWERK: return GFX_MAUERWERK;
1795 case EL_FELSBODEN: return GFX_FELSBODEN;
1796 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1797 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1798 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1799 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1800 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1801 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1802 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1803 case EL_SPIELER1: return GFX_SPIELER1;
1804 case EL_SPIELER2: return GFX_SPIELER2;
1805 case EL_SPIELER3: return GFX_SPIELER3;
1806 case EL_SPIELER4: return GFX_SPIELER4;
1807 case EL_KAEFER: return GFX_KAEFER;
1808 case EL_KAEFER_R: return GFX_KAEFER_R;
1809 case EL_KAEFER_O: return GFX_KAEFER_O;
1810 case EL_KAEFER_L: return GFX_KAEFER_L;
1811 case EL_KAEFER_U: return GFX_KAEFER_U;
1812 case EL_FLIEGER: return GFX_FLIEGER;
1813 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1814 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1815 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1816 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1817 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1818 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1819 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1820 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1821 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1822 case EL_FIREFLY: return GFX_FIREFLY;
1823 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1824 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1825 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1826 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1827 case EL_MAMPFER: return GFX_MAMPFER;
1828 case EL_ROBOT: return GFX_ROBOT;
1829 case EL_BETON: return GFX_BETON;
1830 case EL_DIAMANT: return GFX_DIAMANT;
1831 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1832 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1833 case EL_TROPFEN: return GFX_TROPFEN;
1834 case EL_BOMBE: return GFX_BOMBE;
1835 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1836 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1837 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1838 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1839 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1840 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1841 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1842 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1843 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1844 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1845 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1846 case EL_LIFE: return GFX_LIFE;
1847 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1848 case EL_DYNAMIT: return GFX_DYNAMIT;
1849 case EL_BADEWANNE: return GFX_BADEWANNE;
1850 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1851 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1852 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1853 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1854 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1855 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1856 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1857 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1858 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1859 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1860 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1861 case EL_PFORTE1: return GFX_PFORTE1;
1862 case EL_PFORTE2: return GFX_PFORTE2;
1863 case EL_PFORTE3: return GFX_PFORTE3;
1864 case EL_PFORTE4: return GFX_PFORTE4;
1865 case EL_PFORTE1X: return GFX_PFORTE1X;
1866 case EL_PFORTE2X: return GFX_PFORTE2X;
1867 case EL_PFORTE3X: return GFX_PFORTE3X;
1868 case EL_PFORTE4X: return GFX_PFORTE4X;
1869 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1870 case EL_PACMAN: return GFX_PACMAN;
1871 case EL_PACMAN_R: return GFX_PACMAN_R;
1872 case EL_PACMAN_O: return GFX_PACMAN_O;
1873 case EL_PACMAN_L: return GFX_PACMAN_L;
1874 case EL_PACMAN_U: return GFX_PACMAN_U;
1875 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1876 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1877 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1878 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1879 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1880 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1881 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1882 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1883 case EL_MAUER_X: return GFX_MAUER_X;
1884 case EL_MAUER_Y: return GFX_MAUER_Y;
1885 case EL_MAUER_XY: return GFX_MAUER_XY;
1886 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1887 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1888 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1889 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1890 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1891 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1892 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1893 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1894 case EL_MAMPFER2: return GFX_MAMPFER2;
1895 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1896 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1897 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1898 case EL_DYNABOMB: return GFX_DYNABOMB;
1899 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1900 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1901 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1902 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1903 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1904 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1905 case EL_MAULWURF: return GFX_MAULWURF;
1906 case EL_PINGUIN: return GFX_PINGUIN;
1907 case EL_SCHWEIN: return GFX_SCHWEIN;
1908 case EL_DRACHE: return GFX_DRACHE;
1909 case EL_SONDE: return GFX_SONDE;
1910 case EL_PFEIL_L: return GFX_PFEIL_L;
1911 case EL_PFEIL_R: return GFX_PFEIL_R;
1912 case EL_PFEIL_O: return GFX_PFEIL_O;
1913 case EL_PFEIL_U: return GFX_PFEIL_U;
1916 if (IS_CHAR(element))
1917 return GFX_CHAR_START + (element - EL_CHAR_START);
1918 else if (element >= EL_SP_START && element <= EL_SP_END)
1919 return GFX_START_ROCKSMORE + (element - EL_SP_START);