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 phase4 = ABS(MovPos[ux][uy]) / (TILEX / 4);
940 int phase = phase4 / 2;
941 int dir = MovDir[ux][uy];
943 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
949 else if (dir == MV_LEFT)
951 else if (dir == MV_DOWN)
954 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
955 element == EL_SCHWEIN || element == EL_DRACHE)
958 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
959 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
960 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
961 else if (dir == MV_RIGHT)
962 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
963 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
964 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
965 else if (dir == MV_UP)
966 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
967 element == EL_PINGUIN ? GFX_PINGUIN_UP :
968 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
970 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
971 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
972 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
976 else if (element == EL_SONDE)
978 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
980 else if (element == EL_SALZSAEURE)
982 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
984 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
988 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
990 if (element != EL_SP_INFOTRON)
991 graphic += phase * (element == EL_FELSBROCKEN ? 2 : 1);
993 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
994 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
996 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
998 else if (IS_AMOEBOID(element))
1000 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1001 graphic += (x + 2 * y + 4) % 4;
1003 else if (element == EL_MAUER_LEBT)
1005 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1007 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1008 links_massiv = TRUE;
1009 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1010 rechts_massiv = TRUE;
1012 if (links_massiv && rechts_massiv)
1013 graphic = GFX_MAUERWERK;
1014 else if (links_massiv)
1015 graphic = GFX_MAUER_R;
1016 else if (rechts_massiv)
1017 graphic = GFX_MAUER_L;
1021 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1022 else if (mask_mode == USE_MASKING)
1023 DrawGraphicThruMask(x, y, graphic);
1025 DrawGraphic(x, y, graphic);
1028 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1029 int cut_mode, int mask_mode)
1031 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1032 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1033 cut_mode, mask_mode);
1036 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1039 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1042 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1045 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1048 void DrawScreenElementThruMask(int x, int y, int element)
1050 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1053 void DrawLevelElementThruMask(int x, int y, int element)
1055 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1058 void DrawLevelFieldThruMask(int x, int y)
1060 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1063 void ErdreichAnbroeckeln(int x, int y)
1065 int i, width, height, cx,cy;
1066 int ux = LEVELX(x), uy = LEVELY(y);
1067 int element, graphic;
1069 static int xy[4][2] =
1077 if (!IN_LEV_FIELD(ux, uy))
1080 element = Feld[ux][uy];
1082 if (element == EL_ERDREICH)
1084 if (!IN_SCR_FIELD(x, y))
1087 graphic = GFX_ERDENRAND;
1093 uxx = ux + xy[i][0];
1094 uyy = uy + xy[i][1];
1095 if (!IN_LEV_FIELD(uxx, uyy))
1098 element = Feld[uxx][uyy];
1100 if (element == EL_ERDREICH)
1103 if (i == 1 || i == 2)
1107 cx = (i == 2 ? TILEX - snip : 0);
1115 cy = (i == 3 ? TILEY - snip : 0);
1118 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1119 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1120 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1121 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1124 MarkTileDirty(x, y);
1128 graphic = GFX_ERDENRAND;
1132 int xx, yy, uxx, uyy;
1136 uxx = ux + xy[i][0];
1137 uyy = uy + xy[i][1];
1139 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1140 !IN_SCR_FIELD(xx, yy))
1143 if (i == 1 || i == 2)
1147 cx = (i == 1 ? TILEX - snip : 0);
1155 cy = (i==0 ? TILEY-snip : 0);
1158 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1159 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1160 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1161 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1163 MarkTileDirty(xx, yy);
1168 void DrawScreenElement(int x, int y, int element)
1170 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1171 ErdreichAnbroeckeln(x, y);
1174 void DrawLevelElement(int x, int y, int element)
1176 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1177 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1180 void DrawScreenField(int x, int y)
1182 int ux = LEVELX(x), uy = LEVELY(y);
1185 if (!IN_LEV_FIELD(ux, uy))
1187 DrawScreenElement(x, y, EL_BETON);
1191 element = Feld[ux][uy];
1193 if (IS_MOVING(ux, uy))
1195 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1196 boolean cut_mode = NO_CUTTING;
1198 if (Store[ux][uy] == EL_MORAST_LEER ||
1199 Store[ux][uy] == EL_SIEB_LEER ||
1200 Store[ux][uy] == EL_SIEB2_LEER ||
1201 Store[ux][uy] == EL_AMOEBE_NASS)
1202 cut_mode = CUT_ABOVE;
1203 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1204 Store[ux][uy] == EL_SIEB_VOLL ||
1205 Store[ux][uy] == EL_SIEB2_VOLL)
1206 cut_mode = CUT_BELOW;
1208 if (cut_mode == CUT_ABOVE)
1209 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1211 DrawScreenElement(x, y, EL_LEERRAUM);
1214 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1216 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1218 if (Store[ux][uy] == EL_SALZSAEURE)
1219 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1221 else if (IS_BLOCKED(ux, uy))
1226 boolean cut_mode = NO_CUTTING;
1228 Blocked2Moving(ux, uy, &oldx, &oldy);
1231 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1232 MovDir[oldx][oldy] == MV_RIGHT);
1234 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1235 Store[oldx][oldy] == EL_SIEB_LEER ||
1236 Store[oldx][oldy] == EL_SIEB2_LEER ||
1237 Store[oldx][oldy] == EL_AMOEBE_NASS)
1238 cut_mode = CUT_ABOVE;
1240 DrawScreenElement(x, y, EL_LEERRAUM);
1241 element = Feld[oldx][oldy];
1244 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1246 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1248 else if (IS_DRAWABLE(element))
1249 DrawScreenElement(x, y, element);
1251 DrawScreenElement(x, y, EL_LEERRAUM);
1254 void DrawLevelField(int x, int y)
1256 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1257 DrawScreenField(SCREENX(x), SCREENY(y));
1258 else if (IS_MOVING(x, y))
1262 Moving2Blocked(x, y, &newx, &newy);
1263 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1264 DrawScreenField(SCREENX(newx), SCREENY(newy));
1266 else if (IS_BLOCKED(x, y))
1270 Blocked2Moving(x, y, &oldx, &oldy);
1271 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1272 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1276 void DrawMiniElement(int x, int y, int element)
1282 DrawMiniGraphic(x, y, -1);
1286 graphic = el2gfx(element);
1287 DrawMiniGraphic(x, y, graphic);
1290 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1292 int x = sx + scroll_x, y = sy + scroll_y;
1294 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1295 DrawMiniElement(sx, sy, EL_LEERRAUM);
1296 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1297 DrawMiniElement(sx, sy, EL_BETON);
1299 DrawMiniElement(sx, sy, Feld[x][y]);
1302 void DrawMicroElement(int xpos, int ypos, int element)
1306 if (element == EL_LEERRAUM)
1309 graphic = el2gfx(element);
1311 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1313 graphic -= GFX_START_ROCKSMORE;
1314 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1315 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1316 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1317 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1320 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1321 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1322 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1323 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1332 for(x=BX1; x<=BX2; x++)
1333 for(y=BY1; y<=BY2; y++)
1334 DrawScreenField(x, y);
1336 if (setup.soft_scrolling)
1337 XCopyArea(display, fieldbuffer, backbuffer, gc,
1338 FX, FY, SXSIZE, SYSIZE, SX, SY);
1340 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1343 void DrawMiniLevel(int scroll_x, int scroll_y)
1349 for(x=0; x<2*SCR_FIELDX; x++)
1350 for(y=0; y<2*SCR_FIELDY; y++)
1351 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1353 redraw_mask |= REDRAW_FIELD;
1356 void DrawMicroLevel(int xpos, int ypos)
1360 XFillRectangle(display, drawto, gc,
1361 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1362 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1363 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1364 if (lev_fieldx < STD_LEV_FIELDX)
1365 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1366 if (lev_fieldy < STD_LEV_FIELDY)
1367 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1369 for(x=-1; x<=STD_LEV_FIELDX; x++)
1370 for(y=-1; y<=STD_LEV_FIELDY; y++)
1371 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1372 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1374 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1375 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1378 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1382 int len = strlen(level.name);
1383 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1384 int lypos = MICROLABEL_YPOS;
1386 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1389 redraw_mask |= REDRAW_MICROLEV;
1392 int REQ_in_range(int x, int y)
1394 if (y > DY+249 && y < DY+278)
1396 if (x > DX+1 && x < DX+48)
1398 else if (x > DX+51 && x < DX+98)
1404 boolean Request(char *text, unsigned int req_state)
1406 int mx, my, ty, result = -1;
1407 unsigned int old_door_state;
1410 /* pause network game while waiting for request to answer */
1411 if (options.network &&
1412 game_status == PLAYING &&
1413 req_state & REQUEST_WAIT_FOR)
1414 SendToServer_PausePlaying();
1417 old_door_state = GetDoorState();
1419 CloseDoor(DOOR_CLOSE_1);
1421 /* Alten Türinhalt sichern */
1422 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1423 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1424 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1426 /* Fragetext schreiben */
1427 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1428 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1430 for(ty=0; ty<13; ty++)
1438 for(tl=0,tx=0; tx<7; tl++,tx++)
1441 if (!tc || tc == 32)
1452 DrawTextExt(pix[PIX_DB_DOOR], gc,
1453 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1454 txt, FS_SMALL, FC_YELLOW);
1455 text += tl + (tc == 32 ? 1 : 0);
1458 if (req_state & REQ_ASK)
1460 DrawYesNoButton(BUTTON_OK, DB_INIT);
1461 DrawYesNoButton(BUTTON_NO, DB_INIT);
1463 else if (req_state & REQ_CONFIRM)
1465 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1467 else if (req_state & REQ_PLAYER)
1469 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1470 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1471 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1472 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1475 OpenDoor(DOOR_OPEN_1);
1478 if (!(req_state & REQUEST_WAIT_FOR))
1481 if (game_status != MAINMENU)
1484 button_status = MB_RELEASED;
1488 if (XPending(display))
1492 XNextEvent(display, &event);
1502 if (event.type == MotionNotify)
1504 motion_status = TRUE;
1505 mx = ((XMotionEvent *) &event)->x;
1506 my = ((XMotionEvent *) &event)->y;
1510 motion_status = FALSE;
1511 mx = ((XButtonEvent *) &event)->x;
1512 my = ((XButtonEvent *) &event)->y;
1513 if (event.type==ButtonPress)
1514 button_status = ((XButtonEvent *) &event)->button;
1516 button_status = MB_RELEASED;
1519 if (req_state & REQ_ASK)
1520 choice = CheckYesNoButtons(mx,my,button_status);
1521 else if (req_state & REQ_CONFIRM)
1522 choice = CheckConfirmButton(mx,my,button_status);
1524 choice = CheckPlayerButtons(mx,my,button_status);
1534 case BUTTON_CONFIRM:
1535 result = TRUE | FALSE;
1538 case BUTTON_PLAYER_1:
1541 case BUTTON_PLAYER_2:
1544 case BUTTON_PLAYER_3:
1547 case BUTTON_PLAYER_4:
1558 switch(XLookupKeysym((XKeyEvent *)&event,
1559 ((XKeyEvent *)&event)->state))
1572 if (req_state & REQ_PLAYER)
1577 key_joystick_mapping = 0;
1581 HandleOtherEvents(&event);
1585 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1587 int joy = AnyJoystick();
1589 if (joy & JOY_BUTTON_1)
1591 else if (joy & JOY_BUTTON_2)
1597 /* don't eat all CPU time */
1601 if (game_status != MAINMENU)
1604 if (!(req_state & REQ_STAY_OPEN))
1606 CloseDoor(DOOR_CLOSE_1);
1608 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1610 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1611 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1612 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1613 OpenDoor(DOOR_OPEN_1);
1618 /* continue network game after request */
1619 if (options.network &&
1620 game_status == PLAYING &&
1621 req_state & REQUEST_WAIT_FOR)
1622 SendToServer_ContinuePlaying();
1628 unsigned int OpenDoor(unsigned int door_state)
1630 unsigned int new_door_state;
1632 if (door_state & DOOR_COPY_BACK)
1634 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1635 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1636 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1637 door_state &= ~DOOR_COPY_BACK;
1640 new_door_state = MoveDoor(door_state);
1642 return(new_door_state);
1645 unsigned int CloseDoor(unsigned int door_state)
1647 unsigned int new_door_state;
1649 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1650 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1651 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1652 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1654 new_door_state = MoveDoor(door_state);
1656 return(new_door_state);
1659 unsigned int GetDoorState()
1661 return(MoveDoor(DOOR_GET_STATE));
1664 unsigned int MoveDoor(unsigned int door_state)
1666 static int door1 = DOOR_OPEN_1;
1667 static int door2 = DOOR_CLOSE_2;
1668 static unsigned long door_delay = 0;
1669 int x, start, stepsize = 2;
1670 unsigned long door_delay_value = stepsize * 5;
1672 if (door_state == DOOR_GET_STATE)
1673 return(door1 | door2);
1675 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1676 door_state &= ~DOOR_OPEN_1;
1677 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1678 door_state &= ~DOOR_CLOSE_1;
1679 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1680 door_state &= ~DOOR_OPEN_2;
1681 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1682 door_state &= ~DOOR_CLOSE_2;
1684 if (setup.quick_doors)
1687 door_delay_value = 0;
1688 StopSound(SND_OEFFNEN);
1691 if (door_state & DOOR_ACTION)
1693 if (!(door_state & DOOR_NO_DELAY))
1694 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1696 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1698 for(x=start; x<=DXSIZE; x+=stepsize)
1700 WaitUntilDelayReached(&door_delay, door_delay_value);
1702 if (door_state & DOOR_ACTION_1)
1704 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1705 int j = (DXSIZE - i) / 3;
1707 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1708 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1709 DXSIZE,DYSIZE - i/2, DX, DY);
1711 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1713 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1714 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1715 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1716 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1717 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1718 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1720 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1721 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1722 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1723 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1724 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1725 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1727 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1728 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1730 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1731 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1733 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1734 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1735 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1736 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1737 DX + DXSIZE - i, DY + 77 + j);
1738 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1739 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1740 DX + DXSIZE - i, DY + 203 + j);
1742 redraw_mask |= REDRAW_DOOR_1;
1745 if (door_state & DOOR_ACTION_2)
1747 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1748 int j = (VXSIZE - i) / 3;
1750 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1751 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1752 VXSIZE, VYSIZE - i/2, VX, VY);
1754 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1756 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1757 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1758 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1759 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1760 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1761 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1762 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1763 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1765 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1766 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1767 VX, VY + VYSIZE / 2 - j);
1768 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1769 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1770 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1771 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1772 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1774 redraw_mask |= REDRAW_DOOR_2;
1779 if (game_status == MAINMENU)
1784 if (setup.quick_doors)
1785 StopSound(SND_OEFFNEN);
1787 if (door_state & DOOR_ACTION_1)
1788 door1 = door_state & DOOR_ACTION_1;
1789 if (door_state & DOOR_ACTION_2)
1790 door2 = door_state & DOOR_ACTION_2;
1792 return(door1 | door2);
1795 int ReadPixel(Drawable d, int x, int y)
1797 XImage *pixel_image;
1798 unsigned long pixel_value;
1800 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1801 pixel_value = XGetPixel(pixel_image, 0, 0);
1803 XDestroyImage(pixel_image);
1808 int el2gfx(int element)
1812 case EL_LEERRAUM: return -1;
1813 case EL_ERDREICH: return GFX_ERDREICH;
1814 case EL_MAUERWERK: return GFX_MAUERWERK;
1815 case EL_FELSBODEN: return GFX_FELSBODEN;
1816 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1817 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1818 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1819 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1820 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1821 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1822 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1823 case EL_SPIELER1: return GFX_SPIELER1;
1824 case EL_SPIELER2: return GFX_SPIELER2;
1825 case EL_SPIELER3: return GFX_SPIELER3;
1826 case EL_SPIELER4: return GFX_SPIELER4;
1827 case EL_KAEFER: return GFX_KAEFER;
1828 case EL_KAEFER_R: return GFX_KAEFER_R;
1829 case EL_KAEFER_O: return GFX_KAEFER_O;
1830 case EL_KAEFER_L: return GFX_KAEFER_L;
1831 case EL_KAEFER_U: return GFX_KAEFER_U;
1832 case EL_FLIEGER: return GFX_FLIEGER;
1833 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1834 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1835 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1836 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1837 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1838 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1839 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1840 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1841 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1842 case EL_FIREFLY: return GFX_FIREFLY;
1843 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1844 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1845 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1846 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1847 case EL_MAMPFER: return GFX_MAMPFER;
1848 case EL_ROBOT: return GFX_ROBOT;
1849 case EL_BETON: return GFX_BETON;
1850 case EL_DIAMANT: return GFX_DIAMANT;
1851 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1852 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1853 case EL_TROPFEN: return GFX_TROPFEN;
1854 case EL_BOMBE: return GFX_BOMBE;
1855 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
1856 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1857 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1858 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1859 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1860 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1861 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1862 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1863 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1864 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1865 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1866 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1867 case EL_LIFE: return GFX_LIFE;
1868 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1869 case EL_DYNAMIT: return GFX_DYNAMIT;
1870 case EL_BADEWANNE: return GFX_BADEWANNE;
1871 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1872 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1873 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1874 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1875 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1876 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1877 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1878 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1879 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1880 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1881 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1882 case EL_PFORTE1: return GFX_PFORTE1;
1883 case EL_PFORTE2: return GFX_PFORTE2;
1884 case EL_PFORTE3: return GFX_PFORTE3;
1885 case EL_PFORTE4: return GFX_PFORTE4;
1886 case EL_PFORTE1X: return GFX_PFORTE1X;
1887 case EL_PFORTE2X: return GFX_PFORTE2X;
1888 case EL_PFORTE3X: return GFX_PFORTE3X;
1889 case EL_PFORTE4X: return GFX_PFORTE4X;
1890 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1891 case EL_PACMAN: return GFX_PACMAN;
1892 case EL_PACMAN_R: return GFX_PACMAN_R;
1893 case EL_PACMAN_O: return GFX_PACMAN_O;
1894 case EL_PACMAN_L: return GFX_PACMAN_L;
1895 case EL_PACMAN_U: return GFX_PACMAN_U;
1896 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1897 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1898 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1899 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1900 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1901 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1902 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1903 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1904 case EL_MAUER_X: return GFX_MAUER_X;
1905 case EL_MAUER_Y: return GFX_MAUER_Y;
1906 case EL_MAUER_XY: return GFX_MAUER_XY;
1907 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1908 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1909 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1910 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1911 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1912 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1913 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1914 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1915 case EL_MAMPFER2: return GFX_MAMPFER2;
1916 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
1917 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1918 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1919 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1920 case EL_DYNABOMB: return GFX_DYNABOMB;
1921 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1922 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1923 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1924 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1925 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1926 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1927 case EL_MAULWURF: return GFX_MAULWURF;
1928 case EL_PINGUIN: return GFX_PINGUIN;
1929 case EL_SCHWEIN: return GFX_SCHWEIN;
1930 case EL_DRACHE: return GFX_DRACHE;
1931 case EL_SONDE: return GFX_SONDE;
1932 case EL_PFEIL_L: return GFX_PFEIL_L;
1933 case EL_PFEIL_R: return GFX_PFEIL_R;
1934 case EL_PFEIL_O: return GFX_PFEIL_O;
1935 case EL_PFEIL_U: return GFX_PFEIL_U;
1936 case EL_SPEED_PILL: return GFX_SPEED_PILL;
1937 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
1941 if (IS_CHAR(element))
1942 return GFX_CHAR_START + (element - EL_CHAR_START);
1943 else if (element >= EL_SP_START && element <= EL_SP_END)
1944 return GFX_START_ROCKSMORE + (element - EL_SP_START);