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;
352 boolean print_inverse = FALSE;
354 if (font_size != FS_SMALL && font_size != FS_BIG)
355 font_size = FS_SMALL;
356 if (font_type < FC_RED || font_type > FC_SPECIAL2)
359 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
360 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
361 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
362 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
363 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
364 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
365 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
366 FONT_LINES_PER_FONT);
372 if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
374 print_inverse = TRUE;
378 if (c >= 'a' && c <= 'z')
380 else if (c == 'ä' || c == 'Ä')
382 else if (c == 'ö' || c == 'Ö')
384 else if (c == 'ü' || c == 'Ü')
387 if (c >= 32 && c <= 95)
389 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
390 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
391 int dest_x = x, dest_y = y;
395 XCopyArea(display, pix[font_pixmap], d, gc,
396 FONT_CHARS_PER_LINE * font_width,
397 3 * font_height + font_start,
398 font_width, font_height, x, y);
400 XSetClipOrigin(display, clip_gc[font_pixmap],
401 dest_x - src_x, dest_y - src_y);
402 XCopyArea(display, pix[font_pixmap], drawto, clip_gc[font_pixmap],
403 0, 0, font_width, font_height, dest_x, dest_y);
406 XCopyArea(display, pix[font_pixmap], d, gc,
407 src_x, src_y, font_width, font_height, dest_x, dest_y);
414 void DrawAllPlayers()
418 for(i=0; i<MAX_PLAYERS; i++)
419 if (stored_player[i].active)
420 DrawPlayer(&stored_player[i]);
423 void DrawPlayerField(int x, int y)
428 DrawPlayer(PLAYERINFO(x,y));
431 void DrawPlayer(struct PlayerInfo *player)
433 int jx = player->jx, jy = player->jy;
434 int last_jx = player->last_jx, last_jy = player->last_jy;
435 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
436 int sx = SCREENX(jx), sy = SCREENY(jy);
437 int sxx = 0, syy = 0;
438 int element = Feld[jx][jy];
441 if (!player->active || player->gone ||
442 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
446 if (!IN_LEV_FIELD(jx,jy))
448 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
449 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
450 printf("DrawPlayerField(): This should never happen!\n");
455 if (element == EL_EXPLODING)
458 /* draw things in the field the player is leaving, if needed */
460 if (last_jx != jx || last_jy != jy)
462 if (Store[last_jx][last_jy])
464 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
465 DrawLevelFieldThruMask(last_jx, last_jy);
467 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
468 DrawDynamite(last_jx, last_jy);
470 DrawLevelField(last_jx, last_jy);
472 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
476 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
477 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
479 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
482 DrawLevelField(next_jx, next_jy);
486 if (!IN_SCR_FIELD(sx, sy))
489 if (setup.direct_draw)
490 SetDrawtoField(DRAW_BUFFERED);
492 /* draw things behind the player, if needed */
495 DrawLevelElement(jx, jy, Store[jx][jy]);
496 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
497 DrawLevelField(jx, jy);
499 /* draw player himself */
501 if (player->MovDir == MV_LEFT)
502 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
503 else if (player->MovDir == MV_RIGHT)
504 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
505 else if (player->MovDir == MV_UP)
506 graphic = GFX_SPIELER1_UP;
507 else /* MV_DOWN || MV_NO_MOVING */
508 graphic = GFX_SPIELER1_DOWN;
510 graphic += player->index_nr * 3*HEROES_PER_LINE;
511 graphic += player->Frame;
515 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
516 sxx = player->GfxPos;
518 syy = player->GfxPos;
521 if (!setup.soft_scrolling && ScreenMovPos)
524 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
526 if (player->Pushing && player->GfxPos)
528 int px = SCREENX(next_jx), py = SCREENY(next_jy);
530 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
531 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
532 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
536 int element = Feld[next_jx][next_jy];
537 int graphic = el2gfx(element);
539 if (element == EL_FELSBROCKEN && sxx)
541 int phase = (player->GfxPos / (TILEX/4));
543 if (player->MovDir == MV_LEFT)
546 graphic += (phase+4)%4;
549 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
553 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
555 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
557 graphic = el2gfx(element);
559 if (element == EL_DYNAMIT)
561 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
566 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
570 if (game_emulation == EMU_SUPAPLEX)
571 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
573 DrawGraphicThruMask(sx, sy, graphic + phase);
576 if ((last_jx != jx || last_jy != jy) &&
577 Feld[last_jx][last_jy] == EL_EXPLODING)
579 int phase = Frame[last_jx][last_jy];
583 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
584 GFX_EXPLOSION + ((phase - 1) / delay - 1));
587 if (setup.direct_draw)
589 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
590 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
591 int x_size = TILEX * (1 + ABS(jx - last_jx));
592 int y_size = TILEY * (1 + ABS(jy - last_jy));
594 XCopyArea(display, drawto_field, window, gc,
595 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
596 SetDrawtoField(DRAW_DIRECT);
599 MarkTileDirty(sx,sy);
602 static int getGraphicAnimationPhase(int frames, int delay, int mode)
606 if (mode == ANIM_OSCILLATE)
608 int max_anim_frames = 2 * frames - 2;
609 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
610 phase = (phase < frames ? phase : max_anim_frames - phase);
613 phase = (FrameCounter % (delay * frames)) / delay;
615 if (mode == ANIM_REVERSE)
621 void DrawGraphicAnimationExt(int x, int y, int graphic,
622 int frames, int delay, int mode, int mask_mode)
624 int phase = getGraphicAnimationPhase(frames, delay, mode);
626 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
628 if (mask_mode == USE_MASKING)
629 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
631 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
635 void DrawGraphicAnimation(int x, int y, int graphic,
636 int frames, int delay, int mode)
638 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
641 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
642 int frames, int delay, int mode)
644 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
647 void DrawGraphic(int x, int y, int graphic)
650 if (!IN_SCR_FIELD(x,y))
652 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
653 printf("DrawGraphic(): This should never happen!\n");
658 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
662 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
664 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
666 graphic -= GFX_START_ROCKSSCREEN;
667 XCopyArea(display, pix[PIX_BACK], d, gc,
668 SX + (graphic % GFX_PER_LINE) * TILEX,
669 SY + (graphic / GFX_PER_LINE) * TILEY,
672 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
674 graphic -= GFX_START_ROCKSMORE;
675 XCopyArea(display, pix[PIX_MORE], d, gc,
676 (graphic % MORE_PER_LINE) * TILEX,
677 (graphic / MORE_PER_LINE) * TILEY,
680 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
682 graphic -= GFX_START_ROCKSHEROES;
683 XCopyArea(display, pix[PIX_HEROES], d, gc,
684 (graphic % HEROES_PER_LINE) * TILEX,
685 (graphic / HEROES_PER_LINE) * TILEY,
688 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
690 graphic -= GFX_START_ROCKSFONT;
691 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
692 (graphic % FONT_CHARS_PER_LINE) * TILEX,
693 (graphic / FONT_CHARS_PER_LINE) * TILEY +
694 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
698 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
701 void DrawGraphicThruMask(int x, int y, int graphic)
704 if (!IN_SCR_FIELD(x,y))
706 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
707 printf("DrawGraphicThruMask(): This should never happen!\n");
712 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
716 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
723 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
725 src_pixmap = pix[PIX_BACK];
726 drawing_gc = clip_gc[PIX_BACK];
727 graphic -= GFX_START_ROCKSSCREEN;
728 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
729 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
731 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
733 src_pixmap = pix[PIX_MORE];
734 drawing_gc = clip_gc[PIX_MORE];
735 graphic -= GFX_START_ROCKSMORE;
736 src_x = (graphic % MORE_PER_LINE) * TILEX;
737 src_y = (graphic / MORE_PER_LINE) * TILEY;
739 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
741 src_pixmap = pix[PIX_HEROES];
742 drawing_gc = clip_gc[PIX_HEROES];
743 graphic -= GFX_START_ROCKSHEROES;
744 src_x = (graphic % HEROES_PER_LINE) * TILEX;
745 src_y = (graphic / HEROES_PER_LINE) * TILEY;
749 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
753 if (tile_clipmask[tile] != None)
755 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
756 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
757 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
758 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
763 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
766 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
767 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
768 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
772 void DrawMiniGraphic(int x, int y, int graphic)
774 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
775 MarkTileDirty(x/2, y/2);
778 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
780 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
782 graphic -= GFX_START_ROCKSSCREEN;
783 XCopyArea(display, pix[PIX_BACK], d, gc,
784 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
785 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
786 MINI_TILEX, MINI_TILEY, x, y);
788 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
790 graphic -= GFX_START_ROCKSMORE;
791 XCopyArea(display, pix[PIX_MORE], d, gc,
792 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
793 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
794 MINI_TILEX, MINI_TILEY, x, y);
796 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
798 graphic -= GFX_START_ROCKSFONT;
799 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
800 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
801 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
802 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
803 MINI_TILEX, MINI_TILEY, x, y);
806 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
809 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
810 int cut_mode, int mask_mode)
812 int width = TILEX, height = TILEY;
814 int src_x, src_y, dest_x, dest_y;
821 DrawGraphic(x, y, graphic);
825 if (dx || dy) /* Verschiebung der Grafik? */
827 if (x < BX1) /* Element kommt von links ins Bild */
834 else if (x > BX2) /* Element kommt von rechts ins Bild */
840 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
846 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
848 else if (dx) /* allg. Bewegung in x-Richtung */
849 MarkTileDirty(x + SIGN(dx), y);
851 if (y < BY1) /* Element kommt von oben ins Bild */
853 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
861 else if (y > BY2) /* Element kommt von unten ins Bild */
867 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
873 else if (dy > 0 && cut_mode == CUT_ABOVE)
875 if (y == BY2) /* Element unterhalb des Bildes */
881 MarkTileDirty(x, y + 1);
882 } /* Element verläßt unten das Bild */
883 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
885 else if (dy) /* allg. Bewegung in y-Richtung */
886 MarkTileDirty(x, y + SIGN(dy));
889 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
891 src_pixmap = pix[PIX_BACK];
892 drawing_gc = clip_gc[PIX_BACK];
893 graphic -= GFX_START_ROCKSSCREEN;
894 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
895 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
897 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
899 src_pixmap = pix[PIX_MORE];
900 drawing_gc = clip_gc[PIX_MORE];
901 graphic -= GFX_START_ROCKSMORE;
902 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
903 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
905 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
907 src_pixmap = pix[PIX_HEROES];
908 drawing_gc = clip_gc[PIX_HEROES];
909 graphic -= GFX_START_ROCKSHEROES;
910 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
911 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
913 else /* big font graphics currently not allowed (and not needed) */
916 dest_x = FX + x * TILEX + dx;
917 dest_y = FY + y * TILEY + dy;
920 if (!IN_SCR_FIELD(x,y))
922 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
923 printf("DrawGraphicShifted(): This should never happen!\n");
928 if (mask_mode == USE_MASKING)
930 if (tile_clipmask[tile] != None)
932 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
933 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
934 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
935 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
940 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
943 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
944 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
945 src_x, src_y, width, height, dest_x, dest_y);
949 XCopyArea(display, src_pixmap, drawto_field, gc,
950 src_x, src_y, width, height, dest_x, dest_y);
955 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
958 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
961 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
962 int cut_mode, int mask_mode)
964 int ux = LEVELX(x), uy = LEVELY(y);
965 int graphic = el2gfx(element);
966 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
967 int phase4 = phase8 / 2;
968 int phase2 = phase8 / 4;
969 int dir = MovDir[ux][uy];
971 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
973 graphic += 4 * !phase2;
977 else if (dir == MV_LEFT)
979 else if (dir == MV_DOWN)
982 else if (element == EL_SP_SNIKSNAK)
985 graphic = GFX_SP_SNIKSNAK_LEFT;
986 else if (dir == MV_RIGHT)
987 graphic = GFX_SP_SNIKSNAK_RIGHT;
988 else if (dir == MV_UP)
989 graphic = GFX_SP_SNIKSNAK_UP;
991 graphic = GFX_SP_SNIKSNAK_DOWN;
993 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
995 else if (element == EL_SP_ELECTRON)
997 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
999 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1000 element == EL_SCHWEIN || element == EL_DRACHE)
1003 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1004 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1005 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1006 else if (dir == MV_RIGHT)
1007 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1008 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1009 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1010 else if (dir == MV_UP)
1011 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1012 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1013 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1015 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1016 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1017 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1021 else if (element == EL_SONDE)
1023 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1025 else if (element == EL_SALZSAEURE)
1027 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1029 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1033 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
1035 if (element != EL_SP_INFOTRON)
1036 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1038 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1039 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1041 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1043 else if (IS_AMOEBOID(element))
1045 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1046 graphic += (x + 2 * y + 4) % 4;
1048 else if (element == EL_MAUER_LEBT)
1050 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1052 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1053 links_massiv = TRUE;
1054 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1055 rechts_massiv = TRUE;
1057 if (links_massiv && rechts_massiv)
1058 graphic = GFX_MAUERWERK;
1059 else if (links_massiv)
1060 graphic = GFX_MAUER_R;
1061 else if (rechts_massiv)
1062 graphic = GFX_MAUER_L;
1066 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1067 else if (mask_mode == USE_MASKING)
1068 DrawGraphicThruMask(x, y, graphic);
1070 DrawGraphic(x, y, graphic);
1073 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1074 int cut_mode, int mask_mode)
1076 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1077 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1078 cut_mode, mask_mode);
1081 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1084 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1087 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1090 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1093 void DrawScreenElementThruMask(int x, int y, int element)
1095 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1098 void DrawLevelElementThruMask(int x, int y, int element)
1100 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1103 void DrawLevelFieldThruMask(int x, int y)
1105 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1108 void ErdreichAnbroeckeln(int x, int y)
1110 int i, width, height, cx,cy;
1111 int ux = LEVELX(x), uy = LEVELY(y);
1112 int element, graphic;
1114 static int xy[4][2] =
1122 if (!IN_LEV_FIELD(ux, uy))
1125 element = Feld[ux][uy];
1127 if (element == EL_ERDREICH)
1129 if (!IN_SCR_FIELD(x, y))
1132 graphic = GFX_ERDENRAND;
1138 uxx = ux + xy[i][0];
1139 uyy = uy + xy[i][1];
1140 if (!IN_LEV_FIELD(uxx, uyy))
1143 element = Feld[uxx][uyy];
1145 if (element == EL_ERDREICH)
1148 if (i == 1 || i == 2)
1152 cx = (i == 2 ? TILEX - snip : 0);
1160 cy = (i == 3 ? TILEY - snip : 0);
1163 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1164 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1165 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1166 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1169 MarkTileDirty(x, y);
1173 graphic = GFX_ERDENRAND;
1177 int xx, yy, uxx, uyy;
1181 uxx = ux + xy[i][0];
1182 uyy = uy + xy[i][1];
1184 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1185 !IN_SCR_FIELD(xx, yy))
1188 if (i == 1 || i == 2)
1192 cx = (i == 1 ? TILEX - snip : 0);
1200 cy = (i==0 ? TILEY-snip : 0);
1203 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1204 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1205 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1206 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1208 MarkTileDirty(xx, yy);
1213 void DrawScreenElement(int x, int y, int element)
1215 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1216 ErdreichAnbroeckeln(x, y);
1219 void DrawLevelElement(int x, int y, int element)
1221 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1222 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1225 void DrawScreenField(int x, int y)
1227 int ux = LEVELX(x), uy = LEVELY(y);
1230 if (!IN_LEV_FIELD(ux, uy))
1232 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1233 element = EL_LEERRAUM;
1235 element = BorderElement;
1237 DrawScreenElement(x, y, element);
1241 element = Feld[ux][uy];
1243 if (IS_MOVING(ux, uy))
1245 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1246 boolean cut_mode = NO_CUTTING;
1248 if (Store[ux][uy] == EL_MORAST_LEER ||
1249 Store[ux][uy] == EL_SIEB_LEER ||
1250 Store[ux][uy] == EL_SIEB2_LEER ||
1251 Store[ux][uy] == EL_AMOEBE_NASS)
1252 cut_mode = CUT_ABOVE;
1253 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1254 Store[ux][uy] == EL_SIEB_VOLL ||
1255 Store[ux][uy] == EL_SIEB2_VOLL)
1256 cut_mode = CUT_BELOW;
1258 if (cut_mode == CUT_ABOVE)
1259 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1261 DrawScreenElement(x, y, EL_LEERRAUM);
1264 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1266 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1268 if (Store[ux][uy] == EL_SALZSAEURE)
1269 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1271 else if (IS_BLOCKED(ux, uy))
1276 boolean cut_mode = NO_CUTTING;
1278 Blocked2Moving(ux, uy, &oldx, &oldy);
1281 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1282 MovDir[oldx][oldy] == MV_RIGHT);
1284 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1285 Store[oldx][oldy] == EL_SIEB_LEER ||
1286 Store[oldx][oldy] == EL_SIEB2_LEER ||
1287 Store[oldx][oldy] == EL_AMOEBE_NASS)
1288 cut_mode = CUT_ABOVE;
1290 DrawScreenElement(x, y, EL_LEERRAUM);
1291 element = Feld[oldx][oldy];
1294 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1296 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1298 else if (IS_DRAWABLE(element))
1299 DrawScreenElement(x, y, element);
1301 DrawScreenElement(x, y, EL_LEERRAUM);
1304 void DrawLevelField(int x, int y)
1306 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1307 DrawScreenField(SCREENX(x), SCREENY(y));
1308 else if (IS_MOVING(x, y))
1312 Moving2Blocked(x, y, &newx, &newy);
1313 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1314 DrawScreenField(SCREENX(newx), SCREENY(newy));
1316 else if (IS_BLOCKED(x, y))
1320 Blocked2Moving(x, y, &oldx, &oldy);
1321 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1322 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1326 void DrawMiniElement(int x, int y, int element)
1332 DrawMiniGraphic(x, y, -1);
1336 graphic = el2gfx(element);
1337 DrawMiniGraphic(x, y, graphic);
1340 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1342 int x = sx + scroll_x, y = sy + scroll_y;
1344 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1345 DrawMiniElement(sx, sy, EL_LEERRAUM);
1346 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1347 DrawMiniElement(sx, sy, EL_BETON);
1349 DrawMiniElement(sx, sy, Feld[x][y]);
1352 void DrawMicroElement(int xpos, int ypos, int element)
1356 if (element == EL_LEERRAUM)
1359 graphic = el2gfx(element);
1361 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1363 graphic -= GFX_START_ROCKSMORE;
1364 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1365 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1366 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1367 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1370 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1371 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1372 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1373 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1382 for(x=BX1; x<=BX2; x++)
1383 for(y=BY1; y<=BY2; y++)
1384 DrawScreenField(x, y);
1386 if (setup.soft_scrolling)
1387 XCopyArea(display, fieldbuffer, backbuffer, gc,
1388 FX, FY, SXSIZE, SYSIZE, SX, SY);
1390 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1393 void DrawMiniLevel(int scroll_x, int scroll_y)
1397 for(x=0; x<ED_FIELDX; x++)
1398 for(y=0; y<ED_FIELDY; y++)
1399 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1401 redraw_mask |= REDRAW_FIELD;
1404 void DrawMicroLevel(int xpos, int ypos)
1408 /* determine border element for this level */
1411 XFillRectangle(display, drawto, gc,
1412 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1413 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1414 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1415 if (lev_fieldx < STD_LEV_FIELDX)
1416 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1417 if (lev_fieldy < STD_LEV_FIELDY)
1418 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1420 for(x=-1; x<=STD_LEV_FIELDX; x++)
1421 for(y=-1; y<=STD_LEV_FIELDY; y++)
1422 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1423 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1425 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1426 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1429 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1433 int len = strlen(level.name);
1434 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1435 int lypos = MICROLABEL_YPOS;
1437 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1440 redraw_mask |= REDRAW_MICROLEV;
1443 int REQ_in_range(int x, int y)
1445 if (y > DY+249 && y < DY+278)
1447 if (x > DX+1 && x < DX+48)
1449 else if (x > DX+51 && x < DX+98)
1455 boolean Request(char *text, unsigned int req_state)
1457 int mx, my, ty, result = -1;
1458 unsigned int old_door_state;
1461 /* pause network game while waiting for request to answer */
1462 if (options.network &&
1463 game_status == PLAYING &&
1464 req_state & REQUEST_WAIT_FOR)
1465 SendToServer_PausePlaying();
1468 old_door_state = GetDoorState();
1470 CloseDoor(DOOR_CLOSE_1);
1472 /* Alten Türinhalt sichern */
1473 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1474 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1475 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1477 /* Fragetext schreiben */
1478 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1479 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1481 for(ty=0; ty<13; ty++)
1489 for(tl=0,tx=0; tx<7; tl++,tx++)
1492 if (!tc || tc == 32)
1503 DrawTextExt(pix[PIX_DB_DOOR], gc,
1504 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1505 txt, FS_SMALL, FC_YELLOW);
1506 text += tl + (tc == 32 ? 1 : 0);
1509 if (req_state & REQ_ASK)
1511 DrawYesNoButton(BUTTON_OK, DB_INIT);
1512 DrawYesNoButton(BUTTON_NO, DB_INIT);
1514 else if (req_state & REQ_CONFIRM)
1516 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1518 else if (req_state & REQ_PLAYER)
1520 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1521 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1522 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1523 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1526 OpenDoor(DOOR_OPEN_1);
1529 if (!(req_state & REQUEST_WAIT_FOR))
1532 if (game_status != MAINMENU)
1535 button_status = MB_RELEASED;
1539 if (XPending(display))
1543 XNextEvent(display, &event);
1553 if (event.type == MotionNotify)
1555 motion_status = TRUE;
1556 mx = ((XMotionEvent *) &event)->x;
1557 my = ((XMotionEvent *) &event)->y;
1561 motion_status = FALSE;
1562 mx = ((XButtonEvent *) &event)->x;
1563 my = ((XButtonEvent *) &event)->y;
1564 if (event.type==ButtonPress)
1565 button_status = ((XButtonEvent *) &event)->button;
1567 button_status = MB_RELEASED;
1570 if (req_state & REQ_ASK)
1571 choice = CheckYesNoButtons(mx,my,button_status);
1572 else if (req_state & REQ_CONFIRM)
1573 choice = CheckConfirmButton(mx,my,button_status);
1575 choice = CheckPlayerButtons(mx,my,button_status);
1585 case BUTTON_CONFIRM:
1586 result = TRUE | FALSE;
1589 case BUTTON_PLAYER_1:
1592 case BUTTON_PLAYER_2:
1595 case BUTTON_PLAYER_3:
1598 case BUTTON_PLAYER_4:
1609 switch(XLookupKeysym((XKeyEvent *)&event,
1610 ((XKeyEvent *)&event)->state))
1623 if (req_state & REQ_PLAYER)
1628 key_joystick_mapping = 0;
1632 HandleOtherEvents(&event);
1636 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1638 int joy = AnyJoystick();
1640 if (joy & JOY_BUTTON_1)
1642 else if (joy & JOY_BUTTON_2)
1648 /* don't eat all CPU time */
1652 if (game_status != MAINMENU)
1655 if (!(req_state & REQ_STAY_OPEN))
1657 CloseDoor(DOOR_CLOSE_1);
1659 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1661 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1662 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1663 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1664 OpenDoor(DOOR_OPEN_1);
1669 /* continue network game after request */
1670 if (options.network &&
1671 game_status == PLAYING &&
1672 req_state & REQUEST_WAIT_FOR)
1673 SendToServer_ContinuePlaying();
1679 unsigned int OpenDoor(unsigned int door_state)
1681 unsigned int new_door_state;
1683 if (door_state & DOOR_COPY_BACK)
1685 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1686 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1687 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1688 door_state &= ~DOOR_COPY_BACK;
1691 new_door_state = MoveDoor(door_state);
1693 return(new_door_state);
1696 unsigned int CloseDoor(unsigned int door_state)
1698 unsigned int new_door_state;
1700 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1701 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1702 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1703 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1705 new_door_state = MoveDoor(door_state);
1707 return(new_door_state);
1710 unsigned int GetDoorState()
1712 return(MoveDoor(DOOR_GET_STATE));
1715 unsigned int MoveDoor(unsigned int door_state)
1717 static int door1 = DOOR_OPEN_1;
1718 static int door2 = DOOR_CLOSE_2;
1719 static unsigned long door_delay = 0;
1720 int x, start, stepsize = 2;
1721 unsigned long door_delay_value = stepsize * 5;
1723 if (door_state == DOOR_GET_STATE)
1724 return(door1 | door2);
1726 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1727 door_state &= ~DOOR_OPEN_1;
1728 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1729 door_state &= ~DOOR_CLOSE_1;
1730 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1731 door_state &= ~DOOR_OPEN_2;
1732 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1733 door_state &= ~DOOR_CLOSE_2;
1735 if (setup.quick_doors)
1738 door_delay_value = 0;
1739 StopSound(SND_OEFFNEN);
1742 if (door_state & DOOR_ACTION)
1744 if (!(door_state & DOOR_NO_DELAY))
1745 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1747 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1749 for(x=start; x<=DXSIZE; x+=stepsize)
1751 WaitUntilDelayReached(&door_delay, door_delay_value);
1753 if (door_state & DOOR_ACTION_1)
1755 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1756 int j = (DXSIZE - i) / 3;
1758 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1759 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1760 DXSIZE,DYSIZE - i/2, DX, DY);
1762 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1764 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1765 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1766 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1767 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1768 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1769 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1771 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1772 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1773 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1774 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1775 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1776 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1778 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1779 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1781 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1782 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1784 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1785 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1786 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1787 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1788 DX + DXSIZE - i, DY + 77 + j);
1789 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1790 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1791 DX + DXSIZE - i, DY + 203 + j);
1793 redraw_mask |= REDRAW_DOOR_1;
1796 if (door_state & DOOR_ACTION_2)
1798 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1799 int j = (VXSIZE - i) / 3;
1801 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1802 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1803 VXSIZE, VYSIZE - i/2, VX, VY);
1805 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1807 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1808 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1809 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1810 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1811 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1812 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1813 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1814 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1816 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1817 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1818 VX, VY + VYSIZE / 2 - j);
1819 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1820 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1821 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1822 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1823 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1825 redraw_mask |= REDRAW_DOOR_2;
1830 if (game_status == MAINMENU)
1835 if (setup.quick_doors)
1836 StopSound(SND_OEFFNEN);
1838 if (door_state & DOOR_ACTION_1)
1839 door1 = door_state & DOOR_ACTION_1;
1840 if (door_state & DOOR_ACTION_2)
1841 door2 = door_state & DOOR_ACTION_2;
1843 return(door1 | door2);
1846 int ReadPixel(Drawable d, int x, int y)
1848 XImage *pixel_image;
1849 unsigned long pixel_value;
1851 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1852 pixel_value = XGetPixel(pixel_image, 0, 0);
1854 XDestroyImage(pixel_image);
1859 int el2gfx(int element)
1863 case EL_LEERRAUM: return -1;
1864 case EL_ERDREICH: return GFX_ERDREICH;
1865 case EL_MAUERWERK: return GFX_MAUERWERK;
1866 case EL_FELSBODEN: return GFX_FELSBODEN;
1867 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1868 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1869 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1870 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1871 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1872 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1873 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1874 case EL_SPIELER1: return GFX_SPIELER1;
1875 case EL_SPIELER2: return GFX_SPIELER2;
1876 case EL_SPIELER3: return GFX_SPIELER3;
1877 case EL_SPIELER4: return GFX_SPIELER4;
1878 case EL_KAEFER: return GFX_KAEFER;
1879 case EL_KAEFER_R: return GFX_KAEFER_R;
1880 case EL_KAEFER_O: return GFX_KAEFER_O;
1881 case EL_KAEFER_L: return GFX_KAEFER_L;
1882 case EL_KAEFER_U: return GFX_KAEFER_U;
1883 case EL_FLIEGER: return GFX_FLIEGER;
1884 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1885 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1886 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1887 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1888 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1889 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1890 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1891 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1892 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1893 case EL_FIREFLY: return GFX_FIREFLY;
1894 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1895 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1896 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1897 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1898 case EL_MAMPFER: return GFX_MAMPFER;
1899 case EL_ROBOT: return GFX_ROBOT;
1900 case EL_BETON: return GFX_BETON;
1901 case EL_DIAMANT: return GFX_DIAMANT;
1902 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1903 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1904 case EL_TROPFEN: return GFX_TROPFEN;
1905 case EL_BOMBE: return GFX_BOMBE;
1906 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
1907 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1908 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1909 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1910 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1911 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1912 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1913 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1914 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1915 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1916 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1917 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1918 case EL_LIFE: return GFX_LIFE;
1919 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1920 case EL_DYNAMIT: return GFX_DYNAMIT;
1921 case EL_BADEWANNE: return GFX_BADEWANNE;
1922 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1923 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1924 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1925 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1926 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1927 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1928 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1929 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1930 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1931 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1932 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1933 case EL_PFORTE1: return GFX_PFORTE1;
1934 case EL_PFORTE2: return GFX_PFORTE2;
1935 case EL_PFORTE3: return GFX_PFORTE3;
1936 case EL_PFORTE4: return GFX_PFORTE4;
1937 case EL_PFORTE1X: return GFX_PFORTE1X;
1938 case EL_PFORTE2X: return GFX_PFORTE2X;
1939 case EL_PFORTE3X: return GFX_PFORTE3X;
1940 case EL_PFORTE4X: return GFX_PFORTE4X;
1941 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1942 case EL_PACMAN: return GFX_PACMAN;
1943 case EL_PACMAN_R: return GFX_PACMAN_R;
1944 case EL_PACMAN_O: return GFX_PACMAN_O;
1945 case EL_PACMAN_L: return GFX_PACMAN_L;
1946 case EL_PACMAN_U: return GFX_PACMAN_U;
1947 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1948 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1949 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1950 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1951 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1952 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1953 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1954 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1955 case EL_MAUER_X: return GFX_MAUER_X;
1956 case EL_MAUER_Y: return GFX_MAUER_Y;
1957 case EL_MAUER_XY: return GFX_MAUER_XY;
1958 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1959 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1960 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1961 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1962 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1963 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1964 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1965 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1966 case EL_MAMPFER2: return GFX_MAMPFER2;
1967 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
1968 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1969 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1970 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1971 case EL_DYNABOMB: return GFX_DYNABOMB;
1972 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1973 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1974 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1975 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1976 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1977 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1978 case EL_MAULWURF: return GFX_MAULWURF;
1979 case EL_PINGUIN: return GFX_PINGUIN;
1980 case EL_SCHWEIN: return GFX_SCHWEIN;
1981 case EL_DRACHE: return GFX_DRACHE;
1982 case EL_SONDE: return GFX_SONDE;
1983 case EL_PFEIL_L: return GFX_PFEIL_L;
1984 case EL_PFEIL_R: return GFX_PFEIL_R;
1985 case EL_PFEIL_O: return GFX_PFEIL_O;
1986 case EL_PFEIL_U: return GFX_PFEIL_U;
1987 case EL_SPEED_PILL: return GFX_SPEED_PILL;
1988 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
1989 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
1993 if (IS_CHAR(element))
1994 return GFX_CHAR_START + (element - EL_CHAR_START);
1995 else if (element >= EL_SP_START && element <= EL_SP_END)
1997 int nr_element = element - EL_SP_START;
1998 int gfx_per_line = 8;
2000 (nr_element / gfx_per_line) * MORE_PER_LINE +
2001 (nr_element % gfx_per_line);
2003 return GFX_START_ROCKSMORE + nr_graphic;