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 DrawScreenElement(x, y, EL_BETON);
1212 element = Feld[ux][uy];
1214 if (IS_MOVING(ux, uy))
1216 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1217 boolean cut_mode = NO_CUTTING;
1219 if (Store[ux][uy] == EL_MORAST_LEER ||
1220 Store[ux][uy] == EL_SIEB_LEER ||
1221 Store[ux][uy] == EL_SIEB2_LEER ||
1222 Store[ux][uy] == EL_AMOEBE_NASS)
1223 cut_mode = CUT_ABOVE;
1224 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1225 Store[ux][uy] == EL_SIEB_VOLL ||
1226 Store[ux][uy] == EL_SIEB2_VOLL)
1227 cut_mode = CUT_BELOW;
1229 if (cut_mode == CUT_ABOVE)
1230 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1232 DrawScreenElement(x, y, EL_LEERRAUM);
1235 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1237 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1239 if (Store[ux][uy] == EL_SALZSAEURE)
1240 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1242 else if (IS_BLOCKED(ux, uy))
1247 boolean cut_mode = NO_CUTTING;
1249 Blocked2Moving(ux, uy, &oldx, &oldy);
1252 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1253 MovDir[oldx][oldy] == MV_RIGHT);
1255 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1256 Store[oldx][oldy] == EL_SIEB_LEER ||
1257 Store[oldx][oldy] == EL_SIEB2_LEER ||
1258 Store[oldx][oldy] == EL_AMOEBE_NASS)
1259 cut_mode = CUT_ABOVE;
1261 DrawScreenElement(x, y, EL_LEERRAUM);
1262 element = Feld[oldx][oldy];
1265 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1267 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1269 else if (IS_DRAWABLE(element))
1270 DrawScreenElement(x, y, element);
1272 DrawScreenElement(x, y, EL_LEERRAUM);
1275 void DrawLevelField(int x, int y)
1277 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1278 DrawScreenField(SCREENX(x), SCREENY(y));
1279 else if (IS_MOVING(x, y))
1283 Moving2Blocked(x, y, &newx, &newy);
1284 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1285 DrawScreenField(SCREENX(newx), SCREENY(newy));
1287 else if (IS_BLOCKED(x, y))
1291 Blocked2Moving(x, y, &oldx, &oldy);
1292 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1293 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1297 void DrawMiniElement(int x, int y, int element)
1303 DrawMiniGraphic(x, y, -1);
1307 graphic = el2gfx(element);
1308 DrawMiniGraphic(x, y, graphic);
1311 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1313 int x = sx + scroll_x, y = sy + scroll_y;
1315 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1316 DrawMiniElement(sx, sy, EL_LEERRAUM);
1317 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1318 DrawMiniElement(sx, sy, EL_BETON);
1320 DrawMiniElement(sx, sy, Feld[x][y]);
1323 void DrawMicroElement(int xpos, int ypos, int element)
1327 if (element == EL_LEERRAUM)
1330 graphic = el2gfx(element);
1332 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1334 graphic -= GFX_START_ROCKSMORE;
1335 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1336 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1337 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1338 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1341 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1342 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1343 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1344 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1353 for(x=BX1; x<=BX2; x++)
1354 for(y=BY1; y<=BY2; y++)
1355 DrawScreenField(x, y);
1357 if (setup.soft_scrolling)
1358 XCopyArea(display, fieldbuffer, backbuffer, gc,
1359 FX, FY, SXSIZE, SYSIZE, SX, SY);
1361 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1364 void DrawMiniLevel(int scroll_x, int scroll_y)
1370 for(x=0; x<2*SCR_FIELDX; x++)
1371 for(y=0; y<2*SCR_FIELDY; y++)
1372 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1374 redraw_mask |= REDRAW_FIELD;
1377 void DrawMicroLevel(int xpos, int ypos)
1381 XFillRectangle(display, drawto, gc,
1382 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1383 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1384 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1385 if (lev_fieldx < STD_LEV_FIELDX)
1386 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1387 if (lev_fieldy < STD_LEV_FIELDY)
1388 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1390 for(x=-1; x<=STD_LEV_FIELDX; x++)
1391 for(y=-1; y<=STD_LEV_FIELDY; y++)
1392 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1393 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1395 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1396 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1399 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1403 int len = strlen(level.name);
1404 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1405 int lypos = MICROLABEL_YPOS;
1407 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1410 redraw_mask |= REDRAW_MICROLEV;
1413 int REQ_in_range(int x, int y)
1415 if (y > DY+249 && y < DY+278)
1417 if (x > DX+1 && x < DX+48)
1419 else if (x > DX+51 && x < DX+98)
1425 boolean Request(char *text, unsigned int req_state)
1427 int mx, my, ty, result = -1;
1428 unsigned int old_door_state;
1431 /* pause network game while waiting for request to answer */
1432 if (options.network &&
1433 game_status == PLAYING &&
1434 req_state & REQUEST_WAIT_FOR)
1435 SendToServer_PausePlaying();
1438 old_door_state = GetDoorState();
1440 CloseDoor(DOOR_CLOSE_1);
1442 /* Alten Türinhalt sichern */
1443 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1444 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1445 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1447 /* Fragetext schreiben */
1448 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1449 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1451 for(ty=0; ty<13; ty++)
1459 for(tl=0,tx=0; tx<7; tl++,tx++)
1462 if (!tc || tc == 32)
1473 DrawTextExt(pix[PIX_DB_DOOR], gc,
1474 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1475 txt, FS_SMALL, FC_YELLOW);
1476 text += tl + (tc == 32 ? 1 : 0);
1479 if (req_state & REQ_ASK)
1481 DrawYesNoButton(BUTTON_OK, DB_INIT);
1482 DrawYesNoButton(BUTTON_NO, DB_INIT);
1484 else if (req_state & REQ_CONFIRM)
1486 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1488 else if (req_state & REQ_PLAYER)
1490 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1491 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1492 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1493 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1496 OpenDoor(DOOR_OPEN_1);
1499 if (!(req_state & REQUEST_WAIT_FOR))
1502 if (game_status != MAINMENU)
1505 button_status = MB_RELEASED;
1509 if (XPending(display))
1513 XNextEvent(display, &event);
1523 if (event.type == MotionNotify)
1525 motion_status = TRUE;
1526 mx = ((XMotionEvent *) &event)->x;
1527 my = ((XMotionEvent *) &event)->y;
1531 motion_status = FALSE;
1532 mx = ((XButtonEvent *) &event)->x;
1533 my = ((XButtonEvent *) &event)->y;
1534 if (event.type==ButtonPress)
1535 button_status = ((XButtonEvent *) &event)->button;
1537 button_status = MB_RELEASED;
1540 if (req_state & REQ_ASK)
1541 choice = CheckYesNoButtons(mx,my,button_status);
1542 else if (req_state & REQ_CONFIRM)
1543 choice = CheckConfirmButton(mx,my,button_status);
1545 choice = CheckPlayerButtons(mx,my,button_status);
1555 case BUTTON_CONFIRM:
1556 result = TRUE | FALSE;
1559 case BUTTON_PLAYER_1:
1562 case BUTTON_PLAYER_2:
1565 case BUTTON_PLAYER_3:
1568 case BUTTON_PLAYER_4:
1579 switch(XLookupKeysym((XKeyEvent *)&event,
1580 ((XKeyEvent *)&event)->state))
1593 if (req_state & REQ_PLAYER)
1598 key_joystick_mapping = 0;
1602 HandleOtherEvents(&event);
1606 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1608 int joy = AnyJoystick();
1610 if (joy & JOY_BUTTON_1)
1612 else if (joy & JOY_BUTTON_2)
1618 /* don't eat all CPU time */
1622 if (game_status != MAINMENU)
1625 if (!(req_state & REQ_STAY_OPEN))
1627 CloseDoor(DOOR_CLOSE_1);
1629 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1631 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1632 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1633 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1634 OpenDoor(DOOR_OPEN_1);
1639 /* continue network game after request */
1640 if (options.network &&
1641 game_status == PLAYING &&
1642 req_state & REQUEST_WAIT_FOR)
1643 SendToServer_ContinuePlaying();
1649 unsigned int OpenDoor(unsigned int door_state)
1651 unsigned int new_door_state;
1653 if (door_state & DOOR_COPY_BACK)
1655 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1656 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1657 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1658 door_state &= ~DOOR_COPY_BACK;
1661 new_door_state = MoveDoor(door_state);
1663 return(new_door_state);
1666 unsigned int CloseDoor(unsigned int door_state)
1668 unsigned int new_door_state;
1670 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1671 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1672 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1673 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1675 new_door_state = MoveDoor(door_state);
1677 return(new_door_state);
1680 unsigned int GetDoorState()
1682 return(MoveDoor(DOOR_GET_STATE));
1685 unsigned int MoveDoor(unsigned int door_state)
1687 static int door1 = DOOR_OPEN_1;
1688 static int door2 = DOOR_CLOSE_2;
1689 static unsigned long door_delay = 0;
1690 int x, start, stepsize = 2;
1691 unsigned long door_delay_value = stepsize * 5;
1693 if (door_state == DOOR_GET_STATE)
1694 return(door1 | door2);
1696 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1697 door_state &= ~DOOR_OPEN_1;
1698 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1699 door_state &= ~DOOR_CLOSE_1;
1700 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1701 door_state &= ~DOOR_OPEN_2;
1702 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1703 door_state &= ~DOOR_CLOSE_2;
1705 if (setup.quick_doors)
1708 door_delay_value = 0;
1709 StopSound(SND_OEFFNEN);
1712 if (door_state & DOOR_ACTION)
1714 if (!(door_state & DOOR_NO_DELAY))
1715 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1717 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1719 for(x=start; x<=DXSIZE; x+=stepsize)
1721 WaitUntilDelayReached(&door_delay, door_delay_value);
1723 if (door_state & DOOR_ACTION_1)
1725 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1726 int j = (DXSIZE - i) / 3;
1728 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1729 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1730 DXSIZE,DYSIZE - i/2, DX, DY);
1732 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1734 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1735 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1736 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1737 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1738 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1739 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1741 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1742 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1743 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1744 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1745 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1746 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1748 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1749 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1751 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1752 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1754 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1755 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1756 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1757 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1758 DX + DXSIZE - i, DY + 77 + j);
1759 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1760 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1761 DX + DXSIZE - i, DY + 203 + j);
1763 redraw_mask |= REDRAW_DOOR_1;
1766 if (door_state & DOOR_ACTION_2)
1768 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1769 int j = (VXSIZE - i) / 3;
1771 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1772 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1773 VXSIZE, VYSIZE - i/2, VX, VY);
1775 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1777 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1778 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1779 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1780 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1781 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1782 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1783 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1784 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1786 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1787 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1788 VX, VY + VYSIZE / 2 - j);
1789 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1790 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1791 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1792 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1793 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1795 redraw_mask |= REDRAW_DOOR_2;
1800 if (game_status == MAINMENU)
1805 if (setup.quick_doors)
1806 StopSound(SND_OEFFNEN);
1808 if (door_state & DOOR_ACTION_1)
1809 door1 = door_state & DOOR_ACTION_1;
1810 if (door_state & DOOR_ACTION_2)
1811 door2 = door_state & DOOR_ACTION_2;
1813 return(door1 | door2);
1816 int ReadPixel(Drawable d, int x, int y)
1818 XImage *pixel_image;
1819 unsigned long pixel_value;
1821 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1822 pixel_value = XGetPixel(pixel_image, 0, 0);
1824 XDestroyImage(pixel_image);
1829 int el2gfx(int element)
1833 case EL_LEERRAUM: return -1;
1834 case EL_ERDREICH: return GFX_ERDREICH;
1835 case EL_MAUERWERK: return GFX_MAUERWERK;
1836 case EL_FELSBODEN: return GFX_FELSBODEN;
1837 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1838 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1839 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1840 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1841 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1842 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1843 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1844 case EL_SPIELER1: return GFX_SPIELER1;
1845 case EL_SPIELER2: return GFX_SPIELER2;
1846 case EL_SPIELER3: return GFX_SPIELER3;
1847 case EL_SPIELER4: return GFX_SPIELER4;
1848 case EL_KAEFER: return GFX_KAEFER;
1849 case EL_KAEFER_R: return GFX_KAEFER_R;
1850 case EL_KAEFER_O: return GFX_KAEFER_O;
1851 case EL_KAEFER_L: return GFX_KAEFER_L;
1852 case EL_KAEFER_U: return GFX_KAEFER_U;
1853 case EL_FLIEGER: return GFX_FLIEGER;
1854 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1855 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1856 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1857 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1858 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1859 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1860 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1861 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1862 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1863 case EL_FIREFLY: return GFX_FIREFLY;
1864 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1865 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1866 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1867 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1868 case EL_MAMPFER: return GFX_MAMPFER;
1869 case EL_ROBOT: return GFX_ROBOT;
1870 case EL_BETON: return GFX_BETON;
1871 case EL_DIAMANT: return GFX_DIAMANT;
1872 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1873 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1874 case EL_TROPFEN: return GFX_TROPFEN;
1875 case EL_BOMBE: return GFX_BOMBE;
1876 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
1877 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1878 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1879 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1880 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1881 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1882 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1883 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1884 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1885 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1886 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1887 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1888 case EL_LIFE: return GFX_LIFE;
1889 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1890 case EL_DYNAMIT: return GFX_DYNAMIT;
1891 case EL_BADEWANNE: return GFX_BADEWANNE;
1892 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1893 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1894 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1895 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1896 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1897 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1898 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1899 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1900 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1901 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1902 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1903 case EL_PFORTE1: return GFX_PFORTE1;
1904 case EL_PFORTE2: return GFX_PFORTE2;
1905 case EL_PFORTE3: return GFX_PFORTE3;
1906 case EL_PFORTE4: return GFX_PFORTE4;
1907 case EL_PFORTE1X: return GFX_PFORTE1X;
1908 case EL_PFORTE2X: return GFX_PFORTE2X;
1909 case EL_PFORTE3X: return GFX_PFORTE3X;
1910 case EL_PFORTE4X: return GFX_PFORTE4X;
1911 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1912 case EL_PACMAN: return GFX_PACMAN;
1913 case EL_PACMAN_R: return GFX_PACMAN_R;
1914 case EL_PACMAN_O: return GFX_PACMAN_O;
1915 case EL_PACMAN_L: return GFX_PACMAN_L;
1916 case EL_PACMAN_U: return GFX_PACMAN_U;
1917 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1918 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1919 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1920 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1921 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1922 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1923 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1924 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1925 case EL_MAUER_X: return GFX_MAUER_X;
1926 case EL_MAUER_Y: return GFX_MAUER_Y;
1927 case EL_MAUER_XY: return GFX_MAUER_XY;
1928 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1929 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1930 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1931 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1932 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1933 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1934 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1935 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1936 case EL_MAMPFER2: return GFX_MAMPFER2;
1937 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
1938 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1939 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1940 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1941 case EL_DYNABOMB: return GFX_DYNABOMB;
1942 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1943 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1944 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1945 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1946 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1947 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1948 case EL_MAULWURF: return GFX_MAULWURF;
1949 case EL_PINGUIN: return GFX_PINGUIN;
1950 case EL_SCHWEIN: return GFX_SCHWEIN;
1951 case EL_DRACHE: return GFX_DRACHE;
1952 case EL_SONDE: return GFX_SONDE;
1953 case EL_PFEIL_L: return GFX_PFEIL_L;
1954 case EL_PFEIL_R: return GFX_PFEIL_R;
1955 case EL_PFEIL_O: return GFX_PFEIL_O;
1956 case EL_PFEIL_U: return GFX_PFEIL_U;
1957 case EL_SPEED_PILL: return GFX_SPEED_PILL;
1958 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
1959 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
1963 if (IS_CHAR(element))
1964 return GFX_CHAR_START + (element - EL_CHAR_START);
1965 else if (element >= EL_SP_START && element <= EL_SP_END)
1967 int nr_element = element - EL_SP_START;
1968 int gfx_per_line = 8;
1970 (nr_element / gfx_per_line) * MORE_PER_LINE +
1971 (nr_element % gfx_per_line);
1973 return GFX_START_ROCKSMORE + nr_graphic;