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_MICROLEVEL)
189 XCopyArea(display,backbuffer,window,gc,
190 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
191 MICROLEV_XPOS, MICROLEV_YPOS);
192 redraw_mask &= ~REDRAW_MICROLEVEL;
195 if (redraw_mask & REDRAW_MICROLEVEL_LABEL)
197 XCopyArea(display,backbuffer,window,gc,
198 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
199 SX, MICROLABEL_YPOS);
200 redraw_mask &= ~REDRAW_MICROLEVEL_LABEL;
203 if (redraw_mask & REDRAW_TILES)
205 for(x=0; x<SCR_FIELDX; x++)
206 for(y=0; y<SCR_FIELDY; y++)
207 if (redraw[redraw_x1 + x][redraw_y1 + y])
208 XCopyArea(display,buffer,window,gc,
209 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
210 SX+x*TILEX,SY+y*TILEY);
215 for(x=0; x<MAX_BUF_XSIZE; x++)
216 for(y=0; y<MAX_BUF_YSIZE; y++)
225 long fading_delay = 300;
227 if (setup.fading && (redraw_mask & REDRAW_FIELD))
234 XFillRectangle(display,window,gc,
235 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
238 for(i=0;i<2*FULL_SYSIZE;i++)
240 for(y=0;y<FULL_SYSIZE;y++)
242 XCopyArea(display,backbuffer,window,gc,
243 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
251 for(i=1;i<FULL_SYSIZE;i+=2)
252 XCopyArea(display,backbuffer,window,gc,
253 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
259 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
260 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
261 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
265 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
266 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
267 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
271 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
272 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
273 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
277 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
278 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
279 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
283 redraw_mask &= ~REDRAW_MAIN;
292 XFillRectangle(display, backbuffer, gc,
293 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
295 if (setup.soft_scrolling && game_status == PLAYING)
297 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
298 SetDrawtoField(DRAW_BUFFERED);
301 SetDrawtoField(DRAW_BACKBUFFER);
303 if (setup.direct_draw && game_status == PLAYING)
305 XFillRectangle(display, window, gc,
306 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
307 SetDrawtoField(DRAW_DIRECT);
310 redraw_mask |= REDRAW_FIELD;
313 void DrawTextFCentered(int y, int font_type, char *format, ...)
315 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
319 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
320 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
322 va_start(ap, format);
323 vsprintf(buffer, format, ap);
326 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
327 buffer, FS_SMALL, font_type);
330 void DrawTextF(int x, int y, int font_type, char *format, ...)
332 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
335 va_start(ap, format);
336 vsprintf(buffer, format, ap);
339 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
342 void DrawText(int x, int y, char *text, int font_size, int font_type)
344 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
347 redraw_mask |= REDRAW_FIELD;
349 redraw_mask |= REDRAW_DOOR_1;
352 void DrawTextExt(Drawable d, GC gc, int x, int y,
353 char *text, int font_size, int font_type)
355 int font_width, font_height, font_start;
357 boolean print_inverse = FALSE;
359 if (font_size != FS_SMALL && font_size != FS_BIG)
360 font_size = FS_SMALL;
361 if (font_type < FC_RED || font_type > FC_SPECIAL2)
364 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
365 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
366 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
367 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
368 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
369 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
370 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
371 FONT_LINES_PER_FONT);
377 if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
379 print_inverse = TRUE;
383 if (c >= 'a' && c <= 'z')
385 else if (c == 'ä' || c == 'Ä')
387 else if (c == 'ö' || c == 'Ö')
389 else if (c == 'ü' || c == 'Ü')
392 if (c >= 32 && c <= 95)
394 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
395 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
396 int dest_x = x, dest_y = y;
400 XCopyArea(display, pix[font_pixmap], d, gc,
401 FONT_CHARS_PER_LINE * font_width,
402 3 * font_height + font_start,
403 font_width, font_height, x, y);
405 XSetClipOrigin(display, clip_gc[font_pixmap],
406 dest_x - src_x, dest_y - src_y);
407 XCopyArea(display, pix[font_pixmap], drawto, clip_gc[font_pixmap],
408 0, 0, font_width, font_height, dest_x, dest_y);
411 XCopyArea(display, pix[font_pixmap], d, gc,
412 src_x, src_y, font_width, font_height, dest_x, dest_y);
419 void DrawAllPlayers()
423 for(i=0; i<MAX_PLAYERS; i++)
424 if (stored_player[i].active)
425 DrawPlayer(&stored_player[i]);
428 void DrawPlayerField(int x, int y)
433 DrawPlayer(PLAYERINFO(x,y));
436 void DrawPlayer(struct PlayerInfo *player)
438 int jx = player->jx, jy = player->jy;
439 int last_jx = player->last_jx, last_jy = player->last_jy;
440 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
441 int sx = SCREENX(jx), sy = SCREENY(jy);
442 int sxx = 0, syy = 0;
443 int element = Feld[jx][jy];
446 if (!player->active || player->gone ||
447 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
451 if (!IN_LEV_FIELD(jx,jy))
453 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
454 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
455 printf("DrawPlayerField(): This should never happen!\n");
460 if (element == EL_EXPLODING)
463 /* draw things in the field the player is leaving, if needed */
465 if (last_jx != jx || last_jy != jy)
467 if (Store[last_jx][last_jy])
469 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
470 DrawLevelFieldThruMask(last_jx, last_jy);
472 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
473 DrawDynamite(last_jx, last_jy);
475 DrawLevelField(last_jx, last_jy);
477 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
481 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
482 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
484 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
487 DrawLevelField(next_jx, next_jy);
491 if (!IN_SCR_FIELD(sx, sy))
494 if (setup.direct_draw)
495 SetDrawtoField(DRAW_BUFFERED);
497 /* draw things behind the player, if needed */
500 DrawLevelElement(jx, jy, Store[jx][jy]);
501 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
502 DrawLevelField(jx, jy);
504 /* draw player himself */
506 if (player->MovDir == MV_LEFT)
507 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
508 else if (player->MovDir == MV_RIGHT)
509 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
510 else if (player->MovDir == MV_UP)
511 graphic = GFX_SPIELER1_UP;
512 else /* MV_DOWN || MV_NO_MOVING */
513 graphic = GFX_SPIELER1_DOWN;
515 graphic += player->index_nr * 3*HEROES_PER_LINE;
516 graphic += player->Frame;
520 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
521 sxx = player->GfxPos;
523 syy = player->GfxPos;
526 if (!setup.soft_scrolling && ScreenMovPos)
529 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
531 if (player->Pushing && player->GfxPos)
533 int px = SCREENX(next_jx), py = SCREENY(next_jy);
535 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
536 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
537 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
541 int element = Feld[next_jx][next_jy];
542 int graphic = el2gfx(element);
544 if (element == EL_FELSBROCKEN && sxx)
546 int phase = (player->GfxPos / (TILEX/4));
548 if (player->MovDir == MV_LEFT)
551 graphic += (phase+4)%4;
554 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
558 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
560 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
562 graphic = el2gfx(element);
564 if (element == EL_DYNAMIT)
566 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
571 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
575 if (game_emulation == EMU_SUPAPLEX)
576 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
578 DrawGraphicThruMask(sx, sy, graphic + phase);
581 if ((last_jx != jx || last_jy != jy) &&
582 Feld[last_jx][last_jy] == EL_EXPLODING)
584 int phase = Frame[last_jx][last_jy];
588 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
589 GFX_EXPLOSION + ((phase - 1) / delay - 1));
592 if (setup.direct_draw)
594 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
595 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
596 int x_size = TILEX * (1 + ABS(jx - last_jx));
597 int y_size = TILEY * (1 + ABS(jy - last_jy));
599 XCopyArea(display, drawto_field, window, gc,
600 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
601 SetDrawtoField(DRAW_DIRECT);
604 MarkTileDirty(sx,sy);
607 static int getGraphicAnimationPhase(int frames, int delay, int mode)
611 if (mode == ANIM_OSCILLATE)
613 int max_anim_frames = 2 * frames - 2;
614 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
615 phase = (phase < frames ? phase : max_anim_frames - phase);
618 phase = (FrameCounter % (delay * frames)) / delay;
620 if (mode == ANIM_REVERSE)
626 void DrawGraphicAnimationExt(int x, int y, int graphic,
627 int frames, int delay, int mode, int mask_mode)
629 int phase = getGraphicAnimationPhase(frames, delay, mode);
631 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
633 if (mask_mode == USE_MASKING)
634 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
636 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
640 void DrawGraphicAnimation(int x, int y, int graphic,
641 int frames, int delay, int mode)
643 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
646 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
647 int frames, int delay, int mode)
649 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
652 void DrawGraphic(int x, int y, int graphic)
655 if (!IN_SCR_FIELD(x,y))
657 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
658 printf("DrawGraphic(): This should never happen!\n");
663 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
667 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
669 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
671 graphic -= GFX_START_ROCKSSCREEN;
672 XCopyArea(display, pix[PIX_BACK], d, gc,
673 SX + (graphic % GFX_PER_LINE) * TILEX,
674 SY + (graphic / GFX_PER_LINE) * TILEY,
677 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
679 graphic -= GFX_START_ROCKSMORE;
680 XCopyArea(display, pix[PIX_MORE], d, gc,
681 (graphic % MORE_PER_LINE) * TILEX,
682 (graphic / MORE_PER_LINE) * TILEY,
685 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
687 graphic -= GFX_START_ROCKSHEROES;
688 XCopyArea(display, pix[PIX_HEROES], d, gc,
689 (graphic % HEROES_PER_LINE) * TILEX,
690 (graphic / HEROES_PER_LINE) * TILEY,
693 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
695 graphic -= GFX_START_ROCKSFONT;
696 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
697 (graphic % FONT_CHARS_PER_LINE) * TILEX,
698 (graphic / FONT_CHARS_PER_LINE) * TILEY +
699 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
703 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
706 void DrawGraphicThruMask(int x, int y, int graphic)
709 if (!IN_SCR_FIELD(x,y))
711 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
712 printf("DrawGraphicThruMask(): This should never happen!\n");
717 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
721 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
728 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
730 src_pixmap = pix[PIX_BACK];
731 drawing_gc = clip_gc[PIX_BACK];
732 graphic -= GFX_START_ROCKSSCREEN;
733 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
734 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
736 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
738 src_pixmap = pix[PIX_MORE];
739 drawing_gc = clip_gc[PIX_MORE];
740 graphic -= GFX_START_ROCKSMORE;
741 src_x = (graphic % MORE_PER_LINE) * TILEX;
742 src_y = (graphic / MORE_PER_LINE) * TILEY;
744 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
746 src_pixmap = pix[PIX_HEROES];
747 drawing_gc = clip_gc[PIX_HEROES];
748 graphic -= GFX_START_ROCKSHEROES;
749 src_x = (graphic % HEROES_PER_LINE) * TILEX;
750 src_y = (graphic / HEROES_PER_LINE) * TILEY;
754 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
758 if (tile_clipmask[tile] != None)
760 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
761 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
762 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
763 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
768 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
771 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
772 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
773 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
777 void DrawMiniGraphic(int x, int y, int graphic)
779 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
780 MarkTileDirty(x/2, y/2);
783 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
785 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
787 graphic -= GFX_START_ROCKSSCREEN;
788 XCopyArea(display, pix[PIX_BACK], d, gc,
789 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
790 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
791 MINI_TILEX, MINI_TILEY, x, y);
793 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
795 graphic -= GFX_START_ROCKSMORE;
796 XCopyArea(display, pix[PIX_MORE], d, gc,
797 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
798 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
799 MINI_TILEX, MINI_TILEY, x, y);
801 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
803 graphic -= GFX_START_ROCKSFONT;
804 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
805 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
806 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
807 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
808 MINI_TILEX, MINI_TILEY, x, y);
811 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
814 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
815 int cut_mode, int mask_mode)
817 int width = TILEX, height = TILEY;
819 int src_x, src_y, dest_x, dest_y;
826 DrawGraphic(x, y, graphic);
830 if (dx || dy) /* Verschiebung der Grafik? */
832 if (x < BX1) /* Element kommt von links ins Bild */
839 else if (x > BX2) /* Element kommt von rechts ins Bild */
845 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
851 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
853 else if (dx) /* allg. Bewegung in x-Richtung */
854 MarkTileDirty(x + SIGN(dx), y);
856 if (y < BY1) /* Element kommt von oben ins Bild */
858 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
866 else if (y > BY2) /* Element kommt von unten ins Bild */
872 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
878 else if (dy > 0 && cut_mode == CUT_ABOVE)
880 if (y == BY2) /* Element unterhalb des Bildes */
886 MarkTileDirty(x, y + 1);
887 } /* Element verläßt unten das Bild */
888 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
890 else if (dy) /* allg. Bewegung in y-Richtung */
891 MarkTileDirty(x, y + SIGN(dy));
894 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
896 src_pixmap = pix[PIX_BACK];
897 drawing_gc = clip_gc[PIX_BACK];
898 graphic -= GFX_START_ROCKSSCREEN;
899 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
900 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
902 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
904 src_pixmap = pix[PIX_MORE];
905 drawing_gc = clip_gc[PIX_MORE];
906 graphic -= GFX_START_ROCKSMORE;
907 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
908 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
910 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
912 src_pixmap = pix[PIX_HEROES];
913 drawing_gc = clip_gc[PIX_HEROES];
914 graphic -= GFX_START_ROCKSHEROES;
915 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
916 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
918 else /* big font graphics currently not allowed (and not needed) */
921 dest_x = FX + x * TILEX + dx;
922 dest_y = FY + y * TILEY + dy;
925 if (!IN_SCR_FIELD(x,y))
927 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
928 printf("DrawGraphicShifted(): This should never happen!\n");
933 if (mask_mode == USE_MASKING)
935 if (tile_clipmask[tile] != None)
937 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
938 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
939 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
940 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
945 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
948 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
949 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
950 src_x, src_y, width, height, dest_x, dest_y);
954 XCopyArea(display, src_pixmap, drawto_field, gc,
955 src_x, src_y, width, height, dest_x, dest_y);
960 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
963 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
966 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
967 int cut_mode, int mask_mode)
969 int ux = LEVELX(x), uy = LEVELY(y);
970 int graphic = el2gfx(element);
971 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
972 int phase4 = phase8 / 2;
973 int phase2 = phase8 / 4;
974 int dir = MovDir[ux][uy];
976 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
978 graphic += 4 * !phase2;
982 else if (dir == MV_LEFT)
984 else if (dir == MV_DOWN)
987 else if (element == EL_SP_SNIKSNAK)
990 graphic = GFX_SP_SNIKSNAK_LEFT;
991 else if (dir == MV_RIGHT)
992 graphic = GFX_SP_SNIKSNAK_RIGHT;
993 else if (dir == MV_UP)
994 graphic = GFX_SP_SNIKSNAK_UP;
996 graphic = GFX_SP_SNIKSNAK_DOWN;
998 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1000 else if (element == EL_SP_ELECTRON)
1002 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1004 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1005 element == EL_SCHWEIN || element == EL_DRACHE)
1008 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1009 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1010 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1011 else if (dir == MV_RIGHT)
1012 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1013 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1014 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1015 else if (dir == MV_UP)
1016 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1017 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1018 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1020 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1021 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1022 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1026 else if (element == EL_SONDE)
1028 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1030 else if (element == EL_SALZSAEURE)
1032 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1034 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1038 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
1040 if (element != EL_SP_INFOTRON)
1041 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1043 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1044 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1046 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1048 else if (IS_AMOEBOID(element))
1050 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1051 graphic += (x + 2 * y + 4) % 4;
1053 else if (element == EL_MAUER_LEBT)
1055 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1057 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1058 links_massiv = TRUE;
1059 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1060 rechts_massiv = TRUE;
1062 if (links_massiv && rechts_massiv)
1063 graphic = GFX_MAUERWERK;
1064 else if (links_massiv)
1065 graphic = GFX_MAUER_R;
1066 else if (rechts_massiv)
1067 graphic = GFX_MAUER_L;
1071 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1072 else if (mask_mode == USE_MASKING)
1073 DrawGraphicThruMask(x, y, graphic);
1075 DrawGraphic(x, y, graphic);
1078 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1079 int cut_mode, int mask_mode)
1081 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1082 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1083 cut_mode, mask_mode);
1086 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1089 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1092 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1095 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1098 void DrawScreenElementThruMask(int x, int y, int element)
1100 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1103 void DrawLevelElementThruMask(int x, int y, int element)
1105 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1108 void DrawLevelFieldThruMask(int x, int y)
1110 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1113 void ErdreichAnbroeckeln(int x, int y)
1115 int i, width, height, cx,cy;
1116 int ux = LEVELX(x), uy = LEVELY(y);
1117 int element, graphic;
1119 static int xy[4][2] =
1127 if (!IN_LEV_FIELD(ux, uy))
1130 element = Feld[ux][uy];
1132 if (element == EL_ERDREICH)
1134 if (!IN_SCR_FIELD(x, y))
1137 graphic = GFX_ERDENRAND;
1143 uxx = ux + xy[i][0];
1144 uyy = uy + xy[i][1];
1145 if (!IN_LEV_FIELD(uxx, uyy))
1148 element = Feld[uxx][uyy];
1150 if (element == EL_ERDREICH)
1153 if (i == 1 || i == 2)
1157 cx = (i == 2 ? TILEX - snip : 0);
1165 cy = (i == 3 ? TILEY - snip : 0);
1168 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1169 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1170 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1171 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1174 MarkTileDirty(x, y);
1178 graphic = GFX_ERDENRAND;
1182 int xx, yy, uxx, uyy;
1186 uxx = ux + xy[i][0];
1187 uyy = uy + xy[i][1];
1189 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1190 !IN_SCR_FIELD(xx, yy))
1193 if (i == 1 || i == 2)
1197 cx = (i == 1 ? TILEX - snip : 0);
1205 cy = (i==0 ? TILEY-snip : 0);
1208 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1209 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1210 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1211 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1213 MarkTileDirty(xx, yy);
1218 void DrawScreenElement(int x, int y, int element)
1220 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1221 ErdreichAnbroeckeln(x, y);
1224 void DrawLevelElement(int x, int y, int element)
1226 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1227 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1230 void DrawScreenField(int x, int y)
1232 int ux = LEVELX(x), uy = LEVELY(y);
1235 if (!IN_LEV_FIELD(ux, uy))
1237 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1238 element = EL_LEERRAUM;
1240 element = BorderElement;
1242 DrawScreenElement(x, y, element);
1246 element = Feld[ux][uy];
1248 if (IS_MOVING(ux, uy))
1250 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1251 boolean cut_mode = NO_CUTTING;
1253 if (Store[ux][uy] == EL_MORAST_LEER ||
1254 Store[ux][uy] == EL_SIEB_LEER ||
1255 Store[ux][uy] == EL_SIEB2_LEER ||
1256 Store[ux][uy] == EL_AMOEBE_NASS)
1257 cut_mode = CUT_ABOVE;
1258 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1259 Store[ux][uy] == EL_SIEB_VOLL ||
1260 Store[ux][uy] == EL_SIEB2_VOLL)
1261 cut_mode = CUT_BELOW;
1263 if (cut_mode == CUT_ABOVE)
1264 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1266 DrawScreenElement(x, y, EL_LEERRAUM);
1269 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1271 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1273 if (Store[ux][uy] == EL_SALZSAEURE)
1274 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1276 else if (IS_BLOCKED(ux, uy))
1281 boolean cut_mode = NO_CUTTING;
1283 Blocked2Moving(ux, uy, &oldx, &oldy);
1286 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1287 MovDir[oldx][oldy] == MV_RIGHT);
1289 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1290 Store[oldx][oldy] == EL_SIEB_LEER ||
1291 Store[oldx][oldy] == EL_SIEB2_LEER ||
1292 Store[oldx][oldy] == EL_AMOEBE_NASS)
1293 cut_mode = CUT_ABOVE;
1295 DrawScreenElement(x, y, EL_LEERRAUM);
1296 element = Feld[oldx][oldy];
1299 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1301 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1303 else if (IS_DRAWABLE(element))
1304 DrawScreenElement(x, y, element);
1306 DrawScreenElement(x, y, EL_LEERRAUM);
1309 void DrawLevelField(int x, int y)
1311 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1312 DrawScreenField(SCREENX(x), SCREENY(y));
1313 else if (IS_MOVING(x, y))
1317 Moving2Blocked(x, y, &newx, &newy);
1318 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1319 DrawScreenField(SCREENX(newx), SCREENY(newy));
1321 else if (IS_BLOCKED(x, y))
1325 Blocked2Moving(x, y, &oldx, &oldy);
1326 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1327 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1331 void DrawMiniElement(int x, int y, int element)
1337 DrawMiniGraphic(x, y, -1);
1341 graphic = el2gfx(element);
1342 DrawMiniGraphic(x, y, graphic);
1345 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1347 int x = sx + scroll_x, y = sy + scroll_y;
1349 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1350 DrawMiniElement(sx, sy, EL_LEERRAUM);
1351 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1352 DrawMiniElement(sx, sy, EL_BETON);
1354 DrawMiniElement(sx, sy, Feld[x][y]);
1357 void DrawMicroElement(int xpos, int ypos, int element)
1361 if (element == EL_LEERRAUM)
1364 graphic = el2gfx(element);
1366 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1368 graphic -= GFX_START_ROCKSMORE;
1369 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1370 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1371 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1372 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1375 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1376 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1377 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1378 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1387 for(x=BX1; x<=BX2; x++)
1388 for(y=BY1; y<=BY2; y++)
1389 DrawScreenField(x, y);
1391 if (setup.soft_scrolling)
1392 XCopyArea(display, fieldbuffer, backbuffer, gc,
1393 FX, FY, SXSIZE, SYSIZE, SX, SY);
1395 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1398 void DrawMiniLevel(int scroll_x, int scroll_y)
1402 for(x=0; x<ED_FIELDX; x++)
1403 for(y=0; y<ED_FIELDY; y++)
1404 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1406 redraw_mask |= REDRAW_FIELD;
1409 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1413 /* determine border element for this level */
1416 XFillRectangle(display, drawto, gc,
1417 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1419 if (lev_fieldx < STD_LEV_FIELDX)
1420 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1421 if (lev_fieldy < STD_LEV_FIELDY)
1422 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1424 xpos += MICRO_TILEX;
1425 ypos += MICRO_TILEY;
1427 for(x=-1; x<=STD_LEV_FIELDX; x++)
1429 for(y=-1; y<=STD_LEV_FIELDY; y++)
1431 int lx = from_x + x, ly = from_y + y;
1433 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1434 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1436 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1437 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1442 redraw_mask |= REDRAW_MICROLEVEL;
1445 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1447 static unsigned long scroll_delay = 0;
1448 static int from_x, from_y, scroll_direction;
1452 from_x = from_y = 0;
1453 scroll_direction = MV_RIGHT;
1455 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1457 XFillRectangle(display, drawto,gc,
1458 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1460 if (level.name && restart)
1462 int len = strlen(level.name);
1463 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1464 int lypos = MICROLABEL_YPOS;
1466 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1469 /* initialize delay counter */
1470 DelayReached(&scroll_delay, 0);
1472 redraw_mask |= REDRAW_MICROLEVEL_LABEL;
1476 if ((lev_fieldx <= STD_LEV_FIELDX && lev_fieldy <= STD_LEV_FIELDY) ||
1477 !DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1480 switch (scroll_direction)
1486 scroll_direction = MV_UP;
1490 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1493 scroll_direction = MV_DOWN;
1500 scroll_direction = MV_RIGHT;
1504 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1507 scroll_direction = MV_LEFT;
1514 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1518 int REQ_in_range(int x, int y)
1520 if (y > DY+249 && y < DY+278)
1522 if (x > DX+1 && x < DX+48)
1524 else if (x > DX+51 && x < DX+98)
1530 boolean Request(char *text, unsigned int req_state)
1532 int mx, my, ty, result = -1;
1533 unsigned int old_door_state;
1536 /* pause network game while waiting for request to answer */
1537 if (options.network &&
1538 game_status == PLAYING &&
1539 req_state & REQUEST_WAIT_FOR)
1540 SendToServer_PausePlaying();
1543 old_door_state = GetDoorState();
1545 CloseDoor(DOOR_CLOSE_1);
1547 /* Alten Türinhalt sichern */
1548 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1549 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1550 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1552 /* Fragetext schreiben */
1553 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1554 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1556 for(ty=0; ty<13; ty++)
1564 for(tl=0,tx=0; tx<7; tl++,tx++)
1567 if (!tc || tc == 32)
1578 DrawTextExt(pix[PIX_DB_DOOR], gc,
1579 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1580 txt, FS_SMALL, FC_YELLOW);
1581 text += tl + (tc == 32 ? 1 : 0);
1584 if (req_state & REQ_ASK)
1586 DrawYesNoButton(BUTTON_OK, DB_INIT);
1587 DrawYesNoButton(BUTTON_NO, DB_INIT);
1589 else if (req_state & REQ_CONFIRM)
1591 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1593 else if (req_state & REQ_PLAYER)
1595 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1596 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1597 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1598 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1601 OpenDoor(DOOR_OPEN_1);
1604 if (!(req_state & REQUEST_WAIT_FOR))
1607 if (game_status != MAINMENU)
1610 button_status = MB_RELEASED;
1614 if (XPending(display))
1618 XNextEvent(display, &event);
1628 if (event.type == MotionNotify)
1630 motion_status = TRUE;
1631 mx = ((XMotionEvent *) &event)->x;
1632 my = ((XMotionEvent *) &event)->y;
1636 motion_status = FALSE;
1637 mx = ((XButtonEvent *) &event)->x;
1638 my = ((XButtonEvent *) &event)->y;
1639 if (event.type==ButtonPress)
1640 button_status = ((XButtonEvent *) &event)->button;
1642 button_status = MB_RELEASED;
1645 if (req_state & REQ_ASK)
1646 choice = CheckYesNoButtons(mx,my,button_status);
1647 else if (req_state & REQ_CONFIRM)
1648 choice = CheckConfirmButton(mx,my,button_status);
1650 choice = CheckPlayerButtons(mx,my,button_status);
1660 case BUTTON_CONFIRM:
1661 result = TRUE | FALSE;
1664 case BUTTON_PLAYER_1:
1667 case BUTTON_PLAYER_2:
1670 case BUTTON_PLAYER_3:
1673 case BUTTON_PLAYER_4:
1684 switch(XLookupKeysym((XKeyEvent *)&event,
1685 ((XKeyEvent *)&event)->state))
1698 if (req_state & REQ_PLAYER)
1703 key_joystick_mapping = 0;
1707 HandleOtherEvents(&event);
1711 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1713 int joy = AnyJoystick();
1715 if (joy & JOY_BUTTON_1)
1717 else if (joy & JOY_BUTTON_2)
1723 /* don't eat all CPU time */
1727 if (game_status != MAINMENU)
1730 if (!(req_state & REQ_STAY_OPEN))
1732 CloseDoor(DOOR_CLOSE_1);
1734 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1736 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1737 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1738 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1739 OpenDoor(DOOR_OPEN_1);
1744 /* continue network game after request */
1745 if (options.network &&
1746 game_status == PLAYING &&
1747 req_state & REQUEST_WAIT_FOR)
1748 SendToServer_ContinuePlaying();
1754 unsigned int OpenDoor(unsigned int door_state)
1756 unsigned int new_door_state;
1758 if (door_state & DOOR_COPY_BACK)
1760 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1761 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1762 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1763 door_state &= ~DOOR_COPY_BACK;
1766 new_door_state = MoveDoor(door_state);
1768 return(new_door_state);
1771 unsigned int CloseDoor(unsigned int door_state)
1773 unsigned int new_door_state;
1775 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1776 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1777 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1778 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1780 new_door_state = MoveDoor(door_state);
1782 return(new_door_state);
1785 unsigned int GetDoorState()
1787 return(MoveDoor(DOOR_GET_STATE));
1790 unsigned int MoveDoor(unsigned int door_state)
1792 static int door1 = DOOR_OPEN_1;
1793 static int door2 = DOOR_CLOSE_2;
1794 static unsigned long door_delay = 0;
1795 int x, start, stepsize = 2;
1796 unsigned long door_delay_value = stepsize * 5;
1798 if (door_state == DOOR_GET_STATE)
1799 return(door1 | door2);
1801 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1802 door_state &= ~DOOR_OPEN_1;
1803 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1804 door_state &= ~DOOR_CLOSE_1;
1805 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1806 door_state &= ~DOOR_OPEN_2;
1807 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1808 door_state &= ~DOOR_CLOSE_2;
1810 if (setup.quick_doors)
1813 door_delay_value = 0;
1814 StopSound(SND_OEFFNEN);
1817 if (door_state & DOOR_ACTION)
1819 if (!(door_state & DOOR_NO_DELAY))
1820 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1822 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1824 for(x=start; x<=DXSIZE; x+=stepsize)
1826 WaitUntilDelayReached(&door_delay, door_delay_value);
1828 if (door_state & DOOR_ACTION_1)
1830 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1831 int j = (DXSIZE - i) / 3;
1833 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1834 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1835 DXSIZE,DYSIZE - i/2, DX, DY);
1837 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1839 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1840 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1841 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1842 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1843 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1844 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1846 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1847 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1848 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1849 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1850 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1851 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1853 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1854 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1856 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1857 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1859 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1860 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1861 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1862 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1863 DX + DXSIZE - i, DY + 77 + j);
1864 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1865 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1866 DX + DXSIZE - i, DY + 203 + j);
1868 redraw_mask |= REDRAW_DOOR_1;
1871 if (door_state & DOOR_ACTION_2)
1873 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1874 int j = (VXSIZE - i) / 3;
1876 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1877 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1878 VXSIZE, VYSIZE - i/2, VX, VY);
1880 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1882 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1883 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1884 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1885 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1886 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1887 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1888 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1889 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1891 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1892 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1893 VX, VY + VYSIZE / 2 - j);
1894 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1895 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1896 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1897 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1898 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1900 redraw_mask |= REDRAW_DOOR_2;
1905 if (game_status == MAINMENU)
1910 if (setup.quick_doors)
1911 StopSound(SND_OEFFNEN);
1913 if (door_state & DOOR_ACTION_1)
1914 door1 = door_state & DOOR_ACTION_1;
1915 if (door_state & DOOR_ACTION_2)
1916 door2 = door_state & DOOR_ACTION_2;
1918 return(door1 | door2);
1921 int ReadPixel(Drawable d, int x, int y)
1923 XImage *pixel_image;
1924 unsigned long pixel_value;
1926 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1927 pixel_value = XGetPixel(pixel_image, 0, 0);
1929 XDestroyImage(pixel_image);
1934 int el2gfx(int element)
1938 case EL_LEERRAUM: return -1;
1939 case EL_ERDREICH: return GFX_ERDREICH;
1940 case EL_MAUERWERK: return GFX_MAUERWERK;
1941 case EL_FELSBODEN: return GFX_FELSBODEN;
1942 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1943 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1944 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1945 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1946 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1947 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1948 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1949 case EL_SPIELER1: return GFX_SPIELER1;
1950 case EL_SPIELER2: return GFX_SPIELER2;
1951 case EL_SPIELER3: return GFX_SPIELER3;
1952 case EL_SPIELER4: return GFX_SPIELER4;
1953 case EL_KAEFER: return GFX_KAEFER;
1954 case EL_KAEFER_R: return GFX_KAEFER_R;
1955 case EL_KAEFER_O: return GFX_KAEFER_O;
1956 case EL_KAEFER_L: return GFX_KAEFER_L;
1957 case EL_KAEFER_U: return GFX_KAEFER_U;
1958 case EL_FLIEGER: return GFX_FLIEGER;
1959 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1960 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1961 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1962 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1963 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1964 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1965 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1966 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1967 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1968 case EL_FIREFLY: return GFX_FIREFLY;
1969 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1970 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1971 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1972 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1973 case EL_MAMPFER: return GFX_MAMPFER;
1974 case EL_ROBOT: return GFX_ROBOT;
1975 case EL_BETON: return GFX_BETON;
1976 case EL_DIAMANT: return GFX_DIAMANT;
1977 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1978 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1979 case EL_TROPFEN: return GFX_TROPFEN;
1980 case EL_BOMBE: return GFX_BOMBE;
1981 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
1982 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1983 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1984 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1985 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1986 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1987 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1988 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1989 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1990 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1991 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1992 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1993 case EL_LIFE: return GFX_LIFE;
1994 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1995 case EL_DYNAMIT: return GFX_DYNAMIT;
1996 case EL_BADEWANNE: return GFX_BADEWANNE;
1997 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1998 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1999 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2000 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2001 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2002 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2003 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2004 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2005 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2006 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2007 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2008 case EL_PFORTE1: return GFX_PFORTE1;
2009 case EL_PFORTE2: return GFX_PFORTE2;
2010 case EL_PFORTE3: return GFX_PFORTE3;
2011 case EL_PFORTE4: return GFX_PFORTE4;
2012 case EL_PFORTE1X: return GFX_PFORTE1X;
2013 case EL_PFORTE2X: return GFX_PFORTE2X;
2014 case EL_PFORTE3X: return GFX_PFORTE3X;
2015 case EL_PFORTE4X: return GFX_PFORTE4X;
2016 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2017 case EL_PACMAN: return GFX_PACMAN;
2018 case EL_PACMAN_R: return GFX_PACMAN_R;
2019 case EL_PACMAN_O: return GFX_PACMAN_O;
2020 case EL_PACMAN_L: return GFX_PACMAN_L;
2021 case EL_PACMAN_U: return GFX_PACMAN_U;
2022 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2023 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2024 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2025 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2026 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2027 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2028 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2029 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2030 case EL_MAUER_X: return GFX_MAUER_X;
2031 case EL_MAUER_Y: return GFX_MAUER_Y;
2032 case EL_MAUER_XY: return GFX_MAUER_XY;
2033 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2034 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2035 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2036 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2037 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2038 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2039 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2040 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2041 case EL_MAMPFER2: return GFX_MAMPFER2;
2042 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2043 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2044 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2045 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2046 case EL_DYNABOMB: return GFX_DYNABOMB;
2047 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2048 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2049 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2050 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2051 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2052 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2053 case EL_MAULWURF: return GFX_MAULWURF;
2054 case EL_PINGUIN: return GFX_PINGUIN;
2055 case EL_SCHWEIN: return GFX_SCHWEIN;
2056 case EL_DRACHE: return GFX_DRACHE;
2057 case EL_SONDE: return GFX_SONDE;
2058 case EL_PFEIL_L: return GFX_PFEIL_L;
2059 case EL_PFEIL_R: return GFX_PFEIL_R;
2060 case EL_PFEIL_O: return GFX_PFEIL_O;
2061 case EL_PFEIL_U: return GFX_PFEIL_U;
2062 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2063 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2064 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2065 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2069 if (IS_CHAR(element))
2070 return GFX_CHAR_START + (element - EL_CHAR_START);
2071 else if (element >= EL_SP_START && element <= EL_SP_END)
2073 int nr_element = element - EL_SP_START;
2074 int gfx_per_line = 8;
2076 (nr_element / gfx_per_line) * MORE_PER_LINE +
2077 (nr_element % gfx_per_line);
2079 return GFX_START_ROCKSMORE + nr_graphic;