1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
17 #include <machine/joystick.h>
31 extern boolean wait_for_vsync;
34 void SetDrawtoField(int mode)
36 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
47 drawto_field = fieldbuffer;
49 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
60 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
67 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
69 if (setup.direct_draw && game_status == PLAYING)
70 redraw_mask &= ~REDRAW_MAIN;
72 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
73 redraw_mask |= REDRAW_FIELD;
75 if (redraw_mask & REDRAW_FIELD)
76 redraw_mask &= ~REDRAW_TILES;
79 if (redraw_mask & REDRAW_FIELD ||
80 (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING))
81 redraw_mask &= ~REDRAW_TILES;
87 /* synchronize X11 graphics at this point; if we would synchronize the
88 display immediately after the buffer switching (after the XFlush),
89 this could mean that we have to wait for the graphics to complete,
90 although we could go on doing calculations for the next frame */
92 XSync(display, FALSE);
96 wait_for_vsync = TRUE;
100 if (redraw_mask & REDRAW_ALL)
102 XCopyArea(display,backbuffer,window,gc,
103 0,0, WIN_XSIZE,WIN_YSIZE,
108 if (redraw_mask & REDRAW_FIELD)
110 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
111 XCopyArea(display,backbuffer,window,gc,
112 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
116 int fx = FX, fy = FY;
118 if (setup.soft_scrolling)
120 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
121 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
124 if (setup.soft_scrolling ||
125 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
126 ABS(ScreenMovPos) == ScrollStepSize ||
127 redraw_tiles > REDRAWTILES_THRESHOLD)
129 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
133 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
135 (setup.soft_scrolling ?
136 "setup.soft_scrolling" :
137 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
138 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
139 ABS(ScreenGfxPos) == ScrollStepSize ?
140 "ABS(ScreenGfxPos) == ScrollStepSize" :
141 "redraw_tiles > REDRAWTILES_THRESHOLD"));
146 redraw_mask &= ~REDRAW_MAIN;
149 if (redraw_mask & REDRAW_DOORS)
151 if (redraw_mask & REDRAW_DOOR_1)
152 XCopyArea(display,backbuffer,window,gc,
153 DX,DY, DXSIZE,DYSIZE,
155 if (redraw_mask & REDRAW_DOOR_2)
157 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
158 XCopyArea(display,backbuffer,window,gc,
159 VX,VY, VXSIZE,VYSIZE,
163 if (redraw_mask & REDRAW_VIDEO_1)
164 XCopyArea(display,backbuffer,window,gc,
165 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
166 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
167 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
168 if (redraw_mask & REDRAW_VIDEO_2)
169 XCopyArea(display,backbuffer,window,gc,
170 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
171 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
172 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
173 if (redraw_mask & REDRAW_VIDEO_3)
174 XCopyArea(display,backbuffer,window,gc,
175 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
176 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
177 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
180 if (redraw_mask & REDRAW_DOOR_3)
181 XCopyArea(display, backbuffer, window, gc,
182 EX, EY, EXSIZE, EYSIZE,
184 redraw_mask &= ~REDRAW_DOORS;
187 if (redraw_mask & REDRAW_MICROLEV)
189 XCopyArea(display,backbuffer,window,gc,
190 MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
191 MICROLEV_XPOS,MICROLEV_YPOS);
192 XCopyArea(display,backbuffer,window,gc,
193 SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
195 redraw_mask &= ~REDRAW_MICROLEV;
198 if (redraw_mask & REDRAW_TILES)
200 for(x=0; x<SCR_FIELDX; x++)
201 for(y=0; y<SCR_FIELDY; y++)
202 if (redraw[redraw_x1 + x][redraw_y1 + y])
203 XCopyArea(display,buffer,window,gc,
204 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
205 SX+x*TILEX,SY+y*TILEY);
210 for(x=0; x<MAX_BUF_XSIZE; x++)
211 for(y=0; y<MAX_BUF_YSIZE; y++)
220 long fading_delay = 300;
222 if (setup.fading && (redraw_mask & REDRAW_FIELD))
229 XFillRectangle(display,window,gc,
230 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
233 for(i=0;i<2*FULL_SYSIZE;i++)
235 for(y=0;y<FULL_SYSIZE;y++)
237 XCopyArea(display,backbuffer,window,gc,
238 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
246 for(i=1;i<FULL_SYSIZE;i+=2)
247 XCopyArea(display,backbuffer,window,gc,
248 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
254 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
255 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
256 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
260 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
261 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
262 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
266 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
267 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
268 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
272 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
273 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
274 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
278 redraw_mask &= ~REDRAW_MAIN;
287 XFillRectangle(display, backbuffer, gc,
288 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
290 if (setup.soft_scrolling && game_status == PLAYING)
292 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
293 SetDrawtoField(DRAW_BUFFERED);
296 SetDrawtoField(DRAW_BACKBUFFER);
298 if (setup.direct_draw && game_status == PLAYING)
300 XFillRectangle(display, window, gc,
301 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
302 SetDrawtoField(DRAW_DIRECT);
305 redraw_mask |= REDRAW_FIELD;
308 void DrawTextFCentered(int y, int font_type, char *format, ...)
310 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
314 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
315 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
317 va_start(ap, format);
318 vsprintf(buffer, format, ap);
321 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
322 buffer, FS_SMALL, font_type);
325 void DrawTextF(int x, int y, int font_type, char *format, ...)
327 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
330 va_start(ap, format);
331 vsprintf(buffer, format, ap);
334 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
337 void DrawText(int x, int y, char *text, int font_size, int font_type)
339 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
342 redraw_mask |= REDRAW_FIELD;
344 redraw_mask |= REDRAW_DOOR_1;
347 void DrawTextExt(Drawable d, GC gc, int x, int y,
348 char *text, int font_size, int font_type)
350 int font_width, font_height, font_start;
353 if (font_size != FS_SMALL && font_size != FS_BIG)
354 font_size = FS_SMALL;
355 if (font_type < FC_RED || font_type > FC_SPECIAL2)
358 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
359 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
360 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
361 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
362 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
363 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
364 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
365 FONT_LINES_PER_FONT);
371 if (c >= 'a' && c <= 'z')
373 else if (c == 'ä' || c == 'Ä')
375 else if (c == 'ö' || c == 'Ö')
377 else if (c == 'ü' || c == 'Ü')
380 if (c >= 32 && c <= 95)
381 XCopyArea(display, pix[font_pixmap], d, gc,
382 ((c - 32) % FONT_CHARS_PER_LINE) * font_width,
383 ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start,
384 font_width, font_height, x, y);
390 void DrawAllPlayers()
394 for(i=0; i<MAX_PLAYERS; i++)
395 if (stored_player[i].active)
396 DrawPlayer(&stored_player[i]);
399 void DrawPlayerField(int x, int y)
404 DrawPlayer(PLAYERINFO(x,y));
407 void DrawPlayer(struct PlayerInfo *player)
409 int jx = player->jx, jy = player->jy;
410 int last_jx = player->last_jx, last_jy = player->last_jy;
411 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
412 int sx = SCREENX(jx), sy = SCREENY(jy);
413 int sxx = 0, syy = 0;
414 int element = Feld[jx][jy];
417 if (!player->active || player->gone ||
418 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
422 if (!IN_LEV_FIELD(jx,jy))
424 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
425 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
426 printf("DrawPlayerField(): This should never happen!\n");
431 if (element == EL_EXPLODING)
434 /* draw things in the field the player is leaving, if needed */
436 if (last_jx != jx || last_jy != jy)
438 if (Store[last_jx][last_jy])
440 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
441 DrawLevelFieldThruMask(last_jx, last_jy);
443 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
444 DrawDynamite(last_jx, last_jy);
446 DrawLevelField(last_jx, last_jy);
448 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
452 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
453 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
455 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
458 DrawLevelField(next_jx, next_jy);
462 if (!IN_SCR_FIELD(sx, sy))
465 if (setup.direct_draw)
466 SetDrawtoField(DRAW_BUFFERED);
468 /* draw things behind the player, if needed */
471 DrawLevelElement(jx, jy, Store[jx][jy]);
472 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
473 DrawLevelField(jx, jy);
475 /* draw player himself */
477 if (player->MovDir == MV_LEFT)
478 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
479 else if (player->MovDir == MV_RIGHT)
480 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
481 else if (player->MovDir == MV_UP)
482 graphic = GFX_SPIELER1_UP;
483 else /* MV_DOWN || MV_NO_MOVING */
484 graphic = GFX_SPIELER1_DOWN;
486 graphic += player->index_nr * 3*HEROES_PER_LINE;
487 graphic += player->Frame;
491 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
492 sxx = player->GfxPos;
494 syy = player->GfxPos;
497 if (!setup.soft_scrolling && ScreenMovPos)
500 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
502 if (player->Pushing && player->GfxPos)
504 int px = SCREENX(next_jx), py = SCREENY(next_jy);
506 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
507 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
508 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
512 int element = Feld[next_jx][next_jy];
513 int graphic = el2gfx(element);
515 if (element == EL_FELSBROCKEN && sxx)
517 int phase = (player->GfxPos / (TILEX/4));
519 if (player->MovDir == MV_LEFT)
522 graphic += (phase+4)%4;
525 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
529 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
531 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
533 graphic = el2gfx(element);
535 if (element == EL_DYNAMIT)
537 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
542 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
546 DrawGraphicThruMask(sx, sy, graphic + phase);
549 if ((last_jx != jx || last_jy != jy) &&
550 Feld[last_jx][last_jy] == EL_EXPLODING)
552 int phase = Frame[last_jx][last_jy];
556 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
557 GFX_EXPLOSION + ((phase - 1) / delay - 1));
560 if (setup.direct_draw)
562 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
563 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
564 int x_size = TILEX * (1 + ABS(jx - last_jx));
565 int y_size = TILEY * (1 + ABS(jy - last_jy));
567 XCopyArea(display, drawto_field, window, gc,
568 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
569 SetDrawtoField(DRAW_DIRECT);
572 MarkTileDirty(sx,sy);
575 static int getGraphicAnimationPhase(int frames, int delay, int mode)
579 if (mode == ANIM_OSCILLATE)
581 int max_anim_frames = 2 * frames - 2;
582 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
583 phase = (phase < frames ? phase : max_anim_frames - phase);
586 phase = (FrameCounter % (delay * frames)) / delay;
588 if (mode == ANIM_REVERSE)
594 void DrawGraphicAnimationExt(int x, int y, int graphic,
595 int frames, int delay, int mode, int mask_mode)
597 int phase = getGraphicAnimationPhase(frames, delay, mode);
599 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
601 if (mask_mode == USE_MASKING)
602 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
604 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
608 void DrawGraphicAnimation(int x, int y, int graphic,
609 int frames, int delay, int mode)
611 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
614 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
615 int frames, int delay, int mode)
617 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
620 void DrawGraphic(int x, int y, int graphic)
623 if (!IN_SCR_FIELD(x,y))
625 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
626 printf("DrawGraphic(): This should never happen!\n");
631 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
635 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
637 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
639 graphic -= GFX_START_ROCKSSCREEN;
640 XCopyArea(display, pix[PIX_BACK], d, gc,
641 SX + (graphic % GFX_PER_LINE) * TILEX,
642 SY + (graphic / GFX_PER_LINE) * TILEY,
645 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
647 graphic -= GFX_START_ROCKSMORE;
648 XCopyArea(display, pix[PIX_MORE], d, gc,
649 (graphic % MORE_PER_LINE) * TILEX,
650 (graphic / MORE_PER_LINE) * TILEY,
653 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
655 graphic -= GFX_START_ROCKSHEROES;
656 XCopyArea(display, pix[PIX_HEROES], d, gc,
657 (graphic % HEROES_PER_LINE) * TILEX,
658 (graphic / HEROES_PER_LINE) * TILEY,
661 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
663 graphic -= GFX_START_ROCKSFONT;
664 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
665 (graphic % FONT_CHARS_PER_LINE) * TILEX,
666 (graphic / FONT_CHARS_PER_LINE) * TILEY +
667 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
671 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
674 void DrawGraphicThruMask(int x, int y, int graphic)
677 if (!IN_SCR_FIELD(x,y))
679 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
680 printf("DrawGraphicThruMask(): This should never happen!\n");
685 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
689 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
696 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
698 src_pixmap = pix[PIX_BACK];
699 drawing_gc = clip_gc[PIX_BACK];
700 graphic -= GFX_START_ROCKSSCREEN;
701 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
702 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
704 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
706 src_pixmap = pix[PIX_MORE];
707 drawing_gc = clip_gc[PIX_MORE];
708 graphic -= GFX_START_ROCKSMORE;
709 src_x = (graphic % MORE_PER_LINE) * TILEX;
710 src_y = (graphic / MORE_PER_LINE) * TILEY;
712 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
714 src_pixmap = pix[PIX_HEROES];
715 drawing_gc = clip_gc[PIX_HEROES];
716 graphic -= GFX_START_ROCKSHEROES;
717 src_x = (graphic % HEROES_PER_LINE) * TILEX;
718 src_y = (graphic / HEROES_PER_LINE) * TILEY;
722 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
726 if (tile_clipmask[tile] != None)
728 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
729 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
730 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
731 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
736 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
739 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
740 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
741 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
745 void DrawMiniGraphic(int x, int y, int graphic)
747 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
748 MarkTileDirty(x/2, y/2);
751 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
753 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
755 graphic -= GFX_START_ROCKSSCREEN;
756 XCopyArea(display, pix[PIX_BACK], d, gc,
757 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
758 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
759 MINI_TILEX, MINI_TILEY, x, y);
761 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
763 graphic -= GFX_START_ROCKSMORE;
764 XCopyArea(display, pix[PIX_MORE], d, gc,
765 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
766 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
767 MINI_TILEX, MINI_TILEY, x, y);
769 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
771 graphic -= GFX_START_ROCKSFONT;
772 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
773 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
774 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
775 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
776 MINI_TILEX, MINI_TILEY, x, y);
779 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
782 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
783 int cut_mode, int mask_mode)
785 int width = TILEX, height = TILEY;
787 int src_x, src_y, dest_x, dest_y;
794 DrawGraphic(x, y, graphic);
798 if (dx || dy) /* Verschiebung der Grafik? */
800 if (x < BX1) /* Element kommt von links ins Bild */
807 else if (x > BX2) /* Element kommt von rechts ins Bild */
813 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
819 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
821 else if (dx) /* allg. Bewegung in x-Richtung */
822 MarkTileDirty(x + SIGN(dx), y);
824 if (y < BY1) /* Element kommt von oben ins Bild */
826 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
834 else if (y > BY2) /* Element kommt von unten ins Bild */
840 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
846 else if (dy > 0 && cut_mode == CUT_ABOVE)
848 if (y == BY2) /* Element unterhalb des Bildes */
854 MarkTileDirty(x, y + 1);
855 } /* Element verläßt unten das Bild */
856 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
858 else if (dy) /* allg. Bewegung in y-Richtung */
859 MarkTileDirty(x, y + SIGN(dy));
862 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
864 src_pixmap = pix[PIX_BACK];
865 drawing_gc = clip_gc[PIX_BACK];
866 graphic -= GFX_START_ROCKSSCREEN;
867 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
868 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
870 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
872 src_pixmap = pix[PIX_MORE];
873 drawing_gc = clip_gc[PIX_MORE];
874 graphic -= GFX_START_ROCKSMORE;
875 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
876 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
878 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
880 src_pixmap = pix[PIX_HEROES];
881 drawing_gc = clip_gc[PIX_HEROES];
882 graphic -= GFX_START_ROCKSHEROES;
883 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
884 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
886 else /* big font graphics currently not allowed (and not needed) */
889 dest_x = FX + x * TILEX + dx;
890 dest_y = FY + y * TILEY + dy;
893 if (!IN_SCR_FIELD(x,y))
895 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
896 printf("DrawGraphicShifted(): This should never happen!\n");
901 if (mask_mode == USE_MASKING)
903 if (tile_clipmask[tile] != None)
905 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
906 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
907 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
908 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
913 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
916 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
917 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
918 src_x, src_y, width, height, dest_x, dest_y);
922 XCopyArea(display, src_pixmap, drawto_field, gc,
923 src_x, src_y, width, height, dest_x, dest_y);
928 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
931 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
934 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
935 int cut_mode, int mask_mode)
937 int ux = LEVELX(x), uy = LEVELY(y);
938 int graphic = el2gfx(element);
939 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
940 int phase4 = phase8 / 2;
941 int phase2 = phase8 / 4;
942 int dir = MovDir[ux][uy];
944 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
946 graphic += 4 * !phase2;
950 else if (dir == MV_LEFT)
952 else if (dir == MV_DOWN)
955 else if (element == EL_SP_SNIKSNAK)
958 graphic = GFX_SP_SNIKSNAK_LEFT;
959 else if (dir == MV_RIGHT)
960 graphic = GFX_SP_SNIKSNAK_RIGHT;
961 else if (dir == MV_UP)
962 graphic = GFX_SP_SNIKSNAK_UP;
964 graphic = GFX_SP_SNIKSNAK_DOWN;
966 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
968 else if (element == EL_SP_ELECTRON)
970 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
972 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
973 element == EL_SCHWEIN || element == EL_DRACHE)
976 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
977 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
978 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
979 else if (dir == MV_RIGHT)
980 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
981 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
982 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
983 else if (dir == MV_UP)
984 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
985 element == EL_PINGUIN ? GFX_PINGUIN_UP :
986 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
988 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
989 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
990 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
994 else if (element == EL_SONDE)
996 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
998 else if (element == EL_SALZSAEURE)
1000 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1002 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1006 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
1008 if (element != EL_SP_INFOTRON)
1009 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1011 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1012 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1014 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1016 else if (IS_AMOEBOID(element))
1018 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1019 graphic += (x + 2 * y + 4) % 4;
1021 else if (element == EL_MAUER_LEBT)
1023 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1025 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1026 links_massiv = TRUE;
1027 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1028 rechts_massiv = TRUE;
1030 if (links_massiv && rechts_massiv)
1031 graphic = GFX_MAUERWERK;
1032 else if (links_massiv)
1033 graphic = GFX_MAUER_R;
1034 else if (rechts_massiv)
1035 graphic = GFX_MAUER_L;
1039 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1040 else if (mask_mode == USE_MASKING)
1041 DrawGraphicThruMask(x, y, graphic);
1043 DrawGraphic(x, y, graphic);
1046 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1047 int cut_mode, int mask_mode)
1049 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1050 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1051 cut_mode, mask_mode);
1054 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1057 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1060 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1063 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1066 void DrawScreenElementThruMask(int x, int y, int element)
1068 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1071 void DrawLevelElementThruMask(int x, int y, int element)
1073 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1076 void DrawLevelFieldThruMask(int x, int y)
1078 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1081 void ErdreichAnbroeckeln(int x, int y)
1083 int i, width, height, cx,cy;
1084 int ux = LEVELX(x), uy = LEVELY(y);
1085 int element, graphic;
1087 static int xy[4][2] =
1095 if (!IN_LEV_FIELD(ux, uy))
1098 element = Feld[ux][uy];
1100 if (element == EL_ERDREICH)
1102 if (!IN_SCR_FIELD(x, y))
1105 graphic = GFX_ERDENRAND;
1111 uxx = ux + xy[i][0];
1112 uyy = uy + xy[i][1];
1113 if (!IN_LEV_FIELD(uxx, uyy))
1116 element = Feld[uxx][uyy];
1118 if (element == EL_ERDREICH)
1121 if (i == 1 || i == 2)
1125 cx = (i == 2 ? TILEX - snip : 0);
1133 cy = (i == 3 ? TILEY - snip : 0);
1136 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1137 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1138 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1139 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1142 MarkTileDirty(x, y);
1146 graphic = GFX_ERDENRAND;
1150 int xx, yy, uxx, uyy;
1154 uxx = ux + xy[i][0];
1155 uyy = uy + xy[i][1];
1157 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1158 !IN_SCR_FIELD(xx, yy))
1161 if (i == 1 || i == 2)
1165 cx = (i == 1 ? TILEX - snip : 0);
1173 cy = (i==0 ? TILEY-snip : 0);
1176 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1177 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1178 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1179 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1181 MarkTileDirty(xx, yy);
1186 void DrawScreenElement(int x, int y, int element)
1188 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1189 ErdreichAnbroeckeln(x, y);
1192 void DrawLevelElement(int x, int y, int element)
1194 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1195 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1198 void DrawScreenField(int x, int y)
1200 int ux = LEVELX(x), uy = LEVELY(y);
1203 if (!IN_LEV_FIELD(ux, uy))
1205 DrawScreenElement(x, y, EL_BETON);
1209 element = Feld[ux][uy];
1211 if (IS_MOVING(ux, uy))
1213 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1214 boolean cut_mode = NO_CUTTING;
1216 if (Store[ux][uy] == EL_MORAST_LEER ||
1217 Store[ux][uy] == EL_SIEB_LEER ||
1218 Store[ux][uy] == EL_SIEB2_LEER ||
1219 Store[ux][uy] == EL_AMOEBE_NASS)
1220 cut_mode = CUT_ABOVE;
1221 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1222 Store[ux][uy] == EL_SIEB_VOLL ||
1223 Store[ux][uy] == EL_SIEB2_VOLL)
1224 cut_mode = CUT_BELOW;
1226 if (cut_mode == CUT_ABOVE)
1227 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1229 DrawScreenElement(x, y, EL_LEERRAUM);
1232 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1234 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1236 if (Store[ux][uy] == EL_SALZSAEURE)
1237 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1239 else if (IS_BLOCKED(ux, uy))
1244 boolean cut_mode = NO_CUTTING;
1246 Blocked2Moving(ux, uy, &oldx, &oldy);
1249 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1250 MovDir[oldx][oldy] == MV_RIGHT);
1252 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1253 Store[oldx][oldy] == EL_SIEB_LEER ||
1254 Store[oldx][oldy] == EL_SIEB2_LEER ||
1255 Store[oldx][oldy] == EL_AMOEBE_NASS)
1256 cut_mode = CUT_ABOVE;
1258 DrawScreenElement(x, y, EL_LEERRAUM);
1259 element = Feld[oldx][oldy];
1262 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1264 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1266 else if (IS_DRAWABLE(element))
1267 DrawScreenElement(x, y, element);
1269 DrawScreenElement(x, y, EL_LEERRAUM);
1272 void DrawLevelField(int x, int y)
1274 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1275 DrawScreenField(SCREENX(x), SCREENY(y));
1276 else if (IS_MOVING(x, y))
1280 Moving2Blocked(x, y, &newx, &newy);
1281 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1282 DrawScreenField(SCREENX(newx), SCREENY(newy));
1284 else if (IS_BLOCKED(x, y))
1288 Blocked2Moving(x, y, &oldx, &oldy);
1289 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1290 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1294 void DrawMiniElement(int x, int y, int element)
1300 DrawMiniGraphic(x, y, -1);
1304 graphic = el2gfx(element);
1305 DrawMiniGraphic(x, y, graphic);
1308 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1310 int x = sx + scroll_x, y = sy + scroll_y;
1312 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1313 DrawMiniElement(sx, sy, EL_LEERRAUM);
1314 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1315 DrawMiniElement(sx, sy, EL_BETON);
1317 DrawMiniElement(sx, sy, Feld[x][y]);
1320 void DrawMicroElement(int xpos, int ypos, int element)
1324 if (element == EL_LEERRAUM)
1327 graphic = el2gfx(element);
1329 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1331 graphic -= GFX_START_ROCKSMORE;
1332 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1333 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1334 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1335 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1338 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1339 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1340 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1341 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1350 for(x=BX1; x<=BX2; x++)
1351 for(y=BY1; y<=BY2; y++)
1352 DrawScreenField(x, y);
1354 if (setup.soft_scrolling)
1355 XCopyArea(display, fieldbuffer, backbuffer, gc,
1356 FX, FY, SXSIZE, SYSIZE, SX, SY);
1358 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1361 void DrawMiniLevel(int scroll_x, int scroll_y)
1367 for(x=0; x<2*SCR_FIELDX; x++)
1368 for(y=0; y<2*SCR_FIELDY; y++)
1369 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1371 redraw_mask |= REDRAW_FIELD;
1374 void DrawMicroLevel(int xpos, int ypos)
1378 XFillRectangle(display, drawto, gc,
1379 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1380 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1381 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1382 if (lev_fieldx < STD_LEV_FIELDX)
1383 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1384 if (lev_fieldy < STD_LEV_FIELDY)
1385 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1387 for(x=-1; x<=STD_LEV_FIELDX; x++)
1388 for(y=-1; y<=STD_LEV_FIELDY; y++)
1389 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1390 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1392 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1393 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1396 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1400 int len = strlen(level.name);
1401 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1402 int lypos = MICROLABEL_YPOS;
1404 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1407 redraw_mask |= REDRAW_MICROLEV;
1410 int REQ_in_range(int x, int y)
1412 if (y > DY+249 && y < DY+278)
1414 if (x > DX+1 && x < DX+48)
1416 else if (x > DX+51 && x < DX+98)
1422 boolean Request(char *text, unsigned int req_state)
1424 int mx, my, ty, result = -1;
1425 unsigned int old_door_state;
1428 /* pause network game while waiting for request to answer */
1429 if (options.network &&
1430 game_status == PLAYING &&
1431 req_state & REQUEST_WAIT_FOR)
1432 SendToServer_PausePlaying();
1435 old_door_state = GetDoorState();
1437 CloseDoor(DOOR_CLOSE_1);
1439 /* Alten Türinhalt sichern */
1440 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1441 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1442 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1444 /* Fragetext schreiben */
1445 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1446 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1448 for(ty=0; ty<13; ty++)
1456 for(tl=0,tx=0; tx<7; tl++,tx++)
1459 if (!tc || tc == 32)
1470 DrawTextExt(pix[PIX_DB_DOOR], gc,
1471 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1472 txt, FS_SMALL, FC_YELLOW);
1473 text += tl + (tc == 32 ? 1 : 0);
1476 if (req_state & REQ_ASK)
1478 DrawYesNoButton(BUTTON_OK, DB_INIT);
1479 DrawYesNoButton(BUTTON_NO, DB_INIT);
1481 else if (req_state & REQ_CONFIRM)
1483 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1485 else if (req_state & REQ_PLAYER)
1487 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1488 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1489 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1490 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1493 OpenDoor(DOOR_OPEN_1);
1496 if (!(req_state & REQUEST_WAIT_FOR))
1499 if (game_status != MAINMENU)
1502 button_status = MB_RELEASED;
1506 if (XPending(display))
1510 XNextEvent(display, &event);
1520 if (event.type == MotionNotify)
1522 motion_status = TRUE;
1523 mx = ((XMotionEvent *) &event)->x;
1524 my = ((XMotionEvent *) &event)->y;
1528 motion_status = FALSE;
1529 mx = ((XButtonEvent *) &event)->x;
1530 my = ((XButtonEvent *) &event)->y;
1531 if (event.type==ButtonPress)
1532 button_status = ((XButtonEvent *) &event)->button;
1534 button_status = MB_RELEASED;
1537 if (req_state & REQ_ASK)
1538 choice = CheckYesNoButtons(mx,my,button_status);
1539 else if (req_state & REQ_CONFIRM)
1540 choice = CheckConfirmButton(mx,my,button_status);
1542 choice = CheckPlayerButtons(mx,my,button_status);
1552 case BUTTON_CONFIRM:
1553 result = TRUE | FALSE;
1556 case BUTTON_PLAYER_1:
1559 case BUTTON_PLAYER_2:
1562 case BUTTON_PLAYER_3:
1565 case BUTTON_PLAYER_4:
1576 switch(XLookupKeysym((XKeyEvent *)&event,
1577 ((XKeyEvent *)&event)->state))
1590 if (req_state & REQ_PLAYER)
1595 key_joystick_mapping = 0;
1599 HandleOtherEvents(&event);
1603 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1605 int joy = AnyJoystick();
1607 if (joy & JOY_BUTTON_1)
1609 else if (joy & JOY_BUTTON_2)
1615 /* don't eat all CPU time */
1619 if (game_status != MAINMENU)
1622 if (!(req_state & REQ_STAY_OPEN))
1624 CloseDoor(DOOR_CLOSE_1);
1626 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1628 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1629 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1630 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1631 OpenDoor(DOOR_OPEN_1);
1636 /* continue network game after request */
1637 if (options.network &&
1638 game_status == PLAYING &&
1639 req_state & REQUEST_WAIT_FOR)
1640 SendToServer_ContinuePlaying();
1646 unsigned int OpenDoor(unsigned int door_state)
1648 unsigned int new_door_state;
1650 if (door_state & DOOR_COPY_BACK)
1652 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1653 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1654 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1655 door_state &= ~DOOR_COPY_BACK;
1658 new_door_state = MoveDoor(door_state);
1660 return(new_door_state);
1663 unsigned int CloseDoor(unsigned int door_state)
1665 unsigned int new_door_state;
1667 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1668 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1669 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1670 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1672 new_door_state = MoveDoor(door_state);
1674 return(new_door_state);
1677 unsigned int GetDoorState()
1679 return(MoveDoor(DOOR_GET_STATE));
1682 unsigned int MoveDoor(unsigned int door_state)
1684 static int door1 = DOOR_OPEN_1;
1685 static int door2 = DOOR_CLOSE_2;
1686 static unsigned long door_delay = 0;
1687 int x, start, stepsize = 2;
1688 unsigned long door_delay_value = stepsize * 5;
1690 if (door_state == DOOR_GET_STATE)
1691 return(door1 | door2);
1693 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1694 door_state &= ~DOOR_OPEN_1;
1695 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1696 door_state &= ~DOOR_CLOSE_1;
1697 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1698 door_state &= ~DOOR_OPEN_2;
1699 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1700 door_state &= ~DOOR_CLOSE_2;
1702 if (setup.quick_doors)
1705 door_delay_value = 0;
1706 StopSound(SND_OEFFNEN);
1709 if (door_state & DOOR_ACTION)
1711 if (!(door_state & DOOR_NO_DELAY))
1712 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1714 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1716 for(x=start; x<=DXSIZE; x+=stepsize)
1718 WaitUntilDelayReached(&door_delay, door_delay_value);
1720 if (door_state & DOOR_ACTION_1)
1722 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1723 int j = (DXSIZE - i) / 3;
1725 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1726 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1727 DXSIZE,DYSIZE - i/2, DX, DY);
1729 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1731 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1732 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1733 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1734 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1735 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1736 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1738 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1739 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1740 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1741 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1742 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1743 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1745 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1746 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1748 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1749 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1751 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1752 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1753 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1754 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1755 DX + DXSIZE - i, DY + 77 + j);
1756 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1757 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1758 DX + DXSIZE - i, DY + 203 + j);
1760 redraw_mask |= REDRAW_DOOR_1;
1763 if (door_state & DOOR_ACTION_2)
1765 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1766 int j = (VXSIZE - i) / 3;
1768 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1769 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1770 VXSIZE, VYSIZE - i/2, VX, VY);
1772 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1774 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1775 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1776 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1777 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1778 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1779 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1780 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1781 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1783 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1784 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1785 VX, VY + VYSIZE / 2 - j);
1786 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1787 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1788 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1789 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1790 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1792 redraw_mask |= REDRAW_DOOR_2;
1797 if (game_status == MAINMENU)
1802 if (setup.quick_doors)
1803 StopSound(SND_OEFFNEN);
1805 if (door_state & DOOR_ACTION_1)
1806 door1 = door_state & DOOR_ACTION_1;
1807 if (door_state & DOOR_ACTION_2)
1808 door2 = door_state & DOOR_ACTION_2;
1810 return(door1 | door2);
1813 int ReadPixel(Drawable d, int x, int y)
1815 XImage *pixel_image;
1816 unsigned long pixel_value;
1818 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1819 pixel_value = XGetPixel(pixel_image, 0, 0);
1821 XDestroyImage(pixel_image);
1826 int el2gfx(int element)
1830 case EL_LEERRAUM: return -1;
1831 case EL_ERDREICH: return GFX_ERDREICH;
1832 case EL_MAUERWERK: return GFX_MAUERWERK;
1833 case EL_FELSBODEN: return GFX_FELSBODEN;
1834 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1835 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1836 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1837 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1838 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1839 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1840 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1841 case EL_SPIELER1: return GFX_SPIELER1;
1842 case EL_SPIELER2: return GFX_SPIELER2;
1843 case EL_SPIELER3: return GFX_SPIELER3;
1844 case EL_SPIELER4: return GFX_SPIELER4;
1845 case EL_KAEFER: return GFX_KAEFER;
1846 case EL_KAEFER_R: return GFX_KAEFER_R;
1847 case EL_KAEFER_O: return GFX_KAEFER_O;
1848 case EL_KAEFER_L: return GFX_KAEFER_L;
1849 case EL_KAEFER_U: return GFX_KAEFER_U;
1850 case EL_FLIEGER: return GFX_FLIEGER;
1851 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1852 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1853 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1854 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1855 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1856 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1857 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1858 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1859 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1860 case EL_FIREFLY: return GFX_FIREFLY;
1861 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1862 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1863 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1864 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1865 case EL_MAMPFER: return GFX_MAMPFER;
1866 case EL_ROBOT: return GFX_ROBOT;
1867 case EL_BETON: return GFX_BETON;
1868 case EL_DIAMANT: return GFX_DIAMANT;
1869 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1870 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1871 case EL_TROPFEN: return GFX_TROPFEN;
1872 case EL_BOMBE: return GFX_BOMBE;
1873 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
1874 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1875 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1876 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1877 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1878 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1879 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1880 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1881 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1882 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1883 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1884 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1885 case EL_LIFE: return GFX_LIFE;
1886 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1887 case EL_DYNAMIT: return GFX_DYNAMIT;
1888 case EL_BADEWANNE: return GFX_BADEWANNE;
1889 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1890 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1891 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1892 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1893 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1894 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1895 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1896 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1897 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1898 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1899 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1900 case EL_PFORTE1: return GFX_PFORTE1;
1901 case EL_PFORTE2: return GFX_PFORTE2;
1902 case EL_PFORTE3: return GFX_PFORTE3;
1903 case EL_PFORTE4: return GFX_PFORTE4;
1904 case EL_PFORTE1X: return GFX_PFORTE1X;
1905 case EL_PFORTE2X: return GFX_PFORTE2X;
1906 case EL_PFORTE3X: return GFX_PFORTE3X;
1907 case EL_PFORTE4X: return GFX_PFORTE4X;
1908 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1909 case EL_PACMAN: return GFX_PACMAN;
1910 case EL_PACMAN_R: return GFX_PACMAN_R;
1911 case EL_PACMAN_O: return GFX_PACMAN_O;
1912 case EL_PACMAN_L: return GFX_PACMAN_L;
1913 case EL_PACMAN_U: return GFX_PACMAN_U;
1914 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1915 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1916 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1917 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1918 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1919 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1920 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1921 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1922 case EL_MAUER_X: return GFX_MAUER_X;
1923 case EL_MAUER_Y: return GFX_MAUER_Y;
1924 case EL_MAUER_XY: return GFX_MAUER_XY;
1925 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1926 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1927 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1928 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1929 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1930 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1931 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1932 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1933 case EL_MAMPFER2: return GFX_MAMPFER2;
1934 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
1935 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1936 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1937 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1938 case EL_DYNABOMB: return GFX_DYNABOMB;
1939 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1940 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1941 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1942 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1943 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1944 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1945 case EL_MAULWURF: return GFX_MAULWURF;
1946 case EL_PINGUIN: return GFX_PINGUIN;
1947 case EL_SCHWEIN: return GFX_SCHWEIN;
1948 case EL_DRACHE: return GFX_DRACHE;
1949 case EL_SONDE: return GFX_SONDE;
1950 case EL_PFEIL_L: return GFX_PFEIL_L;
1951 case EL_PFEIL_R: return GFX_PFEIL_R;
1952 case EL_PFEIL_O: return GFX_PFEIL_O;
1953 case EL_PFEIL_U: return GFX_PFEIL_U;
1954 case EL_SPEED_PILL: return GFX_SPEED_PILL;
1955 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
1959 if (IS_CHAR(element))
1960 return GFX_CHAR_START + (element - EL_CHAR_START);
1961 else if (element >= EL_SP_START && element <= EL_SP_END)
1963 int nr_element = element - EL_SP_START;
1964 int gfx_per_line = 8;
1966 (nr_element / gfx_per_line) * MORE_PER_LINE +
1967 (nr_element % gfx_per_line);
1969 return GFX_START_ROCKSMORE + nr_graphic;