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 if (element != EL_SP_INFOTRON)
975 graphic += phase * (element == EL_FELSBROCKEN ? 2 : 1);
977 else if ((element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
978 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL) && SiebAktiv)
980 graphic += 3 - (SiebAktiv % 8) / 2;
982 else if (IS_AMOEBOID(element))
984 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
985 graphic += (x + 2 * y + 4) % 4;
987 else if (element == EL_MAUER_LEBT)
989 boolean links_massiv = FALSE, rechts_massiv = FALSE;
991 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
993 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
994 rechts_massiv = TRUE;
996 if (links_massiv && rechts_massiv)
997 graphic = GFX_MAUERWERK;
998 else if (links_massiv)
999 graphic = GFX_MAUER_R;
1000 else if (rechts_massiv)
1001 graphic = GFX_MAUER_L;
1005 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1006 else if (mask_mode == USE_MASKING)
1007 DrawGraphicThruMask(x, y, graphic);
1009 DrawGraphic(x, y, graphic);
1012 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1013 int cut_mode, int mask_mode)
1015 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1016 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1017 cut_mode, mask_mode);
1020 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1023 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1026 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1029 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1032 void DrawScreenElementThruMask(int x, int y, int element)
1034 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1037 void DrawLevelElementThruMask(int x, int y, int element)
1039 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1042 void DrawLevelFieldThruMask(int x, int y)
1044 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1047 void ErdreichAnbroeckeln(int x, int y)
1049 int i, width, height, cx,cy;
1050 int ux = LEVELX(x), uy = LEVELY(y);
1051 int element, graphic;
1053 static int xy[4][2] =
1061 if (!IN_LEV_FIELD(ux, uy))
1064 element = Feld[ux][uy];
1066 if (element == EL_ERDREICH)
1068 if (!IN_SCR_FIELD(x, y))
1071 graphic = GFX_ERDENRAND;
1077 uxx = ux + xy[i][0];
1078 uyy = uy + xy[i][1];
1079 if (!IN_LEV_FIELD(uxx, uyy))
1082 element = Feld[uxx][uyy];
1084 if (element == EL_ERDREICH)
1087 if (i == 1 || i == 2)
1091 cx = (i == 2 ? TILEX - snip : 0);
1099 cy = (i == 3 ? TILEY - snip : 0);
1102 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1103 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1104 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1105 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1108 MarkTileDirty(x, y);
1112 graphic = GFX_ERDENRAND;
1116 int xx, yy, uxx, uyy;
1120 uxx = ux + xy[i][0];
1121 uyy = uy + xy[i][1];
1123 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1124 !IN_SCR_FIELD(xx, yy))
1127 if (i == 1 || i == 2)
1131 cx = (i == 1 ? TILEX - snip : 0);
1139 cy = (i==0 ? TILEY-snip : 0);
1142 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1143 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1144 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1145 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1147 MarkTileDirty(xx, yy);
1152 void DrawScreenElement(int x, int y, int element)
1154 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1155 ErdreichAnbroeckeln(x, y);
1158 void DrawLevelElement(int x, int y, int element)
1160 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1161 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1164 void DrawScreenField(int x, int y)
1166 int ux = LEVELX(x), uy = LEVELY(y);
1169 if (!IN_LEV_FIELD(ux, uy))
1171 DrawScreenElement(x, y, EL_BETON);
1175 element = Feld[ux][uy];
1177 if (IS_MOVING(ux, uy))
1179 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1180 boolean cut_mode = NO_CUTTING;
1182 if (Store[ux][uy] == EL_MORAST_LEER ||
1183 Store[ux][uy] == EL_SIEB_LEER ||
1184 Store[ux][uy] == EL_SIEB2_LEER ||
1185 Store[ux][uy] == EL_AMOEBE_NASS)
1186 cut_mode = CUT_ABOVE;
1187 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1188 Store[ux][uy] == EL_SIEB_VOLL ||
1189 Store[ux][uy] == EL_SIEB2_VOLL)
1190 cut_mode = CUT_BELOW;
1192 if (cut_mode == CUT_ABOVE)
1193 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1195 DrawScreenElement(x, y, EL_LEERRAUM);
1198 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1200 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1202 if (Store[ux][uy] == EL_SALZSAEURE)
1203 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1205 else if (IS_BLOCKED(ux, uy))
1210 boolean cut_mode = NO_CUTTING;
1212 Blocked2Moving(ux, uy, &oldx, &oldy);
1215 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1216 MovDir[oldx][oldy] == MV_RIGHT);
1218 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1219 Store[oldx][oldy] == EL_SIEB_LEER ||
1220 Store[oldx][oldy] == EL_SIEB2_LEER ||
1221 Store[oldx][oldy] == EL_AMOEBE_NASS)
1222 cut_mode = CUT_ABOVE;
1224 DrawScreenElement(x, y, EL_LEERRAUM);
1225 element = Feld[oldx][oldy];
1228 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1230 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1232 else if (IS_DRAWABLE(element))
1233 DrawScreenElement(x, y, element);
1235 DrawScreenElement(x, y, EL_LEERRAUM);
1238 void DrawLevelField(int x, int y)
1240 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1241 DrawScreenField(SCREENX(x), SCREENY(y));
1242 else if (IS_MOVING(x, y))
1246 Moving2Blocked(x, y, &newx, &newy);
1247 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1248 DrawScreenField(SCREENX(newx), SCREENY(newy));
1250 else if (IS_BLOCKED(x, y))
1254 Blocked2Moving(x, y, &oldx, &oldy);
1255 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1256 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1260 void DrawMiniElement(int x, int y, int element)
1266 DrawMiniGraphic(x, y, -1);
1270 graphic = el2gfx(element);
1271 DrawMiniGraphic(x, y, graphic);
1274 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1276 int x = sx + scroll_x, y = sy + scroll_y;
1278 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1279 DrawMiniElement(sx, sy, EL_LEERRAUM);
1280 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1281 DrawMiniElement(sx, sy, EL_BETON);
1283 DrawMiniElement(sx, sy, Feld[x][y]);
1286 void DrawMicroElement(int xpos, int ypos, int element)
1290 if (element == EL_LEERRAUM)
1293 graphic = el2gfx(element);
1295 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1297 graphic -= GFX_START_ROCKSMORE;
1298 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1299 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1300 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1301 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1304 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1305 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1306 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1307 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1316 for(x=BX1; x<=BX2; x++)
1317 for(y=BY1; y<=BY2; y++)
1318 DrawScreenField(x, y);
1320 if (setup.soft_scrolling)
1321 XCopyArea(display, fieldbuffer, backbuffer, gc,
1322 FX, FY, SXSIZE, SYSIZE, SX, SY);
1324 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1327 void DrawMiniLevel(int scroll_x, int scroll_y)
1333 for(x=0; x<2*SCR_FIELDX; x++)
1334 for(y=0; y<2*SCR_FIELDY; y++)
1335 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1337 redraw_mask |= REDRAW_FIELD;
1340 void DrawMicroLevel(int xpos, int ypos)
1344 XFillRectangle(display, drawto, gc,
1345 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1346 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1347 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1348 if (lev_fieldx < STD_LEV_FIELDX)
1349 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1350 if (lev_fieldy < STD_LEV_FIELDY)
1351 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1353 for(x=-1; x<=STD_LEV_FIELDX; x++)
1354 for(y=-1; y<=STD_LEV_FIELDY; y++)
1355 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1356 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1358 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1359 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1362 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1366 int len = strlen(level.name);
1367 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1368 int lypos = MICROLABEL_YPOS;
1370 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1373 redraw_mask |= REDRAW_MICROLEV;
1376 int REQ_in_range(int x, int y)
1378 if (y > DY+249 && y < DY+278)
1380 if (x > DX+1 && x < DX+48)
1382 else if (x > DX+51 && x < DX+98)
1388 boolean Request(char *text, unsigned int req_state)
1390 int mx, my, ty, result = -1;
1391 unsigned int old_door_state;
1394 /* pause network game while waiting for request to answer */
1395 if (options.network &&
1396 game_status == PLAYING &&
1397 req_state & REQUEST_WAIT_FOR)
1398 SendToServer_PausePlaying();
1401 old_door_state = GetDoorState();
1403 CloseDoor(DOOR_CLOSE_1);
1405 /* Alten Türinhalt sichern */
1406 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1407 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1408 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1410 /* Fragetext schreiben */
1411 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1412 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1414 for(ty=0; ty<13; ty++)
1422 for(tl=0,tx=0; tx<7; tl++,tx++)
1425 if (!tc || tc == 32)
1436 DrawTextExt(pix[PIX_DB_DOOR], gc,
1437 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1438 txt, FS_SMALL, FC_YELLOW);
1439 text += tl + (tc == 32 ? 1 : 0);
1442 if (req_state & REQ_ASK)
1444 DrawYesNoButton(BUTTON_OK, DB_INIT);
1445 DrawYesNoButton(BUTTON_NO, DB_INIT);
1447 else if (req_state & REQ_CONFIRM)
1449 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1451 else if (req_state & REQ_PLAYER)
1453 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1454 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1455 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1456 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1459 OpenDoor(DOOR_OPEN_1);
1462 if (!(req_state & REQUEST_WAIT_FOR))
1465 if (game_status != MAINMENU)
1468 button_status = MB_RELEASED;
1472 if (XPending(display))
1476 XNextEvent(display, &event);
1486 if (event.type == MotionNotify)
1488 motion_status = TRUE;
1489 mx = ((XMotionEvent *) &event)->x;
1490 my = ((XMotionEvent *) &event)->y;
1494 motion_status = FALSE;
1495 mx = ((XButtonEvent *) &event)->x;
1496 my = ((XButtonEvent *) &event)->y;
1497 if (event.type==ButtonPress)
1498 button_status = ((XButtonEvent *) &event)->button;
1500 button_status = MB_RELEASED;
1503 if (req_state & REQ_ASK)
1504 choice = CheckYesNoButtons(mx,my,button_status);
1505 else if (req_state & REQ_CONFIRM)
1506 choice = CheckConfirmButton(mx,my,button_status);
1508 choice = CheckPlayerButtons(mx,my,button_status);
1518 case BUTTON_CONFIRM:
1519 result = TRUE | FALSE;
1522 case BUTTON_PLAYER_1:
1525 case BUTTON_PLAYER_2:
1528 case BUTTON_PLAYER_3:
1531 case BUTTON_PLAYER_4:
1542 switch(XLookupKeysym((XKeyEvent *)&event,
1543 ((XKeyEvent *)&event)->state))
1556 if (req_state & REQ_PLAYER)
1561 key_joystick_mapping = 0;
1565 HandleOtherEvents(&event);
1569 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1571 int joy = AnyJoystick();
1573 if (joy & JOY_BUTTON_1)
1575 else if (joy & JOY_BUTTON_2)
1581 /* don't eat all CPU time */
1585 if (game_status != MAINMENU)
1588 if (!(req_state & REQ_STAY_OPEN))
1590 CloseDoor(DOOR_CLOSE_1);
1592 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1594 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1595 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1596 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1597 OpenDoor(DOOR_OPEN_1);
1602 /* continue network game after request */
1603 if (options.network &&
1604 game_status == PLAYING &&
1605 req_state & REQUEST_WAIT_FOR)
1606 SendToServer_ContinuePlaying();
1612 unsigned int OpenDoor(unsigned int door_state)
1614 unsigned int new_door_state;
1616 if (door_state & DOOR_COPY_BACK)
1618 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1619 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1620 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1621 door_state &= ~DOOR_COPY_BACK;
1624 new_door_state = MoveDoor(door_state);
1626 return(new_door_state);
1629 unsigned int CloseDoor(unsigned int door_state)
1631 unsigned int new_door_state;
1633 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1634 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1635 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1636 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1638 new_door_state = MoveDoor(door_state);
1640 return(new_door_state);
1643 unsigned int GetDoorState()
1645 return(MoveDoor(DOOR_GET_STATE));
1648 unsigned int MoveDoor(unsigned int door_state)
1650 static int door1 = DOOR_OPEN_1;
1651 static int door2 = DOOR_CLOSE_2;
1652 static unsigned long door_delay = 0;
1653 int x, start, stepsize = 2;
1654 unsigned long door_delay_value = stepsize * 5;
1656 if (door_state == DOOR_GET_STATE)
1657 return(door1 | door2);
1659 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1660 door_state &= ~DOOR_OPEN_1;
1661 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1662 door_state &= ~DOOR_CLOSE_1;
1663 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1664 door_state &= ~DOOR_OPEN_2;
1665 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1666 door_state &= ~DOOR_CLOSE_2;
1668 if (setup.quick_doors)
1671 door_delay_value = 0;
1672 StopSound(SND_OEFFNEN);
1675 if (door_state & DOOR_ACTION)
1677 if (!(door_state & DOOR_NO_DELAY))
1678 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1680 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1682 for(x=start; x<=DXSIZE; x+=stepsize)
1684 WaitUntilDelayReached(&door_delay, door_delay_value);
1686 if (door_state & DOOR_ACTION_1)
1688 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1689 int j = (DXSIZE - i) / 3;
1691 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1692 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1693 DXSIZE,DYSIZE - i/2, DX, DY);
1695 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1697 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1698 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1699 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1700 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1701 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1702 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1704 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1705 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1706 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1707 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1708 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1709 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1711 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1712 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1714 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1715 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1717 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1718 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1719 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1720 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1721 DX + DXSIZE - i, DY + 77 + j);
1722 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1723 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1724 DX + DXSIZE - i, DY + 203 + j);
1726 redraw_mask |= REDRAW_DOOR_1;
1729 if (door_state & DOOR_ACTION_2)
1731 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1732 int j = (VXSIZE - i) / 3;
1734 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1735 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1736 VXSIZE, VYSIZE - i/2, VX, VY);
1738 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1740 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1741 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1742 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1743 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1744 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1745 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1746 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1747 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1749 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1750 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1751 VX, VY + VYSIZE / 2 - j);
1752 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1753 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1754 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1755 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1756 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1758 redraw_mask |= REDRAW_DOOR_2;
1763 if (game_status == MAINMENU)
1768 if (setup.quick_doors)
1769 StopSound(SND_OEFFNEN);
1771 if (door_state & DOOR_ACTION_1)
1772 door1 = door_state & DOOR_ACTION_1;
1773 if (door_state & DOOR_ACTION_2)
1774 door2 = door_state & DOOR_ACTION_2;
1776 return(door1 | door2);
1779 int ReadPixel(Drawable d, int x, int y)
1781 XImage *pixel_image;
1782 unsigned long pixel_value;
1784 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1785 pixel_value = XGetPixel(pixel_image, 0, 0);
1787 XDestroyImage(pixel_image);
1792 int el2gfx(int element)
1796 case EL_LEERRAUM: return -1;
1797 case EL_ERDREICH: return GFX_ERDREICH;
1798 case EL_MAUERWERK: return GFX_MAUERWERK;
1799 case EL_FELSBODEN: return GFX_FELSBODEN;
1800 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1801 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1802 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1803 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1804 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1805 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1806 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1807 case EL_SPIELER1: return GFX_SPIELER1;
1808 case EL_SPIELER2: return GFX_SPIELER2;
1809 case EL_SPIELER3: return GFX_SPIELER3;
1810 case EL_SPIELER4: return GFX_SPIELER4;
1811 case EL_KAEFER: return GFX_KAEFER;
1812 case EL_KAEFER_R: return GFX_KAEFER_R;
1813 case EL_KAEFER_O: return GFX_KAEFER_O;
1814 case EL_KAEFER_L: return GFX_KAEFER_L;
1815 case EL_KAEFER_U: return GFX_KAEFER_U;
1816 case EL_FLIEGER: return GFX_FLIEGER;
1817 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1818 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1819 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1820 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1821 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1822 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1823 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1824 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1825 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1826 case EL_FIREFLY: return GFX_FIREFLY;
1827 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1828 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1829 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1830 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1831 case EL_MAMPFER: return GFX_MAMPFER;
1832 case EL_ROBOT: return GFX_ROBOT;
1833 case EL_BETON: return GFX_BETON;
1834 case EL_DIAMANT: return GFX_DIAMANT;
1835 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1836 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1837 case EL_TROPFEN: return GFX_TROPFEN;
1838 case EL_BOMBE: return GFX_BOMBE;
1839 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1840 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1841 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1842 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1843 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1844 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1845 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1846 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1847 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1848 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1849 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1850 case EL_LIFE: return GFX_LIFE;
1851 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1852 case EL_DYNAMIT: return GFX_DYNAMIT;
1853 case EL_BADEWANNE: return GFX_BADEWANNE;
1854 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1855 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1856 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1857 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1858 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1859 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1860 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1861 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1862 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1863 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1864 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1865 case EL_PFORTE1: return GFX_PFORTE1;
1866 case EL_PFORTE2: return GFX_PFORTE2;
1867 case EL_PFORTE3: return GFX_PFORTE3;
1868 case EL_PFORTE4: return GFX_PFORTE4;
1869 case EL_PFORTE1X: return GFX_PFORTE1X;
1870 case EL_PFORTE2X: return GFX_PFORTE2X;
1871 case EL_PFORTE3X: return GFX_PFORTE3X;
1872 case EL_PFORTE4X: return GFX_PFORTE4X;
1873 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1874 case EL_PACMAN: return GFX_PACMAN;
1875 case EL_PACMAN_R: return GFX_PACMAN_R;
1876 case EL_PACMAN_O: return GFX_PACMAN_O;
1877 case EL_PACMAN_L: return GFX_PACMAN_L;
1878 case EL_PACMAN_U: return GFX_PACMAN_U;
1879 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1880 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1881 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1882 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1883 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1884 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1885 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1886 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1887 case EL_MAUER_X: return GFX_MAUER_X;
1888 case EL_MAUER_Y: return GFX_MAUER_Y;
1889 case EL_MAUER_XY: return GFX_MAUER_XY;
1890 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1891 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1892 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1893 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1894 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1895 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1896 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1897 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1898 case EL_MAMPFER2: return GFX_MAMPFER2;
1899 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1900 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1901 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1902 case EL_DYNABOMB: return GFX_DYNABOMB;
1903 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1904 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1905 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1906 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1907 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1908 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1909 case EL_MAULWURF: return GFX_MAULWURF;
1910 case EL_PINGUIN: return GFX_PINGUIN;
1911 case EL_SCHWEIN: return GFX_SCHWEIN;
1912 case EL_DRACHE: return GFX_DRACHE;
1913 case EL_SONDE: return GFX_SONDE;
1914 case EL_PFEIL_L: return GFX_PFEIL_L;
1915 case EL_PFEIL_R: return GFX_PFEIL_R;
1916 case EL_PFEIL_O: return GFX_PFEIL_O;
1917 case EL_PFEIL_U: return GFX_PFEIL_U;
1920 if (IS_CHAR(element))
1921 return GFX_CHAR_START + (element - EL_CHAR_START);
1922 else if (element >= EL_SP_START && element <= EL_SP_END)
1923 return GFX_START_ROCKSMORE + (element - EL_SP_START);