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>
30 extern BOOL wait_for_vsync;
33 void SetDrawtoField(int mode)
35 if (mode == DRAW_BUFFERED && soft_scrolling_on)
46 drawto_field = fieldbuffer;
48 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
59 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
66 Drawable buffer = (drawto_field != window ? drawto_field : backbuffer);
68 if (direct_draw_on && game_status == PLAYING)
69 redraw_mask &= ~REDRAW_MAIN;
71 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
72 redraw_mask |= REDRAW_FIELD;
74 if (redraw_mask & REDRAW_FIELD || ScreenGfxPos)
75 redraw_mask &= ~REDRAW_TILES;
80 /* synchronize X11 graphics at this point; if we would synchronize the
81 display immediately after the buffer switching (after the XFlush),
82 this could mean that we have to wait for the graphics to complete,
83 although we could go on doing calculations for the next frame */
88 wait_for_vsync = TRUE;
91 if (redraw_mask & REDRAW_ALL)
93 XCopyArea(display,backbuffer,window,gc,
94 0,0, WIN_XSIZE,WIN_YSIZE,
99 if (redraw_mask & REDRAW_FIELD)
101 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
102 XCopyArea(display,backbuffer,window,gc,
103 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
107 int fx = FX, fy = FY;
109 if (soft_scrolling_on)
111 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
112 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
115 XCopyArea(display,buffer,window,gc,
116 fx,fy, SXSIZE,SYSIZE,
119 redraw_mask &= ~REDRAW_MAIN;
122 if (redraw_mask & REDRAW_DOORS)
124 if (redraw_mask & REDRAW_DOOR_1)
125 XCopyArea(display,backbuffer,window,gc,
126 DX,DY, DXSIZE,DYSIZE,
128 if (redraw_mask & REDRAW_DOOR_2)
130 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
131 XCopyArea(display,backbuffer,window,gc,
132 VX,VY, VXSIZE,VYSIZE,
136 if (redraw_mask & REDRAW_VIDEO_1)
137 XCopyArea(display,backbuffer,window,gc,
138 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
139 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
140 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
141 if (redraw_mask & REDRAW_VIDEO_2)
142 XCopyArea(display,backbuffer,window,gc,
143 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
144 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
145 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
146 if (redraw_mask & REDRAW_VIDEO_3)
147 XCopyArea(display,backbuffer,window,gc,
148 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
149 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
150 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
153 redraw_mask &= ~REDRAW_DOORS;
156 if (redraw_mask & REDRAW_MICROLEV)
158 XCopyArea(display,backbuffer,window,gc,
159 MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
160 MICROLEV_XPOS,MICROLEV_YPOS);
161 XCopyArea(display,backbuffer,window,gc,
162 SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
164 redraw_mask &= ~REDRAW_MICROLEV;
167 if (redraw_mask & REDRAW_TILES)
169 for(x=0; x<SCR_FIELDX; x++)
170 for(y=0; y<SCR_FIELDY; y++)
171 if (redraw[redraw_x1 + x][redraw_y1 + y])
172 XCopyArea(display,buffer,window,gc,
173 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
174 SX+x*TILEX,SY+y*TILEY);
179 for(x=0; x<MAX_BUF_XSIZE; x++)
180 for(y=0; y<MAX_BUF_YSIZE; y++)
189 long fading_delay = 300;
191 if (fading_on && (redraw_mask & REDRAW_FIELD))
198 XFillRectangle(display,window,gc,
199 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
202 for(i=0;i<2*FULL_SYSIZE;i++)
204 for(y=0;y<FULL_SYSIZE;y++)
206 XCopyArea(display,backbuffer,window,gc,
207 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
215 for(i=1;i<FULL_SYSIZE;i+=2)
216 XCopyArea(display,backbuffer,window,gc,
217 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
223 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
224 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
225 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
229 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
230 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
231 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
235 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
236 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
237 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
241 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
242 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
243 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
247 redraw_mask &= ~REDRAW_MAIN;
256 XFillRectangle(display,backbuffer,gc,
257 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
259 if (soft_scrolling_on && game_status==PLAYING)
261 XFillRectangle(display,fieldbuffer,gc,
263 SetDrawtoField(DRAW_BUFFERED);
266 SetDrawtoField(DRAW_BACKBUFFER);
268 if (direct_draw_on && game_status==PLAYING)
270 XFillRectangle(display,window,gc,
271 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
272 SetDrawtoField(DRAW_DIRECT);
275 redraw_mask |= REDRAW_FIELD;
278 void DrawText(int x, int y, char *text, int font, int col)
280 DrawTextExt(drawto, gc, x, y, text, font, col);
282 redraw_mask |= REDRAW_FIELD;
284 redraw_mask |= REDRAW_DOOR_1;
287 void DrawTextExt(Drawable d, GC gc, int x, int y,
288 char *text, int font, int font_color)
290 int font_width, font_height, font_start;
293 if (font!=FS_SMALL && font!=FS_BIG)
295 if (font_color<FC_RED || font_color>FC_SPECIAL2)
299 (font==FS_BIG ? FONT1_XSIZE :
300 font_color<FC_SPECIAL1 ? FONT2_XSIZE :
301 font_color<FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
303 (font==FS_BIG ? FONT1_XSIZE :
304 font_color<FC_SPECIAL2 ? FONT2_XSIZE: FONT4_XSIZE);
305 font_pixmap = (font==FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
307 font_color*(font==FS_BIG ? FONT1_YSIZE : FONT2_YSIZE)*FONT_LINES_PER_FONT;
313 if (c>='a' && c<='z')
315 else if (c=='ä' || c=='Ä')
317 else if (c=='ö' || c=='Ö')
319 else if (c=='ü' || c=='Ü')
323 XCopyArea(display,pix[font_pixmap],d,gc,
324 ((c-32) % FONT_CHARS_PER_LINE)*font_width,
325 ((c-32) / FONT_CHARS_PER_LINE)*font_height + font_start,
326 font_width,font_height, x,y);
332 void DrawAllPlayers()
336 for(i=0; i<MAX_PLAYERS; i++)
337 if (stored_player[i].active)
338 DrawPlayer(&stored_player[i]);
341 void DrawPlayerField(int x, int y)
346 DrawPlayer(PLAYERINFO(x,y));
349 void DrawPlayer(struct PlayerInfo *player)
351 int jx = player->jx, jy = player->jy;
352 int last_jx = player->last_jx, last_jy = player->last_jy;
353 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
354 int sx = SCREENX(jx), sy = SCREENY(jy);
355 int sxx = 0, syy = 0;
356 int element = Feld[jx][jy];
360 if (!player->active || player->gone || !IN_SCR_FIELD(sx,sy))
364 if (!player->active || player->gone ||
365 !IN_SCR_FIELD(SCREENX(last_jx),SCREENY(last_jy)))
369 if (!IN_LEV_FIELD(jx,jy))
371 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
372 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
373 printf("DrawPlayerField(): This should never happen!\n");
378 if (element == EL_EXPLODING)
381 /* draw things in the field the player is leaving, if needed */
383 if (last_jx != jx || last_jy != jy)
385 if (Store[last_jx][last_jy])
387 DrawLevelElement(last_jx,last_jy, Store[last_jx][last_jy]);
388 DrawLevelFieldThruMask(last_jx,last_jy);
390 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
391 DrawDynamite(last_jx,last_jy);
393 DrawLevelField(last_jx,last_jy);
395 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx),SCREENY(next_jy)))
399 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
400 DrawLevelElement(next_jx,next_jy, EL_SOKOBAN_FELD_LEER);
402 DrawLevelElement(next_jx,next_jy, EL_LEERRAUM);
405 DrawLevelField(next_jx,next_jy);
409 if (!IN_SCR_FIELD(sx,sy))
413 SetDrawtoField(DRAW_BUFFERED);
415 /* draw things behind the player, if needed */
418 DrawLevelElement(jx,jy, Store[jx][jy]);
419 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
420 DrawLevelField(jx,jy);
422 /* draw player himself */
424 if (player->MovDir==MV_LEFT)
425 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
426 else if (player->MovDir==MV_RIGHT)
427 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
428 else if (player->MovDir==MV_UP)
429 graphic = GFX_SPIELER1_UP;
430 else /* MV_DOWN || MV_NO_MOVING */
431 graphic = GFX_SPIELER1_DOWN;
433 graphic += player->index_nr * 3*HEROES_PER_LINE;
434 graphic += player->Frame;
438 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
439 sxx = player->GfxPos;
441 syy = player->GfxPos;
444 if (!soft_scrolling_on && ScreenMovPos)
447 DrawGraphicShiftedThruMask(sx,sy, sxx,syy, graphic, NO_CUTTING);
449 if (player->Pushing && player->GfxPos)
451 int px = SCREENX(next_jx), py = SCREENY(next_jy);
453 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
454 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
455 DrawGraphicShiftedThruMask(px,py,sxx,syy, GFX_SOKOBAN_OBJEKT,NO_CUTTING);
458 int element = Feld[next_jx][next_jy];
459 int graphic = el2gfx(element);
461 if (element == EL_FELSBROCKEN && sxx)
463 int phase = (player->GfxPos / (TILEX/4));
465 if (player->MovDir == MV_LEFT)
468 graphic += (phase+4)%4;
471 DrawGraphicShifted(px,py, sxx,syy, graphic, NO_CUTTING, NO_MASKING);
475 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
477 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
479 graphic = el2gfx(element);
481 if (element == EL_DYNAMIT)
483 if ((phase = (96-MovDelay[jx][jy])/12) > 6)
488 if ((phase = ((96-MovDelay[jx][jy])/6) % 8) > 3)
492 DrawGraphicThruMask(sx,sy, graphic + phase);
495 if ((last_jx != jx || last_jy != jy) && Feld[last_jx][last_jy]==EL_EXPLODING)
497 int phase = Frame[last_jx][last_jy];
501 DrawGraphicThruMask(SCREENX(last_jx),SCREENY(last_jy),
502 GFX_EXPLOSION + ((phase-1)/delay-1));
507 int dest_x = SX + SCREENX(MIN(jx,last_jx))*TILEX;
508 int dest_y = SY + SCREENY(MIN(jy,last_jy))*TILEY;
509 int x_size = TILEX * (1 + ABS(jx - last_jx));
510 int y_size = TILEY * (1 + ABS(jy - last_jy));
512 XCopyArea(display,drawto_field,window,gc,
513 dest_x,dest_y, x_size,y_size, dest_x,dest_y);
514 SetDrawtoField(DRAW_DIRECT);
517 MarkTileDirty(sx,sy);
520 static int getGraphicAnimationPhase(int frames, int delay, int mode)
524 if (mode == ANIM_OSCILLATE)
526 int max_anim_frames = frames*2 - 2;
527 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
528 phase = (phase < frames ? phase : max_anim_frames - phase);
531 phase = (FrameCounter % (delay * frames)) / delay;
533 if (mode == ANIM_REVERSE)
539 void DrawGraphicAnimationExt(int x, int y, int graphic,
540 int frames, int delay, int mode, int mask_mode)
542 int phase = getGraphicAnimationPhase(frames, delay, mode);
544 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
546 if (mask_mode == USE_MASKING)
547 DrawGraphicThruMask(SCREENX(x),SCREENY(y), graphic + phase);
549 DrawGraphic(SCREENX(x),SCREENY(y), graphic + phase);
553 void DrawGraphicAnimation(int x, int y, int graphic,
554 int frames, int delay, int mode)
556 DrawGraphicAnimationExt(x,y, graphic, frames,delay,mode, NO_MASKING);
559 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
560 int frames, int delay, int mode)
562 DrawGraphicAnimationExt(x,y, graphic, frames,delay,mode, USE_MASKING);
565 void DrawGraphic(int x, int y, int graphic)
568 if (!IN_SCR_FIELD(x,y))
570 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
571 printf("DrawGraphic(): This should never happen!\n");
576 DrawGraphicExt(drawto_field, gc, FX+x*TILEX, FY+y*TILEY, graphic);
580 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
582 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
584 graphic -= GFX_START_ROCKSSCREEN;
585 XCopyArea(display,pix[PIX_BACK],d,gc,
586 SX + (graphic % GFX_PER_LINE) * TILEX,
587 SY + (graphic / GFX_PER_LINE) * TILEY,
590 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
592 graphic -= GFX_START_ROCKSHEROES;
593 XCopyArea(display,pix[PIX_HEROES],d,gc,
594 (graphic % HEROES_PER_LINE) * TILEX,
595 (graphic / HEROES_PER_LINE) * TILEY,
598 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
600 graphic -= GFX_START_ROCKSFONT;
601 XCopyArea(display,pix[PIX_BIGFONT],d,gc,
602 (graphic % FONT_CHARS_PER_LINE) * TILEX,
603 (graphic / FONT_CHARS_PER_LINE) * TILEY +
604 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
608 XFillRectangle(display,d,gc, x,y, TILEX,TILEY);
611 void DrawGraphicThruMask(int x, int y, int graphic)
614 if (!IN_SCR_FIELD(x,y))
616 printf("DrawGraphicThruMask(): x = %d, y = %d\n",x,y);
617 printf("DrawGraphicThruMask(): This should never happen!\n");
622 DrawGraphicThruMaskExt(drawto_field, FX+x*TILEX, FY+y*TILEY, graphic);
626 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
633 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
635 src_pixmap = pix[PIX_BACK];
636 drawing_gc = clip_gc[PIX_BACK];
637 graphic -= GFX_START_ROCKSSCREEN;
638 src_x = SX+(graphic % GFX_PER_LINE)*TILEX;
639 src_y = SY+(graphic / GFX_PER_LINE)*TILEY;
641 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
643 src_pixmap = pix[PIX_HEROES];
644 drawing_gc = clip_gc[PIX_HEROES];
645 graphic -= GFX_START_ROCKSHEROES;
646 src_x = (graphic % HEROES_PER_LINE)*TILEX;
647 src_y = (graphic / HEROES_PER_LINE)*TILEY;
651 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
655 if (tile_clipmask[tile] != None)
657 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
658 XSetClipOrigin(display, tile_clip_gc, dest_x,dest_y);
659 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
660 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
665 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
668 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
669 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
670 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
674 void DrawMiniGraphic(int x, int y, int graphic)
676 DrawMiniGraphicExt(drawto,gc, SX+x*MINI_TILEX,SY+y*MINI_TILEY, graphic);
677 MarkTileDirty(x/2, y/2);
680 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
682 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
684 graphic -= GFX_START_ROCKSSCREEN;
685 XCopyArea(display,pix[PIX_BACK],d,gc,
686 MINI_GFX_STARTX+(graphic % MINI_GFX_PER_LINE)*MINI_TILEX,
687 MINI_GFX_STARTY+(graphic / MINI_GFX_PER_LINE)*MINI_TILEY,
688 MINI_TILEX,MINI_TILEY, x,y);
690 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
692 graphic -= GFX_START_ROCKSFONT;
693 XCopyArea(display,pix[PIX_SMALLFONT],d,gc,
694 (graphic % FONT_CHARS_PER_LINE)*FONT4_XSIZE,
695 (graphic / FONT_CHARS_PER_LINE)*FONT4_YSIZE +
696 FC_SPECIAL2*FONT2_YSIZE*FONT_LINES_PER_FONT,
697 MINI_TILEX,MINI_TILEY, x,y);
700 XFillRectangle(display,d,gc, x,y, MINI_TILEX,MINI_TILEY);
703 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
704 int cut_mode, int mask_mode)
706 int width = TILEX, height = TILEY;
708 int src_x,src_y, dest_x,dest_y;
715 DrawGraphic(x,y,graphic);
719 if (dx || dy) /* Verschiebung der Grafik? */
721 if (x < BX1) /* Element kommt von links ins Bild */
728 else if (x > BX2) /* Element kommt von rechts ins Bild */
734 else if (x==BX1 && dx<0) /* Element verläßt links das Bild */
740 else if (x==BX2 && dx>0) /* Element verläßt rechts das Bild */
742 else if (dx) /* allg. Bewegung in x-Richtung */
743 MarkTileDirty(x + SIGN(dx), y);
745 if (y < BY1) /* Element kommt von oben ins Bild */
747 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
755 else if (y > BY2) /* Element kommt von unten ins Bild */
761 else if (y==BY1 && dy<0) /* Element verläßt oben das Bild */
767 else if (dy > 0 && cut_mode==CUT_ABOVE)
769 if (y == BY2) /* Element unterhalb des Bildes */
775 MarkTileDirty(x, y + 1);
776 } /* Element verläßt unten das Bild */
777 else if (dy > 0 && (y == BY2 || cut_mode==CUT_BELOW))
779 else if (dy) /* allg. Bewegung in y-Richtung */
780 MarkTileDirty(x, y + SIGN(dy));
783 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
785 src_pixmap = pix[PIX_BACK];
786 drawing_gc = clip_gc[PIX_BACK];
787 graphic -= GFX_START_ROCKSSCREEN;
788 src_x = SX+(graphic % GFX_PER_LINE)*TILEX+cx;
789 src_y = SY+(graphic / GFX_PER_LINE)*TILEY+cy;
791 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
793 src_pixmap = pix[PIX_HEROES];
794 drawing_gc = clip_gc[PIX_HEROES];
795 graphic -= GFX_START_ROCKSHEROES;
796 src_x = (graphic % HEROES_PER_LINE)*TILEX+cx;
797 src_y = (graphic / HEROES_PER_LINE)*TILEY+cy;
800 dest_x = FX + x*TILEX + dx;
801 dest_y = FY + y*TILEY + dy;
804 if (!IN_SCR_FIELD(x,y))
806 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
807 printf("DrawGraphicShifted(): This should never happen!\n");
812 if (mask_mode == USE_MASKING)
814 if (tile_clipmask[tile] != None)
816 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
817 XSetClipOrigin(display, tile_clip_gc, dest_x,dest_y);
818 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
819 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
824 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
827 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
828 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
829 src_x,src_y, width,height, dest_x,dest_y);
833 XCopyArea(display, src_pixmap, drawto_field, gc,
834 src_x,src_y, width,height, dest_x,dest_y);
839 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
842 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
845 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
846 int cut_mode, int mask_mode)
848 int ux = LEVELX(x), uy = LEVELY(y);
849 int graphic = el2gfx(element);
850 int phase4 = ABS(MovPos[ux][uy])/(TILEX/4);
851 int phase = phase4 / 2;
852 int dir = MovDir[ux][uy];
854 if (element==EL_PACMAN || element==EL_KAEFER || element==EL_FLIEGER)
860 else if (dir == MV_LEFT)
862 else if (dir == MV_DOWN)
865 else if (element==EL_MAULWURF || element==EL_PINGUIN ||
866 element==EL_SCHWEIN || element==EL_DRACHE)
869 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_LEFT :
870 element==EL_PINGUIN ? GFX_PINGUIN_LEFT :
871 element==EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
872 else if (dir==MV_RIGHT)
873 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_RIGHT :
874 element==EL_PINGUIN ? GFX_PINGUIN_RIGHT :
875 element==EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
877 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_UP :
878 element==EL_PINGUIN ? GFX_PINGUIN_UP :
879 element==EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
881 graphic = (element==EL_MAULWURF ? GFX_MAULWURF_DOWN :
882 element==EL_PINGUIN ? GFX_PINGUIN_DOWN :
883 element==EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
887 else if (element==EL_SONDE)
889 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
891 else if (element==EL_SALZSAEURE)
893 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
895 else if (element==EL_BUTTERFLY || element==EL_FIREFLY)
899 else if ((element==EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
901 graphic += phase * (element==EL_FELSBROCKEN ? 2 : 1);
903 else if ((element==EL_SIEB_LEER || element==EL_SIEB2_LEER ||
904 element==EL_SIEB_VOLL || element==EL_SIEB2_VOLL) && SiebAktiv)
906 graphic += 3-(SiebAktiv%8)/2;
908 else if (IS_AMOEBOID(element))
910 graphic = (element==EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
911 graphic += (x+2*y) % 4;
913 else if (element==EL_MAUER_LEBT)
915 BOOL links_massiv = FALSE, rechts_massiv = FALSE;
917 if (!IN_LEV_FIELD(ux-1,uy) || IS_MAUER(Feld[ux-1][uy]))
919 if (!IN_LEV_FIELD(ux+1,uy) || IS_MAUER(Feld[ux+1][uy]))
920 rechts_massiv = TRUE;
922 if (links_massiv && rechts_massiv)
923 graphic = GFX_MAUERWERK;
924 else if (links_massiv)
925 graphic = GFX_MAUER_R;
926 else if (rechts_massiv)
927 graphic = GFX_MAUER_L;
931 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, mask_mode);
932 else if (mask_mode == USE_MASKING)
933 DrawGraphicThruMask(x,y, graphic);
935 DrawGraphic(x,y, graphic);
938 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
939 int cut_mode, int mask_mode)
941 if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
942 DrawScreenElementExt(SCREENX(x),SCREENY(y), dx,dy, element,
943 cut_mode, mask_mode);
946 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
949 DrawScreenElementExt(x,y, dx,dy, element, cut_mode, NO_MASKING);
952 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
955 DrawLevelElementExt(x,y, dx,dy, element, cut_mode, NO_MASKING);
958 void DrawScreenElementThruMask(int x, int y, int element)
960 DrawScreenElementExt(x,y, 0,0, element, NO_CUTTING, USE_MASKING);
963 void DrawLevelElementThruMask(int x, int y, int element)
965 DrawLevelElementExt(x,y, 0,0, element, NO_CUTTING, USE_MASKING);
968 void DrawLevelFieldThruMask(int x, int y)
970 DrawLevelElementExt(x,y, 0,0, Feld[x][y], NO_CUTTING, USE_MASKING);
973 void ErdreichAnbroeckeln(int x, int y)
975 int i, width, height, cx,cy;
976 int ux = LEVELX(x), uy = LEVELY(y);
977 int element, graphic;
979 static int xy[4][2] =
987 if (!IN_LEV_FIELD(ux,uy))
990 element = Feld[ux][uy];
992 if (element==EL_ERDREICH)
994 if (!IN_SCR_FIELD(x,y))
997 graphic = GFX_ERDENRAND;
1005 if (!IN_LEV_FIELD(uxx,uyy))
1008 element = Feld[uxx][uyy];
1010 if (element==EL_ERDREICH)
1017 cx = (i==2 ? TILEX-snip : 0);
1025 cy = (i==3 ? TILEY-snip : 0);
1028 XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
1029 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
1030 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
1031 width,height, FX+x*TILEX+cx,FY+y*TILEY+cy);
1038 graphic = GFX_ERDENRAND;
1049 if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
1050 !IN_SCR_FIELD(xx,yy))
1057 cx = (i==1 ? TILEX-snip : 0);
1065 cy = (i==0 ? TILEY-snip : 0);
1068 XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
1069 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
1070 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
1071 width,height, FX+xx*TILEX+cx,FY+yy*TILEY+cy);
1073 MarkTileDirty(xx,yy);
1078 void DrawScreenElement(int x, int y, int element)
1080 DrawScreenElementExt(x,y, 0,0, element, NO_CUTTING, NO_MASKING);
1081 ErdreichAnbroeckeln(x,y);
1084 void DrawLevelElement(int x, int y, int element)
1086 if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
1087 DrawScreenElement(SCREENX(x),SCREENY(y),element);
1090 void DrawScreenField(int x, int y)
1092 int ux = LEVELX(x), uy = LEVELY(y);
1095 if (!IN_LEV_FIELD(ux,uy))
1097 DrawScreenElement(x,y,EL_BETON);
1101 element = Feld[ux][uy];
1103 if (IS_MOVING(ux,uy))
1105 int horiz_move = (MovDir[ux][uy]==MV_LEFT || MovDir[ux][uy]==MV_RIGHT);
1106 BOOL cut_mode = NO_CUTTING;
1108 if (Store[ux][uy]==EL_MORAST_LEER ||
1109 Store[ux][uy]==EL_SIEB_LEER ||
1110 Store[ux][uy]==EL_SIEB2_LEER ||
1111 Store[ux][uy]==EL_AMOEBE_NASS)
1112 cut_mode = CUT_ABOVE;
1113 else if (Store[ux][uy]==EL_MORAST_VOLL ||
1114 Store[ux][uy]==EL_SIEB_VOLL ||
1115 Store[ux][uy]==EL_SIEB2_VOLL)
1116 cut_mode = CUT_BELOW;
1118 if (cut_mode==CUT_ABOVE)
1119 DrawScreenElementShifted(x,y, 0,0, Store[ux][uy], NO_CUTTING);
1121 DrawScreenElement(x,y,EL_LEERRAUM);
1124 DrawScreenElementShifted(x,y, MovPos[ux][uy],0, element, NO_CUTTING);
1126 DrawScreenElementShifted(x,y, 0,MovPos[ux][uy], element, cut_mode);
1128 if (Store[ux][uy] == EL_SALZSAEURE)
1129 DrawLevelElementThruMask(ux,uy+1, EL_SALZSAEURE);
1131 else if (IS_BLOCKED(ux,uy))
1136 BOOL cut_mode = NO_CUTTING;
1138 Blocked2Moving(ux,uy,&oldx,&oldy);
1141 horiz_move = (MovDir[oldx][oldy]==MV_LEFT || MovDir[oldx][oldy]==MV_RIGHT);
1143 if (Store[oldx][oldy]==EL_MORAST_LEER ||
1144 Store[oldx][oldy]==EL_SIEB_LEER ||
1145 Store[oldx][oldy]==EL_SIEB2_LEER ||
1146 Store[oldx][oldy]==EL_AMOEBE_NASS)
1147 cut_mode = CUT_ABOVE;
1149 DrawScreenElement(x,y,EL_LEERRAUM);
1150 element = Feld[oldx][oldy];
1153 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1155 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1157 else if (IS_DRAWABLE(element))
1158 DrawScreenElement(x,y,element);
1160 DrawScreenElement(x,y,EL_LEERRAUM);
1163 void DrawLevelField(int x, int y)
1165 if (IN_SCR_FIELD(SCREENX(x),SCREENY(y)))
1166 DrawScreenField(SCREENX(x),SCREENY(y));
1167 else if (IS_MOVING(x,y))
1171 Moving2Blocked(x,y,&newx,&newy);
1172 if (IN_SCR_FIELD(SCREENX(newx),SCREENY(newy)))
1173 DrawScreenField(SCREENX(newx),SCREENY(newy));
1175 else if (IS_BLOCKED(x,y))
1179 Blocked2Moving(x,y,&oldx,&oldy);
1180 if (IN_SCR_FIELD(SCREENX(oldx),SCREENY(oldy)))
1181 DrawScreenField(SCREENX(oldx),SCREENY(oldy));
1185 void DrawMiniElement(int x, int y, int element)
1191 DrawMiniGraphic(x,y,-1);
1195 graphic = el2gfx(element);
1196 DrawMiniGraphic(x,y,graphic);
1199 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1201 int x = sx + scroll_x, y = sy + scroll_y;
1203 if (x<-1 || x>lev_fieldx || y<-1 || y>lev_fieldy)
1204 DrawMiniElement(sx,sy,EL_LEERRAUM);
1205 else if (x==-1 || x==lev_fieldx || y==-1 || y==lev_fieldy)
1206 DrawMiniElement(sx,sy,EL_BETON);
1208 DrawMiniElement(sx,sy,Feld[x][y]);
1211 void DrawMicroElement(int xpos, int ypos, int element)
1215 if (element==EL_LEERRAUM)
1218 graphic = el2gfx(element);
1220 XCopyArea(display,pix[PIX_BACK],drawto,gc,
1221 MICRO_GFX_STARTX+(graphic % MICRO_GFX_PER_LINE)*MICRO_TILEX,
1222 MICRO_GFX_STARTY+(graphic / MICRO_GFX_PER_LINE)*MICRO_TILEY,
1223 MICRO_TILEX,MICRO_TILEY, xpos,ypos);
1232 for(x=BX1; x<=BX2; x++)
1233 for(y=BY1; y<=BY2; y++)
1234 DrawScreenField(x,y);
1236 if (soft_scrolling_on)
1237 XCopyArea(display,fieldbuffer,backbuffer,gc,
1238 FX,FY, SXSIZE,SYSIZE,
1241 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1244 void DrawMiniLevel(int scroll_x, int scroll_y)
1250 for(x=0;x<2*SCR_FIELDX;x++)
1251 for(y=0;y<2*SCR_FIELDY;y++)
1252 DrawMiniElementOrWall(x,y,scroll_x,scroll_y);
1254 redraw_mask |= REDRAW_FIELD;
1257 void DrawMicroLevel(int xpos, int ypos)
1261 XFillRectangle(display,drawto,gc,
1262 xpos-MICRO_TILEX,ypos-MICRO_TILEY,
1263 MICRO_TILEX*(STD_LEV_FIELDX+2),
1264 MICRO_TILEY*(STD_LEV_FIELDY+2));
1265 if (lev_fieldx < STD_LEV_FIELDX)
1266 xpos += (STD_LEV_FIELDX - lev_fieldx)/2 * MICRO_TILEX;
1267 if (lev_fieldy < STD_LEV_FIELDY)
1268 ypos += (STD_LEV_FIELDY - lev_fieldy)/2 * MICRO_TILEY;
1270 for(x=-1;x<=STD_LEV_FIELDX;x++)
1271 for(y=-1;y<=STD_LEV_FIELDY;y++)
1272 if (x>=0 && x<lev_fieldx && y>=0 && y<lev_fieldy)
1273 DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
1274 Feld[x][y]=Ur[x][y]);
1275 else if (x>=-1 && x<lev_fieldx+1 && y>=-1 && y<lev_fieldy+1)
1276 DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
1279 XFillRectangle(display,drawto,gc, SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE);
1283 int len = strlen(level.name);
1284 int lxpos = SX+(SXSIZE-len*FONT4_XSIZE)/2;
1285 int lypos = MICROLABEL_YPOS;
1287 DrawText(lxpos,lypos,level.name,FS_SMALL,FC_SPECIAL2);
1290 redraw_mask |= REDRAW_MICROLEV;
1293 int REQ_in_range(int x, int y)
1295 if (y>DY+249 && y<DY+278)
1297 if (x>DX+1 && x<DX+48)
1299 else if (x>DX+51 && x<DX+98)
1305 BOOL Request(char *text, unsigned int req_state)
1307 int mx,my, ty, result = -1;
1308 unsigned int old_door_state;
1310 old_door_state = GetDoorState();
1312 CloseDoor(DOOR_CLOSE_1);
1314 /* Alten Türinhalt sichern */
1315 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1316 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1317 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1);
1319 /* Fragetext schreiben */
1320 XFillRectangle(display,pix[PIX_DB_DOOR],gc,
1321 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1,DXSIZE,DYSIZE);
1323 for(ty=0;ty<13;ty++)
1330 for(tl=0,tx=0;tx<7;tl++,tx++)
1344 DrawTextExt(pix[PIX_DB_DOOR],gc,
1345 DOOR_GFX_PAGEX1+51-(tl*14)/2,SY+ty*16,txt,FS_SMALL,FC_YELLOW);
1346 text+=(tl+(tc==32));
1349 if (req_state & REQ_ASK)
1350 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1351 DOOR_GFX_PAGEX4,OK_BUTTON_GFX_YPOS,
1352 DXSIZE,OK_BUTTON_YSIZE,
1353 DOOR_GFX_PAGEX1,OK_BUTTON_YPOS);
1354 else if (req_state & REQ_CONFIRM)
1355 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1356 DOOR_GFX_PAGEX4,CONFIRM_BUTTON_GFX_YPOS,
1357 DXSIZE,CONFIRM_BUTTON_YSIZE,
1358 DOOR_GFX_PAGEX1,CONFIRM_BUTTON_YPOS);
1359 else if (req_state & REQ_PLAYER)
1361 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1362 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1363 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1364 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1367 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1368 DOOR_GFX_PAGEX4 + PLAYER_BUTTON_GFX_XPOS, PLAYER_BUTTON_GFX_YPOS,
1369 PLAYER_BUTTON_XSIZE,PLAYER_BUTTON_YSIZE,
1370 DOOR_GFX_PAGEX1 + PLAYER_BUTTON_1_XPOS, PLAYER_BUTTON_1_YPOS);
1371 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1372 DOOR_GFX_PAGEX4 + PLAYER_BUTTON_GFX_XPOS, PLAYER_BUTTON_GFX_YPOS,
1373 PLAYER_BUTTON_XSIZE,PLAYER_BUTTON_YSIZE,
1374 DOOR_GFX_PAGEX1 + PLAYER_BUTTON_1_XPOS, PLAYER_BUTTON_1_YPOS);
1375 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1376 DOOR_GFX_PAGEX4 + PLAYER_BUTTON_GFX_XPOS, PLAYER_BUTTON_GFX_YPOS,
1377 PLAYER_BUTTON_XSIZE,PLAYER_BUTTON_YSIZE,
1378 DOOR_GFX_PAGEX1 + PLAYER_BUTTON_2_XPOS, PLAYER_BUTTON_2_YPOS);
1379 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1380 DOOR_GFX_PAGEX4 + PLAYER_BUTTON_GFX_XPOS, PLAYER_BUTTON_GFX_YPOS,
1381 PLAYER_BUTTON_XSIZE,PLAYER_BUTTON_YSIZE,
1382 DOOR_GFX_PAGEX1 + PLAYER_BUTTON_3_XPOS, PLAYER_BUTTON_3_YPOS);
1383 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1384 DOOR_GFX_PAGEX4 + PLAYER_BUTTON_GFX_XPOS, PLAYER_BUTTON_GFX_YPOS,
1385 PLAYER_BUTTON_XSIZE,PLAYER_BUTTON_YSIZE,
1386 DOOR_GFX_PAGEX1 + PLAYER_BUTTON_4_XPOS, PLAYER_BUTTON_4_YPOS);
1390 OpenDoor(DOOR_OPEN_1);
1393 if (!(req_state & REQ_ASK) &&
1394 !(req_state & REQ_CONFIRM) &&
1395 !(req_state & REQ_PLAYER))
1398 if (game_status != MAINMENU)
1401 button_status = MB_RELEASED;
1408 if (XPending(display))
1412 XNextEvent(display, &event);
1416 HandleExposeEvent((XExposeEvent *) &event);
1419 SleepWhileUnmapped();
1427 if (event.type == MotionNotify)
1429 motion_status = TRUE;
1430 mx = ((XMotionEvent *) &event)->x;
1431 my = ((XMotionEvent *) &event)->y;
1435 motion_status = FALSE;
1436 mx = ((XButtonEvent *) &event)->x;
1437 my = ((XButtonEvent *) &event)->y;
1438 if (event.type==ButtonPress)
1439 button_status = ((XButtonEvent *) &event)->button;
1441 button_status = MB_RELEASED;
1444 if (req_state & REQ_ASK)
1445 choice = CheckYesNoButtons(mx,my,button_status);
1446 else if (req_state & REQ_CONFIRM)
1447 choice = CheckConfirmButton(mx,my,button_status);
1449 choice = CheckPlayerButtons(mx,my,button_status);
1459 case BUTTON_CONFIRM:
1460 result = TRUE | FALSE;
1462 case BUTTON_PLAYER_1:
1465 case BUTTON_PLAYER_2:
1468 case BUTTON_PLAYER_3:
1471 case BUTTON_PLAYER_4:
1480 switch(XLookupKeysym((XKeyEvent *)&event,
1481 ((XKeyEvent *)&event)->state))
1490 if (req_state & REQ_PLAYER)
1494 key_joystick_mapping = 0;
1498 HandleFocusEvent((XFocusChangeEvent *) &event);
1501 HandleClientMessageEvent((XClientMessageEvent *) &event);
1507 else if (JoystickButton() == JOY_BUTTON_NEW_PRESSED)
1511 if (joy & JOY_BUTTON_1)
1513 else if (joy & JOY_BUTTON_2)
1518 if (game_status != MAINMENU)
1521 if (!(req_state & REQ_STAY_OPEN))
1523 CloseDoor(DOOR_CLOSE_1);
1525 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1527 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1528 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1529 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1530 OpenDoor(DOOR_OPEN_1);
1537 unsigned int OpenDoor(unsigned int door_state)
1539 unsigned int new_door_state;
1541 if (door_state & DOOR_COPY_BACK)
1543 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1544 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE+VYSIZE,
1545 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1546 door_state &= ~DOOR_COPY_BACK;
1549 new_door_state = MoveDoor(door_state);
1551 return(new_door_state);
1554 unsigned int CloseDoor(unsigned int door_state)
1556 unsigned int new_door_state;
1558 XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1559 DX,DY, DXSIZE,DYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1560 XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1561 VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1563 new_door_state = MoveDoor(door_state);
1565 return(new_door_state);
1568 unsigned int GetDoorState()
1570 return(MoveDoor(DOOR_GET_STATE));
1573 unsigned int MoveDoor(unsigned int door_state)
1575 static unsigned int door1 = DOOR_OPEN_1;
1576 static unsigned int door2 = DOOR_CLOSE_2;
1577 static long door_delay = 0;
1578 int x, start, stepsize = 2;
1579 long door_delay_value = stepsize * 5;
1581 if (door_state == DOOR_GET_STATE)
1582 return(door1 | door2);
1584 if (door1==DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1585 door_state &= ~DOOR_OPEN_1;
1586 else if (door1==DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1587 door_state &= ~DOOR_CLOSE_1;
1588 if (door2==DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1589 door_state &= ~DOOR_OPEN_2;
1590 else if (door2==DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1591 door_state &= ~DOOR_CLOSE_2;
1596 door_delay_value = 0;
1597 StopSound(SND_OEFFNEN);
1600 if (door_state & DOOR_ACTION)
1602 if (!(door_state & DOOR_NO_DELAY))
1603 PlaySoundStereo(SND_OEFFNEN,PSND_MAX_RIGHT);
1605 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1607 for(x=start; x<=DXSIZE; x+=stepsize)
1609 WaitUntilDelayReached(&door_delay, door_delay_value);
1611 if (door_state & DOOR_ACTION_1)
1613 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1614 int j = (DXSIZE - i)/3;
1616 XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1617 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1+i/2,
1618 DXSIZE,DYSIZE-i/2, DX,DY);
1620 XFillRectangle(display,drawto,gc,DX,DY+DYSIZE-i/2,DXSIZE,i/2);
1622 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1623 DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1624 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1625 DXSIZE,DOOR_GFX_PAGEY1, i,77, DX+DXSIZE-i,DY+j);
1626 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1627 DXSIZE,DOOR_GFX_PAGEY1+140, i,63, DX+DXSIZE-i,DY+140+j);
1628 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1629 DX-DXSIZE+i,DY-(DOOR_GFX_PAGEY1+j));
1630 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1631 DXSIZE-i,DOOR_GFX_PAGEY1+j, i,77-j, DX,DY);
1632 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1633 DXSIZE-i,DOOR_GFX_PAGEY1+140, i,63, DX,DY+140-j);
1635 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1636 DXSIZE-i,DOOR_GFX_PAGEY1+77, i,63,
1638 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1639 DXSIZE-i,DOOR_GFX_PAGEY1+203, i,77,
1641 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1642 DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1643 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1644 DXSIZE,DOOR_GFX_PAGEY1+77, i,63,
1645 DX+DXSIZE-i,DY+77+j);
1646 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1647 DXSIZE,DOOR_GFX_PAGEY1+203, i,77-j,
1648 DX+DXSIZE-i,DY+203+j);
1650 redraw_mask |= REDRAW_DOOR_1;
1653 if (door_state & DOOR_ACTION_2)
1655 int i = (door_state & DOOR_OPEN_2 ? VXSIZE-x : x);
1656 int j = (VXSIZE - i)/3;
1658 XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1659 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2+i/2,
1660 VXSIZE,VYSIZE-i/2, VX,VY);
1662 XFillRectangle(display,drawto,gc,VX,VY+VYSIZE-i/2,VXSIZE,i/2);
1664 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1665 VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1666 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1667 VXSIZE,DOOR_GFX_PAGEY2, i,VYSIZE/2, VX+VXSIZE-i,VY+j);
1668 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1669 VX-VXSIZE+i,VY-(DOOR_GFX_PAGEY2+j));
1670 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1671 VXSIZE-i,DOOR_GFX_PAGEY2+j, i,VYSIZE/2-j, VX,VY);
1673 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1674 VXSIZE-i,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2,
1676 XSetClipOrigin(display,clip_gc[PIX_DOOR],
1677 VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1678 XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1679 VXSIZE,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2-j,
1680 VX+VXSIZE-i,VY+VYSIZE/2+j);
1682 redraw_mask |= REDRAW_DOOR_2;
1687 if (game_status == MAINMENU)
1692 if (door_state & DOOR_ACTION_1)
1693 door1 = door_state & DOOR_ACTION_1;
1694 if (door_state & DOOR_ACTION_2)
1695 door2 = door_state & DOOR_ACTION_2;
1697 return(door1 | door2);
1700 int ReadPixel(Drawable d, int x, int y)
1702 static XImage *pixelimage;
1704 pixelimage = XGetImage(display, d, x,y, 1,1, AllPlanes, ZPixmap);
1705 return(XGetPixel(pixelimage,0,0));
1708 int el2gfx(int element)
1712 case EL_LEERRAUM: return(-1);
1713 case EL_ERDREICH: return(GFX_ERDREICH);
1714 case EL_MAUERWERK: return(GFX_MAUERWERK);
1715 case EL_FELSBODEN: return(GFX_FELSBODEN);
1716 case EL_FELSBROCKEN: return(GFX_FELSBROCKEN);
1717 case EL_SCHLUESSEL: return(GFX_SCHLUESSEL);
1718 case EL_EDELSTEIN: return(GFX_EDELSTEIN);
1719 case EL_AUSGANG_ZU: return(GFX_AUSGANG_ZU);
1720 case EL_AUSGANG_ACT: return(GFX_AUSGANG_ACT);
1721 case EL_AUSGANG_AUF: return(GFX_AUSGANG_AUF);
1722 case EL_SPIELFIGUR: return(GFX_SPIELFIGUR);
1723 case EL_SPIELER1: return(GFX_SPIELER1);
1724 case EL_SPIELER2: return(GFX_SPIELER2);
1725 case EL_SPIELER3: return(GFX_SPIELER3);
1726 case EL_SPIELER4: return(GFX_SPIELER4);
1727 case EL_KAEFER: return(GFX_KAEFER);
1728 case EL_KAEFER_R: return(GFX_KAEFER_R);
1729 case EL_KAEFER_O: return(GFX_KAEFER_O);
1730 case EL_KAEFER_L: return(GFX_KAEFER_L);
1731 case EL_KAEFER_U: return(GFX_KAEFER_U);
1732 case EL_FLIEGER: return(GFX_FLIEGER);
1733 case EL_FLIEGER_R: return(GFX_FLIEGER_R);
1734 case EL_FLIEGER_O: return(GFX_FLIEGER_O);
1735 case EL_FLIEGER_L: return(GFX_FLIEGER_L);
1736 case EL_FLIEGER_U: return(GFX_FLIEGER_U);
1737 case EL_BUTTERFLY: return(GFX_BUTTERFLY);
1738 case EL_BUTTERFLY_R: return(GFX_BUTTERFLY_R);
1739 case EL_BUTTERFLY_O: return(GFX_BUTTERFLY_O);
1740 case EL_BUTTERFLY_L: return(GFX_BUTTERFLY_L);
1741 case EL_BUTTERFLY_U: return(GFX_BUTTERFLY_U);
1742 case EL_FIREFLY: return(GFX_FIREFLY);
1743 case EL_FIREFLY_R: return(GFX_FIREFLY_R);
1744 case EL_FIREFLY_O: return(GFX_FIREFLY_O);
1745 case EL_FIREFLY_L: return(GFX_FIREFLY_L);
1746 case EL_FIREFLY_U: return(GFX_FIREFLY_U);
1747 case EL_MAMPFER: return(GFX_MAMPFER);
1748 case EL_ROBOT: return(GFX_ROBOT);
1749 case EL_BETON: return(GFX_BETON);
1750 case EL_DIAMANT: return(GFX_DIAMANT);
1751 case EL_MORAST_LEER: return(GFX_MORAST_LEER);
1752 case EL_MORAST_VOLL: return(GFX_MORAST_VOLL);
1753 case EL_TROPFEN: return(GFX_TROPFEN);
1754 case EL_BOMBE: return(GFX_BOMBE);
1755 case EL_SIEB_LEER: return(GFX_SIEB_LEER);
1756 case EL_SIEB_VOLL: return(GFX_SIEB_VOLL);
1757 case EL_SIEB_TOT: return(GFX_SIEB_TOT);
1758 case EL_SALZSAEURE: return(GFX_SALZSAEURE);
1759 case EL_AMOEBE_TOT: return(GFX_AMOEBE_TOT);
1760 case EL_AMOEBE_NASS: return(GFX_AMOEBE_NASS);
1761 case EL_AMOEBE_NORM: return(GFX_AMOEBE_NORM);
1762 case EL_AMOEBE_VOLL: return(GFX_AMOEBE_VOLL);
1763 case EL_AMOEBE_BD: return(GFX_AMOEBE_BD);
1764 case EL_AMOEBA2DIAM: return(GFX_AMOEBA2DIAM);
1765 case EL_KOKOSNUSS: return(GFX_KOKOSNUSS);
1766 case EL_LIFE: return(GFX_LIFE);
1767 case EL_LIFE_ASYNC: return(GFX_LIFE_ASYNC);
1768 case EL_DYNAMIT: return(GFX_DYNAMIT);
1769 case EL_BADEWANNE: return(GFX_BADEWANNE);
1770 case EL_BADEWANNE1: return(GFX_BADEWANNE1);
1771 case EL_BADEWANNE2: return(GFX_BADEWANNE2);
1772 case EL_BADEWANNE3: return(GFX_BADEWANNE3);
1773 case EL_BADEWANNE4: return(GFX_BADEWANNE4);
1774 case EL_BADEWANNE5: return(GFX_BADEWANNE5);
1775 case EL_ABLENK_AUS: return(GFX_ABLENK_AUS);
1776 case EL_ABLENK_EIN: return(GFX_ABLENK_EIN);
1777 case EL_SCHLUESSEL1: return(GFX_SCHLUESSEL1);
1778 case EL_SCHLUESSEL2: return(GFX_SCHLUESSEL2);
1779 case EL_SCHLUESSEL3: return(GFX_SCHLUESSEL3);
1780 case EL_SCHLUESSEL4: return(GFX_SCHLUESSEL4);
1781 case EL_PFORTE1: return(GFX_PFORTE1);
1782 case EL_PFORTE2: return(GFX_PFORTE2);
1783 case EL_PFORTE3: return(GFX_PFORTE3);
1784 case EL_PFORTE4: return(GFX_PFORTE4);
1785 case EL_PFORTE1X: return(GFX_PFORTE1X);
1786 case EL_PFORTE2X: return(GFX_PFORTE2X);
1787 case EL_PFORTE3X: return(GFX_PFORTE3X);
1788 case EL_PFORTE4X: return(GFX_PFORTE4X);
1789 case EL_DYNAMIT_AUS: return(GFX_DYNAMIT_AUS);
1790 case EL_PACMAN: return(GFX_PACMAN);
1791 case EL_PACMAN_R: return(GFX_PACMAN_R);
1792 case EL_PACMAN_O: return(GFX_PACMAN_O);
1793 case EL_PACMAN_L: return(GFX_PACMAN_L);
1794 case EL_PACMAN_U: return(GFX_PACMAN_U);
1795 case EL_UNSICHTBAR: return(GFX_UNSICHTBAR);
1796 case EL_ERZ_EDEL: return(GFX_ERZ_EDEL);
1797 case EL_ERZ_DIAM: return(GFX_ERZ_DIAM);
1798 case EL_BIRNE_AUS: return(GFX_BIRNE_AUS);
1799 case EL_BIRNE_EIN: return(GFX_BIRNE_EIN);
1800 case EL_ZEIT_VOLL: return(GFX_ZEIT_VOLL);
1801 case EL_ZEIT_LEER: return(GFX_ZEIT_LEER);
1802 case EL_MAUER_LEBT: return(GFX_MAUER_LEBT);
1803 case EL_MAUER_X: return(GFX_MAUER_X);
1804 case EL_MAUER_Y: return(GFX_MAUER_Y);
1805 case EL_MAUER_XY: return(GFX_MAUER_XY);
1806 case EL_EDELSTEIN_BD: return(GFX_EDELSTEIN_BD);
1807 case EL_EDELSTEIN_GELB: return(GFX_EDELSTEIN_GELB);
1808 case EL_EDELSTEIN_ROT: return(GFX_EDELSTEIN_ROT);
1809 case EL_EDELSTEIN_LILA: return(GFX_EDELSTEIN_LILA);
1810 case EL_ERZ_EDEL_BD: return(GFX_ERZ_EDEL_BD);
1811 case EL_ERZ_EDEL_GELB: return(GFX_ERZ_EDEL_GELB);
1812 case EL_ERZ_EDEL_ROT: return(GFX_ERZ_EDEL_ROT);
1813 case EL_ERZ_EDEL_LILA: return(GFX_ERZ_EDEL_LILA);
1814 case EL_MAMPFER2: return(GFX_MAMPFER2);
1815 case EL_SIEB2_LEER: return(GFX_SIEB2_LEER);
1816 case EL_SIEB2_VOLL: return(GFX_SIEB2_VOLL);
1817 case EL_SIEB2_TOT: return(GFX_SIEB2_TOT);
1818 case EL_DYNABOMB: return(GFX_DYNABOMB);
1819 case EL_DYNABOMB_NR: return(GFX_DYNABOMB_NR);
1820 case EL_DYNABOMB_SZ: return(GFX_DYNABOMB_SZ);
1821 case EL_DYNABOMB_XL: return(GFX_DYNABOMB_XL);
1822 case EL_SOKOBAN_OBJEKT: return(GFX_SOKOBAN_OBJEKT);
1823 case EL_SOKOBAN_FELD_LEER: return(GFX_SOKOBAN_FELD_LEER);
1824 case EL_SOKOBAN_FELD_VOLL: return(GFX_SOKOBAN_FELD_VOLL);
1825 case EL_MAULWURF: return(GFX_MAULWURF);
1826 case EL_PINGUIN: return(GFX_PINGUIN);
1827 case EL_SCHWEIN: return(GFX_SCHWEIN);
1828 case EL_DRACHE: return(GFX_DRACHE);
1829 case EL_SONDE: return(GFX_SONDE);
1830 case EL_PFEIL_L: return(GFX_PFEIL_L);
1831 case EL_PFEIL_R: return(GFX_PFEIL_R);
1832 case EL_PFEIL_O: return(GFX_PFEIL_O);
1833 case EL_PFEIL_U: return(GFX_PFEIL_U);
1836 if (IS_CHAR(element))
1837 return(GFX_CHAR_START + (element-EL_CHAR_START));