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 ***********************************************************/
15 #include <machine/joystick.h>
31 extern BOOL wait_for_vsync;
34 void SetDrawtoField(int mode)
36 if (mode == DRAW_BUFFERED && soft_scrolling_on)
47 drawto_field = fieldbuffer;
49 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
60 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
67 Drawable buffer = (drawto_field != window ? drawto_field : backbuffer);
69 if (direct_draw_on && 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 || ScreenGfxPos)
76 redraw_mask &= ~REDRAW_TILES;
81 /* synchronize X11 graphics at this point; if we would synchronize the
82 display immediately after the buffer switching (after the XFlush),
83 this could mean that we have to wait for the graphics to complete,
84 although we could go on doing calculations for the next frame */
89 wait_for_vsync = TRUE;
92 if (redraw_mask & REDRAW_ALL)
94 XCopyArea(display,backbuffer,window,gc,
95 0,0, WIN_XSIZE,WIN_YSIZE,
100 if (redraw_mask & REDRAW_FIELD)
102 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
103 XCopyArea(display,backbuffer,window,gc,
104 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
108 int fx = FX, fy = FY;
110 if (soft_scrolling_on)
112 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
113 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
116 XCopyArea(display,buffer,window,gc,
117 fx,fy, SXSIZE,SYSIZE,
120 redraw_mask &= ~REDRAW_MAIN;
123 if (redraw_mask & REDRAW_DOORS)
125 if (redraw_mask & REDRAW_DOOR_1)
126 XCopyArea(display,backbuffer,window,gc,
127 DX,DY, DXSIZE,DYSIZE,
129 if (redraw_mask & REDRAW_DOOR_2)
131 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
132 XCopyArea(display,backbuffer,window,gc,
133 VX,VY, VXSIZE,VYSIZE,
137 if (redraw_mask & REDRAW_VIDEO_1)
138 XCopyArea(display,backbuffer,window,gc,
139 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
140 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
141 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
142 if (redraw_mask & REDRAW_VIDEO_2)
143 XCopyArea(display,backbuffer,window,gc,
144 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
145 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
146 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
147 if (redraw_mask & REDRAW_VIDEO_3)
148 XCopyArea(display,backbuffer,window,gc,
149 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
150 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
151 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
154 redraw_mask &= ~REDRAW_DOORS;
157 if (redraw_mask & REDRAW_MICROLEV)
159 XCopyArea(display,backbuffer,window,gc,
160 MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
161 MICROLEV_XPOS,MICROLEV_YPOS);
162 XCopyArea(display,backbuffer,window,gc,
163 SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
165 redraw_mask &= ~REDRAW_MICROLEV;
168 if (redraw_mask & REDRAW_TILES)
170 for(x=0; x<SCR_FIELDX; x++)
171 for(y=0; y<SCR_FIELDY; y++)
172 if (redraw[redraw_x1 + x][redraw_y1 + y])
173 XCopyArea(display,buffer,window,gc,
174 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
175 SX+x*TILEX,SY+y*TILEY);
180 for(x=0; x<MAX_BUF_XSIZE; x++)
181 for(y=0; y<MAX_BUF_YSIZE; y++)
190 long fading_delay = 300;
192 if (fading_on && (redraw_mask & REDRAW_FIELD))
199 XFillRectangle(display,window,gc,
200 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
203 for(i=0;i<2*FULL_SYSIZE;i++)
205 for(y=0;y<FULL_SYSIZE;y++)
207 XCopyArea(display,backbuffer,window,gc,
208 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
216 for(i=1;i<FULL_SYSIZE;i+=2)
217 XCopyArea(display,backbuffer,window,gc,
218 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
224 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
225 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
226 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
230 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
231 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
232 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
236 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
237 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
238 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
242 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
243 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
244 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
248 redraw_mask &= ~REDRAW_MAIN;
257 XFillRectangle(display,backbuffer,gc,
258 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
260 if (soft_scrolling_on && game_status==PLAYING)
262 XFillRectangle(display,fieldbuffer,gc,
264 SetDrawtoField(DRAW_BUFFERED);
267 SetDrawtoField(DRAW_BACKBUFFER);
269 if (direct_draw_on && game_status==PLAYING)
271 XFillRectangle(display,window,gc,
272 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
273 SetDrawtoField(DRAW_DIRECT);
276 redraw_mask |= REDRAW_FIELD;
279 void DrawText(int x, int y, char *text, int font, int col)
281 DrawTextExt(drawto, gc, x, y, text, font, col);
283 redraw_mask |= REDRAW_FIELD;
285 redraw_mask |= REDRAW_DOOR_1;
288 void DrawTextExt(Drawable d, GC gc, int x, int y,
289 char *text, int font, int font_color)
291 int font_width, font_height, font_start;
294 if (font!=FS_SMALL && font!=FS_BIG)
296 if (font_color<FC_RED || font_color>FC_SPECIAL2)
300 (font==FS_BIG ? FONT1_XSIZE :
301 font_color<FC_SPECIAL1 ? FONT2_XSIZE :
302 font_color<FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
304 (font==FS_BIG ? FONT1_XSIZE :
305 font_color<FC_SPECIAL2 ? FONT2_XSIZE: FONT4_XSIZE);
306 font_pixmap = (font==FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
308 font_color*(font==FS_BIG ? FONT1_YSIZE : FONT2_YSIZE)*FONT_LINES_PER_FONT;
314 if (c>='a' && c<='z')
316 else if (c=='ä' || c=='Ä')
318 else if (c=='ö' || c=='Ö')
320 else if (c=='ü' || c=='Ü')
324 XCopyArea(display,pix[font_pixmap],d,gc,
325 ((c-32) % FONT_CHARS_PER_LINE)*font_width,
326 ((c-32) / FONT_CHARS_PER_LINE)*font_height + font_start,
327 font_width,font_height, x,y);
333 void DrawAllPlayers()
337 for(i=0; i<MAX_PLAYERS; i++)
338 if (stored_player[i].active)
339 DrawPlayer(&stored_player[i]);
342 void DrawPlayerField(int x, int y)
347 DrawPlayer(PLAYERINFO(x,y));
350 void DrawPlayer(struct PlayerInfo *player)
352 int jx = player->jx, jy = player->jy;
353 int last_jx = player->last_jx, last_jy = player->last_jy;
354 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
355 int sx = SCREENX(jx), sy = SCREENY(jy);
356 int sxx = 0, syy = 0;
357 int element = Feld[jx][jy];
361 if (!player->active || player->gone || !IN_SCR_FIELD(sx,sy))
365 if (!player->active || player->gone ||
366 !IN_SCR_FIELD(SCREENX(last_jx),SCREENY(last_jy)))
370 if (!IN_LEV_FIELD(jx,jy))
372 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
373 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
374 printf("DrawPlayerField(): This should never happen!\n");
379 if (element == EL_EXPLODING)
382 /* draw things in the field the player is leaving, if needed */
384 if (last_jx != jx || last_jy != jy)
386 if (Store[last_jx][last_jy])
388 DrawLevelElement(last_jx,last_jy, Store[last_jx][last_jy]);
389 DrawLevelFieldThruMask(last_jx,last_jy);
391 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
392 DrawDynamite(last_jx,last_jy);
394 DrawLevelField(last_jx,last_jy);
396 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx),SCREENY(next_jy)))
400 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
401 DrawLevelElement(next_jx,next_jy, EL_SOKOBAN_FELD_LEER);
403 DrawLevelElement(next_jx,next_jy, EL_LEERRAUM);
406 DrawLevelField(next_jx,next_jy);
410 if (!IN_SCR_FIELD(sx,sy))
414 SetDrawtoField(DRAW_BUFFERED);
416 /* draw things behind the player, if needed */
419 DrawLevelElement(jx,jy, Store[jx][jy]);
420 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
421 DrawLevelField(jx,jy);
423 /* draw player himself */
425 if (player->MovDir==MV_LEFT)
426 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
427 else if (player->MovDir==MV_RIGHT)
428 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
429 else if (player->MovDir==MV_UP)
430 graphic = GFX_SPIELER1_UP;
431 else /* MV_DOWN || MV_NO_MOVING */
432 graphic = GFX_SPIELER1_DOWN;
434 graphic += player->index_nr * 3*HEROES_PER_LINE;
435 graphic += player->Frame;
439 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
440 sxx = player->GfxPos;
442 syy = player->GfxPos;
445 if (!soft_scrolling_on && ScreenMovPos)
448 DrawGraphicShiftedThruMask(sx,sy, sxx,syy, graphic, NO_CUTTING);
450 if (player->Pushing && player->GfxPos)
452 int px = SCREENX(next_jx), py = SCREENY(next_jy);
454 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
455 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
456 DrawGraphicShiftedThruMask(px,py,sxx,syy, GFX_SOKOBAN_OBJEKT,NO_CUTTING);
459 int element = Feld[next_jx][next_jy];
460 int graphic = el2gfx(element);
462 if (element == EL_FELSBROCKEN && sxx)
464 int phase = (player->GfxPos / (TILEX/4));
466 if (player->MovDir == MV_LEFT)
469 graphic += (phase+4)%4;
472 DrawGraphicShifted(px,py, sxx,syy, graphic, NO_CUTTING, NO_MASKING);
476 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
478 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
480 graphic = el2gfx(element);
482 if (element == EL_DYNAMIT)
484 if ((phase = (96-MovDelay[jx][jy])/12) > 6)
489 if ((phase = ((96-MovDelay[jx][jy])/6) % 8) > 3)
493 DrawGraphicThruMask(sx,sy, graphic + phase);
496 if ((last_jx != jx || last_jy != jy) && Feld[last_jx][last_jy]==EL_EXPLODING)
498 int phase = Frame[last_jx][last_jy];
502 DrawGraphicThruMask(SCREENX(last_jx),SCREENY(last_jy),
503 GFX_EXPLOSION + ((phase-1)/delay-1));
508 int dest_x = SX + SCREENX(MIN(jx,last_jx))*TILEX;
509 int dest_y = SY + SCREENY(MIN(jy,last_jy))*TILEY;
510 int x_size = TILEX * (1 + ABS(jx - last_jx));
511 int y_size = TILEY * (1 + ABS(jy - last_jy));
513 XCopyArea(display,drawto_field,window,gc,
514 dest_x,dest_y, x_size,y_size, dest_x,dest_y);
515 SetDrawtoField(DRAW_DIRECT);
518 MarkTileDirty(sx,sy);
521 static int getGraphicAnimationPhase(int frames, int delay, int mode)
525 if (mode == ANIM_OSCILLATE)
527 int max_anim_frames = frames*2 - 2;
528 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
529 phase = (phase < frames ? phase : max_anim_frames - phase);
532 phase = (FrameCounter % (delay * frames)) / delay;
534 if (mode == ANIM_REVERSE)
540 void DrawGraphicAnimationExt(int x, int y, int graphic,
541 int frames, int delay, int mode, int mask_mode)
543 int phase = getGraphicAnimationPhase(frames, delay, mode);
545 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
547 if (mask_mode == USE_MASKING)
548 DrawGraphicThruMask(SCREENX(x),SCREENY(y), graphic + phase);
550 DrawGraphic(SCREENX(x),SCREENY(y), graphic + phase);
554 void DrawGraphicAnimation(int x, int y, int graphic,
555 int frames, int delay, int mode)
557 DrawGraphicAnimationExt(x,y, graphic, frames,delay,mode, NO_MASKING);
560 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
561 int frames, int delay, int mode)
563 DrawGraphicAnimationExt(x,y, graphic, frames,delay,mode, USE_MASKING);
566 void DrawGraphic(int x, int y, int graphic)
569 if (!IN_SCR_FIELD(x,y))
571 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
572 printf("DrawGraphic(): This should never happen!\n");
577 DrawGraphicExt(drawto_field, gc, FX+x*TILEX, FY+y*TILEY, graphic);
581 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
583 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
585 graphic -= GFX_START_ROCKSSCREEN;
586 XCopyArea(display,pix[PIX_BACK],d,gc,
587 SX + (graphic % GFX_PER_LINE) * TILEX,
588 SY + (graphic / GFX_PER_LINE) * TILEY,
591 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
593 graphic -= GFX_START_ROCKSHEROES;
594 XCopyArea(display,pix[PIX_HEROES],d,gc,
595 (graphic % HEROES_PER_LINE) * TILEX,
596 (graphic / HEROES_PER_LINE) * TILEY,
599 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
601 graphic -= GFX_START_ROCKSFONT;
602 XCopyArea(display,pix[PIX_BIGFONT],d,gc,
603 (graphic % FONT_CHARS_PER_LINE) * TILEX,
604 (graphic / FONT_CHARS_PER_LINE) * TILEY +
605 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
609 XFillRectangle(display,d,gc, x,y, TILEX,TILEY);
612 void DrawGraphicThruMask(int x, int y, int graphic)
615 if (!IN_SCR_FIELD(x,y))
617 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
618 printf("DrawGraphicThruMask(): This should never happen!\n");
623 DrawGraphicThruMaskExt(drawto_field, FX+x*TILEX, FY+y*TILEY, graphic);
627 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
634 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
636 src_pixmap = pix[PIX_BACK];
637 drawing_gc = clip_gc[PIX_BACK];
638 graphic -= GFX_START_ROCKSSCREEN;
639 src_x = SX+(graphic % GFX_PER_LINE)*TILEX;
640 src_y = SY+(graphic / GFX_PER_LINE)*TILEY;
642 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
644 src_pixmap = pix[PIX_HEROES];
645 drawing_gc = clip_gc[PIX_HEROES];
646 graphic -= GFX_START_ROCKSHEROES;
647 src_x = (graphic % HEROES_PER_LINE)*TILEX;
648 src_y = (graphic / HEROES_PER_LINE)*TILEY;
652 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
656 if (tile_clipmask[tile] != None)
658 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
659 XSetClipOrigin(display, tile_clip_gc, dest_x,dest_y);
660 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
661 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
666 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
669 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
670 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
671 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
675 void DrawMiniGraphic(int x, int y, int graphic)
677 DrawMiniGraphicExt(drawto,gc, SX+x*MINI_TILEX,SY+y*MINI_TILEY, graphic);
678 MarkTileDirty(x/2, y/2);
681 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
683 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
685 graphic -= GFX_START_ROCKSSCREEN;
686 XCopyArea(display,pix[PIX_BACK],d,gc,
687 MINI_GFX_STARTX+(graphic % MINI_GFX_PER_LINE)*MINI_TILEX,
688 MINI_GFX_STARTY+(graphic / MINI_GFX_PER_LINE)*MINI_TILEY,
689 MINI_TILEX,MINI_TILEY, x,y);
691 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
693 graphic -= GFX_START_ROCKSFONT;
694 XCopyArea(display,pix[PIX_SMALLFONT],d,gc,
695 (graphic % FONT_CHARS_PER_LINE)*FONT4_XSIZE,
696 (graphic / FONT_CHARS_PER_LINE)*FONT4_YSIZE +
697 FC_SPECIAL2*FONT2_YSIZE*FONT_LINES_PER_FONT,
698 MINI_TILEX,MINI_TILEY, x,y);
701 XFillRectangle(display,d,gc, x,y, MINI_TILEX,MINI_TILEY);
704 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
705 int cut_mode, int mask_mode)
707 int width = TILEX, height = TILEY;
709 int src_x,src_y, dest_x,dest_y;
716 DrawGraphic(x,y,graphic);
720 if (dx || dy) /* Verschiebung der Grafik? */
722 if (x < BX1) /* Element kommt von links ins Bild */
729 else if (x > BX2) /* Element kommt von rechts ins Bild */
735 else if (x==BX1 && dx<0) /* Element verläßt links das Bild */
741 else if (x==BX2 && dx>0) /* Element verläßt rechts das Bild */
743 else if (dx) /* allg. Bewegung in x-Richtung */
744 MarkTileDirty(x + SIGN(dx), y);
746 if (y < BY1) /* Element kommt von oben ins Bild */
748 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
756 else if (y > BY2) /* Element kommt von unten ins Bild */
762 else if (y==BY1 && dy<0) /* Element verläßt oben das Bild */
768 else if (dy > 0 && cut_mode==CUT_ABOVE)
770 if (y == BY2) /* Element unterhalb des Bildes */
776 MarkTileDirty(x, y + 1);
777 } /* Element verläßt unten das Bild */
778 else if (dy > 0 && (y == BY2 || cut_mode==CUT_BELOW))
780 else if (dy) /* allg. Bewegung in y-Richtung */
781 MarkTileDirty(x, y + SIGN(dy));
784 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
786 src_pixmap = pix[PIX_BACK];
787 drawing_gc = clip_gc[PIX_BACK];
788 graphic -= GFX_START_ROCKSSCREEN;
789 src_x = SX+(graphic % GFX_PER_LINE)*TILEX+cx;
790 src_y = SY+(graphic / GFX_PER_LINE)*TILEY+cy;
792 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
794 src_pixmap = pix[PIX_HEROES];
795 drawing_gc = clip_gc[PIX_HEROES];
796 graphic -= GFX_START_ROCKSHEROES;
797 src_x = (graphic % HEROES_PER_LINE)*TILEX+cx;
798 src_y = (graphic / HEROES_PER_LINE)*TILEY+cy;
801 dest_x = FX + x*TILEX + dx;
802 dest_y = FY + y*TILEY + dy;
805 if (!IN_SCR_FIELD(x,y))
807 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
808 printf("DrawGraphicShifted(): This should never happen!\n");
813 if (mask_mode == USE_MASKING)
815 if (tile_clipmask[tile] != None)
817 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
818 XSetClipOrigin(display, tile_clip_gc, dest_x,dest_y);
819 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
820 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
825 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
828 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
829 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
830 src_x,src_y, width,height, dest_x,dest_y);
834 XCopyArea(display, src_pixmap, drawto_field, gc,
835 src_x,src_y, width,height, dest_x,dest_y);
840 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
843 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
846 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
847 int cut_mode, int mask_mode)
849 int ux = LEVELX(x), uy = LEVELY(y);
850 int graphic = el2gfx(element);
851 int phase4 = ABS(MovPos[ux][uy])/(TILEX/4);
852 int phase = phase4 / 2;
853 int dir = MovDir[ux][uy];
855 if (element==EL_PACMAN || element==EL_KAEFER || element==EL_FLIEGER)
861 else if (dir == MV_LEFT)
863 else if (dir == MV_DOWN)
866 else if (element==EL_MAULWURF || element==EL_PINGUIN ||
867 element==EL_SCHWEIN || element==EL_DRACHE)
870 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_LEFT :
871 element==EL_PINGUIN ? GFX_PINGUIN_LEFT :
872 element==EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
873 else if (dir==MV_RIGHT)
874 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_RIGHT :
875 element==EL_PINGUIN ? GFX_PINGUIN_RIGHT :
876 element==EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
878 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_UP :
879 element==EL_PINGUIN ? GFX_PINGUIN_UP :
880 element==EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
882 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_DOWN :
883 element==EL_PINGUIN ? GFX_PINGUIN_DOWN :
884 element==EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
888 else if (element==EL_SONDE)
890 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
892 else if (element==EL_SALZSAEURE)
894 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
896 else if (element==EL_BUTTERFLY || element==EL_FIREFLY)
900 else if ((element==EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
902 graphic += phase * (element==EL_FELSBROCKEN ? 2 : 1);
904 else if ((element==EL_SIEB_LEER || element==EL_SIEB2_LEER ||
905 element==EL_SIEB_VOLL || element==EL_SIEB2_VOLL) && SiebAktiv)
907 graphic += 3-(SiebAktiv%8)/2;
909 else if (IS_AMOEBOID(element))
911 graphic = (element==EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
912 graphic += (x+2*y) % 4;
914 else if (element==EL_MAUER_LEBT)
916 BOOL links_massiv = FALSE, rechts_massiv = FALSE;
918 if (!IN_LEV_FIELD(ux-1,uy) || IS_MAUER(Feld[ux-1][uy]))
920 if (!IN_LEV_FIELD(ux+1,uy) || IS_MAUER(Feld[ux+1][uy]))
921 rechts_massiv = TRUE;
923 if (links_massiv && rechts_massiv)
924 graphic = GFX_MAUERWERK;
925 else if (links_massiv)
926 graphic = GFX_MAUER_R;
927 else if (rechts_massiv)
928 graphic = GFX_MAUER_L;
932 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, mask_mode);
933 else if (mask_mode == USE_MASKING)
934 DrawGraphicThruMask(x,y, graphic);
936 DrawGraphic(x,y, graphic);
939 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
940 int cut_mode, int mask_mode)
942 if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
943 DrawScreenElementExt(SCREENX(x),SCREENY(y), dx,dy, element,
944 cut_mode, mask_mode);
947 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
950 DrawScreenElementExt(x,y, dx,dy, element, cut_mode, NO_MASKING);
953 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
956 DrawLevelElementExt(x,y, dx,dy, element, cut_mode, NO_MASKING);
959 void DrawScreenElementThruMask(int x, int y, int element)
961 DrawScreenElementExt(x,y, 0,0, element, NO_CUTTING, USE_MASKING);
964 void DrawLevelElementThruMask(int x, int y, int element)
966 DrawLevelElementExt(x,y, 0,0, element, NO_CUTTING, USE_MASKING);
969 void DrawLevelFieldThruMask(int x, int y)
971 DrawLevelElementExt(x,y, 0,0, Feld[x][y], NO_CUTTING, USE_MASKING);
974 void ErdreichAnbroeckeln(int x, int y)
976 int i, width, height, cx,cy;
977 int ux = LEVELX(x), uy = LEVELY(y);
978 int element, graphic;
980 static int xy[4][2] =
988 if (!IN_LEV_FIELD(ux,uy))
991 element = Feld[ux][uy];
993 if (element==EL_ERDREICH)
995 if (!IN_SCR_FIELD(x,y))
998 graphic = GFX_ERDENRAND;
1006 if (!IN_LEV_FIELD(uxx,uyy))
1009 element = Feld[uxx][uyy];
1011 if (element==EL_ERDREICH)
1018 cx = (i==2 ? TILEX-snip : 0);
1026 cy = (i==3 ? TILEY-snip : 0);
1029 XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
1030 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
1031 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
1032 width,height, FX+x*TILEX+cx,FY+y*TILEY+cy);
1039 graphic = GFX_ERDENRAND;
1050 if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
1051 !IN_SCR_FIELD(xx,yy))
1058 cx = (i==1 ? TILEX-snip : 0);
1066 cy = (i==0 ? TILEY-snip : 0);
1069 XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
1070 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
1071 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
1072 width,height, FX+xx*TILEX+cx,FY+yy*TILEY+cy);
1074 MarkTileDirty(xx,yy);
1079 void DrawScreenElement(int x, int y, int element)
1081 DrawScreenElementExt(x,y, 0,0, element, NO_CUTTING, NO_MASKING);
1082 ErdreichAnbroeckeln(x,y);
1085 void DrawLevelElement(int x, int y, int element)
1087 if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
1088 DrawScreenElement(SCREENX(x),SCREENY(y),element);
1091 void DrawScreenField(int x, int y)
1093 int ux = LEVELX(x), uy = LEVELY(y);
1096 if (!IN_LEV_FIELD(ux,uy))
1098 DrawScreenElement(x,y,EL_BETON);
1102 element = Feld[ux][uy];
1104 if (IS_MOVING(ux,uy))
1106 int horiz_move = (MovDir[ux][uy]==MV_LEFT || MovDir[ux][uy]==MV_RIGHT);
1107 BOOL cut_mode = NO_CUTTING;
1109 if (Store[ux][uy]==EL_MORAST_LEER ||
1110 Store[ux][uy]==EL_SIEB_LEER ||
1111 Store[ux][uy]==EL_SIEB2_LEER ||
1112 Store[ux][uy]==EL_AMOEBE_NASS)
1113 cut_mode = CUT_ABOVE;
1114 else if (Store[ux][uy]==EL_MORAST_VOLL ||
1115 Store[ux][uy]==EL_SIEB_VOLL ||
1116 Store[ux][uy]==EL_SIEB2_VOLL)
1117 cut_mode = CUT_BELOW;
1119 if (cut_mode==CUT_ABOVE)
1120 DrawScreenElementShifted(x,y, 0,0, Store[ux][uy], NO_CUTTING);
1122 DrawScreenElement(x,y,EL_LEERRAUM);
1125 DrawScreenElementShifted(x,y, MovPos[ux][uy],0, element, NO_CUTTING);
1127 DrawScreenElementShifted(x,y, 0,MovPos[ux][uy], element, cut_mode);
1129 if (Store[ux][uy] == EL_SALZSAEURE)
1130 DrawLevelElementThruMask(ux,uy+1, EL_SALZSAEURE);
1132 else if (IS_BLOCKED(ux,uy))
1137 BOOL cut_mode = NO_CUTTING;
1139 Blocked2Moving(ux,uy,&oldx,&oldy);
1142 horiz_move = (MovDir[oldx][oldy]==MV_LEFT || MovDir[oldx][oldy]==MV_RIGHT);
1144 if (Store[oldx][oldy]==EL_MORAST_LEER ||
1145 Store[oldx][oldy]==EL_SIEB_LEER ||
1146 Store[oldx][oldy]==EL_SIEB2_LEER ||
1147 Store[oldx][oldy]==EL_AMOEBE_NASS)
1148 cut_mode = CUT_ABOVE;
1150 DrawScreenElement(x,y,EL_LEERRAUM);
1151 element = Feld[oldx][oldy];
1154 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1156 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1158 else if (IS_DRAWABLE(element))
1159 DrawScreenElement(x,y,element);
1161 DrawScreenElement(x,y,EL_LEERRAUM);
1164 void DrawLevelField(int x, int y)
1166 if (IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
1167 DrawScreenField(SCREENX(x),SCREENY(y));
1168 else if (IS_MOVING(x,y))
1172 Moving2Blocked(x,y,&newx,&newy);
1173 if (IN_SCR_FIELD(SCREENX(newx),SCREENY(newy)))
1174 DrawScreenField(SCREENX(newx),SCREENY(newy));
1176 else if (IS_BLOCKED(x,y))
1180 Blocked2Moving(x,y,&oldx,&oldy);
1181 if (IN_SCR_FIELD(SCREENX(oldx),SCREENY(oldy)))
1182 DrawScreenField(SCREENX(oldx),SCREENY(oldy));
1186 void DrawMiniElement(int x, int y, int element)
1192 DrawMiniGraphic(x,y,-1);
1196 graphic = el2gfx(element);
1197 DrawMiniGraphic(x,y,graphic);
1200 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1202 int x = sx + scroll_x, y = sy + scroll_y;
1204 if (x<-1 || x>lev_fieldx || y<-1 || y>lev_fieldy)
1205 DrawMiniElement(sx,sy,EL_LEERRAUM);
1206 else if (x==-1 || x==lev_fieldx || y==-1 || y==lev_fieldy)
1207 DrawMiniElement(sx,sy,EL_BETON);
1209 DrawMiniElement(sx,sy,Feld[x][y]);
1212 void DrawMicroElement(int xpos, int ypos, int element)
1216 if (element==EL_LEERRAUM)
1219 graphic = el2gfx(element);
1221 XCopyArea(display,pix[PIX_BACK],drawto,gc,
1222 MICRO_GFX_STARTX+(graphic % MICRO_GFX_PER_LINE)*MICRO_TILEX,
1223 MICRO_GFX_STARTY+(graphic / MICRO_GFX_PER_LINE)*MICRO_TILEY,
1224 MICRO_TILEX,MICRO_TILEY, xpos,ypos);
1233 for(x=BX1; x<=BX2; x++)
1234 for(y=BY1; y<=BY2; y++)
1235 DrawScreenField(x,y);
1237 if (soft_scrolling_on)
1238 XCopyArea(display,fieldbuffer,backbuffer,gc,
1239 FX,FY, SXSIZE,SYSIZE,
1242 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1245 void DrawMiniLevel(int scroll_x, int scroll_y)
1251 for(x=0;x<2*SCR_FIELDX;x++)
1252 for(y=0;y<2*SCR_FIELDY;y++)
1253 DrawMiniElementOrWall(x,y,scroll_x,scroll_y);
1255 redraw_mask |= REDRAW_FIELD;
1258 void DrawMicroLevel(int xpos, int ypos)
1262 XFillRectangle(display,drawto,gc,
1263 xpos-MICRO_TILEX,ypos-MICRO_TILEY,
1264 MICRO_TILEX*(STD_LEV_FIELDX+2),
1265 MICRO_TILEY*(STD_LEV_FIELDY+2));
1266 if (lev_fieldx < STD_LEV_FIELDX)
1267 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1268 if (lev_fieldy < STD_LEV_FIELDY)
1269 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1271 for(x=-1;x<=STD_LEV_FIELDX;x++)
1272 for(y=-1;y<=STD_LEV_FIELDY;y++)
1273 if (x>=0 && x<lev_fieldx && y>=0 && y<lev_fieldy)
1274 DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
1275 Feld[x][y]=Ur[x][y]);
1276 else if (x>=-1 && x<lev_fieldx+1 && y>=-1 && y<lev_fieldy+1)
1277 DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
1280 XFillRectangle(display,drawto,gc, SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE);
1284 int len = strlen(level.name);
1285 int lxpos = SX+(SXSIZE-len*FONT4_XSIZE)/2;
1286 int lypos = MICROLABEL_YPOS;
1288 DrawText(lxpos,lypos,level.name,FS_SMALL,FC_SPECIAL2);
1291 redraw_mask |= REDRAW_MICROLEV;
1294 int REQ_in_range(int x, int y)
1296 if (y>DY+249 && y<DY+278)
1298 if (x>DX+1 && x<DX+48)
1300 else if (x>DX+51 && x<DX+98)
1306 BOOL Request(char *text, unsigned int req_state)
1308 int mx,my, ty, result = -1;
1309 unsigned int old_door_state;
1311 /* pause network game while waiting for request to answer */
1312 if (network && game_status == PLAYING && req_state & REQUEST_WAIT_FOR)
1313 SendToServer_PausePlaying();
1315 old_door_state = GetDoorState();
1317 CloseDoor(DOOR_CLOSE_1);
1319 /* Alten Türinhalt sichern */
1320 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1321 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1322 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1);
1324 /* Fragetext schreiben */
1325 XFillRectangle(display,pix[PIX_DB_DOOR],gc,
1326 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1,DXSIZE,DYSIZE);
1328 for(ty=0;ty<13;ty++)
1335 for(tl=0,tx=0;tx<7;tl++,tx++)
1349 DrawTextExt(pix[PIX_DB_DOOR],gc,
1350 DOOR_GFX_PAGEX1+51-(tl*14)/2,SY+ty*16,txt,FS_SMALL,FC_YELLOW);
1351 text+=(tl+(tc==32));
1354 if (req_state & REQ_ASK)
1355 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1356 DOOR_GFX_PAGEX4,OK_BUTTON_GFX_YPOS,
1357 DXSIZE,OK_BUTTON_YSIZE,
1358 DOOR_GFX_PAGEX1,OK_BUTTON_YPOS);
1359 else if (req_state & REQ_CONFIRM)
1360 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1361 DOOR_GFX_PAGEX4,CONFIRM_BUTTON_GFX_YPOS,
1362 DXSIZE,CONFIRM_BUTTON_YSIZE,
1363 DOOR_GFX_PAGEX1,CONFIRM_BUTTON_YPOS);
1364 else if (req_state & REQ_PLAYER)
1366 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1367 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1368 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1369 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1372 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1373 DOOR_GFX_PAGEX4 + PLAYER_BUTTON_GFX_XPOS, PLAYER_BUTTON_GFX_YPOS,
1374 PLAYER_BUTTON_XSIZE,PLAYER_BUTTON_YSIZE,
1375 DOOR_GFX_PAGEX1 + PLAYER_BUTTON_1_XPOS, PLAYER_BUTTON_1_YPOS);
1376 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1377 DOOR_GFX_PAGEX4 + PLAYER_BUTTON_GFX_XPOS, PLAYER_BUTTON_GFX_YPOS,
1378 PLAYER_BUTTON_XSIZE,PLAYER_BUTTON_YSIZE,
1379 DOOR_GFX_PAGEX1 + PLAYER_BUTTON_1_XPOS, PLAYER_BUTTON_1_YPOS);
1380 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1381 DOOR_GFX_PAGEX4 + PLAYER_BUTTON_GFX_XPOS, PLAYER_BUTTON_GFX_YPOS,
1382 PLAYER_BUTTON_XSIZE,PLAYER_BUTTON_YSIZE,
1383 DOOR_GFX_PAGEX1 + PLAYER_BUTTON_2_XPOS, PLAYER_BUTTON_2_YPOS);
1384 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1385 DOOR_GFX_PAGEX4 + PLAYER_BUTTON_GFX_XPOS, PLAYER_BUTTON_GFX_YPOS,
1386 PLAYER_BUTTON_XSIZE,PLAYER_BUTTON_YSIZE,
1387 DOOR_GFX_PAGEX1 + PLAYER_BUTTON_3_XPOS, PLAYER_BUTTON_3_YPOS);
1388 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1389 DOOR_GFX_PAGEX4 + PLAYER_BUTTON_GFX_XPOS, PLAYER_BUTTON_GFX_YPOS,
1390 PLAYER_BUTTON_XSIZE,PLAYER_BUTTON_YSIZE,
1391 DOOR_GFX_PAGEX1 + PLAYER_BUTTON_4_XPOS, PLAYER_BUTTON_4_YPOS);
1395 OpenDoor(DOOR_OPEN_1);
1398 if (!(req_state & REQUEST_WAIT_FOR))
1401 if (game_status != MAINMENU)
1404 button_status = MB_RELEASED;
1411 if (XPending(display))
1415 XNextEvent(display, &event);
1419 HandleExposeEvent((XExposeEvent *) &event);
1422 SleepWhileUnmapped();
1430 if (event.type == MotionNotify)
1432 motion_status = TRUE;
1433 mx = ((XMotionEvent *) &event)->x;
1434 my = ((XMotionEvent *) &event)->y;
1438 motion_status = FALSE;
1439 mx = ((XButtonEvent *) &event)->x;
1440 my = ((XButtonEvent *) &event)->y;
1441 if (event.type==ButtonPress)
1442 button_status = ((XButtonEvent *) &event)->button;
1444 button_status = MB_RELEASED;
1447 if (req_state & REQ_ASK)
1448 choice = CheckYesNoButtons(mx,my,button_status);
1449 else if (req_state & REQ_CONFIRM)
1450 choice = CheckConfirmButton(mx,my,button_status);
1452 choice = CheckPlayerButtons(mx,my,button_status);
1462 case BUTTON_CONFIRM:
1463 result = TRUE | FALSE;
1465 case BUTTON_PLAYER_1:
1468 case BUTTON_PLAYER_2:
1471 case BUTTON_PLAYER_3:
1474 case BUTTON_PLAYER_4:
1483 switch(XLookupKeysym((XKeyEvent *)&event,
1484 ((XKeyEvent *)&event)->state))
1493 if (req_state & REQ_PLAYER)
1497 key_joystick_mapping = 0;
1501 HandleFocusEvent((XFocusChangeEvent *) &event);
1504 HandleClientMessageEvent((XClientMessageEvent *) &event);
1510 else if (JoystickButton() == JOY_BUTTON_NEW_PRESSED)
1514 if (joy & JOY_BUTTON_1)
1516 else if (joy & JOY_BUTTON_2)
1521 if (game_status != MAINMENU)
1524 if (!(req_state & REQ_STAY_OPEN))
1526 CloseDoor(DOOR_CLOSE_1);
1528 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1530 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1531 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1532 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1533 OpenDoor(DOOR_OPEN_1);
1537 /* continue network game after request */
1538 if (network && game_status == PLAYING && req_state & REQUEST_WAIT_FOR)
1539 SendToServer_ContinuePlaying();
1544 unsigned int OpenDoor(unsigned int door_state)
1546 unsigned int new_door_state;
1548 if (door_state & DOOR_COPY_BACK)
1550 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1551 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE+VYSIZE,
1552 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1553 door_state &= ~DOOR_COPY_BACK;
1556 new_door_state = MoveDoor(door_state);
1558 return(new_door_state);
1561 unsigned int CloseDoor(unsigned int door_state)
1563 unsigned int new_door_state;
1565 XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1566 DX,DY, DXSIZE,DYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1567 XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1568 VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1570 new_door_state = MoveDoor(door_state);
1572 return(new_door_state);
1575 unsigned int GetDoorState()
1577 return(MoveDoor(DOOR_GET_STATE));
1580 unsigned int MoveDoor(unsigned int door_state)
1582 static unsigned int door1 = DOOR_OPEN_1;
1583 static unsigned int door2 = DOOR_CLOSE_2;
1584 static long door_delay = 0;
1585 int x, start, stepsize = 2;
1586 long door_delay_value = stepsize * 5;
1588 if (door_state == DOOR_GET_STATE)
1589 return(door1 | door2);
1591 if (door1==DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1592 door_state &= ~DOOR_OPEN_1;
1593 else if (door1==DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1594 door_state &= ~DOOR_CLOSE_1;
1595 if (door2==DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1596 door_state &= ~DOOR_OPEN_2;
1597 else if (door2==DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1598 door_state &= ~DOOR_CLOSE_2;
1603 door_delay_value = 0;
1604 StopSound(SND_OEFFNEN);
1607 if (door_state & DOOR_ACTION)
1609 if (!(door_state & DOOR_NO_DELAY))
1610 PlaySoundStereo(SND_OEFFNEN,PSND_MAX_RIGHT);
1612 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1614 for(x=start; x<=DXSIZE; x+=stepsize)
1616 WaitUntilDelayReached(&door_delay, door_delay_value);
1618 if (door_state & DOOR_ACTION_1)
1620 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1621 int j = (DXSIZE - i)/3;
1623 XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1624 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1+i/2,
1625 DXSIZE,DYSIZE-i/2, DX,DY);
1627 XFillRectangle(display,drawto,gc,DX,DY+DYSIZE-i/2,DXSIZE,i/2);
1629 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1630 DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1631 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1632 DXSIZE,DOOR_GFX_PAGEY1, i,77, DX+DXSIZE-i,DY+j);
1633 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1634 DXSIZE,DOOR_GFX_PAGEY1+140, i,63, DX+DXSIZE-i,DY+140+j);
1635 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1636 DX-DXSIZE+i,DY-(DOOR_GFX_PAGEY1+j));
1637 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1638 DXSIZE-i,DOOR_GFX_PAGEY1+j, i,77-j, DX,DY);
1639 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1640 DXSIZE-i,DOOR_GFX_PAGEY1+140, i,63, DX,DY+140-j);
1642 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1643 DXSIZE-i,DOOR_GFX_PAGEY1+77, i,63,
1645 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1646 DXSIZE-i,DOOR_GFX_PAGEY1+203, i,77,
1648 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1649 DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1650 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1651 DXSIZE,DOOR_GFX_PAGEY1+77, i,63,
1652 DX+DXSIZE-i,DY+77+j);
1653 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1654 DXSIZE,DOOR_GFX_PAGEY1+203, i,77-j,
1655 DX+DXSIZE-i,DY+203+j);
1657 redraw_mask |= REDRAW_DOOR_1;
1660 if (door_state & DOOR_ACTION_2)
1662 int i = (door_state & DOOR_OPEN_2 ? VXSIZE-x : x);
1663 int j = (VXSIZE - i)/3;
1665 XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1666 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2+i/2,
1667 VXSIZE,VYSIZE-i/2, VX,VY);
1669 XFillRectangle(display,drawto,gc,VX,VY+VYSIZE-i/2,VXSIZE,i/2);
1671 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1672 VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1673 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1674 VXSIZE,DOOR_GFX_PAGEY2, i,VYSIZE/2, VX+VXSIZE-i,VY+j);
1675 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1676 VX-VXSIZE+i,VY-(DOOR_GFX_PAGEY2+j));
1677 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1678 VXSIZE-i,DOOR_GFX_PAGEY2+j, i,VYSIZE/2-j, VX,VY);
1680 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1681 VXSIZE-i,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2,
1683 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1684 VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1685 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1686 VXSIZE,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2-j,
1687 VX+VXSIZE-i,VY+VYSIZE/2+j);
1689 redraw_mask |= REDRAW_DOOR_2;
1694 if (game_status == MAINMENU)
1699 if (door_state & DOOR_ACTION_1)
1700 door1 = door_state & DOOR_ACTION_1;
1701 if (door_state & DOOR_ACTION_2)
1702 door2 = door_state & DOOR_ACTION_2;
1704 return(door1 | door2);
1707 int ReadPixel(Drawable d, int x, int y)
1709 static XImage *pixelimage;
1711 pixelimage = XGetImage(display, d, x,y, 1,1, AllPlanes, ZPixmap);
1712 return(XGetPixel(pixelimage,0,0));
1715 int el2gfx(int element)
1719 case EL_LEERRAUM: return(-1);
1720 case EL_ERDREICH: return(GFX_ERDREICH);
1721 case EL_MAUERWERK: return(GFX_MAUERWERK);
1722 case EL_FELSBODEN: return(GFX_FELSBODEN);
1723 case EL_FELSBROCKEN: return(GFX_FELSBROCKEN);
1724 case EL_SCHLUESSEL: return(GFX_SCHLUESSEL);
1725 case EL_EDELSTEIN: return(GFX_EDELSTEIN);
1726 case EL_AUSGANG_ZU: return(GFX_AUSGANG_ZU);
1727 case EL_AUSGANG_ACT: return(GFX_AUSGANG_ACT);
1728 case EL_AUSGANG_AUF: return(GFX_AUSGANG_AUF);
1729 case EL_SPIELFIGUR: return(GFX_SPIELFIGUR);
1730 case EL_SPIELER1: return(GFX_SPIELER1);
1731 case EL_SPIELER2: return(GFX_SPIELER2);
1732 case EL_SPIELER3: return(GFX_SPIELER3);
1733 case EL_SPIELER4: return(GFX_SPIELER4);
1734 case EL_KAEFER: return(GFX_KAEFER);
1735 case EL_KAEFER_R: return(GFX_KAEFER_R);
1736 case EL_KAEFER_O: return(GFX_KAEFER_O);
1737 case EL_KAEFER_L: return(GFX_KAEFER_L);
1738 case EL_KAEFER_U: return(GFX_KAEFER_U);
1739 case EL_FLIEGER: return(GFX_FLIEGER);
1740 case EL_FLIEGER_R: return(GFX_FLIEGER_R);
1741 case EL_FLIEGER_O: return(GFX_FLIEGER_O);
1742 case EL_FLIEGER_L: return(GFX_FLIEGER_L);
1743 case EL_FLIEGER_U: return(GFX_FLIEGER_U);
1744 case EL_BUTTERFLY: return(GFX_BUTTERFLY);
1745 case EL_BUTTERFLY_R: return(GFX_BUTTERFLY_R);
1746 case EL_BUTTERFLY_O: return(GFX_BUTTERFLY_O);
1747 case EL_BUTTERFLY_L: return(GFX_BUTTERFLY_L);
1748 case EL_BUTTERFLY_U: return(GFX_BUTTERFLY_U);
1749 case EL_FIREFLY: return(GFX_FIREFLY);
1750 case EL_FIREFLY_R: return(GFX_FIREFLY_R);
1751 case EL_FIREFLY_O: return(GFX_FIREFLY_O);
1752 case EL_FIREFLY_L: return(GFX_FIREFLY_L);
1753 case EL_FIREFLY_U: return(GFX_FIREFLY_U);
1754 case EL_MAMPFER: return(GFX_MAMPFER);
1755 case EL_ROBOT: return(GFX_ROBOT);
1756 case EL_BETON: return(GFX_BETON);
1757 case EL_DIAMANT: return(GFX_DIAMANT);
1758 case EL_MORAST_LEER: return(GFX_MORAST_LEER);
1759 case EL_MORAST_VOLL: return(GFX_MORAST_VOLL);
1760 case EL_TROPFEN: return(GFX_TROPFEN);
1761 case EL_BOMBE: return(GFX_BOMBE);
1762 case EL_SIEB_LEER: return(GFX_SIEB_LEER);
1763 case EL_SIEB_VOLL: return(GFX_SIEB_VOLL);
1764 case EL_SIEB_TOT: return(GFX_SIEB_TOT);
1765 case EL_SALZSAEURE: return(GFX_SALZSAEURE);
1766 case EL_AMOEBE_TOT: return(GFX_AMOEBE_TOT);
1767 case EL_AMOEBE_NASS: return(GFX_AMOEBE_NASS);
1768 case EL_AMOEBE_NORM: return(GFX_AMOEBE_NORM);
1769 case EL_AMOEBE_VOLL: return(GFX_AMOEBE_VOLL);
1770 case EL_AMOEBE_BD: return(GFX_AMOEBE_BD);
1771 case EL_AMOEBA2DIAM: return(GFX_AMOEBA2DIAM);
1772 case EL_KOKOSNUSS: return(GFX_KOKOSNUSS);
1773 case EL_LIFE: return(GFX_LIFE);
1774 case EL_LIFE_ASYNC: return(GFX_LIFE_ASYNC);
1775 case EL_DYNAMIT: return(GFX_DYNAMIT);
1776 case EL_BADEWANNE: return(GFX_BADEWANNE);
1777 case EL_BADEWANNE1: return(GFX_BADEWANNE1);
1778 case EL_BADEWANNE2: return(GFX_BADEWANNE2);
1779 case EL_BADEWANNE3: return(GFX_BADEWANNE3);
1780 case EL_BADEWANNE4: return(GFX_BADEWANNE4);
1781 case EL_BADEWANNE5: return(GFX_BADEWANNE5);
1782 case EL_ABLENK_AUS: return(GFX_ABLENK_AUS);
1783 case EL_ABLENK_EIN: return(GFX_ABLENK_EIN);
1784 case EL_SCHLUESSEL1: return(GFX_SCHLUESSEL1);
1785 case EL_SCHLUESSEL2: return(GFX_SCHLUESSEL2);
1786 case EL_SCHLUESSEL3: return(GFX_SCHLUESSEL3);
1787 case EL_SCHLUESSEL4: return(GFX_SCHLUESSEL4);
1788 case EL_PFORTE1: return(GFX_PFORTE1);
1789 case EL_PFORTE2: return(GFX_PFORTE2);
1790 case EL_PFORTE3: return(GFX_PFORTE3);
1791 case EL_PFORTE4: return(GFX_PFORTE4);
1792 case EL_PFORTE1X: return(GFX_PFORTE1X);
1793 case EL_PFORTE2X: return(GFX_PFORTE2X);
1794 case EL_PFORTE3X: return(GFX_PFORTE3X);
1795 case EL_PFORTE4X: return(GFX_PFORTE4X);
1796 case EL_DYNAMIT_AUS: return(GFX_DYNAMIT_AUS);
1797 case EL_PACMAN: return(GFX_PACMAN);
1798 case EL_PACMAN_R: return(GFX_PACMAN_R);
1799 case EL_PACMAN_O: return(GFX_PACMAN_O);
1800 case EL_PACMAN_L: return(GFX_PACMAN_L);
1801 case EL_PACMAN_U: return(GFX_PACMAN_U);
1802 case EL_UNSICHTBAR: return(GFX_UNSICHTBAR);
1803 case EL_ERZ_EDEL: return(GFX_ERZ_EDEL);
1804 case EL_ERZ_DIAM: return(GFX_ERZ_DIAM);
1805 case EL_BIRNE_AUS: return(GFX_BIRNE_AUS);
1806 case EL_BIRNE_EIN: return(GFX_BIRNE_EIN);
1807 case EL_ZEIT_VOLL: return(GFX_ZEIT_VOLL);
1808 case EL_ZEIT_LEER: return(GFX_ZEIT_LEER);
1809 case EL_MAUER_LEBT: return(GFX_MAUER_LEBT);
1810 case EL_MAUER_X: return(GFX_MAUER_X);
1811 case EL_MAUER_Y: return(GFX_MAUER_Y);
1812 case EL_MAUER_XY: return(GFX_MAUER_XY);
1813 case EL_EDELSTEIN_BD: return(GFX_EDELSTEIN_BD);
1814 case EL_EDELSTEIN_GELB: return(GFX_EDELSTEIN_GELB);
1815 case EL_EDELSTEIN_ROT: return(GFX_EDELSTEIN_ROT);
1816 case EL_EDELSTEIN_LILA: return(GFX_EDELSTEIN_LILA);
1817 case EL_ERZ_EDEL_BD: return(GFX_ERZ_EDEL_BD);
1818 case EL_ERZ_EDEL_GELB: return(GFX_ERZ_EDEL_GELB);
1819 case EL_ERZ_EDEL_ROT: return(GFX_ERZ_EDEL_ROT);
1820 case EL_ERZ_EDEL_LILA: return(GFX_ERZ_EDEL_LILA);
1821 case EL_MAMPFER2: return(GFX_MAMPFER2);
1822 case EL_SIEB2_LEER: return(GFX_SIEB2_LEER);
1823 case EL_SIEB2_VOLL: return(GFX_SIEB2_VOLL);
1824 case EL_SIEB2_TOT: return(GFX_SIEB2_TOT);
1825 case EL_DYNABOMB: return(GFX_DYNABOMB);
1826 case EL_DYNABOMB_NR: return(GFX_DYNABOMB_NR);
1827 case EL_DYNABOMB_SZ: return(GFX_DYNABOMB_SZ);
1828 case EL_DYNABOMB_XL: return(GFX_DYNABOMB_XL);
1829 case EL_SOKOBAN_OBJEKT: return(GFX_SOKOBAN_OBJEKT);
1830 case EL_SOKOBAN_FELD_LEER: return(GFX_SOKOBAN_FELD_LEER);
1831 case EL_SOKOBAN_FELD_VOLL: return(GFX_SOKOBAN_FELD_VOLL);
1832 case EL_MAULWURF: return(GFX_MAULWURF);
1833 case EL_PINGUIN: return(GFX_PINGUIN);
1834 case EL_SCHWEIN: return(GFX_SCHWEIN);
1835 case EL_DRACHE: return(GFX_DRACHE);
1836 case EL_SONDE: return(GFX_SONDE);
1837 case EL_PFEIL_L: return(GFX_PFEIL_L);
1838 case EL_PFEIL_R: return(GFX_PFEIL_R);
1839 case EL_PFEIL_O: return(GFX_PFEIL_O);
1840 case EL_PFEIL_U: return(GFX_PFEIL_U);
1843 if (IS_CHAR(element))
1844 return(GFX_CHAR_START + (element-EL_CHAR_START));