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 DrawTextFCentered(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 DrawTextF(int x, int y, int font_type, char *format, ...)
304 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
307 va_start(ap, format);
308 vsprintf(buffer, format, ap);
311 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
314 void DrawText(int x, int y, char *text, int font_size, int font_type)
316 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
319 redraw_mask |= REDRAW_FIELD;
321 redraw_mask |= REDRAW_DOOR_1;
324 void DrawTextExt(Drawable d, GC gc, int x, int y,
325 char *text, int font_size, int font_type)
327 int font_width, font_height, font_start;
330 if (font_size != FS_SMALL && font_size != FS_BIG)
331 font_size = FS_SMALL;
332 if (font_type < FC_RED || font_type > FC_SPECIAL2)
335 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
336 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
337 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
338 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
339 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
340 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
341 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
342 FONT_LINES_PER_FONT);
348 if (c >= 'a' && c <= 'z')
350 else if (c == 'ä' || c == 'Ä')
352 else if (c == 'ö' || c == 'Ö')
354 else if (c == 'ü' || c == 'Ü')
357 if (c >= 32 && c <= 95)
358 XCopyArea(display, pix[font_pixmap], d, gc,
359 ((c - 32) % FONT_CHARS_PER_LINE) * font_width,
360 ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start,
361 font_width, font_height, x, y);
367 void DrawAllPlayers()
371 for(i=0; i<MAX_PLAYERS; i++)
372 if (stored_player[i].active)
373 DrawPlayer(&stored_player[i]);
376 void DrawPlayerField(int x, int y)
381 DrawPlayer(PLAYERINFO(x,y));
384 void DrawPlayer(struct PlayerInfo *player)
386 int jx = player->jx, jy = player->jy;
387 int last_jx = player->last_jx, last_jy = player->last_jy;
388 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
389 int sx = SCREENX(jx), sy = SCREENY(jy);
390 int sxx = 0, syy = 0;
391 int element = Feld[jx][jy];
394 if (!player->active || player->gone ||
395 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
399 if (!IN_LEV_FIELD(jx,jy))
401 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
402 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
403 printf("DrawPlayerField(): This should never happen!\n");
408 if (element == EL_EXPLODING)
411 /* draw things in the field the player is leaving, if needed */
413 if (last_jx != jx || last_jy != jy)
415 if (Store[last_jx][last_jy])
417 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
418 DrawLevelFieldThruMask(last_jx, last_jy);
420 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
421 DrawDynamite(last_jx, last_jy);
423 DrawLevelField(last_jx, last_jy);
425 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
429 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
430 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
432 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
435 DrawLevelField(next_jx, next_jy);
439 if (!IN_SCR_FIELD(sx, sy))
442 if (setup.direct_draw)
443 SetDrawtoField(DRAW_BUFFERED);
445 /* draw things behind the player, if needed */
448 DrawLevelElement(jx, jy, Store[jx][jy]);
449 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
450 DrawLevelField(jx, jy);
452 /* draw player himself */
454 if (player->MovDir == MV_LEFT)
455 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
456 else if (player->MovDir == MV_RIGHT)
457 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
458 else if (player->MovDir == MV_UP)
459 graphic = GFX_SPIELER1_UP;
460 else /* MV_DOWN || MV_NO_MOVING */
461 graphic = GFX_SPIELER1_DOWN;
463 graphic += player->index_nr * 3*HEROES_PER_LINE;
464 graphic += player->Frame;
468 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
469 sxx = player->GfxPos;
471 syy = player->GfxPos;
474 if (!setup.soft_scrolling && ScreenMovPos)
477 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
479 if (player->Pushing && player->GfxPos)
481 int px = SCREENX(next_jx), py = SCREENY(next_jy);
483 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
484 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
485 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
489 int element = Feld[next_jx][next_jy];
490 int graphic = el2gfx(element);
492 if (element == EL_FELSBROCKEN && sxx)
494 int phase = (player->GfxPos / (TILEX/4));
496 if (player->MovDir == MV_LEFT)
499 graphic += (phase+4)%4;
502 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
506 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
508 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
510 graphic = el2gfx(element);
512 if (element == EL_DYNAMIT)
514 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
519 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
523 DrawGraphicThruMask(sx, sy, graphic + phase);
526 if ((last_jx != jx || last_jy != jy) &&
527 Feld[last_jx][last_jy] == EL_EXPLODING)
529 int phase = Frame[last_jx][last_jy];
533 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
534 GFX_EXPLOSION + ((phase - 1) / delay - 1));
537 if (setup.direct_draw)
539 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
540 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
541 int x_size = TILEX * (1 + ABS(jx - last_jx));
542 int y_size = TILEY * (1 + ABS(jy - last_jy));
544 XCopyArea(display, drawto_field, window, gc,
545 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
546 SetDrawtoField(DRAW_DIRECT);
549 MarkTileDirty(sx,sy);
552 static int getGraphicAnimationPhase(int frames, int delay, int mode)
556 if (mode == ANIM_OSCILLATE)
558 int max_anim_frames = 2 * frames - 2;
559 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
560 phase = (phase < frames ? phase : max_anim_frames - phase);
563 phase = (FrameCounter % (delay * frames)) / delay;
565 if (mode == ANIM_REVERSE)
571 void DrawGraphicAnimationExt(int x, int y, int graphic,
572 int frames, int delay, int mode, int mask_mode)
574 int phase = getGraphicAnimationPhase(frames, delay, mode);
576 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
578 if (mask_mode == USE_MASKING)
579 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
581 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
585 void DrawGraphicAnimation(int x, int y, int graphic,
586 int frames, int delay, int mode)
588 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
591 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
592 int frames, int delay, int mode)
594 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
597 void DrawGraphic(int x, int y, int graphic)
600 if (!IN_SCR_FIELD(x,y))
602 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
603 printf("DrawGraphic(): This should never happen!\n");
608 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
612 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
614 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
616 graphic -= GFX_START_ROCKSSCREEN;
617 XCopyArea(display, pix[PIX_BACK], d, gc,
618 SX + (graphic % GFX_PER_LINE) * TILEX,
619 SY + (graphic / GFX_PER_LINE) * TILEY,
622 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
624 graphic -= GFX_START_ROCKSHEROES;
625 XCopyArea(display, pix[PIX_HEROES], d, gc,
626 (graphic % HEROES_PER_LINE) * TILEX,
627 (graphic / HEROES_PER_LINE) * TILEY,
630 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
632 graphic -= GFX_START_ROCKSFONT;
633 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
634 (graphic % FONT_CHARS_PER_LINE) * TILEX,
635 (graphic / FONT_CHARS_PER_LINE) * TILEY +
636 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
640 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
643 void DrawGraphicThruMask(int x, int y, int graphic)
646 if (!IN_SCR_FIELD(x,y))
648 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
649 printf("DrawGraphicThruMask(): This should never happen!\n");
654 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
658 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
665 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
667 src_pixmap = pix[PIX_BACK];
668 drawing_gc = clip_gc[PIX_BACK];
669 graphic -= GFX_START_ROCKSSCREEN;
670 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
671 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
673 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
675 src_pixmap = pix[PIX_HEROES];
676 drawing_gc = clip_gc[PIX_HEROES];
677 graphic -= GFX_START_ROCKSHEROES;
678 src_x = (graphic % HEROES_PER_LINE) * TILEX;
679 src_y = (graphic / HEROES_PER_LINE) * TILEY;
683 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
687 if (tile_clipmask[tile] != None)
689 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
690 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
691 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
692 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
697 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
700 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
701 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
702 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
706 void DrawMiniGraphic(int x, int y, int graphic)
708 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
709 MarkTileDirty(x/2, y/2);
712 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
714 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
716 graphic -= GFX_START_ROCKSSCREEN;
717 XCopyArea(display, pix[PIX_BACK], d, gc,
718 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
719 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
720 MINI_TILEX, MINI_TILEY, x, y);
722 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
724 graphic -= GFX_START_ROCKSFONT;
725 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
726 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
727 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
728 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
729 MINI_TILEX, MINI_TILEY, x, y);
732 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
735 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
736 int cut_mode, int mask_mode)
738 int width = TILEX, height = TILEY;
740 int src_x, src_y, dest_x, dest_y;
747 DrawGraphic(x, y, graphic);
751 if (dx || dy) /* Verschiebung der Grafik? */
753 if (x < BX1) /* Element kommt von links ins Bild */
760 else if (x > BX2) /* Element kommt von rechts ins Bild */
766 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
772 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
774 else if (dx) /* allg. Bewegung in x-Richtung */
775 MarkTileDirty(x + SIGN(dx), y);
777 if (y < BY1) /* Element kommt von oben ins Bild */
779 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
787 else if (y > BY2) /* Element kommt von unten ins Bild */
793 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
799 else if (dy > 0 && cut_mode == CUT_ABOVE)
801 if (y == BY2) /* Element unterhalb des Bildes */
807 MarkTileDirty(x, y + 1);
808 } /* Element verläßt unten das Bild */
809 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
811 else if (dy) /* allg. Bewegung in y-Richtung */
812 MarkTileDirty(x, y + SIGN(dy));
815 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
817 src_pixmap = pix[PIX_BACK];
818 drawing_gc = clip_gc[PIX_BACK];
819 graphic -= GFX_START_ROCKSSCREEN;
820 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
821 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
823 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
825 src_pixmap = pix[PIX_HEROES];
826 drawing_gc = clip_gc[PIX_HEROES];
827 graphic -= GFX_START_ROCKSHEROES;
828 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
829 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
832 dest_x = FX + x * TILEX + dx;
833 dest_y = FY + y * TILEY + dy;
836 if (!IN_SCR_FIELD(x,y))
838 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
839 printf("DrawGraphicShifted(): This should never happen!\n");
844 if (mask_mode == USE_MASKING)
846 if (tile_clipmask[tile] != None)
848 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
849 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
850 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
851 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
856 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
859 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
860 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
861 src_x, src_y, width, height, dest_x, dest_y);
865 XCopyArea(display, src_pixmap, drawto_field, gc,
866 src_x, src_y, width, height, dest_x, dest_y);
871 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
874 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
877 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
878 int cut_mode, int mask_mode)
880 int ux = LEVELX(x), uy = LEVELY(y);
881 int graphic = el2gfx(element);
882 int phase4 = ABS(MovPos[ux][uy]) / (TILEX / 4);
883 int phase = phase4 / 2;
884 int dir = MovDir[ux][uy];
886 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
892 else if (dir == MV_LEFT)
894 else if (dir == MV_DOWN)
897 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
898 element == EL_SCHWEIN || element == EL_DRACHE)
901 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
902 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
903 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
904 else if (dir == MV_RIGHT)
905 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
906 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
907 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
908 else if (dir == MV_UP)
909 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
910 element == EL_PINGUIN ? GFX_PINGUIN_UP :
911 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
913 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
914 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
915 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
919 else if (element == EL_SONDE)
921 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
923 else if (element == EL_SALZSAEURE)
925 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
927 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
931 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
933 graphic += phase * (element == EL_FELSBROCKEN ? 2 : 1);
935 else if ((element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
936 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL) && SiebAktiv)
938 graphic += 3 - (SiebAktiv % 8) / 2;
940 else if (IS_AMOEBOID(element))
942 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
943 graphic += (x + 2 * y + 4) % 4;
945 else if (element == EL_MAUER_LEBT)
947 boolean links_massiv = FALSE, rechts_massiv = FALSE;
949 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
951 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
952 rechts_massiv = TRUE;
954 if (links_massiv && rechts_massiv)
955 graphic = GFX_MAUERWERK;
956 else if (links_massiv)
957 graphic = GFX_MAUER_R;
958 else if (rechts_massiv)
959 graphic = GFX_MAUER_L;
963 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
964 else if (mask_mode == USE_MASKING)
965 DrawGraphicThruMask(x, y, graphic);
967 DrawGraphic(x, y, graphic);
970 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
971 int cut_mode, int mask_mode)
973 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
974 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
975 cut_mode, mask_mode);
978 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
981 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
984 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
987 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
990 void DrawScreenElementThruMask(int x, int y, int element)
992 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
995 void DrawLevelElementThruMask(int x, int y, int element)
997 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1000 void DrawLevelFieldThruMask(int x, int y)
1002 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1005 void ErdreichAnbroeckeln(int x, int y)
1007 int i, width, height, cx,cy;
1008 int ux = LEVELX(x), uy = LEVELY(y);
1009 int element, graphic;
1011 static int xy[4][2] =
1019 if (!IN_LEV_FIELD(ux, uy))
1022 element = Feld[ux][uy];
1024 if (element == EL_ERDREICH)
1026 if (!IN_SCR_FIELD(x, y))
1029 graphic = GFX_ERDENRAND;
1035 uxx = ux + xy[i][0];
1036 uyy = uy + xy[i][1];
1037 if (!IN_LEV_FIELD(uxx, uyy))
1040 element = Feld[uxx][uyy];
1042 if (element == EL_ERDREICH)
1045 if (i == 1 || i == 2)
1049 cx = (i == 2 ? TILEX - snip : 0);
1057 cy = (i == 3 ? TILEY - snip : 0);
1060 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1061 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1062 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1063 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1066 MarkTileDirty(x, y);
1070 graphic = GFX_ERDENRAND;
1074 int xx, yy, uxx, uyy;
1078 uxx = ux + xy[i][0];
1079 uyy = uy + xy[i][1];
1081 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1082 !IN_SCR_FIELD(xx, yy))
1085 if (i == 1 || i == 2)
1089 cx = (i == 1 ? TILEX - snip : 0);
1097 cy = (i==0 ? TILEY-snip : 0);
1100 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1101 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1102 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1103 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1105 MarkTileDirty(xx, yy);
1110 void DrawScreenElement(int x, int y, int element)
1112 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1113 ErdreichAnbroeckeln(x, y);
1116 void DrawLevelElement(int x, int y, int element)
1118 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1119 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1122 void DrawScreenField(int x, int y)
1124 int ux = LEVELX(x), uy = LEVELY(y);
1127 if (!IN_LEV_FIELD(ux, uy))
1129 DrawScreenElement(x, y, EL_BETON);
1133 element = Feld[ux][uy];
1135 if (IS_MOVING(ux, uy))
1137 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1138 boolean cut_mode = NO_CUTTING;
1140 if (Store[ux][uy] == EL_MORAST_LEER ||
1141 Store[ux][uy] == EL_SIEB_LEER ||
1142 Store[ux][uy] == EL_SIEB2_LEER ||
1143 Store[ux][uy] == EL_AMOEBE_NASS)
1144 cut_mode = CUT_ABOVE;
1145 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1146 Store[ux][uy] == EL_SIEB_VOLL ||
1147 Store[ux][uy] == EL_SIEB2_VOLL)
1148 cut_mode = CUT_BELOW;
1150 if (cut_mode == CUT_ABOVE)
1151 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1153 DrawScreenElement(x, y, EL_LEERRAUM);
1156 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1158 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1160 if (Store[ux][uy] == EL_SALZSAEURE)
1161 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1163 else if (IS_BLOCKED(ux, uy))
1168 boolean cut_mode = NO_CUTTING;
1170 Blocked2Moving(ux, uy, &oldx, &oldy);
1173 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1174 MovDir[oldx][oldy] == MV_RIGHT);
1176 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1177 Store[oldx][oldy] == EL_SIEB_LEER ||
1178 Store[oldx][oldy] == EL_SIEB2_LEER ||
1179 Store[oldx][oldy] == EL_AMOEBE_NASS)
1180 cut_mode = CUT_ABOVE;
1182 DrawScreenElement(x, y, EL_LEERRAUM);
1183 element = Feld[oldx][oldy];
1186 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1188 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1190 else if (IS_DRAWABLE(element))
1191 DrawScreenElement(x, y, element);
1193 DrawScreenElement(x, y, EL_LEERRAUM);
1196 void DrawLevelField(int x, int y)
1198 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1199 DrawScreenField(SCREENX(x), SCREENY(y));
1200 else if (IS_MOVING(x, y))
1204 Moving2Blocked(x, y, &newx, &newy);
1205 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1206 DrawScreenField(SCREENX(newx), SCREENY(newy));
1208 else if (IS_BLOCKED(x, y))
1212 Blocked2Moving(x, y, &oldx, &oldy);
1213 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1214 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1218 void DrawMiniElement(int x, int y, int element)
1224 DrawMiniGraphic(x, y, -1);
1228 graphic = el2gfx(element);
1229 DrawMiniGraphic(x, y, graphic);
1232 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1234 int x = sx + scroll_x, y = sy + scroll_y;
1236 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1237 DrawMiniElement(sx, sy, EL_LEERRAUM);
1238 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1239 DrawMiniElement(sx, sy, EL_BETON);
1241 DrawMiniElement(sx, sy, Feld[x][y]);
1244 void DrawMicroElement(int xpos, int ypos, int element)
1248 if (element == EL_LEERRAUM)
1251 graphic = el2gfx(element);
1253 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1254 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1255 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1256 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1265 for(x=BX1; x<=BX2; x++)
1266 for(y=BY1; y<=BY2; y++)
1267 DrawScreenField(x, y);
1269 if (setup.soft_scrolling)
1270 XCopyArea(display, fieldbuffer, backbuffer, gc,
1271 FX, FY, SXSIZE, SYSIZE, SX, SY);
1273 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1276 void DrawMiniLevel(int scroll_x, int scroll_y)
1282 for(x=0; x<2*SCR_FIELDX; x++)
1283 for(y=0; y<2*SCR_FIELDY; y++)
1284 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1286 redraw_mask |= REDRAW_FIELD;
1289 void DrawMicroLevel(int xpos, int ypos)
1293 XFillRectangle(display, drawto, gc,
1294 xpos - MICRO_TILEX, ypos - MICRO_TILEY,
1295 MICRO_TILEX * (STD_LEV_FIELDX + 2),
1296 MICRO_TILEY * (STD_LEV_FIELDY + 2));
1297 if (lev_fieldx < STD_LEV_FIELDX)
1298 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1299 if (lev_fieldy < STD_LEV_FIELDY)
1300 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1302 for(x=-1; x<=STD_LEV_FIELDX; x++)
1303 for(y=-1; y<=STD_LEV_FIELDY; y++)
1304 if (x >= 0 && x < lev_fieldx && y >= 0 && y < lev_fieldy)
1305 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1307 else if (x >= -1 && x < lev_fieldx+1 && y >= -1 && y < lev_fieldy+1)
1308 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1311 XFillRectangle(display, drawto,gc, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1315 int len = strlen(level.name);
1316 int lxpos = SX + (SXSIZE - len * FONT4_XSIZE) / 2;
1317 int lypos = MICROLABEL_YPOS;
1319 DrawText(lxpos, lypos, level.name, FS_SMALL, FC_SPECIAL2);
1322 redraw_mask |= REDRAW_MICROLEV;
1325 int REQ_in_range(int x, int y)
1327 if (y > DY+249 && y < DY+278)
1329 if (x > DX+1 && x < DX+48)
1331 else if (x > DX+51 && x < DX+98)
1337 boolean Request(char *text, unsigned int req_state)
1339 int mx, my, ty, result = -1;
1340 unsigned int old_door_state;
1342 /* pause network game while waiting for request to answer */
1343 if (options.network &&
1344 game_status == PLAYING &&
1345 req_state & REQUEST_WAIT_FOR)
1346 SendToServer_PausePlaying();
1348 old_door_state = GetDoorState();
1350 CloseDoor(DOOR_CLOSE_1);
1352 /* Alten Türinhalt sichern */
1353 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1354 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1355 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1357 /* Fragetext schreiben */
1358 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1359 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1361 for(ty=0; ty<13; ty++)
1369 for(tl=0,tx=0; tx<7; tl++,tx++)
1372 if (!tc || tc == 32)
1383 DrawTextExt(pix[PIX_DB_DOOR], gc,
1384 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1385 txt, FS_SMALL, FC_YELLOW);
1386 text += tl + (tc == 32 ? 1 : 0);
1389 if (req_state & REQ_ASK)
1391 DrawYesNoButton(BUTTON_OK, DB_INIT);
1392 DrawYesNoButton(BUTTON_NO, DB_INIT);
1394 else if (req_state & REQ_CONFIRM)
1396 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1398 else if (req_state & REQ_PLAYER)
1400 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1401 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1402 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1403 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1406 OpenDoor(DOOR_OPEN_1);
1409 if (!(req_state & REQUEST_WAIT_FOR))
1412 if (game_status != MAINMENU)
1415 button_status = MB_RELEASED;
1419 if (XPending(display))
1423 XNextEvent(display, &event);
1433 if (event.type == MotionNotify)
1435 motion_status = TRUE;
1436 mx = ((XMotionEvent *) &event)->x;
1437 my = ((XMotionEvent *) &event)->y;
1441 motion_status = FALSE;
1442 mx = ((XButtonEvent *) &event)->x;
1443 my = ((XButtonEvent *) &event)->y;
1444 if (event.type==ButtonPress)
1445 button_status = ((XButtonEvent *) &event)->button;
1447 button_status = MB_RELEASED;
1450 if (req_state & REQ_ASK)
1451 choice = CheckYesNoButtons(mx,my,button_status);
1452 else if (req_state & REQ_CONFIRM)
1453 choice = CheckConfirmButton(mx,my,button_status);
1455 choice = CheckPlayerButtons(mx,my,button_status);
1465 case BUTTON_CONFIRM:
1466 result = TRUE | FALSE;
1469 case BUTTON_PLAYER_1:
1472 case BUTTON_PLAYER_2:
1475 case BUTTON_PLAYER_3:
1478 case BUTTON_PLAYER_4:
1489 switch(XLookupKeysym((XKeyEvent *)&event,
1490 ((XKeyEvent *)&event)->state))
1503 if (req_state & REQ_PLAYER)
1508 key_joystick_mapping = 0;
1512 HandleOtherEvents(&event);
1516 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1518 int joy = AnyJoystick();
1520 if (joy & JOY_BUTTON_1)
1522 else if (joy & JOY_BUTTON_2)
1528 /* don't eat all CPU time */
1532 if (game_status != MAINMENU)
1535 if (!(req_state & REQ_STAY_OPEN))
1537 CloseDoor(DOOR_CLOSE_1);
1539 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1541 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1542 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1543 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1544 OpenDoor(DOOR_OPEN_1);
1548 /* continue network game after request */
1549 if (options.network &&
1550 game_status == PLAYING &&
1551 req_state & REQUEST_WAIT_FOR)
1552 SendToServer_ContinuePlaying();
1557 unsigned int OpenDoor(unsigned int door_state)
1559 unsigned int new_door_state;
1561 if (door_state & DOOR_COPY_BACK)
1563 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1564 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1565 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1566 door_state &= ~DOOR_COPY_BACK;
1569 new_door_state = MoveDoor(door_state);
1571 return(new_door_state);
1574 unsigned int CloseDoor(unsigned int door_state)
1576 unsigned int new_door_state;
1578 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1579 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1580 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1581 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1583 new_door_state = MoveDoor(door_state);
1585 return(new_door_state);
1588 unsigned int GetDoorState()
1590 return(MoveDoor(DOOR_GET_STATE));
1593 unsigned int MoveDoor(unsigned int door_state)
1595 static unsigned int door1 = DOOR_OPEN_1;
1596 static unsigned int door2 = DOOR_CLOSE_2;
1597 static long door_delay = 0;
1598 int x, start, stepsize = 2;
1599 long door_delay_value = stepsize * 5;
1601 if (door_state == DOOR_GET_STATE)
1602 return(door1 | door2);
1604 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1605 door_state &= ~DOOR_OPEN_1;
1606 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1607 door_state &= ~DOOR_CLOSE_1;
1608 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1609 door_state &= ~DOOR_OPEN_2;
1610 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1611 door_state &= ~DOOR_CLOSE_2;
1613 if (setup.quick_doors)
1616 door_delay_value = 0;
1617 StopSound(SND_OEFFNEN);
1620 if (door_state & DOOR_ACTION)
1622 if (!(door_state & DOOR_NO_DELAY))
1623 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1625 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1627 for(x=start; x<=DXSIZE; x+=stepsize)
1629 WaitUntilDelayReached(&door_delay, door_delay_value);
1631 if (door_state & DOOR_ACTION_1)
1633 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1634 int j = (DXSIZE - i) / 3;
1636 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1637 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1638 DXSIZE,DYSIZE - i/2, DX, DY);
1640 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1642 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1643 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1644 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1645 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1646 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1647 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1649 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1650 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1651 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1652 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1653 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1654 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1656 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1657 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1659 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1660 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1662 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1663 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1664 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1665 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1666 DX + DXSIZE - i, DY + 77 + j);
1667 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1668 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1669 DX + DXSIZE - i, DY + 203 + j);
1671 redraw_mask |= REDRAW_DOOR_1;
1674 if (door_state & DOOR_ACTION_2)
1676 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1677 int j = (VXSIZE - i) / 3;
1679 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1680 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1681 VXSIZE, VYSIZE - i/2, VX, VY);
1683 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
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, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1689 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1690 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1691 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1692 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1694 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1695 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1696 VX, VY + VYSIZE / 2 - j);
1697 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1698 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1699 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1700 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1701 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1703 redraw_mask |= REDRAW_DOOR_2;
1708 if (game_status == MAINMENU)
1713 if (setup.quick_doors)
1714 StopSound(SND_OEFFNEN);
1716 if (door_state & DOOR_ACTION_1)
1717 door1 = door_state & DOOR_ACTION_1;
1718 if (door_state & DOOR_ACTION_2)
1719 door2 = door_state & DOOR_ACTION_2;
1721 return(door1 | door2);
1724 int ReadPixel(Drawable d, int x, int y)
1726 static XImage *pixelimage;
1728 pixelimage = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1729 return(XGetPixel(pixelimage, 0, 0));
1732 int el2gfx(int element)
1736 case EL_LEERRAUM: return -1;
1737 case EL_ERDREICH: return GFX_ERDREICH;
1738 case EL_MAUERWERK: return GFX_MAUERWERK;
1739 case EL_FELSBODEN: return GFX_FELSBODEN;
1740 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1741 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1742 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1743 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1744 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1745 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1746 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1747 case EL_SPIELER1: return GFX_SPIELER1;
1748 case EL_SPIELER2: return GFX_SPIELER2;
1749 case EL_SPIELER3: return GFX_SPIELER3;
1750 case EL_SPIELER4: return GFX_SPIELER4;
1751 case EL_KAEFER: return GFX_KAEFER;
1752 case EL_KAEFER_R: return GFX_KAEFER_R;
1753 case EL_KAEFER_O: return GFX_KAEFER_O;
1754 case EL_KAEFER_L: return GFX_KAEFER_L;
1755 case EL_KAEFER_U: return GFX_KAEFER_U;
1756 case EL_FLIEGER: return GFX_FLIEGER;
1757 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1758 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1759 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1760 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1761 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1762 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1763 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1764 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1765 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1766 case EL_FIREFLY: return GFX_FIREFLY;
1767 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1768 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1769 case EL_FIREFLY_L: return GFX_FIREFLY_L;
1770 case EL_FIREFLY_U: return GFX_FIREFLY_U;
1771 case EL_MAMPFER: return GFX_MAMPFER;
1772 case EL_ROBOT: return GFX_ROBOT;
1773 case EL_BETON: return GFX_BETON;
1774 case EL_DIAMANT: return GFX_DIAMANT;
1775 case EL_MORAST_LEER: return GFX_MORAST_LEER;
1776 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
1777 case EL_TROPFEN: return GFX_TROPFEN;
1778 case EL_BOMBE: return GFX_BOMBE;
1779 case EL_SIEB_LEER: return GFX_SIEB_LEER;
1780 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
1781 case EL_SIEB_TOT: return GFX_SIEB_TOT;
1782 case EL_SALZSAEURE: return GFX_SALZSAEURE;
1783 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
1784 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
1785 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
1786 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
1787 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
1788 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
1789 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
1790 case EL_LIFE: return GFX_LIFE;
1791 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
1792 case EL_DYNAMIT: return GFX_DYNAMIT;
1793 case EL_BADEWANNE: return GFX_BADEWANNE;
1794 case EL_BADEWANNE1: return GFX_BADEWANNE1;
1795 case EL_BADEWANNE2: return GFX_BADEWANNE2;
1796 case EL_BADEWANNE3: return GFX_BADEWANNE3;
1797 case EL_BADEWANNE4: return GFX_BADEWANNE4;
1798 case EL_BADEWANNE5: return GFX_BADEWANNE5;
1799 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
1800 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
1801 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
1802 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
1803 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
1804 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
1805 case EL_PFORTE1: return GFX_PFORTE1;
1806 case EL_PFORTE2: return GFX_PFORTE2;
1807 case EL_PFORTE3: return GFX_PFORTE3;
1808 case EL_PFORTE4: return GFX_PFORTE4;
1809 case EL_PFORTE1X: return GFX_PFORTE1X;
1810 case EL_PFORTE2X: return GFX_PFORTE2X;
1811 case EL_PFORTE3X: return GFX_PFORTE3X;
1812 case EL_PFORTE4X: return GFX_PFORTE4X;
1813 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
1814 case EL_PACMAN: return GFX_PACMAN;
1815 case EL_PACMAN_R: return GFX_PACMAN_R;
1816 case EL_PACMAN_O: return GFX_PACMAN_O;
1817 case EL_PACMAN_L: return GFX_PACMAN_L;
1818 case EL_PACMAN_U: return GFX_PACMAN_U;
1819 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
1820 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
1821 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
1822 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
1823 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
1824 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
1825 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
1826 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
1827 case EL_MAUER_X: return GFX_MAUER_X;
1828 case EL_MAUER_Y: return GFX_MAUER_Y;
1829 case EL_MAUER_XY: return GFX_MAUER_XY;
1830 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
1831 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
1832 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
1833 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
1834 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
1835 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
1836 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
1837 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
1838 case EL_MAMPFER2: return GFX_MAMPFER2;
1839 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
1840 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
1841 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
1842 case EL_DYNABOMB: return GFX_DYNABOMB;
1843 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
1844 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
1845 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
1846 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
1847 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
1848 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
1849 case EL_MAULWURF: return GFX_MAULWURF;
1850 case EL_PINGUIN: return GFX_PINGUIN;
1851 case EL_SCHWEIN: return GFX_SCHWEIN;
1852 case EL_DRACHE: return GFX_DRACHE;
1853 case EL_SONDE: return GFX_SONDE;
1854 case EL_PFEIL_L: return GFX_PFEIL_L;
1855 case EL_PFEIL_R: return GFX_PFEIL_R;
1856 case EL_PFEIL_O: return GFX_PFEIL_O;
1857 case EL_PFEIL_U: return GFX_PFEIL_U;
1860 if (IS_CHAR(element))
1861 return GFX_CHAR_START + (element - EL_CHAR_START);