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(ScreenMovPos) + ScrollStepSize == TILEX ||
126 ABS(ScreenMovPos) == ScrollStepSize ||
127 redraw_tiles > REDRAWTILES_THRESHOLD)
129 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
133 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
135 (setup.soft_scrolling ?
136 "setup.soft_scrolling" :
137 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
138 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
139 ABS(ScreenGfxPos) == ScrollStepSize ?
140 "ABS(ScreenGfxPos) == ScrollStepSize" :
141 "redraw_tiles > REDRAWTILES_THRESHOLD"));
146 redraw_mask &= ~REDRAW_MAIN;
149 if (redraw_mask & REDRAW_DOORS)
151 if (redraw_mask & REDRAW_DOOR_1)
152 XCopyArea(display,backbuffer,window,gc,
153 DX,DY, DXSIZE,DYSIZE,
155 if (redraw_mask & REDRAW_DOOR_2)
157 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
158 XCopyArea(display,backbuffer,window,gc,
159 VX,VY, VXSIZE,VYSIZE,
163 if (redraw_mask & REDRAW_VIDEO_1)
164 XCopyArea(display,backbuffer,window,gc,
165 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
166 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
167 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
168 if (redraw_mask & REDRAW_VIDEO_2)
169 XCopyArea(display,backbuffer,window,gc,
170 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
171 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
172 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
173 if (redraw_mask & REDRAW_VIDEO_3)
174 XCopyArea(display,backbuffer,window,gc,
175 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
176 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
177 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
180 if (redraw_mask & REDRAW_DOOR_3)
181 XCopyArea(display, backbuffer, window, gc,
182 EX, EY, EXSIZE, EYSIZE,
184 redraw_mask &= ~REDRAW_DOORS;
187 if (redraw_mask & REDRAW_MICROLEV)
189 XCopyArea(display,backbuffer,window,gc,
190 MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
191 MICROLEV_XPOS,MICROLEV_YPOS);
192 XCopyArea(display,backbuffer,window,gc,
193 SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
195 redraw_mask &= ~REDRAW_MICROLEV;
198 if (redraw_mask & REDRAW_TILES)
200 for(x=0; x<SCR_FIELDX; x++)
201 for(y=0; y<SCR_FIELDY; y++)
202 if (redraw[redraw_x1 + x][redraw_y1 + y])
203 XCopyArea(display,buffer,window,gc,
204 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
205 SX+x*TILEX,SY+y*TILEY);
210 for(x=0; x<MAX_BUF_XSIZE; x++)
211 for(y=0; y<MAX_BUF_YSIZE; y++)
220 long fading_delay = 300;
222 if (setup.fading && (redraw_mask & REDRAW_FIELD))
229 XFillRectangle(display,window,gc,
230 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
233 for(i=0;i<2*FULL_SYSIZE;i++)
235 for(y=0;y<FULL_SYSIZE;y++)
237 XCopyArea(display,backbuffer,window,gc,
238 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
246 for(i=1;i<FULL_SYSIZE;i+=2)
247 XCopyArea(display,backbuffer,window,gc,
248 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
254 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
255 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
256 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
260 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
261 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
262 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
266 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
267 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
268 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
272 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
273 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
274 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
278 redraw_mask &= ~REDRAW_MAIN;
287 XFillRectangle(display, backbuffer, gc,
288 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
290 if (setup.soft_scrolling && game_status == PLAYING)
292 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
293 SetDrawtoField(DRAW_BUFFERED);
296 SetDrawtoField(DRAW_BACKBUFFER);
298 if (setup.direct_draw && game_status == PLAYING)
300 XFillRectangle(display, window, gc,
301 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
302 SetDrawtoField(DRAW_DIRECT);
305 redraw_mask |= REDRAW_FIELD;
308 void DrawTextFCentered(int y, int font_type, char *format, ...)
310 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
314 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
315 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
317 va_start(ap, format);
318 vsprintf(buffer, format, ap);
321 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
322 buffer, FS_SMALL, font_type);
325 void DrawTextF(int x, int y, int font_type, char *format, ...)
327 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
330 va_start(ap, format);
331 vsprintf(buffer, format, ap);
334 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
337 void DrawText(int x, int y, char *text, int font_size, int font_type)
339 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
342 redraw_mask |= REDRAW_FIELD;
344 redraw_mask |= REDRAW_DOOR_1;
347 void DrawTextExt(Drawable d, GC gc, int x, int y,
348 char *text, int font_size, int font_type)
350 int font_width, font_height, font_start;
353 if (font_size != FS_SMALL && font_size != FS_BIG)
354 font_size = FS_SMALL;
355 if (font_type < FC_RED || font_type > FC_SPECIAL2)
358 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
359 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
360 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
361 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
362 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
363 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
364 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
365 FONT_LINES_PER_FONT);
371 if (c >= 'a' && c <= 'z')
373 else if (c == 'ä' || c == 'Ä')
375 else if (c == 'ö' || c == 'Ö')
377 else if (c == 'ü' || c == 'Ü')
380 if (c >= 32 && c <= 95)
381 XCopyArea(display, pix[font_pixmap], d, gc,
382 ((c - 32) % FONT_CHARS_PER_LINE) * font_width,
383 ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start,
384 font_width, font_height, x, y);
390 void DrawAllPlayers()
394 for(i=0; i<MAX_PLAYERS; i++)
395 if (stored_player[i].active)
396 DrawPlayer(&stored_player[i]);
399 void DrawPlayerField(int x, int y)
404 DrawPlayer(PLAYERINFO(x,y));
407 void DrawPlayer(struct PlayerInfo *player)
409 int jx = player->jx, jy = player->jy;
410 int last_jx = player->last_jx, last_jy = player->last_jy;
411 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
412 int sx = SCREENX(jx), sy = SCREENY(jy);
413 int sxx = 0, syy = 0;
414 int element = Feld[jx][jy];
417 if (!player->active || player->gone ||
418 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
422 if (!IN_LEV_FIELD(jx,jy))
424 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
425 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
426 printf("DrawPlayerField(): This should never happen!\n");
431 if (element == EL_EXPLODING)
434 /* draw things in the field the player is leaving, if needed */
436 if (last_jx != jx || last_jy != jy)
438 if (Store[last_jx][last_jy])
440 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
441 DrawLevelFieldThruMask(last_jx, last_jy);
443 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
444 DrawDynamite(last_jx, last_jy);
446 DrawLevelField(last_jx, last_jy);
448 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
452 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
453 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
455 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
458 DrawLevelField(next_jx, next_jy);
462 if (!IN_SCR_FIELD(sx, sy))
465 if (setup.direct_draw)
466 SetDrawtoField(DRAW_BUFFERED);
468 /* draw things behind the player, if needed */
471 DrawLevelElement(jx, jy, Store[jx][jy]);
472 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
473 DrawLevelField(jx, jy);
475 /* draw player himself */
477 if (player->MovDir == MV_LEFT)
478 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
479 else if (player->MovDir == MV_RIGHT)
480 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
481 else if (player->MovDir == MV_UP)
482 graphic = GFX_SPIELER1_UP;
483 else /* MV_DOWN || MV_NO_MOVING */
484 graphic = GFX_SPIELER1_DOWN;
486 graphic += player->index_nr * 3*HEROES_PER_LINE;
487 graphic += player->Frame;
491 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
492 sxx = player->GfxPos;
494 syy = player->GfxPos;
497 if (!setup.soft_scrolling && ScreenMovPos)
500 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
502 if (player->Pushing && player->GfxPos)
504 int px = SCREENX(next_jx), py = SCREENY(next_jy);
506 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
507 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
508 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
512 int element = Feld[next_jx][next_jy];
513 int graphic = el2gfx(element);
515 if (element == EL_FELSBROCKEN && sxx)
517 int phase = (player->GfxPos / (TILEX/4));
519 if (player->MovDir == MV_LEFT)
522 graphic += (phase+4)%4;
525 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
529 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
531 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
533 graphic = el2gfx(element);
535 if (element == EL_DYNAMIT)
537 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
542 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
546 if (game_emulation == EMU_SUPAPLEX)
547 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
549 DrawGraphicThruMask(sx, sy, graphic + phase);
552 if ((last_jx != jx || last_jy != jy) &&
553 Feld[last_jx][last_jy] == EL_EXPLODING)
555 int phase = Frame[last_jx][last_jy];
559 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
560 GFX_EXPLOSION + ((phase - 1) / delay - 1));
563 if (setup.direct_draw)
565 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
566 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
567 int x_size = TILEX * (1 + ABS(jx - last_jx));
568 int y_size = TILEY * (1 + ABS(jy - last_jy));
570 XCopyArea(display, drawto_field, window, gc,
571 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
572 SetDrawtoField(DRAW_DIRECT);
575 MarkTileDirty(sx,sy);
578 static int getGraphicAnimationPhase(int frames, int delay, int mode)
582 if (mode == ANIM_OSCILLATE)
584 int max_anim_frames = 2 * frames - 2;
585 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
586 phase = (phase < frames ? phase : max_anim_frames - phase);
589 phase = (FrameCounter % (delay * frames)) / delay;
591 if (mode == ANIM_REVERSE)
597 void DrawGraphicAnimationExt(int x, int y, int graphic,
598 int frames, int delay, int mode, int mask_mode)
600 int phase = getGraphicAnimationPhase(frames, delay, mode);
602 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
604 if (mask_mode == USE_MASKING)
605 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
607 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
611 void DrawGraphicAnimation(int x, int y, int graphic,
612 int frames, int delay, int mode)
614 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
617 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
618 int frames, int delay, int mode)
620 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
623 void DrawGraphic(int x, int y, int graphic)
626 if (!IN_SCR_FIELD(x,y))
628 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
629 printf("DrawGraphic(): This should never happen!\n");
634 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
638 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
640 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
642 graphic -= GFX_START_ROCKSSCREEN;
643 XCopyArea(display, pix[PIX_BACK], d, gc,
644 SX + (graphic % GFX_PER_LINE) * TILEX,
645 SY + (graphic / GFX_PER_LINE) * TILEY,
648 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
650 graphic -= GFX_START_ROCKSMORE;
651 XCopyArea(display, pix[PIX_MORE], d, gc,
652 (graphic % MORE_PER_LINE) * TILEX,
653 (graphic / MORE_PER_LINE) * TILEY,
656 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
658 graphic -= GFX_START_ROCKSHEROES;
659 XCopyArea(display, pix[PIX_HEROES], d, gc,
660 (graphic % HEROES_PER_LINE) * TILEX,
661 (graphic / HEROES_PER_LINE) * TILEY,
664 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
666 graphic -= GFX_START_ROCKSFONT;
667 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
668 (graphic % FONT_CHARS_PER_LINE) * TILEX,
669 (graphic / FONT_CHARS_PER_LINE) * TILEY +
670 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
674 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
677 void DrawGraphicThruMask(int x, int y, int graphic)
680 if (!IN_SCR_FIELD(x,y))
682 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
683 printf("DrawGraphicThruMask(): This should never happen!\n");
688 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
692 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
699 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
701 src_pixmap = pix[PIX_BACK];
702 drawing_gc = clip_gc[PIX_BACK];
703 graphic -= GFX_START_ROCKSSCREEN;
704 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
705 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
707 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
709 src_pixmap = pix[PIX_MORE];
710 drawing_gc = clip_gc[PIX_MORE];
711 graphic -= GFX_START_ROCKSMORE;
712 src_x = (graphic % MORE_PER_LINE) * TILEX;
713 src_y = (graphic / MORE_PER_LINE) * TILEY;
715 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
717 src_pixmap = pix[PIX_HEROES];
718 drawing_gc = clip_gc[PIX_HEROES];
719 graphic -= GFX_START_ROCKSHEROES;
720 src_x = (graphic % HEROES_PER_LINE) * TILEX;
721 src_y = (graphic / HEROES_PER_LINE) * TILEY;
725 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
729 if (tile_clipmask[tile] != None)
731 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
732 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
733 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
734 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
739 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
742 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
743 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
744 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
748 void DrawMiniGraphic(int x, int y, int graphic)
750 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
751 MarkTileDirty(x/2, y/2);
754 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
756 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
758 graphic -= GFX_START_ROCKSSCREEN;
759 XCopyArea(display, pix[PIX_BACK], d, gc,
760 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
761 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
762 MINI_TILEX, MINI_TILEY, x, y);
764 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
766 graphic -= GFX_START_ROCKSMORE;
767 XCopyArea(display, pix[PIX_MORE], d, gc,
768 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
769 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
770 MINI_TILEX, MINI_TILEY, x, y);
772 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
774 graphic -= GFX_START_ROCKSFONT;
775 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
776 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
777 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
778 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
779 MINI_TILEX, MINI_TILEY, x, y);
782 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
785 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
786 int cut_mode, int mask_mode)
788 int width = TILEX, height = TILEY;
790 int src_x, src_y, dest_x, dest_y;
797 DrawGraphic(x, y, graphic);
801 if (dx || dy) /* Verschiebung der Grafik? */
803 if (x < BX1) /* Element kommt von links ins Bild */
810 else if (x > BX2) /* Element kommt von rechts ins Bild */
816 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
822 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
824 else if (dx) /* allg. Bewegung in x-Richtung */
825 MarkTileDirty(x + SIGN(dx), y);
827 if (y < BY1) /* Element kommt von oben ins Bild */
829 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
837 else if (y > BY2) /* Element kommt von unten ins Bild */
843 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
849 else if (dy > 0 && cut_mode == CUT_ABOVE)
851 if (y == BY2) /* Element unterhalb des Bildes */
857 MarkTileDirty(x, y + 1);
858 } /* Element verläßt unten das Bild */
859 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
861 else if (dy) /* allg. Bewegung in y-Richtung */
862 MarkTileDirty(x, y + SIGN(dy));
865 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
867 src_pixmap = pix[PIX_BACK];
868 drawing_gc = clip_gc[PIX_BACK];
869 graphic -= GFX_START_ROCKSSCREEN;
870 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
871 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
873 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
875 src_pixmap = pix[PIX_MORE];
876 drawing_gc = clip_gc[PIX_MORE];
877 graphic -= GFX_START_ROCKSMORE;
878 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
879 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
881 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
883 src_pixmap = pix[PIX_HEROES];
884 drawing_gc = clip_gc[PIX_HEROES];
885 graphic -= GFX_START_ROCKSHEROES;
886 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
887 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
889 else /* big font graphics currently not allowed (and not needed) */
892 dest_x = FX + x * TILEX + dx;
893 dest_y = FY + y * TILEY + dy;
896 if (!IN_SCR_FIELD(x,y))
898 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
899 printf("DrawGraphicShifted(): This should never happen!\n");
904 if (mask_mode == USE_MASKING)
906 if (tile_clipmask[tile] != None)
908 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
909 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
910 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
911 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
916 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
919 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
920 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
921 src_x, src_y, width, height, dest_x, dest_y);
925 XCopyArea(display, src_pixmap, drawto_field, gc,
926 src_x, src_y, width, height, dest_x, dest_y);
931 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
934 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
937 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
938 int cut_mode, int mask_mode)
940 int ux = LEVELX(x), uy = LEVELY(y);
941 int graphic = el2gfx(element);
942 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
943 int phase4 = phase8 / 2;
944 int phase2 = phase8 / 4;
945 int dir = MovDir[ux][uy];
947 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
949 graphic += 4 * !phase2;
953 else if (dir == MV_LEFT)
955 else if (dir == MV_DOWN)
958 else if (element == EL_SP_SNIKSNAK)
961 graphic = GFX_SP_SNIKSNAK_LEFT;
962 else if (dir == MV_RIGHT)
963 graphic = GFX_SP_SNIKSNAK_RIGHT;
964 else if (dir == MV_UP)
965 graphic = GFX_SP_SNIKSNAK_UP;
967 graphic = GFX_SP_SNIKSNAK_DOWN;
969 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
971 else if (element == EL_SP_ELECTRON)
973 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
975 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
976 element == EL_SCHWEIN || element == EL_DRACHE)
979 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
980 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
981 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
982 else if (dir == MV_RIGHT)
983 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
984 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
985 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
986 else if (dir == MV_UP)
987 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
988 element == EL_PINGUIN ? GFX_PINGUIN_UP :
989 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
991 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
992 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
993 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
997 else if (element == EL_SONDE)
999 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1001 else if (element == EL_SALZSAEURE)
1003 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1005 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1009 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
1011 if (element != EL_SP_INFOTRON)
1012 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1014 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1015 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1017 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1019 else if (IS_AMOEBOID(element))
1021 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1022 graphic += (x + 2 * y + 4) % 4;
1024 else if (element == EL_MAUER_LEBT)
1026 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1028 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1029 links_massiv = TRUE;
1030 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1031 rechts_massiv = TRUE;
1033 if (links_massiv && rechts_massiv)
1034 graphic = GFX_MAUERWERK;
1035 else if (links_massiv)
1036 graphic = GFX_MAUER_R;
1037 else if (rechts_massiv)
1038 graphic = GFX_MAUER_L;
1042 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1043 else if (mask_mode == USE_MASKING)
1044 DrawGraphicThruMask(x, y, graphic);
1046 DrawGraphic(x, y, graphic);
1049 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1050 int cut_mode, int mask_mode)
1052 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1053 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1054 cut_mode, mask_mode);
1057 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1060 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1063 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1066 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1069 void DrawScreenElementThruMask(int x, int y, int element)
1071 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1074 void DrawLevelElementThruMask(int x, int y, int element)
1076 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1079 void DrawLevelFieldThruMask(int x, int y)
1081 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1084 void ErdreichAnbroeckeln(int x, int y)
1086 int i, width, height, cx,cy;
1087 int ux = LEVELX(x), uy = LEVELY(y);
1088 int element, graphic;
1090 static int xy[4][2] =
1098 if (!IN_LEV_FIELD(ux, uy))
1101 element = Feld[ux][uy];
1103 if (element == EL_ERDREICH)
1105 if (!IN_SCR_FIELD(x, y))
1108 graphic = GFX_ERDENRAND;
1114 uxx = ux + xy[i][0];
1115 uyy = uy + xy[i][1];
1116 if (!IN_LEV_FIELD(uxx, uyy))
1119 element = Feld[uxx][uyy];
1121 if (element == EL_ERDREICH)
1124 if (i == 1 || i == 2)
1128 cx = (i == 2 ? TILEX - snip : 0);
1136 cy = (i == 3 ? TILEY - snip : 0);
1139 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1140 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1141 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1142 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1145 MarkTileDirty(x, y);
1149 graphic = GFX_ERDENRAND;
1153 int xx, yy, uxx, uyy;
1157 uxx = ux + xy[i][0];
1158 uyy = uy + xy[i][1];
1160 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1161 !IN_SCR_FIELD(xx, yy))
1164 if (i == 1 || i == 2)
1168 cx = (i == 1 ? TILEX - snip : 0);
1176 cy = (i==0 ? TILEY-snip : 0);
1179 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1180 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1181 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1182 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1184 MarkTileDirty(xx, yy);
1189 void DrawScreenElement(int x, int y, int element)
1191 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1192 ErdreichAnbroeckeln(x, y);
1195 void DrawLevelElement(int x, int y, int element)
1197 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1198 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1201 void DrawScreenField(int x, int y)
1203 int ux = LEVELX(x), uy = LEVELY(y);
1206 if (!IN_LEV_FIELD(ux, uy))
1208 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1209 element = EL_LEERRAUM;
1211 element = BorderElement;
1213 DrawScreenElement(x, y, element);
1217 element = Feld[ux][uy];
1219 if (IS_MOVING(ux, uy))
1221 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1222 boolean cut_mode = NO_CUTTING;
1224 if (Store[ux][uy] == EL_MORAST_LEER ||
1225 Store[ux][uy] == EL_SIEB_LEER ||
1226 Store[ux][uy] == EL_SIEB2_LEER ||
1227 Store[ux][uy] == EL_AMOEBE_NASS)
1228 cut_mode = CUT_ABOVE;
1229 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1230 Store[ux][uy] == EL_SIEB_VOLL ||
1231 Store[ux][uy] == EL_SIEB2_VOLL)
1232 cut_mode = CUT_BELOW;
1234 if (cut_mode == CUT_ABOVE)
1235 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1237 DrawScreenElement(x, y, EL_LEERRAUM);
1240 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1242 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1244 if (Store[ux][uy] == EL_SALZSAEURE)
1245 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1247 else if (IS_BLOCKED(ux, uy))
1252 boolean cut_mode = NO_CUTTING;
1254 Blocked2Moving(ux, uy, &oldx, &oldy);
1257 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1258 MovDir[oldx][oldy] == MV_RIGHT);
1260 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1261 Store[oldx][oldy] == EL_SIEB_LEER ||
1262 Store[oldx][oldy] == EL_SIEB2_LEER ||
1263 Store[oldx][oldy] == EL_AMOEBE_NASS)
1264 cut_mode = CUT_ABOVE;
1266 DrawScreenElement(x, y, EL_LEERRAUM);
1267 element = Feld[oldx][oldy];
1270 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1272 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1274 else if (IS_DRAWABLE(element))
1275 DrawScreenElement(x, y, element);
1277 DrawScreenElement(x, y, EL_LEERRAUM);
1280 void DrawLevelField(int x, int y)
1282 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1283 DrawScreenField(SCREENX(x), SCREENY(y));
1284 else if (IS_MOVING(x, y))
1288 Moving2Blocked(x, y, &newx, &newy);
1289 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1290 DrawScreenField(SCREENX(newx), SCREENY(newy));
1292 else if (IS_BLOCKED(x, y))
1296 Blocked2Moving(x, y, &oldx, &oldy);
1297 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1298 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1302 void DrawMiniElement(int x, int y, int element)
1308 DrawMiniGraphic(x, y, -1);
1312 graphic = el2gfx(element);
1313 DrawMiniGraphic(x, y, graphic);
1316 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1318 int x = sx + scroll_x, y = sy + scroll_y;
1320 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1321 DrawMiniElement(sx, sy, EL_LEERRAUM);
1322 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1323 DrawMiniElement(sx, sy, EL_BETON);
1325 DrawMiniElement(sx, sy, Feld[x][y]);
1328 void DrawMicroElement(int xpos, int ypos, int element)
1332 if (element == EL_LEERRAUM)
1335 graphic = el2gfx(element);
1337 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1339 graphic -= GFX_START_ROCKSMORE;
1340 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1341 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1342 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1343 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1346 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1347 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1348 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1349 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1358 for(x=BX1; x<=BX2; x++)
1359 for(y=BY1; y<=BY2; y++)
1360 DrawScreenField(x, y);
1362 if (setup.soft_scrolling)
1363 XCopyArea(display, fieldbuffer, backbuffer, gc,
1364 FX, FY, SXSIZE, SYSIZE, SX, SY);
1366 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1369 void DrawMiniLevel(int scroll_x, int scroll_y)
1375 for(x=0; x<2*SCR_FIELDX; x++)
1376 for(y=0; y<2*SCR_FIELDY; y++)
1377 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1379 redraw_mask |= REDRAW_FIELD;
1382 void DrawMicroLevel(int xpos, int ypos)
1386 /* determine border element for this level */
1389 XFillRectangle(display, drawto, gc,
1390 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1391 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1392 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1393 if (lev_fieldx < STD_LEV_FIELDX)
1394 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1395 if (lev_fieldy < STD_LEV_FIELDY)
1396 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1398 for(x=-1; x<=STD_LEV_FIELDX; x++)
1399 for(y=-1; y<=STD_LEV_FIELDY; y++)
1400 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1401 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1403 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1404 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1407 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1411 int len = strlen(level.name);
1412 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1413 int lypos = MICROLABEL_YPOS;
1415 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1418 redraw_mask |= REDRAW_MICROLEV;
1421 int REQ_in_range(int x, int y)
1423 if (y > DY+249 && y < DY+278)
1425 if (x > DX+1 && x < DX+48)
1427 else if (x > DX+51 && x < DX+98)
1433 boolean Request(char *text, unsigned int req_state)
1435 int mx, my, ty, result = -1;
1436 unsigned int old_door_state;
1439 /* pause network game while waiting for request to answer */
1440 if (options.network &&
1441 game_status == PLAYING &&
1442 req_state & REQUEST_WAIT_FOR)
1443 SendToServer_PausePlaying();
1446 old_door_state = GetDoorState();
1448 CloseDoor(DOOR_CLOSE_1);
1450 /* Alten Türinhalt sichern */
1451 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1452 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1453 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1455 /* Fragetext schreiben */
1456 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1457 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1459 for(ty=0; ty<13; ty++)
1467 for(tl=0,tx=0; tx<7; tl++,tx++)
1470 if (!tc || tc == 32)
1481 DrawTextExt(pix[PIX_DB_DOOR], gc,
1482 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1483 txt, FS_SMALL, FC_YELLOW);
1484 text += tl + (tc == 32 ? 1 : 0);
1487 if (req_state & REQ_ASK)
1489 DrawYesNoButton(BUTTON_OK, DB_INIT);
1490 DrawYesNoButton(BUTTON_NO, DB_INIT);
1492 else if (req_state & REQ_CONFIRM)
1494 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1496 else if (req_state & REQ_PLAYER)
1498 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1499 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1500 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1501 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1504 OpenDoor(DOOR_OPEN_1);
1507 if (!(req_state & REQUEST_WAIT_FOR))
1510 if (game_status != MAINMENU)
1513 button_status = MB_RELEASED;
1517 if (XPending(display))
1521 XNextEvent(display, &event);
1531 if (event.type == MotionNotify)
1533 motion_status = TRUE;
1534 mx = ((XMotionEvent *) &event)->x;
1535 my = ((XMotionEvent *) &event)->y;
1539 motion_status = FALSE;
1540 mx = ((XButtonEvent *) &event)->x;
1541 my = ((XButtonEvent *) &event)->y;
1542 if (event.type==ButtonPress)
1543 button_status = ((XButtonEvent *) &event)->button;
1545 button_status = MB_RELEASED;
1548 if (req_state & REQ_ASK)
1549 choice = CheckYesNoButtons(mx,my,button_status);
1550 else if (req_state & REQ_CONFIRM)
1551 choice = CheckConfirmButton(mx,my,button_status);
1553 choice = CheckPlayerButtons(mx,my,button_status);
1563 case BUTTON_CONFIRM:
1564 result = TRUE | FALSE;
1567 case BUTTON_PLAYER_1:
1570 case BUTTON_PLAYER_2:
1573 case BUTTON_PLAYER_3:
1576 case BUTTON_PLAYER_4:
1587 switch(XLookupKeysym((XKeyEvent *)&event,
1588 ((XKeyEvent *)&event)->state))
1601 if (req_state & REQ_PLAYER)
1606 key_joystick_mapping = 0;
1610 HandleOtherEvents(&event);
1614 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1616 int joy = AnyJoystick();
1618 if (joy & JOY_BUTTON_1)
1620 else if (joy & JOY_BUTTON_2)
1626 /* don't eat all CPU time */
1630 if (game_status != MAINMENU)
1633 if (!(req_state & REQ_STAY_OPEN))
1635 CloseDoor(DOOR_CLOSE_1);
1637 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1639 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1640 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1641 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1642 OpenDoor(DOOR_OPEN_1);
1647 /* continue network game after request */
1648 if (options.network &&
1649 game_status == PLAYING &&
1650 req_state & REQUEST_WAIT_FOR)
1651 SendToServer_ContinuePlaying();
1657 unsigned int OpenDoor(unsigned int door_state)
1659 unsigned int new_door_state;
1661 if (door_state & DOOR_COPY_BACK)
1663 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1664 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1665 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1666 door_state &= ~DOOR_COPY_BACK;
1669 new_door_state = MoveDoor(door_state);
1671 return(new_door_state);
1674 unsigned int CloseDoor(unsigned int door_state)
1676 unsigned int new_door_state;
1678 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1679 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1680 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1681 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1683 new_door_state = MoveDoor(door_state);
1685 return(new_door_state);
1688 unsigned int GetDoorState()
1690 return(MoveDoor(DOOR_GET_STATE));
1693 unsigned int MoveDoor(unsigned int door_state)
1695 static int door1 = DOOR_OPEN_1;
1696 static int door2 = DOOR_CLOSE_2;
1697 static unsigned long door_delay = 0;
1698 int x, start, stepsize = 2;
1699 unsigned long door_delay_value = stepsize * 5;
1701 if (door_state == DOOR_GET_STATE)
1702 return(door1 | door2);
1704 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1705 door_state &= ~DOOR_OPEN_1;
1706 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1707 door_state &= ~DOOR_CLOSE_1;
1708 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1709 door_state &= ~DOOR_OPEN_2;
1710 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1711 door_state &= ~DOOR_CLOSE_2;
1713 if (setup.quick_doors)
1716 door_delay_value = 0;
1717 StopSound(SND_OEFFNEN);
1720 if (door_state & DOOR_ACTION)
1722 if (!(door_state & DOOR_NO_DELAY))
1723 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1725 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1727 for(x=start; x<=DXSIZE; x+=stepsize)
1729 WaitUntilDelayReached(&door_delay, door_delay_value);
1731 if (door_state & DOOR_ACTION_1)
1733 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1734 int j = (DXSIZE - i) / 3;
1736 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1737 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1738 DXSIZE,DYSIZE - i/2, DX, DY);
1740 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1742 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1743 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1744 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1745 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1746 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1747 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1749 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1750 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1751 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1752 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1753 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1754 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1756 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1757 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1759 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1760 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1762 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1763 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1764 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1765 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1766 DX + DXSIZE - i, DY + 77 + j);
1767 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1768 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1769 DX + DXSIZE - i, DY + 203 + j);
1771 redraw_mask |= REDRAW_DOOR_1;
1774 if (door_state & DOOR_ACTION_2)
1776 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1777 int j = (VXSIZE - i) / 3;
1779 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1780 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1781 VXSIZE, VYSIZE - i/2, VX, VY);
1783 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1785 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1786 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1787 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1788 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1789 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1790 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1791 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1792 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1794 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1795 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1796 VX, VY + VYSIZE / 2 - j);
1797 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1798 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1799 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1800 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1801 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1803 redraw_mask |= REDRAW_DOOR_2;
1808 if (game_status == MAINMENU)
1813 if (setup.quick_doors)
1814 StopSound(SND_OEFFNEN);
1816 if (door_state & DOOR_ACTION_1)
1817 door1 = door_state & DOOR_ACTION_1;
1818 if (door_state & DOOR_ACTION_2)
1819 door2 = door_state & DOOR_ACTION_2;
1821 return(door1 | door2);
1824 int ReadPixel(Drawable d, int x, int y)
1826 XImage *pixel_image;
1827 unsigned long pixel_value;
1829 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1830 pixel_value = XGetPixel(pixel_image, 0, 0);
1832 XDestroyImage(pixel_image);
1837 int el2gfx(int element)
1841 case EL_LEERRAUM: return -1;
1842 case EL_ERDREICH: return GFX_ERDREICH;
1843 case EL_MAUERWERK: return GFX_MAUERWERK;
1844 case EL_FELSBODEN: return GFX_FELSBODEN;
1845 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1846 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1847 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1848 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1849 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1850 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1851 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1852 case EL_SPIELER1: return GFX_SPIELER1;
1853 case EL_SPIELER2: return GFX_SPIELER2;
1854 case EL_SPIELER3: return GFX_SPIELER3;
1855 case EL_SPIELER4: return GFX_SPIELER4;
1856 case EL_KAEFER: return GFX_KAEFER;
1857 case EL_KAEFER_R: return GFX_KAEFER_R;
1858 case EL_KAEFER_O: return GFX_KAEFER_O;
1859 case EL_KAEFER_L: return GFX_KAEFER_L;
1860 case EL_KAEFER_U: return GFX_KAEFER_U;
1861 case EL_FLIEGER: return GFX_FLIEGER;
1862 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1863 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1864 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1865 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1866 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1867 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1868 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1869 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1870 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1871 case EL_FIREFLY: return GFX_FIREFLY;
1872 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1873 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1874 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1875 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1876 case EL_MAMPFER: return GFX_MAMPFER;
1877 case EL_ROBOT: return GFX_ROBOT;
1878 case EL_BETON: return GFX_BETON;
1879 case EL_DIAMANT: return GFX_DIAMANT;
1880 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1881 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1882 case EL_TROPFEN: return GFX_TROPFEN;
1883 case EL_BOMBE: return GFX_BOMBE;
1884 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
1885 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1886 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1887 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1888 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1889 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1890 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1891 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1892 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1893 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1894 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1895 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1896 case EL_LIFE: return GFX_LIFE;
1897 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1898 case EL_DYNAMIT: return GFX_DYNAMIT;
1899 case EL_BADEWANNE: return GFX_BADEWANNE;
1900 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1901 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1902 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1903 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1904 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1905 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1906 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1907 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1908 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1909 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1910 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1911 case EL_PFORTE1: return GFX_PFORTE1;
1912 case EL_PFORTE2: return GFX_PFORTE2;
1913 case EL_PFORTE3: return GFX_PFORTE3;
1914 case EL_PFORTE4: return GFX_PFORTE4;
1915 case EL_PFORTE1X: return GFX_PFORTE1X;
1916 case EL_PFORTE2X: return GFX_PFORTE2X;
1917 case EL_PFORTE3X: return GFX_PFORTE3X;
1918 case EL_PFORTE4X: return GFX_PFORTE4X;
1919 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1920 case EL_PACMAN: return GFX_PACMAN;
1921 case EL_PACMAN_R: return GFX_PACMAN_R;
1922 case EL_PACMAN_O: return GFX_PACMAN_O;
1923 case EL_PACMAN_L: return GFX_PACMAN_L;
1924 case EL_PACMAN_U: return GFX_PACMAN_U;
1925 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1926 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1927 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1928 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1929 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1930 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1931 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1932 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1933 case EL_MAUER_X: return GFX_MAUER_X;
1934 case EL_MAUER_Y: return GFX_MAUER_Y;
1935 case EL_MAUER_XY: return GFX_MAUER_XY;
1936 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1937 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1938 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1939 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1940 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1941 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1942 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1943 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1944 case EL_MAMPFER2: return GFX_MAMPFER2;
1945 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
1946 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1947 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1948 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1949 case EL_DYNABOMB: return GFX_DYNABOMB;
1950 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1951 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1952 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1953 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1954 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1955 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1956 case EL_MAULWURF: return GFX_MAULWURF;
1957 case EL_PINGUIN: return GFX_PINGUIN;
1958 case EL_SCHWEIN: return GFX_SCHWEIN;
1959 case EL_DRACHE: return GFX_DRACHE;
1960 case EL_SONDE: return GFX_SONDE;
1961 case EL_PFEIL_L: return GFX_PFEIL_L;
1962 case EL_PFEIL_R: return GFX_PFEIL_R;
1963 case EL_PFEIL_O: return GFX_PFEIL_O;
1964 case EL_PFEIL_U: return GFX_PFEIL_U;
1965 case EL_SPEED_PILL: return GFX_SPEED_PILL;
1966 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
1967 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
1971 if (IS_CHAR(element))
1972 return GFX_CHAR_START + (element - EL_CHAR_START);
1973 else if (element >= EL_SP_START && element <= EL_SP_END)
1975 int nr_element = element - EL_SP_START;
1976 int gfx_per_line = 8;
1978 (nr_element / gfx_per_line) * MORE_PER_LINE +
1979 (nr_element % gfx_per_line);
1981 return GFX_START_ROCKSMORE + nr_graphic;