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 ***********************************************************/
18 #include <machine/joystick.h>
32 extern boolean wait_for_vsync;
35 void SetDrawtoField(int mode)
37 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
48 drawto_field = fieldbuffer;
50 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
61 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
68 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
70 if (setup.direct_draw && game_status == PLAYING)
71 redraw_mask &= ~REDRAW_MAIN;
73 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
74 redraw_mask |= REDRAW_FIELD;
76 if (redraw_mask & REDRAW_FIELD)
77 redraw_mask &= ~REDRAW_TILES;
80 if (redraw_mask & REDRAW_FIELD ||
81 (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING))
82 redraw_mask &= ~REDRAW_TILES;
88 /* synchronize X11 graphics at this point; if we would synchronize the
89 display immediately after the buffer switching (after the XFlush),
90 this could mean that we have to wait for the graphics to complete,
91 although we could go on doing calculations for the next frame */
96 wait_for_vsync = TRUE;
99 if (redraw_mask & REDRAW_ALL)
101 XCopyArea(display,backbuffer,window,gc,
102 0,0, WIN_XSIZE,WIN_YSIZE,
107 if (redraw_mask & REDRAW_FIELD)
109 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
110 XCopyArea(display,backbuffer,window,gc,
111 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
115 int fx = FX, fy = FY;
117 if (setup.soft_scrolling)
119 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
120 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
123 XCopyArea(display,buffer,window,gc,
124 fx,fy, SXSIZE,SYSIZE,
127 redraw_mask &= ~REDRAW_MAIN;
130 if (redraw_mask & REDRAW_DOORS)
132 if (redraw_mask & REDRAW_DOOR_1)
133 XCopyArea(display,backbuffer,window,gc,
134 DX,DY, DXSIZE,DYSIZE,
136 if (redraw_mask & REDRAW_DOOR_2)
138 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
139 XCopyArea(display,backbuffer,window,gc,
140 VX,VY, VXSIZE,VYSIZE,
144 if (redraw_mask & REDRAW_VIDEO_1)
145 XCopyArea(display,backbuffer,window,gc,
146 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
147 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
148 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
149 if (redraw_mask & REDRAW_VIDEO_2)
150 XCopyArea(display,backbuffer,window,gc,
151 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
152 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
153 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
154 if (redraw_mask & REDRAW_VIDEO_3)
155 XCopyArea(display,backbuffer,window,gc,
156 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
157 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
158 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
161 redraw_mask &= ~REDRAW_DOORS;
164 if (redraw_mask & REDRAW_MICROLEV)
166 XCopyArea(display,backbuffer,window,gc,
167 MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
168 MICROLEV_XPOS,MICROLEV_YPOS);
169 XCopyArea(display,backbuffer,window,gc,
170 SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
172 redraw_mask &= ~REDRAW_MICROLEV;
175 if (redraw_mask & REDRAW_TILES)
177 for(x=0; x<SCR_FIELDX; x++)
178 for(y=0; y<SCR_FIELDY; y++)
179 if (redraw[redraw_x1 + x][redraw_y1 + y])
180 XCopyArea(display,buffer,window,gc,
181 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
182 SX+x*TILEX,SY+y*TILEY);
187 for(x=0; x<MAX_BUF_XSIZE; x++)
188 for(y=0; y<MAX_BUF_YSIZE; y++)
197 long fading_delay = 300;
199 if (setup.fading && (redraw_mask & REDRAW_FIELD))
206 XFillRectangle(display,window,gc,
207 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
210 for(i=0;i<2*FULL_SYSIZE;i++)
212 for(y=0;y<FULL_SYSIZE;y++)
214 XCopyArea(display,backbuffer,window,gc,
215 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
223 for(i=1;i<FULL_SYSIZE;i+=2)
224 XCopyArea(display,backbuffer,window,gc,
225 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
231 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
232 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
233 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
237 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
238 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
239 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
243 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
244 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
245 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
249 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
250 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
251 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
255 redraw_mask &= ~REDRAW_MAIN;
264 XFillRectangle(display, backbuffer, gc,
265 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
267 if (setup.soft_scrolling && game_status == PLAYING)
269 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
270 SetDrawtoField(DRAW_BUFFERED);
273 SetDrawtoField(DRAW_BACKBUFFER);
275 if (setup.direct_draw && game_status == PLAYING)
277 XFillRectangle(display, window, gc,
278 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
279 SetDrawtoField(DRAW_DIRECT);
282 redraw_mask |= REDRAW_FIELD;
285 void DrawTextCentered(int y, int font_type, char *format, ...)
287 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
291 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
292 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
294 va_start(ap, format);
295 vsprintf(buffer, format, ap);
298 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
299 buffer, FS_SMALL, font_type);
302 void DrawText(int x, int y, char *text, int font_size, int font_type)
304 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
307 redraw_mask |= REDRAW_FIELD;
309 redraw_mask |= REDRAW_DOOR_1;
312 void DrawTextExt(Drawable d, GC gc, int x, int y,
313 char *text, int font_size, int font_type)
315 int font_width, font_height, font_start;
318 if (font_size != FS_SMALL && font_size != FS_BIG)
319 font_size = FS_SMALL;
320 if (font_type < FC_RED || font_type > FC_SPECIAL2)
323 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
324 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
325 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
326 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
327 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
328 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
329 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
330 FONT_LINES_PER_FONT);
336 if (c >= 'a' && c <= 'z')
338 else if (c == 'ä' || c == 'Ä')
340 else if (c == 'ö' || c == 'Ö')
342 else if (c == 'ü' || c == 'Ü')
345 if (c >= 32 && c <= 95)
346 XCopyArea(display, pix[font_pixmap], d, gc,
347 ((c - 32) % FONT_CHARS_PER_LINE) * font_width,
348 ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start,
349 font_width, font_height, x, y);
355 void DrawAllPlayers()
359 for(i=0; i<MAX_PLAYERS; i++)
360 if (stored_player[i].active)
361 DrawPlayer(&stored_player[i]);
364 void DrawPlayerField(int x, int y)
369 DrawPlayer(PLAYERINFO(x,y));
372 void DrawPlayer(struct PlayerInfo *player)
374 int jx = player->jx, jy = player->jy;
375 int last_jx = player->last_jx, last_jy = player->last_jy;
376 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
377 int sx = SCREENX(jx), sy = SCREENY(jy);
378 int sxx = 0, syy = 0;
379 int element = Feld[jx][jy];
382 if (!player->active || player->gone ||
383 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
387 if (!IN_LEV_FIELD(jx,jy))
389 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
390 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
391 printf("DrawPlayerField(): This should never happen!\n");
396 if (element == EL_EXPLODING)
399 /* draw things in the field the player is leaving, if needed */
401 if (last_jx != jx || last_jy != jy)
403 if (Store[last_jx][last_jy])
405 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
406 DrawLevelFieldThruMask(last_jx, last_jy);
408 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
409 DrawDynamite(last_jx, last_jy);
411 DrawLevelField(last_jx, last_jy);
413 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
417 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
418 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
420 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
423 DrawLevelField(next_jx, next_jy);
427 if (!IN_SCR_FIELD(sx, sy))
430 if (setup.direct_draw)
431 SetDrawtoField(DRAW_BUFFERED);
433 /* draw things behind the player, if needed */
436 DrawLevelElement(jx, jy, Store[jx][jy]);
437 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
438 DrawLevelField(jx, jy);
440 /* draw player himself */
442 if (player->MovDir == MV_LEFT)
443 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
444 else if (player->MovDir == MV_RIGHT)
445 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
446 else if (player->MovDir == MV_UP)
447 graphic = GFX_SPIELER1_UP;
448 else /* MV_DOWN || MV_NO_MOVING */
449 graphic = GFX_SPIELER1_DOWN;
451 graphic += player->index_nr * 3*HEROES_PER_LINE;
452 graphic += player->Frame;
456 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
457 sxx = player->GfxPos;
459 syy = player->GfxPos;
462 if (!setup.soft_scrolling && ScreenMovPos)
465 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
467 if (player->Pushing && player->GfxPos)
469 int px = SCREENX(next_jx), py = SCREENY(next_jy);
471 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
472 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
473 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
477 int element = Feld[next_jx][next_jy];
478 int graphic = el2gfx(element);
480 if (element == EL_FELSBROCKEN && sxx)
482 int phase = (player->GfxPos / (TILEX/4));
484 if (player->MovDir == MV_LEFT)
487 graphic += (phase+4)%4;
490 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
494 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
496 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
498 graphic = el2gfx(element);
500 if (element == EL_DYNAMIT)
502 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
507 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
511 DrawGraphicThruMask(sx, sy, graphic + phase);
514 if ((last_jx != jx || last_jy != jy) &&
515 Feld[last_jx][last_jy] == EL_EXPLODING)
517 int phase = Frame[last_jx][last_jy];
521 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
522 GFX_EXPLOSION + ((phase - 1) / delay - 1));
525 if (setup.direct_draw)
527 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
528 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
529 int x_size = TILEX * (1 + ABS(jx - last_jx));
530 int y_size = TILEY * (1 + ABS(jy - last_jy));
532 XCopyArea(display, drawto_field, window, gc,
533 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
534 SetDrawtoField(DRAW_DIRECT);
537 MarkTileDirty(sx,sy);
540 static int getGraphicAnimationPhase(int frames, int delay, int mode)
544 if (mode == ANIM_OSCILLATE)
546 int max_anim_frames = 2 * frames - 2;
547 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
548 phase = (phase < frames ? phase : max_anim_frames - phase);
551 phase = (FrameCounter % (delay * frames)) / delay;
553 if (mode == ANIM_REVERSE)
559 void DrawGraphicAnimationExt(int x, int y, int graphic,
560 int frames, int delay, int mode, int mask_mode)
562 int phase = getGraphicAnimationPhase(frames, delay, mode);
564 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
566 if (mask_mode == USE_MASKING)
567 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
569 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
573 void DrawGraphicAnimation(int x, int y, int graphic,
574 int frames, int delay, int mode)
576 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
579 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
580 int frames, int delay, int mode)
582 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
585 void DrawGraphic(int x, int y, int graphic)
588 if (!IN_SCR_FIELD(x,y))
590 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
591 printf("DrawGraphic(): This should never happen!\n");
596 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
600 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
602 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
604 graphic -= GFX_START_ROCKSSCREEN;
605 XCopyArea(display, pix[PIX_BACK], d, gc,
606 SX + (graphic % GFX_PER_LINE) * TILEX,
607 SY + (graphic / GFX_PER_LINE) * TILEY,
610 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
612 graphic -= GFX_START_ROCKSHEROES;
613 XCopyArea(display, pix[PIX_HEROES], d, gc,
614 (graphic % HEROES_PER_LINE) * TILEX,
615 (graphic / HEROES_PER_LINE) * TILEY,
618 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
620 graphic -= GFX_START_ROCKSFONT;
621 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
622 (graphic % FONT_CHARS_PER_LINE) * TILEX,
623 (graphic / FONT_CHARS_PER_LINE) * TILEY +
624 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
628 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
631 void DrawGraphicThruMask(int x, int y, int graphic)
634 if (!IN_SCR_FIELD(x,y))
636 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
637 printf("DrawGraphicThruMask(): This should never happen!\n");
642 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
646 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
653 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
655 src_pixmap = pix[PIX_BACK];
656 drawing_gc = clip_gc[PIX_BACK];
657 graphic -= GFX_START_ROCKSSCREEN;
658 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
659 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
661 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
663 src_pixmap = pix[PIX_HEROES];
664 drawing_gc = clip_gc[PIX_HEROES];
665 graphic -= GFX_START_ROCKSHEROES;
666 src_x = (graphic % HEROES_PER_LINE) * TILEX;
667 src_y = (graphic / HEROES_PER_LINE) * TILEY;
671 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
675 if (tile_clipmask[tile] != None)
677 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
678 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
679 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
680 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
685 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
688 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
689 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
690 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
694 void DrawMiniGraphic(int x, int y, int graphic)
696 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
697 MarkTileDirty(x/2, y/2);
700 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
702 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
704 graphic -= GFX_START_ROCKSSCREEN;
705 XCopyArea(display, pix[PIX_BACK], d, gc,
706 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
707 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
708 MINI_TILEX, MINI_TILEY, x, y);
710 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
712 graphic -= GFX_START_ROCKSFONT;
713 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
714 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
715 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
716 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
717 MINI_TILEX, MINI_TILEY, x, y);
720 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
723 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
724 int cut_mode, int mask_mode)
726 int width = TILEX, height = TILEY;
728 int src_x, src_y, dest_x, dest_y;
735 DrawGraphic(x, y, graphic);
739 if (dx || dy) /* Verschiebung der Grafik? */
741 if (x < BX1) /* Element kommt von links ins Bild */
748 else if (x > BX2) /* Element kommt von rechts ins Bild */
754 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
760 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
762 else if (dx) /* allg. Bewegung in x-Richtung */
763 MarkTileDirty(x + SIGN(dx), y);
765 if (y < BY1) /* Element kommt von oben ins Bild */
767 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
775 else if (y > BY2) /* Element kommt von unten ins Bild */
781 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
787 else if (dy > 0 && cut_mode == CUT_ABOVE)
789 if (y == BY2) /* Element unterhalb des Bildes */
795 MarkTileDirty(x, y + 1);
796 } /* Element verläßt unten das Bild */
797 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
799 else if (dy) /* allg. Bewegung in y-Richtung */
800 MarkTileDirty(x, y + SIGN(dy));
803 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
805 src_pixmap = pix[PIX_BACK];
806 drawing_gc = clip_gc[PIX_BACK];
807 graphic -= GFX_START_ROCKSSCREEN;
808 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
809 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
811 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
813 src_pixmap = pix[PIX_HEROES];
814 drawing_gc = clip_gc[PIX_HEROES];
815 graphic -= GFX_START_ROCKSHEROES;
816 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
817 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
820 dest_x = FX + x * TILEX + dx;
821 dest_y = FY + y * TILEY + dy;
824 if (!IN_SCR_FIELD(x,y))
826 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
827 printf("DrawGraphicShifted(): This should never happen!\n");
832 if (mask_mode == USE_MASKING)
834 if (tile_clipmask[tile] != None)
836 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
837 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
838 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
839 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
844 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
847 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
848 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
849 src_x, src_y, width, height, dest_x, dest_y);
853 XCopyArea(display, src_pixmap, drawto_field, gc,
854 src_x, src_y, width, height, dest_x, dest_y);
859 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
862 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
865 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
866 int cut_mode, int mask_mode)
868 int ux = LEVELX(x), uy = LEVELY(y);
869 int graphic = el2gfx(element);
870 int phase4 = ABS(MovPos[ux][uy]) / (TILEX / 4);
871 int phase = phase4 / 2;
872 int dir = MovDir[ux][uy];
874 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
880 else if (dir == MV_LEFT)
882 else if (dir == MV_DOWN)
885 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
886 element == EL_SCHWEIN || element == EL_DRACHE)
889 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
890 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
891 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
892 else if (dir == MV_RIGHT)
893 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
894 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
895 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
896 else if (dir == MV_UP)
897 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
898 element == EL_PINGUIN ? GFX_PINGUIN_UP :
899 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
901 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
902 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
903 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
907 else if (element == EL_SONDE)
909 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
911 else if (element == EL_SALZSAEURE)
913 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
915 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
919 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
921 graphic += phase * (element == EL_FELSBROCKEN ? 2 : 1);
923 else if ((element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
924 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL) && SiebAktiv)
926 graphic += 3 - (SiebAktiv % 8) / 2;
928 else if (IS_AMOEBOID(element))
930 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
931 graphic += (x + 2 * y + 4) % 4;
933 else if (element == EL_MAUER_LEBT)
935 boolean links_massiv = FALSE, rechts_massiv = FALSE;
937 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
939 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
940 rechts_massiv = TRUE;
942 if (links_massiv && rechts_massiv)
943 graphic = GFX_MAUERWERK;
944 else if (links_massiv)
945 graphic = GFX_MAUER_R;
946 else if (rechts_massiv)
947 graphic = GFX_MAUER_L;
951 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
952 else if (mask_mode == USE_MASKING)
953 DrawGraphicThruMask(x, y, graphic);
955 DrawGraphic(x, y, graphic);
958 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
959 int cut_mode, int mask_mode)
961 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
962 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
963 cut_mode, mask_mode);
966 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
969 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
972 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
975 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
978 void DrawScreenElementThruMask(int x, int y, int element)
980 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
983 void DrawLevelElementThruMask(int x, int y, int element)
985 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
988 void DrawLevelFieldThruMask(int x, int y)
990 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
993 void ErdreichAnbroeckeln(int x, int y)
995 int i, width, height, cx,cy;
996 int ux = LEVELX(x), uy = LEVELY(y);
997 int element, graphic;
999 static int xy[4][2] =
1007 if (!IN_LEV_FIELD(ux, uy))
1010 element = Feld[ux][uy];
1012 if (element == EL_ERDREICH)
1014 if (!IN_SCR_FIELD(x, y))
1017 graphic = GFX_ERDENRAND;
1023 uxx = ux + xy[i][0];
1024 uyy = uy + xy[i][1];
1025 if (!IN_LEV_FIELD(uxx, uyy))
1028 element = Feld[uxx][uyy];
1030 if (element == EL_ERDREICH)
1033 if (i == 1 || i == 2)
1037 cx = (i == 2 ? TILEX - snip : 0);
1045 cy = (i == 3 ? TILEY - snip : 0);
1048 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1049 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1050 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1051 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1054 MarkTileDirty(x, y);
1058 graphic = GFX_ERDENRAND;
1062 int xx, yy, uxx, uyy;
1066 uxx = ux + xy[i][0];
1067 uyy = uy + xy[i][1];
1069 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1070 !IN_SCR_FIELD(xx, yy))
1073 if (i == 1 || i == 2)
1077 cx = (i == 1 ? TILEX - snip : 0);
1085 cy = (i==0 ? TILEY-snip : 0);
1088 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1089 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1090 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1091 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1093 MarkTileDirty(xx, yy);
1098 void DrawScreenElement(int x, int y, int element)
1100 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1101 ErdreichAnbroeckeln(x, y);
1104 void DrawLevelElement(int x, int y, int element)
1106 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1107 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1110 void DrawScreenField(int x, int y)
1112 int ux = LEVELX(x), uy = LEVELY(y);
1115 if (!IN_LEV_FIELD(ux, uy))
1117 DrawScreenElement(x, y, EL_BETON);
1121 element = Feld[ux][uy];
1123 if (IS_MOVING(ux, uy))
1125 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1126 boolean cut_mode = NO_CUTTING;
1128 if (Store[ux][uy] == EL_MORAST_LEER ||
1129 Store[ux][uy] == EL_SIEB_LEER ||
1130 Store[ux][uy] == EL_SIEB2_LEER ||
1131 Store[ux][uy] == EL_AMOEBE_NASS)
1132 cut_mode = CUT_ABOVE;
1133 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1134 Store[ux][uy] == EL_SIEB_VOLL ||
1135 Store[ux][uy] == EL_SIEB2_VOLL)
1136 cut_mode = CUT_BELOW;
1138 if (cut_mode == CUT_ABOVE)
1139 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1141 DrawScreenElement(x, y, EL_LEERRAUM);
1144 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1146 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1148 if (Store[ux][uy] == EL_SALZSAEURE)
1149 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1151 else if (IS_BLOCKED(ux, uy))
1156 boolean cut_mode = NO_CUTTING;
1158 Blocked2Moving(ux, uy, &oldx, &oldy);
1161 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1162 MovDir[oldx][oldy] == MV_RIGHT);
1164 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1165 Store[oldx][oldy] == EL_SIEB_LEER ||
1166 Store[oldx][oldy] == EL_SIEB2_LEER ||
1167 Store[oldx][oldy] == EL_AMOEBE_NASS)
1168 cut_mode = CUT_ABOVE;
1170 DrawScreenElement(x, y, EL_LEERRAUM);
1171 element = Feld[oldx][oldy];
1174 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1176 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1178 else if (IS_DRAWABLE(element))
1179 DrawScreenElement(x, y, element);
1181 DrawScreenElement(x, y, EL_LEERRAUM);
1184 void DrawLevelField(int x, int y)
1186 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1187 DrawScreenField(SCREENX(x), SCREENY(y));
1188 else if (IS_MOVING(x, y))
1192 Moving2Blocked(x, y, &newx, &newy);
1193 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1194 DrawScreenField(SCREENX(newx), SCREENY(newy));
1196 else if (IS_BLOCKED(x, y))
1200 Blocked2Moving(x, y, &oldx, &oldy);
1201 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1202 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1206 void DrawMiniElement(int x, int y, int element)
1212 DrawMiniGraphic(x, y, -1);
1216 graphic = el2gfx(element);
1217 DrawMiniGraphic(x, y, graphic);
1220 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1222 int x = sx + scroll_x, y = sy + scroll_y;
1224 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1225 DrawMiniElement(sx, sy, EL_LEERRAUM);
1226 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1227 DrawMiniElement(sx, sy, EL_BETON);
1229 DrawMiniElement(sx, sy, Feld[x][y]);
1232 void DrawMicroElement(int xpos, int ypos, int element)
1236 if (element == EL_LEERRAUM)
1239 graphic = el2gfx(element);
1241 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1242 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1243 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1244 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1253 for(x=BX1; x<=BX2; x++)
1254 for(y=BY1; y<=BY2; y++)
1255 DrawScreenField(x, y);
1257 if (setup.soft_scrolling)
1258 XCopyArea(display, fieldbuffer, backbuffer, gc,
1259 FX, FY, SXSIZE, SYSIZE, SX, SY);
1261 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1264 void DrawMiniLevel(int scroll_x, int scroll_y)
1270 for(x=0; x<2*SCR_FIELDX; x++)
1271 for(y=0; y<2*SCR_FIELDY; y++)
1272 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1274 redraw_mask |= REDRAW_FIELD;
1277 void DrawMicroLevel(int xpos, int ypos)
1281 XFillRectangle(display, drawto, gc,
1282 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1283 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1284 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1285 if (lev_fieldx < STD_LEV_FIELDX)
1286 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1287 if (lev_fieldy < STD_LEV_FIELDY)
1288 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1290 for(x=-1; x<=STD_LEV_FIELDX; x++)
1291 for(y=-1; y<=STD_LEV_FIELDY; y++)
1292 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1293 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1295 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1296 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1299 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1303 int len = strlen(level.name);
1304 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1305 int lypos = MICROLABEL_YPOS;
1307 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1310 redraw_mask |= REDRAW_MICROLEV;
1313 int REQ_in_range(int x, int y)
1315 if (y > DY+249 && y < DY+278)
1317 if (x > DX+1 && x < DX+48)
1319 else if (x > DX+51 && x < DX+98)
1325 boolean Request(char *text, unsigned int req_state)
1327 int mx, my, ty, result = -1;
1328 unsigned int old_door_state;
1330 /* pause network game while waiting for request to answer */
1331 if (options.network &&
1332 game_status == PLAYING &&
1333 req_state & REQUEST_WAIT_FOR)
1334 SendToServer_PausePlaying();
1336 old_door_state = GetDoorState();
1338 CloseDoor(DOOR_CLOSE_1);
1340 /* Alten Türinhalt sichern */
1341 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1342 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1343 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1345 /* Fragetext schreiben */
1346 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1347 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1349 for(ty=0; ty<13; ty++)
1357 for(tl=0,tx=0; tx<7; tl++,tx++)
1360 if (!tc || tc == 32)
1371 DrawTextExt(pix[PIX_DB_DOOR], gc,
1372 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1373 txt, FS_SMALL, FC_YELLOW);
1374 text += tl + (tc == 32 ? 1 : 0);
1377 if (req_state & REQ_ASK)
1379 DrawYesNoButton(BUTTON_OK, DB_INIT);
1380 DrawYesNoButton(BUTTON_NO, DB_INIT);
1382 else if (req_state & REQ_CONFIRM)
1384 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1386 else if (req_state & REQ_PLAYER)
1388 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1389 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1390 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1391 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1394 OpenDoor(DOOR_OPEN_1);
1397 if (!(req_state & REQUEST_WAIT_FOR))
1400 if (game_status != MAINMENU)
1403 button_status = MB_RELEASED;
1407 if (XPending(display))
1411 XNextEvent(display, &event);
1421 if (event.type == MotionNotify)
1423 motion_status = TRUE;
1424 mx = ((XMotionEvent *) &event)->x;
1425 my = ((XMotionEvent *) &event)->y;
1429 motion_status = FALSE;
1430 mx = ((XButtonEvent *) &event)->x;
1431 my = ((XButtonEvent *) &event)->y;
1432 if (event.type==ButtonPress)
1433 button_status = ((XButtonEvent *) &event)->button;
1435 button_status = MB_RELEASED;
1438 if (req_state & REQ_ASK)
1439 choice = CheckYesNoButtons(mx,my,button_status);
1440 else if (req_state & REQ_CONFIRM)
1441 choice = CheckConfirmButton(mx,my,button_status);
1443 choice = CheckPlayerButtons(mx,my,button_status);
1453 case BUTTON_CONFIRM:
1454 result = TRUE | FALSE;
1457 case BUTTON_PLAYER_1:
1460 case BUTTON_PLAYER_2:
1463 case BUTTON_PLAYER_3:
1466 case BUTTON_PLAYER_4:
1477 switch(XLookupKeysym((XKeyEvent *)&event,
1478 ((XKeyEvent *)&event)->state))
1491 if (req_state & REQ_PLAYER)
1496 key_joystick_mapping = 0;
1500 HandleOtherEvents(&event);
1504 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1506 int joy = AnyJoystick();
1508 if (joy & JOY_BUTTON_1)
1510 else if (joy & JOY_BUTTON_2)
1516 /* don't eat all CPU time */
1520 if (game_status != MAINMENU)
1523 if (!(req_state & REQ_STAY_OPEN))
1525 CloseDoor(DOOR_CLOSE_1);
1527 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1529 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1530 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1531 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1532 OpenDoor(DOOR_OPEN_1);
1536 /* continue network game after request */
1537 if (options.network &&
1538 game_status == PLAYING &&
1539 req_state & REQUEST_WAIT_FOR)
1540 SendToServer_ContinuePlaying();
1545 unsigned int OpenDoor(unsigned int door_state)
1547 unsigned int new_door_state;
1549 if (door_state & DOOR_COPY_BACK)
1551 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1552 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1553 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1554 door_state &= ~DOOR_COPY_BACK;
1557 new_door_state = MoveDoor(door_state);
1559 return(new_door_state);
1562 unsigned int CloseDoor(unsigned int door_state)
1564 unsigned int new_door_state;
1566 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1567 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1568 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1569 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1571 new_door_state = MoveDoor(door_state);
1573 return(new_door_state);
1576 unsigned int GetDoorState()
1578 return(MoveDoor(DOOR_GET_STATE));
1581 unsigned int MoveDoor(unsigned int door_state)
1583 static unsigned int door1 = DOOR_OPEN_1;
1584 static unsigned int door2 = DOOR_CLOSE_2;
1585 static long door_delay = 0;
1586 int x, start, stepsize = 2;
1587 long door_delay_value = stepsize * 5;
1589 if (door_state == DOOR_GET_STATE)
1590 return(door1 | door2);
1592 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1593 door_state &= ~DOOR_OPEN_1;
1594 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1595 door_state &= ~DOOR_CLOSE_1;
1596 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1597 door_state &= ~DOOR_OPEN_2;
1598 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1599 door_state &= ~DOOR_CLOSE_2;
1601 if (setup.quick_doors)
1604 door_delay_value = 0;
1605 StopSound(SND_OEFFNEN);
1608 if (door_state & DOOR_ACTION)
1610 if (!(door_state & DOOR_NO_DELAY))
1611 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1613 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1615 for(x=start; x<=DXSIZE; x+=stepsize)
1617 WaitUntilDelayReached(&door_delay, door_delay_value);
1619 if (door_state & DOOR_ACTION_1)
1621 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1622 int j = (DXSIZE - i) / 3;
1624 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1625 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1626 DXSIZE,DYSIZE - i/2, DX, DY);
1628 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1630 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1631 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1632 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1633 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1634 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1635 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1637 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1638 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1639 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1640 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1641 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1642 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1644 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1645 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1647 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1648 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1650 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1651 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1652 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1653 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1654 DX + DXSIZE - i, DY + 77 + j);
1655 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1656 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1657 DX + DXSIZE - i, DY + 203 + j);
1659 redraw_mask |= REDRAW_DOOR_1;
1662 if (door_state & DOOR_ACTION_2)
1664 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1665 int j = (VXSIZE - i) / 3;
1667 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1668 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1669 VXSIZE, VYSIZE - i/2, VX, VY);
1671 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1673 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1674 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1675 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1676 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1677 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1678 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1679 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1680 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1682 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1683 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1684 VX, VY + VYSIZE / 2 - j);
1685 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1686 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1687 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1688 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1689 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1691 redraw_mask |= REDRAW_DOOR_2;
1696 if (game_status == MAINMENU)
1701 if (setup.quick_doors)
1702 StopSound(SND_OEFFNEN);
1704 if (door_state & DOOR_ACTION_1)
1705 door1 = door_state & DOOR_ACTION_1;
1706 if (door_state & DOOR_ACTION_2)
1707 door2 = door_state & DOOR_ACTION_2;
1709 return(door1 | door2);
1712 int ReadPixel(Drawable d, int x, int y)
1714 static XImage *pixelimage;
1716 pixelimage = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1717 return(XGetPixel(pixelimage, 0, 0));
1720 int el2gfx(int element)
1724 case EL_LEERRAUM: return -1;
1725 case EL_ERDREICH: return GFX_ERDREICH;
1726 case EL_MAUERWERK: return GFX_MAUERWERK;
1727 case EL_FELSBODEN: return GFX_FELSBODEN;
1728 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1729 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1730 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1731 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1732 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1733 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1734 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1735 case EL_SPIELER1: return GFX_SPIELER1;
1736 case EL_SPIELER2: return GFX_SPIELER2;
1737 case EL_SPIELER3: return GFX_SPIELER3;
1738 case EL_SPIELER4: return GFX_SPIELER4;
1739 case EL_KAEFER: return GFX_KAEFER;
1740 case EL_KAEFER_R: return GFX_KAEFER_R;
1741 case EL_KAEFER_O: return GFX_KAEFER_O;
1742 case EL_KAEFER_L: return GFX_KAEFER_L;
1743 case EL_KAEFER_U: return GFX_KAEFER_U;
1744 case EL_FLIEGER: return GFX_FLIEGER;
1745 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1746 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1747 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1748 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1749 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1750 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1751 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1752 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1753 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1754 case EL_FIREFLY: return GFX_FIREFLY;
1755 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1756 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1757 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1758 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1759 case EL_MAMPFER: return GFX_MAMPFER;
1760 case EL_ROBOT: return GFX_ROBOT;
1761 case EL_BETON: return GFX_BETON;
1762 case EL_DIAMANT: return GFX_DIAMANT;
1763 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1764 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1765 case EL_TROPFEN: return GFX_TROPFEN;
1766 case EL_BOMBE: return GFX_BOMBE;
1767 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1768 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1769 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1770 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1771 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1772 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1773 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1774 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1775 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1776 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1777 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1778 case EL_LIFE: return GFX_LIFE;
1779 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1780 case EL_DYNAMIT: return GFX_DYNAMIT;
1781 case EL_BADEWANNE: return GFX_BADEWANNE;
1782 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1783 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1784 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1785 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1786 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1787 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1788 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1789 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1790 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1791 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1792 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1793 case EL_PFORTE1: return GFX_PFORTE1;
1794 case EL_PFORTE2: return GFX_PFORTE2;
1795 case EL_PFORTE3: return GFX_PFORTE3;
1796 case EL_PFORTE4: return GFX_PFORTE4;
1797 case EL_PFORTE1X: return GFX_PFORTE1X;
1798 case EL_PFORTE2X: return GFX_PFORTE2X;
1799 case EL_PFORTE3X: return GFX_PFORTE3X;
1800 case EL_PFORTE4X: return GFX_PFORTE4X;
1801 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1802 case EL_PACMAN: return GFX_PACMAN;
1803 case EL_PACMAN_R: return GFX_PACMAN_R;
1804 case EL_PACMAN_O: return GFX_PACMAN_O;
1805 case EL_PACMAN_L: return GFX_PACMAN_L;
1806 case EL_PACMAN_U: return GFX_PACMAN_U;
1807 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1808 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1809 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1810 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1811 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1812 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1813 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1814 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1815 case EL_MAUER_X: return GFX_MAUER_X;
1816 case EL_MAUER_Y: return GFX_MAUER_Y;
1817 case EL_MAUER_XY: return GFX_MAUER_XY;
1818 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1819 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1820 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1821 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1822 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1823 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1824 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1825 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1826 case EL_MAMPFER2: return GFX_MAMPFER2;
1827 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1828 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1829 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1830 case EL_DYNABOMB: return GFX_DYNABOMB;
1831 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1832 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1833 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1834 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1835 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1836 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1837 case EL_MAULWURF: return GFX_MAULWURF;
1838 case EL_PINGUIN: return GFX_PINGUIN;
1839 case EL_SCHWEIN: return GFX_SCHWEIN;
1840 case EL_DRACHE: return GFX_DRACHE;
1841 case EL_SONDE: return GFX_SONDE;
1842 case EL_PFEIL_L: return GFX_PFEIL_L;
1843 case EL_PFEIL_R: return GFX_PFEIL_R;
1844 case EL_PFEIL_O: return GFX_PFEIL_O;
1845 case EL_PFEIL_U: return GFX_PFEIL_U;
1848 if (IS_CHAR(element))
1849 return GFX_CHAR_START + (element - EL_CHAR_START);