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)
1373 for(x=0; x<ED_FIELDX; x++)
1374 for(y=0; y<ED_FIELDY; y++)
1375 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1377 redraw_mask |= REDRAW_FIELD;
1380 void DrawMicroLevel(int xpos, int ypos)
1384 /* determine border element for this level */
1387 XFillRectangle(display, drawto, gc,
1388 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1389 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1390 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1391 if (lev_fieldx < STD_LEV_FIELDX)
1392 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1393 if (lev_fieldy < STD_LEV_FIELDY)
1394 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1396 for(x=-1; x<=STD_LEV_FIELDX; x++)
1397 for(y=-1; y<=STD_LEV_FIELDY; y++)
1398 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1399 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1401 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1402 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1405 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1409 int len = strlen(level.name);
1410 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1411 int lypos = MICROLABEL_YPOS;
1413 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1416 redraw_mask |= REDRAW_MICROLEV;
1419 int REQ_in_range(int x, int y)
1421 if (y > DY+249 && y < DY+278)
1423 if (x > DX+1 && x < DX+48)
1425 else if (x > DX+51 && x < DX+98)
1431 boolean Request(char *text, unsigned int req_state)
1433 int mx, my, ty, result = -1;
1434 unsigned int old_door_state;
1437 /* pause network game while waiting for request to answer */
1438 if (options.network &&
1439 game_status == PLAYING &&
1440 req_state & REQUEST_WAIT_FOR)
1441 SendToServer_PausePlaying();
1444 old_door_state = GetDoorState();
1446 CloseDoor(DOOR_CLOSE_1);
1448 /* Alten Türinhalt sichern */
1449 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1450 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1451 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1453 /* Fragetext schreiben */
1454 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1455 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1457 for(ty=0; ty<13; ty++)
1465 for(tl=0,tx=0; tx<7; tl++,tx++)
1468 if (!tc || tc == 32)
1479 DrawTextExt(pix[PIX_DB_DOOR], gc,
1480 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1481 txt, FS_SMALL, FC_YELLOW);
1482 text += tl + (tc == 32 ? 1 : 0);
1485 if (req_state & REQ_ASK)
1487 DrawYesNoButton(BUTTON_OK, DB_INIT);
1488 DrawYesNoButton(BUTTON_NO, DB_INIT);
1490 else if (req_state & REQ_CONFIRM)
1492 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1494 else if (req_state & REQ_PLAYER)
1496 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1497 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1498 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1499 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1502 OpenDoor(DOOR_OPEN_1);
1505 if (!(req_state & REQUEST_WAIT_FOR))
1508 if (game_status != MAINMENU)
1511 button_status = MB_RELEASED;
1515 if (XPending(display))
1519 XNextEvent(display, &event);
1529 if (event.type == MotionNotify)
1531 motion_status = TRUE;
1532 mx = ((XMotionEvent *) &event)->x;
1533 my = ((XMotionEvent *) &event)->y;
1537 motion_status = FALSE;
1538 mx = ((XButtonEvent *) &event)->x;
1539 my = ((XButtonEvent *) &event)->y;
1540 if (event.type==ButtonPress)
1541 button_status = ((XButtonEvent *) &event)->button;
1543 button_status = MB_RELEASED;
1546 if (req_state & REQ_ASK)
1547 choice = CheckYesNoButtons(mx,my,button_status);
1548 else if (req_state & REQ_CONFIRM)
1549 choice = CheckConfirmButton(mx,my,button_status);
1551 choice = CheckPlayerButtons(mx,my,button_status);
1561 case BUTTON_CONFIRM:
1562 result = TRUE | FALSE;
1565 case BUTTON_PLAYER_1:
1568 case BUTTON_PLAYER_2:
1571 case BUTTON_PLAYER_3:
1574 case BUTTON_PLAYER_4:
1585 switch(XLookupKeysym((XKeyEvent *)&event,
1586 ((XKeyEvent *)&event)->state))
1599 if (req_state & REQ_PLAYER)
1604 key_joystick_mapping = 0;
1608 HandleOtherEvents(&event);
1612 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1614 int joy = AnyJoystick();
1616 if (joy & JOY_BUTTON_1)
1618 else if (joy & JOY_BUTTON_2)
1624 /* don't eat all CPU time */
1628 if (game_status != MAINMENU)
1631 if (!(req_state & REQ_STAY_OPEN))
1633 CloseDoor(DOOR_CLOSE_1);
1635 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1637 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1638 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1639 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1640 OpenDoor(DOOR_OPEN_1);
1645 /* continue network game after request */
1646 if (options.network &&
1647 game_status == PLAYING &&
1648 req_state & REQUEST_WAIT_FOR)
1649 SendToServer_ContinuePlaying();
1655 unsigned int OpenDoor(unsigned int door_state)
1657 unsigned int new_door_state;
1659 if (door_state & DOOR_COPY_BACK)
1661 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1662 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1663 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1664 door_state &= ~DOOR_COPY_BACK;
1667 new_door_state = MoveDoor(door_state);
1669 return(new_door_state);
1672 unsigned int CloseDoor(unsigned int door_state)
1674 unsigned int new_door_state;
1676 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1677 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1678 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1679 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1681 new_door_state = MoveDoor(door_state);
1683 return(new_door_state);
1686 unsigned int GetDoorState()
1688 return(MoveDoor(DOOR_GET_STATE));
1691 unsigned int MoveDoor(unsigned int door_state)
1693 static int door1 = DOOR_OPEN_1;
1694 static int door2 = DOOR_CLOSE_2;
1695 static unsigned long door_delay = 0;
1696 int x, start, stepsize = 2;
1697 unsigned long door_delay_value = stepsize * 5;
1699 if (door_state == DOOR_GET_STATE)
1700 return(door1 | door2);
1702 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1703 door_state &= ~DOOR_OPEN_1;
1704 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1705 door_state &= ~DOOR_CLOSE_1;
1706 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1707 door_state &= ~DOOR_OPEN_2;
1708 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1709 door_state &= ~DOOR_CLOSE_2;
1711 if (setup.quick_doors)
1714 door_delay_value = 0;
1715 StopSound(SND_OEFFNEN);
1718 if (door_state & DOOR_ACTION)
1720 if (!(door_state & DOOR_NO_DELAY))
1721 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1723 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1725 for(x=start; x<=DXSIZE; x+=stepsize)
1727 WaitUntilDelayReached(&door_delay, door_delay_value);
1729 if (door_state & DOOR_ACTION_1)
1731 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1732 int j = (DXSIZE - i) / 3;
1734 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1735 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1736 DXSIZE,DYSIZE - i/2, DX, DY);
1738 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1740 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1741 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1742 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1743 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1744 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1745 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1747 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1748 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1749 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1750 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1751 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1752 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1754 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1755 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1757 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1758 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1760 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1761 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1762 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1763 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1764 DX + DXSIZE - i, DY + 77 + j);
1765 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1766 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1767 DX + DXSIZE - i, DY + 203 + j);
1769 redraw_mask |= REDRAW_DOOR_1;
1772 if (door_state & DOOR_ACTION_2)
1774 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1775 int j = (VXSIZE - i) / 3;
1777 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1778 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1779 VXSIZE, VYSIZE - i/2, VX, VY);
1781 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1783 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1784 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1785 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1786 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1787 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1788 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1789 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1790 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1792 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1793 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1794 VX, VY + VYSIZE / 2 - j);
1795 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1796 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1797 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1798 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1799 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1801 redraw_mask |= REDRAW_DOOR_2;
1806 if (game_status == MAINMENU)
1811 if (setup.quick_doors)
1812 StopSound(SND_OEFFNEN);
1814 if (door_state & DOOR_ACTION_1)
1815 door1 = door_state & DOOR_ACTION_1;
1816 if (door_state & DOOR_ACTION_2)
1817 door2 = door_state & DOOR_ACTION_2;
1819 return(door1 | door2);
1822 int ReadPixel(Drawable d, int x, int y)
1824 XImage *pixel_image;
1825 unsigned long pixel_value;
1827 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1828 pixel_value = XGetPixel(pixel_image, 0, 0);
1830 XDestroyImage(pixel_image);
1835 int el2gfx(int element)
1839 case EL_LEERRAUM: return -1;
1840 case EL_ERDREICH: return GFX_ERDREICH;
1841 case EL_MAUERWERK: return GFX_MAUERWERK;
1842 case EL_FELSBODEN: return GFX_FELSBODEN;
1843 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1844 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1845 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1846 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1847 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1848 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1849 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1850 case EL_SPIELER1: return GFX_SPIELER1;
1851 case EL_SPIELER2: return GFX_SPIELER2;
1852 case EL_SPIELER3: return GFX_SPIELER3;
1853 case EL_SPIELER4: return GFX_SPIELER4;
1854 case EL_KAEFER: return GFX_KAEFER;
1855 case EL_KAEFER_R: return GFX_KAEFER_R;
1856 case EL_KAEFER_O: return GFX_KAEFER_O;
1857 case EL_KAEFER_L: return GFX_KAEFER_L;
1858 case EL_KAEFER_U: return GFX_KAEFER_U;
1859 case EL_FLIEGER: return GFX_FLIEGER;
1860 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1861 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1862 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1863 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1864 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1865 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1866 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1867 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1868 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1869 case EL_FIREFLY: return GFX_FIREFLY;
1870 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1871 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1872 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1873 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1874 case EL_MAMPFER: return GFX_MAMPFER;
1875 case EL_ROBOT: return GFX_ROBOT;
1876 case EL_BETON: return GFX_BETON;
1877 case EL_DIAMANT: return GFX_DIAMANT;
1878 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1879 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1880 case EL_TROPFEN: return GFX_TROPFEN;
1881 case EL_BOMBE: return GFX_BOMBE;
1882 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
1883 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1884 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1885 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1886 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1887 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1888 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1889 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1890 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1891 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1892 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1893 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1894 case EL_LIFE: return GFX_LIFE;
1895 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1896 case EL_DYNAMIT: return GFX_DYNAMIT;
1897 case EL_BADEWANNE: return GFX_BADEWANNE;
1898 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1899 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1900 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1901 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1902 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1903 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1904 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1905 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1906 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1907 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1908 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1909 case EL_PFORTE1: return GFX_PFORTE1;
1910 case EL_PFORTE2: return GFX_PFORTE2;
1911 case EL_PFORTE3: return GFX_PFORTE3;
1912 case EL_PFORTE4: return GFX_PFORTE4;
1913 case EL_PFORTE1X: return GFX_PFORTE1X;
1914 case EL_PFORTE2X: return GFX_PFORTE2X;
1915 case EL_PFORTE3X: return GFX_PFORTE3X;
1916 case EL_PFORTE4X: return GFX_PFORTE4X;
1917 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1918 case EL_PACMAN: return GFX_PACMAN;
1919 case EL_PACMAN_R: return GFX_PACMAN_R;
1920 case EL_PACMAN_O: return GFX_PACMAN_O;
1921 case EL_PACMAN_L: return GFX_PACMAN_L;
1922 case EL_PACMAN_U: return GFX_PACMAN_U;
1923 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1924 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1925 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1926 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1927 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1928 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1929 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1930 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1931 case EL_MAUER_X: return GFX_MAUER_X;
1932 case EL_MAUER_Y: return GFX_MAUER_Y;
1933 case EL_MAUER_XY: return GFX_MAUER_XY;
1934 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1935 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1936 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1937 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1938 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1939 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1940 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1941 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1942 case EL_MAMPFER2: return GFX_MAMPFER2;
1943 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
1944 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1945 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1946 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1947 case EL_DYNABOMB: return GFX_DYNABOMB;
1948 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1949 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1950 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1951 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1952 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1953 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1954 case EL_MAULWURF: return GFX_MAULWURF;
1955 case EL_PINGUIN: return GFX_PINGUIN;
1956 case EL_SCHWEIN: return GFX_SCHWEIN;
1957 case EL_DRACHE: return GFX_DRACHE;
1958 case EL_SONDE: return GFX_SONDE;
1959 case EL_PFEIL_L: return GFX_PFEIL_L;
1960 case EL_PFEIL_R: return GFX_PFEIL_R;
1961 case EL_PFEIL_O: return GFX_PFEIL_O;
1962 case EL_PFEIL_U: return GFX_PFEIL_U;
1963 case EL_SPEED_PILL: return GFX_SPEED_PILL;
1964 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
1965 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
1969 if (IS_CHAR(element))
1970 return GFX_CHAR_START + (element - EL_CHAR_START);
1971 else if (element >= EL_SP_START && element <= EL_SP_END)
1973 int nr_element = element - EL_SP_START;
1974 int gfx_per_line = 8;
1976 (nr_element / gfx_per_line) * MORE_PER_LINE +
1977 (nr_element % gfx_per_line);
1979 return GFX_START_ROCKSMORE + nr_graphic;