From: Holger Schemel Date: Sun, 21 Sep 1997 21:59:59 +0000 (+0200) Subject: rnd-19970921-src X-Git-Tag: 1.2.0^2~100 X-Git-Url: https://git.artsoft.org/?a=commitdiff_plain;h=b7d31643c9c84104fb3ebef778e545928610ff65;p=rocksndiamonds.git rnd-19970921-src --- diff --git a/REGISTRATION b/REGISTRATION deleted file mode 120000 index 5f4a260c..00000000 --- a/REGISTRATION +++ /dev/null @@ -1 +0,0 @@ -THIS_IS_NOW_FREEWARE \ No newline at end of file diff --git a/src/Makefile b/src/Makefile index 273cecdd..22682e11 100644 --- a/src/Makefile +++ b/src/Makefile @@ -15,8 +15,12 @@ GAME_DIR = -DGAME_DIR=\".\" # path of the game and its data # SCORE_ENTRIES = -DONE_PER_NAME # only one score entry per name SCORE_ENTRIES = -DMANY_PER_NAME # many score entries per name -# the XPM-Library is needed to build this program: -XPM_INCLUDE_FILE = -DXPM_INCLUDE_FILE="" +# The XPM-Library is no longer needed to build this program, +# but is used to load graphics if XPM_INCLUDE_FILE is defined, +# because the GIF loading routines are still a bit beta. +# If you use the Xpm library, convert the GIF files to Xpm +# files (and the mask files ('*Maske.gif') to xbm files). +# XPM_INCLUDE_FILE = -DXPM_INCLUDE_FILE="" CONFIG = $(GAME_DIR) $(SOUNDS) $(JOYSTICK) \ $(SCORE_ENTRIES) $(XPM_INCLUDE_FILE) @@ -27,10 +31,15 @@ DEBUG = -DDEBUG -g -Wall # SYSTEM = -Aa -D_HPUX_SOURCE -Dhpux # for HP-UX (obsolete) # SYSTEM = -DSYSV -Ae # for HP-UX -# SYSTEM = -DSYSV # for systems without 'usleep()' # INCL = -I/usr/include/X11R5 # for HP-UX and others -# LIBS = -L/usr/lib/X11R5 -lXpm -lX11 -lm # for HP-UX and others -LIBS = -L/usr/X11R6/lib -lXpm -lX11 -lm +# INCL = -I/usr/local/X11/include # for SunOS and others +# LIBS = -L/usr/lib/X11R5 -lXpm -lX11 -lm +# # for HP-UX and others +# LIBS = -L/usr/local/X11/lib -lXpm -lX11 -lm -lsocket -R/usr/local/X11/lib +# # for SunOS and others + +# LIBS = -L/usr/X11R6/lib -lXpm -lX11 -lm +LIBS = -L/usr/X11R6/lib -lX11 -lm # CFLAGS = -O2 $(CONFIG) $(SYSTEM) CFLAGS = $(DEBUG) $(CONFIG) $(SYSTEM) $(INCL) @@ -46,7 +55,11 @@ SRCS = main.c \ buttons.c \ files.c \ tape.c \ - sound.c + sound.c \ + joystick.c \ + cartoons.c \ + gfxloader.c \ + random.c OBJS = main.o \ init.o \ @@ -59,7 +72,11 @@ OBJS = main.o \ buttons.o \ files.o \ tape.o \ - sound.o + sound.o \ + joystick.o \ + cartoons.o \ + gfxloader.o \ + random.o all: $(OBJS) $(CC) $(CFLAGS) $(OBJS) $(LIBS) -o $(PROGNAME) @@ -69,3 +86,14 @@ all: $(OBJS) clean: $(RM) $(OBJS) + +backup: + @echo "tar cvzf /usr/AEGLOS/BACKUP/rnd-`date +%Y%m%d | cut -b 3-8`.tgz *.c *.h Makefile" + @tar cvzf /usr/AEGLOS/BACKUP/rnd-`date +%Y%m%d | cut -b 3-8`.tgz *.c *.h Makefile + +depend: + for i in $(SRCS); do $(CPP) $(CFLAGS) -M $$i; done > .depend + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/src/cartoons.c b/src/cartoons.c new file mode 100644 index 00000000..a295844f --- /dev/null +++ b/src/cartoons.c @@ -0,0 +1,552 @@ +/*********************************************************** +* Rocks'n'Diamonds -- McDuffin Strikes Back! * +*----------------------------------------------------------* +* ©1995 Artsoft Development * +* Holger Schemel * +* 33659 Bielefeld-Senne * +* Telefon: (0521) 493245 * +* eMail: aeglos@valinor.owl.de * +* aeglos@uni-paderborn.de * +* q99492@pbhrzx.uni-paderborn.de * +*----------------------------------------------------------* +* cartoons.c * +***********************************************************/ + +#include "cartoons.h" +#include "main.h" +#include "misc.h" +#include "tools.h" + +static void HandleAnimation(int); +static BOOL AnimateToon(int, BOOL); +static void DrawAnim(Pixmap, GC, int, int, int, int, int, int, int, int); + +struct AnimInfo +{ + int width, height; + int src_x, src_y; + int frames; + int frames_per_second; + int stepsize; + BOOL pingpong; + int direction; + int position; +}; + +/* values for cartoon figures */ +#define NUM_TOONS 18 + +#define DWARF_XSIZE 40 +#define DWARF_YSIZE 48 +#define DWARF_X 2 +#define DWARF_Y 72 +#define DWARF2_Y 186 +#define DWARF_FRAMES 8 +#define DWARF_FPS 10 +#define DWARF_STEPSIZE 4 +#define JUMPER_XSIZE 48 +#define JUMPER_YSIZE 56 +#define JUMPER_X 2 +#define JUMPER_Y 125 +#define JUMPER_FRAMES 8 +#define JUMPER_FPS 10 +#define JUMPER_STEPSIZE 4 +#define CLOWN_XSIZE 80 +#define CLOWN_YSIZE 110 +#define CLOWN_X 327 +#define CLOWN_Y 10 +#define CLOWN_FRAMES 1 +#define CLOWN_FPS 10 +#define CLOWN_STEPSIZE 4 +#define BIRD_XSIZE 32 +#define BIRD_YSIZE 30 +#define BIRD1_X 2 +#define BIRD1_Y 2 +#define BIRD2_X 2 +#define BIRD2_Y 37 +#define BIRD_FRAMES 8 +#define BIRD_FPS 20 +#define BIRD_STEPSIZE 4 + +#define GAMETOON_XSIZE TILEX +#define GAMETOON_YSIZE TILEY +#define GAMETOON_FRAMES_4 4 +#define GAMETOON_FRAMES_8 8 +#define GAMETOON_FPS 20 +#define GAMETOON_STEPSIZE 4 + +#define ANIMDIR_LEFT 1 +#define ANIMDIR_RIGHT 2 +#define ANIMDIR_UP 4 +#define ANIMDIR_DOWN 8 + +#define ANIMPOS_ANY 0 +#define ANIMPOS_LEFT 1 +#define ANIMPOS_RIGHT 2 +#define ANIMPOS_UP 4 +#define ANIMPOS_DOWN 8 +#define ANIMPOS_UPPER 16 + +#define ANIM_START 0 +#define ANIM_CONTINUE 1 +#define ANIM_STOP 2 + +void InitAnimation() +{ + HandleAnimation(ANIM_START); +} + +void StopAnimation() +{ + HandleAnimation(ANIM_STOP); +} + +void DoAnimation() +{ + HandleAnimation(ANIM_CONTINUE); +} + +void HandleAnimation(int mode) +{ + static long animstart_delay = -1; + static long animstart_delay_value = 0; + static BOOL anim_restart = TRUE; + static BOOL reset_delay = TRUE; + static int toon_nr = 0; + int draw_mode; + + if (!toons_on) + return; + + switch(mode) + { + case ANIM_START: + anim_restart = TRUE; + reset_delay = TRUE; + + /* Fill empty backbuffer for animation functions */ + if (direct_draw_on && game_status==PLAYING) + { + int xx,yy; + + drawto_field = backbuffer; + + for(xx=0;xxdirection & (ANIMDIR_LEFT | ANIMDIR_RIGHT)); + vert_move = (anim->direction & (ANIMDIR_UP | ANIMDIR_DOWN)); + anim_delay_value = 100/anim->frames_per_second; + frame = 0; + + if (horiz_move) + { + if (anim->position==ANIMPOS_UP) + pos_y = 0; + else if (anim->position==ANIMPOS_DOWN) + pos_y = FULL_SYSIZE-anim->height; + else if (anim->position==ANIMPOS_UPPER) + pos_y = SimpleRND((FULL_SYSIZE-anim->height)/2); + else + pos_y = SimpleRND(FULL_SYSIZE-anim->height); + + if (anim->direction==ANIMDIR_RIGHT) + { + delta_x = anim->stepsize; + pos_x = -anim->width+delta_x; + } + else + { + delta_x = -anim->stepsize; + pos_x = FULL_SXSIZE+delta_x; + } + delta_y = 0; + } + else + { + if (anim->position==ANIMPOS_LEFT) + pos_x = 0; + else if (anim->position==ANIMPOS_RIGHT) + pos_x = FULL_SXSIZE-anim->width; + else + pos_x = SimpleRND(FULL_SXSIZE-anim->width); + + if (anim->direction==ANIMDIR_DOWN) + { + delta_y = anim->stepsize; + pos_y = -anim->height+delta_y; + } + else + { + delta_y = -anim->stepsize; + pos_y = FULL_SYSIZE+delta_y; + } + delta_x = 0; + } + } + + if (pos_x <= -anim->width - anim->stepsize || + pos_x >= FULL_SXSIZE + anim->stepsize || + pos_y <= -anim->height - anim->stepsize || + pos_y >= FULL_SYSIZE + anim->stepsize) + return(TRUE); + + if (!DelayReached(&anim_delay,anim_delay_value)) + { + if (game_status==HELPSCREEN && !restart) + DrawAnim(anim_pixmap,anim_clip_gc, + src_x+cut_x,src_y+cut_y, width,height, + REAL_SX+dest_x,REAL_SY+dest_y, pad_x,pad_y); + + return(FALSE); + } + + if (pos_x<-anim->width) + pos_x = -anim->width; + else if (pos_x>FULL_SXSIZE) + pos_x = FULL_SXSIZE; + if (pos_y<-anim->height) + pos_y = -anim->height; + else if (pos_y>FULL_SYSIZE) + pos_y = FULL_SYSIZE; + + pad_x = (horiz_move ? anim->stepsize : 0); + pad_y = (vert_move ? anim->stepsize : 0); + src_x = anim->src_x + frame * anim->width; + src_y = anim->src_y; + dest_x = pos_x; + dest_y = pos_y; + cut_x = cut_y = 0; + width = anim->width; + height = anim->height; + + if (pos_x<0) + { + dest_x = 0; + width += pos_x; + cut_x = -pos_x; + } + else if (pos_x>FULL_SXSIZE-anim->width) + width -= (pos_x - (FULL_SXSIZE-anim->width)); + + if (pos_y<0) + { + dest_y = 0; + height += pos_y; + cut_y = -pos_y; + } + else if (pos_y>FULL_SYSIZE-anim->height) + height -= (pos_y - (FULL_SYSIZE-anim->height)); + + DrawAnim(anim_pixmap,anim_clip_gc, + src_x+cut_x,src_y+cut_y, width,height, + REAL_SX+dest_x,REAL_SY+dest_y, pad_x,pad_y); + + pos_x += delta_x; + pos_y += delta_y; + frame += frame_step; + + if (frame<0 || frame>=anim->frames) + { + if (anim->pingpong) + { + frame_step *= -1; + frame = (frame<0 ? 1 : anim->frames-2); + } + else + frame = (frame<0 ? anim->frames-1 : 0); + } + + return(FALSE); +} + +void DrawAnim(Pixmap toon_pixmap, GC toon_clip_gc, + int src_x, int src_y, int width, int height, + int dest_x, int dest_y, int pad_x, int pad_y) +{ + int buf_x = DOOR_GFX_PAGEX3, buf_y = DOOR_GFX_PAGEY1; + +#if 1 + /* special method to avoid flickering interference with BackToFront() */ + XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,dest_x-pad_x,dest_y-pad_y, + width+2*pad_x,height+2*pad_y, buf_x,buf_y); + XSetClipOrigin(display,toon_clip_gc,dest_x-src_x,dest_y-src_y); + XCopyArea(display,toon_pixmap,backbuffer,toon_clip_gc, + src_x,src_y, width,height, dest_x,dest_y); + XCopyArea(display,backbuffer,window,gc, dest_x-pad_x,dest_y-pad_y, + width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y); + BackToFront(); + XCopyArea(display,pix[PIX_DB_DOOR],backbuffer,gc, buf_x,buf_y, + width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y); +#else + /* normal method, causing flickering interference with BackToFront() */ + XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,dest_x-pad_x,dest_y-pad_y, + width+2*pad_x,height+2*pad_y, buf_x,buf_y); + XSetClipOrigin(display,toon_clip_gc, + buf_x-src_x+pad_x,buf_y-src_y+pad_y); + XCopyArea(display,toon_pixmap,pix[PIX_DB_DOOR],toon_clip_gc, + src_x,src_y, width,height, buf_x+pad_x,buf_y+pad_y); + XCopyArea(display,pix[PIX_DB_DOOR],window,gc, buf_x,buf_y, + width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y); +#endif + + XFlush(display); +} diff --git a/src/cartoons.h b/src/cartoons.h new file mode 100644 index 00000000..25b4d2c4 --- /dev/null +++ b/src/cartoons.h @@ -0,0 +1,22 @@ +/*********************************************************** +* Rocks'n'Diamonds -- McDuffin Strikes Back! * +*----------------------------------------------------------* +* ©1995 Artsoft Development * +* Holger Schemel * +* 33659 Bielefeld-Senne * +* Telefon: (0521) 493245 * +* eMail: aeglos@valinor.owl.de * +* aeglos@uni-paderborn.de * +* q99492@pbhrzx.uni-paderborn.de * +*----------------------------------------------------------* +* cartoons.h * +***********************************************************/ + +#ifndef CARTOONS_H +#define CARTOONS_H + +void InitAnimation(void); +void StopAnimation(void); +void DoAnimation(void); + +#endif diff --git a/src/editor.c b/src/editor.c index 871eafa8..b5567dfd 100644 --- a/src/editor.c +++ b/src/editor.c @@ -112,7 +112,7 @@ int editor_element[] = EL_MAMPFER, EL_KAEFER_O, EL_FLIEGER_O, - EL_ZOMBIE, + EL_ROBOT, EL_KAEFER_L, EL_FLIEGER_L, @@ -159,6 +159,11 @@ int editor_element[] = EL_CHAR_A + ('R' - 'A'), EL_CHAR_A + ('E' - 'A'), + EL_PFEIL_L, + EL_PFEIL_R, + EL_PFEIL_O, + EL_PFEIL_U, + EL_AMOEBE_VOLL, EL_EDELSTEIN_GELB, EL_EDELSTEIN_ROT, @@ -189,6 +194,16 @@ int editor_element[] = EL_DYNABOMB_XL, EL_BADEWANNE, + EL_MAULWURF, + EL_PINGUIN, + EL_SCHWEIN, + EL_DRACHE, + + EL_SONDE, + EL_LEERRAUM, + EL_LEERRAUM, + EL_LEERRAUM, + EL_CHAR_A + ('S' - 'A'), EL_CHAR_A + ('O' - 'A'), EL_CHAR_A + ('K' - 'A'), @@ -221,6 +236,11 @@ int editor_element[] = EL_CHAR_A + ('R' - 'A'), */ + EL_LEERRAUM, + EL_LEERRAUM, + EL_LEERRAUM, + EL_LEERRAUM, + EL_CHAR_AUSRUF, EL_CHAR_ZOLL, EL_CHAR_DOLLAR, @@ -1188,7 +1208,7 @@ void LevelNameTyping(KeySym key) ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE, "<",FS_SMALL,FC_RED); } - else if (key==XK_Delete && len>0) + else if ((key==XK_Delete || key==XK_BackSpace) && len>0) { level.name[len-1] = 0; len--; diff --git a/src/events.c b/src/events.c index cbf6e1da..63856e59 100644 --- a/src/events.c +++ b/src/events.c @@ -19,6 +19,7 @@ #include "editor.h" #include "misc.h" #include "tape.h" +#include "joystick.h" void EventLoop(void) { @@ -39,8 +40,6 @@ void EventLoop(void) SleepWhileUnmapped(); break; case ButtonPress: - HandleButtonEvent((XButtonEvent *) &event); - break; case ButtonRelease: HandleButtonEvent((XButtonEvent *) &event); break; @@ -48,16 +47,12 @@ void EventLoop(void) HandleMotionEvent((XMotionEvent *) &event); break; case KeyPress: - HandleKeyEvent((XKeyEvent *) &event); - break; case KeyRelease: HandleKeyEvent((XKeyEvent *) &event); break; case FocusIn: - HandleFocusEvent(FOCUS_IN); - break; case FocusOut: - HandleFocusEvent(FOCUS_OUT); + HandleFocusEvent((XFocusChangeEvent *) &event); break; default: break; @@ -99,10 +94,8 @@ void ClearEventQueue() key_joystick_mapping = 0; break; case FocusIn: - HandleFocusEvent(FOCUS_IN); - break; case FocusOut: - HandleFocusEvent(FOCUS_OUT); + HandleFocusEvent((XFocusChangeEvent *) &event); break; default: break; @@ -150,21 +143,25 @@ void HandleExposeEvent(XExposeEvent *event) int x = event->x, y = event->y; int width = event->width, height = event->height; - XCopyArea(display,drawto,window,gc, x,y, width,height, x,y); - if (direct_draw_on && game_status==PLAYING) { int xx,yy; int x1 = (x-SX)/TILEX, y1 = (y-SY)/TILEY; int x2 = (x-SX+width)/TILEX, y2 = (y-SY+height)/TILEY; + drawto_field = backbuffer; + for(xx=0;xx=x1 && xx<=x2 && yy>=y1 && yy<=y2) DrawScreenField(xx,yy); - DrawLevelElement(JX,JY,EL_SPIELFIGUR); + DrawPlayerField(); + + drawto_field = window; } + XCopyArea(display,drawto,window,gc, x,y, width,height, x,y); + XFlush(display); } @@ -196,17 +193,17 @@ void HandleKeyEvent(XKeyEvent *event) HandleKey(key, key_status); } -void HandleFocusEvent(int focus_status) +void HandleFocusEvent(XFocusChangeEvent *event) { static int old_joystick_status = -1; - if (focus_status==FOCUS_OUT) + if (event->type == FocusOut) { XAutoRepeatOn(display); old_joystick_status = joystick_status; joystick_status = JOYSTICK_OFF; } - else + else if (event->type == FocusIn) { if (game_status == PLAYING) XAutoRepeatOff(display); @@ -381,6 +378,14 @@ void HandleKey(KeySym key, int key_status) if (key_status == KEY_RELEASED) return; + if (key==XK_Return && game_status==PLAYING && GameOver) + { + CloseDoor(DOOR_CLOSE_1); + game_status = MAINMENU; + DrawMainMenu(); + return; + } + if (key==XK_Escape && game_status!=MAINMENU) /* quick quit to MAINMENU */ { CloseDoor(DOOR_CLOSE_1 | DOOR_NO_DELAY); @@ -568,6 +573,9 @@ void HandleJoystick() int dx = (left ? -1 : right ? 1 : 0); int dy = (up ? -1 : down ? 1 : 0); + if (game_status==PLAYING && (tape.playing || keyboard)) + newbutton = ((joy & JOY_BUTTON) != 0); + switch(game_status) { case MAINMENU: @@ -577,7 +585,7 @@ void HandleJoystick() static long joystickmove_delay = 0; if (joystick && !button && !DelayReached(&joystickmove_delay,15)) - break; + newbutton = dx = dy = 0; if (game_status==MAINMENU) HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK); @@ -597,16 +605,6 @@ void HandleJoystick() { BOOL moved = FALSE, snapped = FALSE, bombed = FALSE; - if (tape.pausing) - joy = 0; - - if (!joy) - { - DigField(0,0,0,0,DF_NO_PUSH); - SnapField(0,0); - break; - } - if (GameOver && newbutton) { CloseDoor(DOOR_CLOSE_1); @@ -615,23 +613,61 @@ void HandleJoystick() return; } - if (button1) - snapped = SnapField(dx,dy); + if (tape.pausing || PlayerGone) + joy = 0; + + if (joy) + { + if (button1) + snapped = SnapField(dx,dy); + else + { + if (button2) + bombed = PlaceBomb(); + moved = MoveFigure(dx,dy); + } + + if (tape.recording && (moved || snapped || bombed)) + { + if (bombed && !moved) + joy &= JOY_BUTTON; + TapeRecordAction(joy); + } + else if (tape.playing && snapped) + SnapField(0,0); /* stop snapping */ + } else { - if (button2) - bombed = PlaceBomb(); - moved = MoveFigure(dx,dy); + DigField(0,0,0,0,DF_NO_PUSH); + SnapField(0,0); + PlayerFrame = 0; } - if (tape.recording && (moved || snapped || bombed)) + if (tape.playing && !tape.pausing && !joy && tape.counter= tape.pos[tape.counter].delay) + { + PlayerMovDir = next_joy; + PlayerFrame = FrameCounter % 4; + PlayerPushing = TRUE; + } + } + } } - else if (tape.playing && snapped) - SnapField(0,0); /* stop snapping */ + + DrawPlayerField(); break; } diff --git a/src/events.h b/src/events.h index 31948c11..700f8ae2 100644 --- a/src/events.h +++ b/src/events.h @@ -25,7 +25,7 @@ void HandleExposeEvent(XExposeEvent *); void HandleButtonEvent(XButtonEvent *); void HandleMotionEvent(XMotionEvent *); void HandleKeyEvent(XKeyEvent *); -void HandleFocusEvent(int); +void HandleFocusEvent(XFocusChangeEvent *); void HandleNoXEvent(void); void HandleButton(int, int, int); diff --git a/src/files.c b/src/files.c index 1441cd0f..bbd282a3 100644 --- a/src/files.c +++ b/src/files.c @@ -16,6 +16,7 @@ #include "tools.h" #include "misc.h" #include "tape.h" +#include "joystick.h" BOOL CreateNewScoreFile() { diff --git a/src/game.c b/src/game.c index cda9257a..e170331d 100644 --- a/src/game.c +++ b/src/game.c @@ -21,6 +21,7 @@ #include "buttons.h" #include "files.h" #include "tape.h" +#include "joystick.h" extern int Gamespeed; extern int Movemethod; @@ -65,7 +66,7 @@ void InitGame() Dynamite = Score = 0; Gems = level.edelsteine; - SokobanFields = Lights = 0; + SokobanFields = Lights = Friends = 0; DynaBombCount = DynaBombSize = DynaBombsLeft = 0; DynaBombXL = FALSE; Key[0] = Key[1] = Key[2] = Key[3] = FALSE; @@ -73,7 +74,10 @@ void InitGame() FrameCounter = 0; TimeFrames = 0; TimeLeft = level.time; - LevelSolved = GameOver = SiebAktiv = FALSE; + PlayerMovDir = MV_NO_MOVING; + PlayerFrame = 0; + PlayerPushing = FALSE; + PlayerGone = LevelSolved = GameOver = SiebAktiv = FALSE; JX = JY = 0; ZX = ZY = -1; @@ -144,7 +148,7 @@ void InitGame() case EL_PACMAN_U: case EL_MAMPFER: case EL_MAMPFER2: - case EL_ZOMBIE: + case EL_ROBOT: case EL_PACMAN: InitMovDir(x,y); break; @@ -168,6 +172,14 @@ void InitGame() case EL_SOKOBAN_FELD_LEER: SokobanFields++; break; + case EL_MAULWURF: + case EL_PINGUIN: + Friends++; + break; + case EL_SCHWEIN: + case EL_DRACHE: + MovDir[x][y] = 1<6) + if ((phase = (48-MovDelay[x][y])/6) > 6) phase = 6; - - if (Store[x][y] || IS_PLAYER(x,y)) - DrawGraphicThruMask(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase); - else - DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase); } else { - int phase = ((48-MovDelay[x][y])/3) % 8; - - if (phase>3) + if ((phase = ((48-MovDelay[x][y])/3) % 8) > 3) phase = 7-phase; - - if (Store[x][y] || IS_PLAYER(x,y)) - DrawGraphicThruMask(SCROLLX(x),SCROLLY(y),GFX_DYNABOMB+phase); - else - DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_DYNABOMB+phase); } + + if (Store[x][y]) + DrawGraphicThruMask(sx,sy, graphic + phase); + else + DrawGraphic(sx,sy, graphic + phase); } void CheckDynamite(int x, int y) @@ -624,14 +636,23 @@ void Explode(int ex, int ey, int phase, int mode) { int center_element = Feld[ex][ey]; - if (center_element==EL_BLOCKED) + if (IS_MOVING(ex,ey) || IS_BLOCKED(ex,ey)) + { center_element = MovingOrBlocked2Element(ex,ey); + RemoveMovingField(ex,ey); + } for(y=ey-1;y rnd_value/8) + MovDir[x][y] = old_move_dir; + else if (can_turn_left && can_turn_right) + MovDir[x][y] = (rnd < rnd_value/2 ? left_dir : right_dir); + else if (can_turn_left && rnd > rnd_value/8) + MovDir[x][y] = left_dir; + else if (can_turn_right && rnd > rnd_value/8) + MovDir[x][y] = right_dir; + else + MovDir[x][y] = back_dir; + + if (!IS_FREE(x+move_xy[MovDir[x][y]].x,y+move_xy[MovDir[x][y]].y) && + !IS_GEM(Feld[x+move_xy[MovDir[x][y]].x][y+move_xy[MovDir[x][y]].y])) + MovDir[x][y] = old_move_dir; + + MovDelay[x][y] = 0; + } + else if (element==EL_DRACHE) + { + BOOL can_turn_left = FALSE, can_turn_right = FALSE, can_move_on = FALSE; + int rnd_value = 24; + int rnd = RND(rnd_value); + + if (IN_LEV_FIELD(left_x,left_y) && IS_FREE(left_x,left_y)) + can_turn_left = TRUE; + if (IN_LEV_FIELD(right_x,right_y) && IS_FREE(right_x,right_y)) + can_turn_right = TRUE; + if (IN_LEV_FIELD(move_x,move_y) && IS_FREE(move_x,move_y)) + can_move_on = TRUE; + + if (can_move_on && rnd > rnd_value/8) + MovDir[x][y] = old_move_dir; + else if (can_turn_left && can_turn_right) + MovDir[x][y] = (rnd < rnd_value/2 ? left_dir : right_dir); + else if (can_turn_left && rnd > rnd_value/8) + MovDir[x][y] = left_dir; + else if (can_turn_right && rnd > rnd_value/8) + MovDir[x][y] = right_dir; + else + MovDir[x][y] = back_dir; + + if (!IS_FREE(x+move_xy[MovDir[x][y]].x,y+move_xy[MovDir[x][y]].y)) + MovDir[x][y] = old_move_dir; + + MovDelay[x][y] = 0; + } + else if (element==EL_ROBOT || element==EL_SONDE || + element==EL_MAULWURF || element==EL_PINGUIN) { int attr_x = JX, attr_y = JY; int newx, newy; - if (ZX>=0 && ZY>=0) + if (PlayerGone) + { + attr_x = ExitX; + attr_y = ExitY; + } + + if (element==EL_ROBOT && ZX>=0 && ZY>=0) { attr_x = ZX; attr_y = ZY; } + if (element==EL_MAULWURF || element==EL_PINGUIN) + { + int i; + static int xy[4][2] = + { + { 0,-1 }, + { -1,0 }, + { +1,0 }, + { 0,+1 } + }; + + for(i=0;i<4;i++) + { + int ex = x+xy[i%4][0]; + int ey = y+xy[i%4][1]; + + if (IN_LEV_FIELD(ex,ey) && Feld[ex][ey] == EL_AUSGANG_AUF) + { + attr_x = ex; + attr_y = ey; + break; + } + } + } + MovDir[x][y] = MV_NO_MOVING; if (attr_xy) MovDir[x][y] |= (GameOver ? MV_UP : MV_DOWN); - if ((MovDir[x][y]&(MV_LEFT|MV_RIGHT)) && (MovDir[x][y]&(MV_UP|MV_DOWN))) - MovDir[x][y] &= (RND(2) ? (MV_LEFT|MV_RIGHT) : (MV_UP|MV_DOWN)); - Moving2Blocked(x,y,&newx,&newy); - if (IN_LEV_FIELD(newx,newy) && IS_FREE_OR_PLAYER(newx,newy)) - MovDelay[x][y] = 4+4*!RND(3); + if (element==EL_ROBOT) + { + if ((MovDir[x][y]&(MV_LEFT|MV_RIGHT)) && (MovDir[x][y]&(MV_UP|MV_DOWN))) + MovDir[x][y] &= (RND(2) ? (MV_LEFT|MV_RIGHT) : (MV_UP|MV_DOWN)); + Moving2Blocked(x,y,&newx,&newy); + + if (IN_LEV_FIELD(newx,newy) && IS_FREE_OR_PLAYER(newx,newy)) + MovDelay[x][y] = 4+4*!RND(3); + else + MovDelay[x][y] = 8; + } else - MovDelay[x][y] = 8; + { + MovDelay[x][y] = 1; + + if ((MovDir[x][y]&(MV_LEFT|MV_RIGHT)) && (MovDir[x][y]&(MV_UP|MV_DOWN))) + { + BOOL first_horiz = RND(2); + int new_move_dir = MovDir[x][y]; + + MovDir[x][y] = + new_move_dir & (first_horiz ? (MV_LEFT|MV_RIGHT) : (MV_UP|MV_DOWN)); + Moving2Blocked(x,y,&newx,&newy); + + if (IN_LEV_FIELD(newx,newy) && + (IS_FREE(newx,newy) || + Feld[newx][newy] == EL_SALZSAEURE || + ((element == EL_MAULWURF || element==EL_PINGUIN) && + (Feld[newx][newy] == EL_AUSGANG_AUF || + IS_MAMPF3(Feld[newx][newy]))))) + return; + + MovDir[x][y] = + new_move_dir & (!first_horiz ? (MV_LEFT|MV_RIGHT) : (MV_UP|MV_DOWN)); + Moving2Blocked(x,y,&newx,&newy); + + if (IN_LEV_FIELD(newx,newy) && + (IS_FREE(newx,newy) || + Feld[newx][newy] == EL_SALZSAEURE || + ((element == EL_MAULWURF || element==EL_PINGUIN) && + (Feld[newx][newy] == EL_AUSGANG_AUF || + IS_MAMPF3(Feld[newx][newy]))))) + return; + + MovDir[x][y] = old_move_dir; + return; + } + } } } @@ -1224,6 +1426,23 @@ void StartMoving(int x, int y) Feld[x][y] = EL_CHANGED(Store2[x][y]); Store[x][y] = EL_SIEB_LEER; } + else if (Feld[x][y+1]==EL_SIEB_LEER) + { + if (!MovDelay[x][y]) + MovDelay[x][y] = 2; + + if (MovDelay[x][y]) + { + MovDelay[x][y]--; + if (MovDelay[x][y]) + return; + } + + Feld[x][y] = EL_SIEB_LEER; + Feld[x][y+1] = EL_SIEB_VOLL; + Store2[x][y+1] = EL_CHANGED(Store2[x][y]); + Store2[x][y] = 0; + } } else if (element==EL_SIEB2_VOLL) { @@ -1233,6 +1452,23 @@ void StartMoving(int x, int y) Feld[x][y] = EL_CHANGED2(Store2[x][y]); Store[x][y] = EL_SIEB2_LEER; } + else if (Feld[x][y+1]==EL_SIEB2_LEER) + { + if (!MovDelay[x][y]) + MovDelay[x][y] = 2; + + if (MovDelay[x][y]) + { + MovDelay[x][y]--; + if (MovDelay[x][y]) + return; + } + + Feld[x][y] = EL_SIEB2_LEER; + Feld[x][y+1] = EL_SIEB2_VOLL; + Store2[x][y+1] = EL_CHANGED2(Store2[x][y]); + Store2[x][y] = 0; + } } else if (SiebAktiv && CAN_CHANGE(element) && (Feld[x][y+1]==EL_SIEB_LEER || Feld[x][y+1]==EL_SIEB2_LEER)) @@ -1283,8 +1519,11 @@ void StartMoving(int x, int y) if (!MovDelay[x][y]) /* neuer Schritt / noch nicht gewartet */ { - if (element==EL_ZOMBIE || element==EL_KAEFER || element==EL_FLIEGER || - element==EL_BUTTERFLY || element==EL_FIREFLY) + /* Alle Figuren, die nach jeden Schritt die Richtung wechseln können. + * (MAMPFER, MAMPFER2 und PACMAN laufen bis zur nächsten Wand.) + */ + + if (element!=EL_MAMPFER && element!=EL_MAMPFER2 && element!=EL_PACMAN) { TurnRound(x,y); if (MovDelay[x][y] && (element == EL_KAEFER || element == EL_FLIEGER)) @@ -1296,7 +1535,7 @@ void StartMoving(int x, int y) { MovDelay[x][y]--; - if (element==EL_ZOMBIE || element==EL_MAMPFER || element==EL_MAMPFER2) + if (element==EL_ROBOT || element==EL_MAMPFER || element==EL_MAMPFER2) { int phase = MovDelay[x][y] % 8; @@ -1310,12 +1549,47 @@ void StartMoving(int x, int y) && MovDelay[x][y]%4==3) PlaySoundLevel(x,y,SND_NJAM); } - else if (element==EL_BUTTERFLY || element==EL_FIREFLY) + else if (element==EL_DRACHE) { - int phase = (FrameCounter % 4) / 2; + int i; + int dir = MovDir[x][y]; + int dx = (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0); + int dy = (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0); + int graphic = (dir == MV_LEFT ? GFX_FLAMMEN_LEFT : + dir == MV_RIGHT ? GFX_FLAMMEN_RIGHT : + dir == MV_UP ? GFX_FLAMMEN_UP : + dir == MV_DOWN ? GFX_FLAMMEN_DOWN : GFX_LEERRAUM); + int phase = FrameCounter % 2; + + for(i=1;i<=3;i++) + { + int xx = x + i*dx, yy = y + i*dy; + int sx = SCROLLX(xx), sy = SCROLLY(yy); - if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) - DrawGraphic(SCROLLX(x),SCROLLY(y), el2gfx(element)+phase); + if (!IN_LEV_FIELD(xx,yy) || + IS_SOLID(Feld[xx][yy]) || Feld[xx][yy]==EL_EXPLODING) + break; + + if (MovDelay[x][y]) + { + int flamed = MovingOrBlocked2Element(xx,yy); + + if (IS_ENEMY(flamed) || IS_EXPLOSIVE(flamed)) + Bang(xx,yy); + else + RemoveMovingField(xx,yy); + + Feld[xx][yy] = EL_BURNING; + if (IN_SCR_FIELD(sx,sy)) + DrawGraphic(sx,sy, graphic + phase*3 + i-1); + } + else + { + if (Feld[xx][yy] == EL_BURNING) + Feld[xx][yy] = EL_LEERRAUM; + DrawLevelField(xx,yy); + } + } } if (MovDelay[x][y]) @@ -1335,12 +1609,116 @@ void StartMoving(int x, int y) Moving2Blocked(x,y,&newx,&newy); /* wohin soll's gehen? */ - if (IS_PLAYER(newx,newy)) /* Spieler erwischt */ + if (IS_ENEMY(element) && IS_PLAYER(newx,newy)) { + /* Spieler erwischt */ MovDir[x][y] = 0; KillHero(); return; } + else if ((element == EL_MAULWURF || element == EL_PINGUIN || + element==EL_ROBOT || element==EL_SONDE) && + IN_LEV_FIELD(newx,newy) && + MovDir[x][y]==MV_DOWN && Feld[newx][newy]==EL_SALZSAEURE) + { + Blurb(x,y); + Store[x][y] = EL_SALZSAEURE; + } + else if ((element == EL_MAULWURF || element == EL_PINGUIN) && + IN_LEV_FIELD(newx,newy)) + { + if (Feld[newx][newy] == EL_AUSGANG_AUF) + { + Feld[x][y] = EL_LEERRAUM; + DrawLevelField(x,y); + + PlaySoundLevel(newx,newy,SND_BUING); + if (IN_SCR_FIELD(SCROLLX(newx),SCROLLY(newy))) + DrawGraphicThruMask(SCROLLX(newx),SCROLLY(newy),el2gfx(element)); + + Friends--; + if (!Friends && PlayerGone && !GameOver) + LevelSolved = GameOver = TRUE; + + return; + } + else if (IS_MAMPF3(Feld[newx][newy])) + { + if (DigField(newx,newy, 0,0, DF_DIG) == MF_MOVING) + DrawLevelField(newx,newy); + else + MovDir[x][y] = MV_NO_MOVING; + } + else if (!IS_FREE(newx,newy)) + { + if (IS_PLAYER(x,y)) + DrawPlayerField(); + else + DrawLevelField(x,y); + return; + } + } + else if (element == EL_SCHWEIN && IN_LEV_FIELD(newx,newy)) + { + if (IS_GEM(Feld[newx][newy])) + { + if (IS_MOVING(newx,newy)) + RemoveMovingField(newx,newy); + else + { + Feld[newx][newy] = EL_LEERRAUM; + DrawLevelField(newx,newy); + } + } + else if (!IS_FREE(newx,newy)) + { + if (IS_PLAYER(x,y)) + DrawPlayerField(); + else + DrawLevelField(x,y); + return; + } + } + else if (element==EL_DRACHE && IN_LEV_FIELD(newx,newy)) + { + if (!IS_FREE(newx,newy)) + { + if (IS_PLAYER(x,y)) + DrawPlayerField(); + else + DrawLevelField(x,y); + return; + } + else + { + BOOL wanna_flame = !RND(10); + int dx = newx - x, dy = newy - y; + int newx1 = newx+1*dx, newy1 = newy+1*dy; + int newx2 = newx+2*dx, newy2 = newy+2*dy; + int element1 = (IN_LEV_FIELD(newx1,newy1) ? + MovingOrBlocked2Element(newx1,newy1) : EL_BETON); + int element2 = (IN_LEV_FIELD(newx2,newy2) ? + MovingOrBlocked2Element(newx2,newy2) : EL_BETON); + + if ((wanna_flame || IS_ENEMY(element1) || IS_ENEMY(element2)) && + element1 != EL_DRACHE && element2 != EL_DRACHE && + element1 != EL_BURNING && element2 != EL_BURNING) + { + if (IS_PLAYER(x,y)) + DrawPlayerField(); + else + DrawLevelField(x,y); + + MovDelay[x][y] = 25; + Feld[newx][newy] = EL_BURNING; + if (IN_LEV_FIELD(newx1,newy1) && Feld[newx1][newy1] == EL_LEERRAUM) + Feld[newx1][newy1] = EL_BURNING; + if (IN_LEV_FIELD(newx2,newy2) && Feld[newx2][newy2] == EL_LEERRAUM) + Feld[newx2][newy2] = EL_BURNING; + return; + } + } + } else if (element==EL_MAMPFER && IN_LEV_FIELD(newx,newy) && Feld[newx][newy]==EL_DIAMANT) { @@ -1383,21 +1761,21 @@ void StartMoving(int x, int y) Feld[newx][newy] = EL_LEERRAUM; DrawLevelField(newx,newy); } - else if (element==EL_ZOMBIE && IN_LEV_FIELD(newx,newy) && - MovDir[x][y]==MV_DOWN && Feld[newx][newy]==EL_SALZSAEURE) - { - Blurb(x,y); - Store[x][y] = EL_SALZSAEURE; - } else if (!IN_LEV_FIELD(newx,newy) || !IS_FREE(newx,newy)) { /* gegen Wand gelaufen */ TurnRound(x,y); - if (MovDelay[x][y] && (element == EL_KAEFER || element == EL_FLIEGER)) + + if (element == EL_KAEFER || element == EL_FLIEGER) DrawLevelField(x,y); + else if (element == EL_BUTTERFLY || element == EL_FIREFLY) + DrawGraphicAnimation(x,y, el2gfx(element), 2, 2, ANIM_NORMAL); + else if (element==EL_SONDE) + DrawGraphicAnimation(x,y, GFX_SONDE_START, 8, 1, ANIM_NORMAL); + return; } - if (element==EL_ZOMBIE) + if (element==EL_ROBOT && IN_SCR_FIELD(x,y)) PlaySoundLevel(x,y,SND_SCHLURF); InitMovingField(x,y,MovDir[x][y]); @@ -1489,8 +1867,11 @@ void ContinueMoving(int x, int y) if (DONT_TOUCH(element)) /* Käfer oder Flieger */ { TestIfBadThingHitsHero(); + TestIfBadThingHitsFriend(newx,newy); TestIfBadThingHitsOtherBadThing(newx,newy); } + else if (element == EL_PINGUIN) + TestIfFriendHitsBadThing(newx,newy); if (CAN_SMASH(element) && direction==MV_DOWN && (newy==lev_fieldy-1 || !IS_FREE(x,newy+1))) @@ -1938,17 +2319,9 @@ void NussKnacken(int x, int y) void SiebAktivieren(int x, int y, int typ) { - if (SiebAktiv>1) - { - if (SiebAktiv%2 && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) - DrawGraphic(SCROLLX(x),SCROLLY(y), - (typ==1 ? GFX_SIEB_VOLL : GFX_SIEB2_VOLL)+3-(SiebAktiv%8)/2); - } - else - { - Feld[x][y] = (typ==1 ? EL_SIEB_TOT : EL_SIEB2_TOT); - DrawLevelField(x,y); - } + if (SiebAktiv%2 && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) + DrawGraphic(SCROLLX(x),SCROLLY(y), + (typ==1 ? GFX_SIEB_VOLL : GFX_SIEB2_VOLL)+3-(SiebAktiv%8)/2); } void AusgangstuerPruefen(int x, int y) @@ -2126,6 +2499,55 @@ void MauerAbleger(int ax, int ay) Feld[ax][ay] = EL_MAUERWERK; } +void CheckForDragon(int x, int y) +{ + int i,j; + BOOL dragon_found = FALSE; + static int xy[4][2] = + { + { 0,-1 }, + { -1,0 }, + { +1,0 }, + { 0,+1 } + }; + + for(i=0;i<4;i++) + { + for(j=0;j<4;j++) + { + int xx = x + j*xy[i][0], yy = y + j*xy[i][1]; + + if (IN_LEV_FIELD(xx,yy) && + (Feld[xx][yy] == EL_BURNING || Feld[xx][yy] == EL_DRACHE)) + { + if (Feld[xx][yy] == EL_DRACHE) + dragon_found = TRUE; + } + else + break; + } + } + + if (!dragon_found) + { + for(i=0;i<4;i++) + { + for(j=0;j<3;j++) + { + int xx = x + j*xy[i][0], yy = y + j*xy[i][1]; + + if (IN_LEV_FIELD(xx,yy) && Feld[xx][yy] == EL_BURNING) + { + Feld[xx][yy] = EL_LEERRAUM; + DrawLevelField(xx,yy); + } + else + break; + } + } + } +} + void GameActions() { static long action_delay=0; @@ -2147,19 +2569,36 @@ void GameActions() int x,y,element; int sieb_x = 0, sieb_y = 0; - FrameCounter++; - TimeFrames++; - if (tape.pausing || (tape.playing && !TapePlayDelay())) return; else if (tape.recording) TapeRecordDelay(); + FrameCounter++; + TimeFrames++; + for(y=0;y0) JustHit[x][y]--; + +#if DEBUG + if (IS_BLOCKED(x,y)) + { + int oldx,oldy; + + Blocked2Moving(x,y,&oldx,&oldy); + if (!IS_MOVING(oldx,oldy)) + { + printf("GameActions(): (BLOCKED=>MOVING) context corrupted!\n"); + printf("GameActions(): BLOCKED: x = %d, y = %d\n",x,y); + printf("GameActions(): !MOVING: oldx = %d, oldy = %d\n",oldx,oldy); + printf("GameActions(): This should never happen!\n"); + } + } +#endif + } for(y=0;y 0 ? MV_RIGHT : + dy < 0 ? MV_UP : + dy > 0 ? MV_DOWN : MV_NO_MOVING); +/* + if (old_move_dir != PlayerMovDir) + PlayerFrame = 0; + else + PlayerFrame = (PlayerFrame + 1) % 4; +*/ + if (!IN_LEV_FIELD(newJX,newJY)) return(MF_NO_ACTION); @@ -2312,11 +2781,7 @@ BOOL MoveFigureOneStep(int dx, int dy, int real_dx, int real_dy) InitMovingField(JX,JY,MV_DOWN); Store[JX][JY] = EL_SALZSAEURE; ContinueMoving(JX,JY); - - PlaySoundLevel(JX,JY,SND_AUTSCH); - PlaySoundLevel(JX,JY,SND_LACHEN); - GameOver = TRUE; - JX = JY = -1; + BuryHero(); } else KillHero(); @@ -2351,8 +2816,9 @@ BOOL MoveFigure(int dx, int dy) { static long move_delay = 0; int moved = MF_NO_ACTION; + int oldJX = JX, oldJY = JY; - if (GameOver || (!dx && !dy)) + if (PlayerGone || (!dx && !dy)) return(FALSE); /* @@ -2394,18 +2860,6 @@ BOOL MoveFigure(int dx, int dy) int old_scroll_x=scroll_x, old_scroll_y=scroll_y; int offset = (scroll_delay_on ? 3 : 0); -/* - if (scroll_x!=JX-MIDPOSX && JX>=MIDPOSX-1 && JX<=lev_fieldx-MIDPOSX) - scroll_x = JX-MIDPOSX; - if (scroll_y!=JY-MIDPOSY && JY>=MIDPOSY-1 && JY<=lev_fieldy-MIDPOSY) - scroll_y = JY-MIDPOSY; -*/ - -/* - printf("(scroll_x, scroll_y, JX, JY) == (%d, %d, %d, %d)\n", - scroll_x, scroll_y, JX, JY); -*/ - if ((scroll_x < JX-MIDPOSX-offset || scroll_x > JX-MIDPOSX+offset) && JX>=MIDPOSX-1-offset && JX<=lev_fieldx-(MIDPOSX-offset)) scroll_x = JX-MIDPOSX + (scroll_x < JX-MIDPOSX ? -offset : offset); @@ -2415,28 +2869,36 @@ BOOL MoveFigure(int dx, int dy) if (scroll_x!=old_scroll_x || scroll_y!=old_scroll_y) ScrollLevel(old_scroll_x-scroll_x,old_scroll_y-scroll_y); + } - if (Feld[JX][JY]==EL_LEERRAUM) - DrawLevelElement(JX,JY,EL_SPIELFIGUR); - else - DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR); + if (!(moved & MF_MOVING) && !PlayerPushing) + PlayerFrame = 0; + else + PlayerFrame = (PlayerFrame + 1) % 4; + + if (moved & MF_MOVING) + { + if (oldJX != JX && oldJY == JY) + PlayerMovDir = (oldJX < JX ? MV_RIGHT : MV_LEFT); + else if (oldJX == JX && oldJY != JY) + PlayerMovDir = (oldJY < JY ? MV_DOWN : MV_UP); + + DrawLevelField(JX,JY); /* für "ErdreichAnbroeckeln()" */ } TestIfHeroHitsBadThing(); BackToFront(); -/* - if (LevelSolved) - GameWon(); -*/ + if (PlayerGone) + RemoveHero(); return(moved); } -void TestIfHeroHitsBadThing() +void TestIfGoodThingHitsBadThing(int goodx, int goody) { - int i, killx = JX,killy = JY; + int i, killx = goodx, killy = goody; static int xy[4][2] = { { 0,-1 }, @@ -2456,8 +2918,8 @@ void TestIfHeroHitsBadThing() { int x,y,element; - x = JX+xy[i][0]; - y = JY+xy[i][1]; + x = goodx+xy[i][0]; + y = goody+xy[i][1]; if (!IN_LEV_FIELD(x,y)) continue; @@ -2474,13 +2936,78 @@ void TestIfHeroHitsBadThing() } } - if (killx!=JX || killy!=JY) - KillHero(); + if (killx!=goodx || killy!=goody) + { + if (IS_PLAYER(goodx,goody)) + KillHero(); + else + Bang(goodx,goody); + } +} + +void TestIfBadThingHitsGoodThing(int badx, int bady) +{ + int i, killx = badx, killy = bady; + static int xy[4][2] = + { + { 0,-1 }, + { -1,0 }, + { +1,0 }, + { 0,+1 } + }; + static int harmless[4] = + { + MV_UP, + MV_LEFT, + MV_RIGHT, + MV_DOWN + }; + + for(i=0;i<4;i++) + { + int x,y,element; + + x = badx+xy[i][0]; + y = bady+xy[i][1]; + if (!IN_LEV_FIELD(x,y)) + continue; + + element = Feld[x][y]; + + if (element==EL_PINGUIN) + { + if (MovDir[x][y]==harmless[i] && IS_MOVING(x,y)) + continue; + + killx = x; + killy = y; + break; + } + } + + if (killx!=badx || killy!=bady) + Bang(killx,killy); +} + +void TestIfHeroHitsBadThing() +{ + TestIfGoodThingHitsBadThing(JX,JY); } void TestIfBadThingHitsHero() { - TestIfHeroHitsBadThing(); + TestIfGoodThingHitsBadThing(JX,JY); + /* (no typo!) */ +} + +void TestIfFriendHitsBadThing(int x, int y) +{ + TestIfGoodThingHitsBadThing(x,y); +} + +void TestIfBadThingHitsFriend(int x, int y) +{ + TestIfBadThingHitsGoodThing(x,y); } void TestIfBadThingHitsOtherBadThing(int badx, int bady) @@ -2519,18 +3046,34 @@ void TestIfBadThingHitsOtherBadThing(int badx, int bady) void KillHero() { - if (IS_PLAYER(-1,-1)) + if (PlayerGone) return; if (IS_PFORTE(Feld[JX][JY])) Feld[JX][JY] = EL_LEERRAUM; + Bang(JX,JY); + BuryHero(); +} + +void BuryHero() +{ + if (PlayerGone) + return; + PlaySoundLevel(JX,JY,SND_AUTSCH); PlaySoundLevel(JX,JY,SND_LACHEN); - Bang(JX,JY); + GameOver = TRUE; - ZX = JX; - ZY = JY; + RemoveHero(); +} + +void RemoveHero() +{ + PlayerGone = TRUE; + + ExitX = ZX = JX; + ExitY = ZY = JY; JX = JY = -1; } @@ -2541,6 +3084,8 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) static long push_delay = 0; static int push_delay_value = 5; + PlayerPushing = FALSE; + if (mode == DF_NO_PUSH) { push_delay = 0; @@ -2556,9 +3101,11 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) { case EL_LEERRAUM: break; + case EL_ERDREICH: Feld[x][y] = EL_LEERRAUM; break; + case EL_EDELSTEIN: case EL_EDELSTEIN_BD: case EL_EDELSTEIN_GELB: @@ -2572,6 +3119,7 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW); PlaySoundLevel(x,y,SND_PONG); break; + case EL_DIAMANT: Feld[x][y] = EL_LEERRAUM; Gems -= 3; @@ -2581,6 +3129,7 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW); PlaySoundLevel(x,y,SND_PONG); break; + case EL_DYNAMIT_AUS: Feld[x][y] = EL_LEERRAUM; Dynamite++; @@ -2588,6 +3137,7 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) DrawText(DX_DYNAMITE,DY_DYNAMITE,int2str(Dynamite,3),FS_SMALL,FC_YELLOW); PlaySoundLevel(x,y,SND_PONG); break; + case EL_DYNABOMB_NR: Feld[x][y] = EL_LEERRAUM; DynaBombCount++; @@ -2596,17 +3146,20 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) PlaySoundLevel(x,y,SND_PONG); break; case EL_DYNABOMB_SZ: + Feld[x][y] = EL_LEERRAUM; DynaBombSize++; RaiseScoreElement(EL_DYNAMIT); PlaySoundLevel(x,y,SND_PONG); break; + case EL_DYNABOMB_XL: Feld[x][y] = EL_LEERRAUM; DynaBombXL = TRUE; RaiseScoreElement(EL_DYNAMIT); PlaySoundLevel(x,y,SND_PONG); break; + case EL_SCHLUESSEL1: case EL_SCHLUESSEL2: case EL_SCHLUESSEL3: @@ -2626,20 +3179,25 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) PlaySoundLevel(x,y,SND_PONG); break; } + case EL_ABLENK_AUS: Feld[x][y] = EL_ABLENK_EIN; - ZX=x; - ZY=y; + ZX = x; + ZY = y; DrawLevelField(x,y); return(MF_ACTION); break; + case EL_FELSBROCKEN: case EL_BOMBE: case EL_KOKOSNUSS: case EL_ZEIT_LEER: - if (mode==DF_SNAP) + if (dy || mode==DF_SNAP) return(MF_NO_ACTION); - if (dy || !IN_LEV_FIELD(x+dx,y+dy) || Feld[x+dx][y+dy] != EL_LEERRAUM) + + PlayerPushing = TRUE; + + if (!IN_LEV_FIELD(x+dx,y+dy) || Feld[x+dx][y+dy] != EL_LEERRAUM) return(MF_NO_ACTION); if (real_dy) @@ -2666,6 +3224,7 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) else PlaySoundLevel(x+dx,y+dy,SND_KLOPF); break; + case EL_PFORTE1: case EL_PFORTE2: case EL_PFORTE3: @@ -2673,6 +3232,7 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) if (!Key[element-EL_PFORTE1]) return(MF_NO_ACTION); break; + case EL_PFORTE1X: case EL_PFORTE2X: case EL_PFORTE3X: @@ -2680,17 +3240,25 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) if (!Key[element-EL_PFORTE1X]) return(MF_NO_ACTION); break; + case EL_AUSGANG_ZU: case EL_AUSGANG_ACT: /* Tür ist (noch) nicht offen! */ return(MF_NO_ACTION); break; + case EL_AUSGANG_AUF: if (mode==DF_SNAP) return(MF_NO_ACTION); - LevelSolved = GameOver = TRUE; + + PlayerGone = TRUE; PlaySoundLevel(x,y,SND_BUING); + + if (!Friends) + LevelSolved = GameOver = TRUE; + break; + case EL_BIRNE_AUS: Feld[x][y] = EL_BIRNE_EIN; Lights--; @@ -2698,6 +3266,7 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) PlaySoundLevel(x,y,SND_DENG); return(MF_ACTION); break; + case EL_ZEIT_VOLL: Feld[x][y] = EL_ZEIT_LEER; TimeLeft += 10; @@ -2706,15 +3275,22 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) PlaySoundStereo(SND_GONG,PSND_MAX_RIGHT); return(MF_ACTION); break; + case EL_SOKOBAN_FELD_LEER: break; + case EL_SOKOBAN_FELD_VOLL: case EL_SOKOBAN_OBJEKT: + case EL_SONDE: if (mode==DF_SNAP) return(MF_NO_ACTION); + + PlayerPushing = TRUE; + if (!IN_LEV_FIELD(x+dx,y+dy) || (Feld[x+dx][y+dy] != EL_LEERRAUM - && Feld[x+dx][y+dy] != EL_SOKOBAN_FELD_LEER)) + && (Feld[x+dx][y+dy] != EL_SOKOBAN_FELD_LEER + || !IS_SB_ELEMENT(element)))) return(MF_NO_ACTION); if (dx && real_dy) @@ -2733,23 +3309,31 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) if (!FrameReached(&push_delay,push_delay_value) && !tape.playing) return(MF_NO_ACTION); - if (element == EL_SOKOBAN_FELD_VOLL) + if (IS_SB_ELEMENT(element)) { - Feld[x][y] = EL_SOKOBAN_FELD_LEER; - SokobanFields++; + if (element == EL_SOKOBAN_FELD_VOLL) + { + Feld[x][y] = EL_SOKOBAN_FELD_LEER; + SokobanFields++; + } + else + Feld[x][y] = EL_LEERRAUM; + + if (Feld[x+dx][y+dy] == EL_SOKOBAN_FELD_LEER) + { + Feld[x+dx][y+dy] = EL_SOKOBAN_FELD_VOLL; + SokobanFields--; + if (element == EL_SOKOBAN_OBJEKT) + PlaySoundLevel(x,y,SND_DENG); + } + else + Feld[x+dx][y+dy] = EL_SOKOBAN_OBJEKT; } else - Feld[x][y] = EL_LEERRAUM; - - if (Feld[x+dx][y+dy] == EL_SOKOBAN_FELD_LEER) { - Feld[x+dx][y+dy] = EL_SOKOBAN_FELD_VOLL; - SokobanFields--; - if (element == EL_SOKOBAN_OBJEKT) - PlaySoundLevel(x,y,SND_DENG); + Feld[x][y] = EL_LEERRAUM; + Feld[x+dx][y+dy] = element; } - else - Feld[x+dx][y+dy] = EL_SOKOBAN_OBJEKT; push_delay_value = 2; @@ -2757,13 +3341,21 @@ int DigField(int x, int y, int real_dx, int real_dy, int mode) DrawLevelField(x+dx,y+dy); PlaySoundLevel(x+dx,y+dy,SND_PUSCH); - if (SokobanFields == 0 && game_emulation == EMU_SOKOBAN) + if (IS_SB_ELEMENT(element) && + SokobanFields == 0 && game_emulation == EMU_SOKOBAN) { LevelSolved = GameOver = TRUE; PlaySoundLevel(x,y,SND_BUING); } break; + + case EL_MAULWURF: + case EL_PINGUIN: + case EL_SCHWEIN: + case EL_DRACHE: + break; + default: return(MF_NO_ACTION); break; @@ -2779,7 +3371,7 @@ BOOL SnapField(int dx, int dy) int x = JX+dx, y = JY+dy; static int snapped = FALSE; - if (GameOver || !IN_LEV_FIELD(x,y)) + if (PlayerGone || !IN_LEV_FIELD(x,y)) return(FALSE); if (dx && dy) return(FALSE); @@ -2791,6 +3383,11 @@ BOOL SnapField(int dx, int dy) if (snapped) return(FALSE); + PlayerMovDir = (dx < 0 ? MV_LEFT : + dx > 0 ? MV_RIGHT : + dy < 0 ? MV_UP : + dy > 0 ? MV_DOWN : MV_NO_MOVING); + if (!DigField(x,y, 0,0, DF_SNAP)) return(FALSE); @@ -2805,7 +3402,7 @@ BOOL PlaceBomb(void) { int element; - if (GameOver) + if (PlayerGone) return(FALSE); element = Feld[JX][JY]; @@ -2814,7 +3411,7 @@ BOOL PlaceBomb(void) element==EL_DYNAMIT || element==EL_DYNABOMB || element==EL_EXPLODING) return(FALSE); - if (element!=EL_LEERRAUM) + if (element != EL_LEERRAUM) Store[JX][JY] = element; if (Dynamite) @@ -2840,12 +3437,15 @@ void PlaySoundLevel(int x, int y, int sound_nr) { int sx = SCROLLX(x), sy = SCROLLY(y); int volume, stereo; + int silence_distance = 8; if ((!sound_simple_on && !IS_LOOP_SOUND(sound_nr)) || (!sound_loops_on && IS_LOOP_SOUND(sound_nr))) return; - if (!IN_LEV_FIELD(x,y)) + if (!IN_LEV_FIELD(x,y) || + sx < -silence_distance || sx >= SCR_FIELDX+silence_distance || + sy < -silence_distance || sy >= SCR_FIELDY+silence_distance) return; volume = PSND_MAX_VOLUME; @@ -2853,10 +3453,10 @@ void PlaySoundLevel(int x, int y, int sound_nr) if (!IN_SCR_FIELD(sx,sy)) { - if (sx<0 || sx>=SCR_FIELDX) - volume = PSND_MAX_VOLUME - 2*ABS(sx-SCR_FIELDX/2); - else - volume = PSND_MAX_VOLUME - 2*ABS(sy-SCR_FIELDY/2); + int dx = ABS(sx-SCR_FIELDX/2)-SCR_FIELDX/2; + int dy = ABS(sy-SCR_FIELDY/2)-SCR_FIELDY/2; + + volume -= volume*(dx > dy ? dx : dy)/silence_distance; } PlaySoundExt(sound_nr, volume, stereo, PSND_NO_LOOP); @@ -2891,8 +3491,8 @@ void RaiseScoreElement(int element) case EL_MAMPFER2: RaiseScore(level.score[SC_MAMPFER]); break; - case EL_ZOMBIE: - RaiseScore(level.score[SC_ZOMBIE]); + case EL_ROBOT: + RaiseScore(level.score[SC_ROBOT]); break; case EL_PACMAN: RaiseScore(level.score[SC_PACMAN]); diff --git a/src/game.h b/src/game.h index a0a21073..8b76cb7a 100644 --- a/src/game.h +++ b/src/game.h @@ -76,10 +76,16 @@ void GameActions(void); void ScrollLevel(int, int); BOOL MoveFigureOneStep(int, int, int, int); BOOL MoveFigure(int, int); +void TestIfGoodThingHitsBadThing(int, int); +void TestIfBadThingHitsGoodThing(int, int); void TestIfHeroHitsBadThing(void); void TestIfBadThingHitsHero(void); +void TestIfFriendHitsBadThing(int, int); +void TestIfBadThingHitsFriend(int, int); void TestIfBadThingHitsOtherBadThing(int, int); void KillHero(void); +void BuryHero(void); +void RemoveHero(void); int DigField(int, int, int, int, int); BOOL SnapField(int, int); BOOL PlaceBomb(void); diff --git a/src/gfxloader.c b/src/gfxloader.c new file mode 100644 index 00000000..d0bd1cba --- /dev/null +++ b/src/gfxloader.c @@ -0,0 +1,1068 @@ +/*********************************************************** +* Rocks'n'Diamonds -- McDuffin Strikes Back! * +*----------------------------------------------------------* +* ©1995 Artsoft Development * +* Holger Schemel * +* 33659 Bielefeld-Senne * +* Telefon: (0521) 493245 * +* eMail: aeglos@valinor.owl.de * +* aeglos@uni-paderborn.de * +* q99492@pbhrzx.uni-paderborn.de * +*----------------------------------------------------------* +* gfxloader.c * +***********************************************************/ + +#include "gfxloader.h" + +#ifdef DEBUG +/* +#define DEBUG_GIF +#define DEBUG_ILBM +*/ +#endif + +struct IFF_ILBM_FORM_big_endian +{ + char magic_FORM[4]; + unsigned char chunk_size[4]; + char magic_ILBM[4]; +}; + +struct IFF_ILBM_BMHD_big_endian +{ + char Width[2], Height[2]; + char LeftEdge[2], TopEdge[2]; + char Depth; + char Mask; + char Compression; + char pad1; + char transparentColor[2]; + char xAspect, yAspect; + char pageWidth[2], pageHeight[2]; +}; + +struct IFF_ILBM_BMHD +{ + unsigned int Width, Height; + int LeftEdge, TopEdge; + unsigned int Depth; + unsigned int Mask; + unsigned int Compression; + unsigned char pad1; + unsigned int transparentColor; + unsigned int xAspect, yAspect; + int pageWidth, pageHeight; +}; + +static int ConvertXImageDepth(Display *, XImage **); +static int Read_GIF_to_Pixmap_or_Bitmap(Display *, char *, Pixmap *, int); + +#define READ_GIF_TO_BITMAP 0 +#define READ_GIF_TO_PIXMAP 1 + + +int Read_GIF_to_Bitmap(Display *display, char *filename, Pixmap *pixmap) +{ + return(Read_GIF_to_Pixmap_or_Bitmap(display, filename, + pixmap, READ_GIF_TO_BITMAP)); +} + +int Read_GIF_to_Pixmap(Display *display, char *filename, Pixmap *pixmap) +{ + return(Read_GIF_to_Pixmap_or_Bitmap(display, filename, + pixmap, READ_GIF_TO_PIXMAP)); +} + +int Read_GIF_to_Pixmap_or_Bitmap(Display *display, char *filename, + Pixmap *pixmap, int mode) +{ + XImage *image = NULL; + Pixmap new_pixmap = 0; + int return_code; + + *pixmap = 0; + return_code = Read_GIF_to_XImage(display, filename, &image); + if (return_code != GIF_Success) + return(return_code); + + if (image) + { + int screen = DefaultScreen(display); + Drawable root = RootWindow(display,screen); + int depth = DefaultDepth(display, screen); + int width = image->width; + int height = image->height; + + if (mode == READ_GIF_TO_BITMAP) + { + int i,x,y; + unsigned long black_pixel = BlackPixel(display,screen); + int bytes_per_line = (width+7) / 8; + int size = bytes_per_line * height; + char *data, *ptr; + + data = (char *)malloc(size); + if (!data) + return(GIF_NoMemory); + + ptr = data; + for(i=0;i filesize) + return(GIF_FileInvalid); + } + while(ch1); + + free(RawGIF); /* We're done with the raw data now... */ + +#ifdef DEBUG_GIF + fprintf(stderr, "done\n"); + fprintf(stderr, " Decompressing... "); +#endif + + /* Allocate the X Image */ + ImageData = (byte *) malloc(Width*Height); + if (!ImageData) + return(GIF_NoMemory); + + new_image = XCreateImage(display,visual,8,ZPixmap,0,ImageData, + Width,Height,8,Width); + if (!new_image) + return(GIF_NoMemory); + + BytesPerScanline = Width; + + + /* Decompress the file, continuing until you see the GIF EOF code. + * One obvious enhancement is to add checking for corrupt files here. + */ + + Code = ReadCode(); + while (Code != EOFCode) + { + /* Clear code sets everything back to its initial value, then reads the + * immediately subsequent code as uncompressed data. + */ + + if (Code == ClearCode) + { + CodeSize = InitCodeSize; + MaxCode = (1 << CodeSize); + ReadMask = MaxCode - 1; + FreeCode = FirstFree; + CurCode = OldCode = Code = ReadCode(); + FinChar = CurCode & BitMask; + AddToPixel(FinChar); + } + else + { + /* If not a clear code, then must be data: + * save same as CurCode and InCode + */ + + CurCode = InCode = Code; + + /* If greater or equal to FreeCode, not in the hash table yet; + * repeat the last character decoded + */ + + if (CurCode >= FreeCode) + { + CurCode = OldCode; + OutCode[OutCount++] = FinChar; + } + + /* Unless this code is raw data, pursue the chain pointed to by CurCode + * through the hash table to its end; each code in the chain puts its + * associated output code on the output queue. + */ + + while (CurCode > BitMask) + { + if (OutCount > 1024) + return(GIF_FileInvalid); + + OutCode[OutCount++] = Suffix[CurCode]; + CurCode = Prefix[CurCode]; + } + + /* The last code in the chain is treated as raw data. */ + + FinChar = CurCode & BitMask; + OutCode[OutCount++] = FinChar; + + /* Now we put the data out to the Output routine. + * It's been stacked LIFO, so deal with it that way... + */ + + for (i = OutCount - 1; i >= 0; i--) + AddToPixel(OutCode[i]); + OutCount = 0; + + /* Build the hash table on-the-fly. No table is stored in the file. */ + + Prefix[FreeCode] = OldCode; + Suffix[FreeCode] = FinChar; + OldCode = InCode; + + /* Point to the next slot in the table. If we exceed the current + * MaxCode value, increment the code size unless it's already 12. If it + * is, do nothing: the next code decompressed better be CLEAR + */ + + FreeCode++; + if (FreeCode >= MaxCode) + { + if (CodeSize < 12) + { + CodeSize++; + MaxCode *= 2; + ReadMask = (1 << CodeSize) - 1; + } + } + } + Code = ReadCode(); + } + + free(Raster); + +#ifdef DEBUG_GIF + fprintf(stderr, "done\n"); + fprintf(stderr," %d colors used\n",numused); +#endif + + if (file != stdin) + fclose(file); + + if (ColorDicking(display) != GIF_Success) + return(GIF_ColorFailed); + + *image = new_image; + return(GIF_Success); +} + + +/* Fetch the next code from the raster data stream. The codes can be + * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to + * maintain our location in the Raster array as a BIT Offset. We compute + * the byte Offset into the raster array by dividing this by 8, pick up + * three bytes, compute the bit Offset into our 24-bit chunk, shift to + * bring the desired code to the bottom, then mask it off and return it. + */ + +static int ReadCode() +{ + int RawCode, ByteOffset; + + ByteOffset = BitOffset / 8; + RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]); + if (CodeSize >= 8) + RawCode += (0x10000 * Raster[ByteOffset + 2]); + RawCode >>= (BitOffset % 8); + BitOffset += CodeSize; + return(RawCode & ReadMask); +} + + +static void AddToPixel(byte Index) +{ + if (YC= Height) + { + Pass++; + YC = 4; + } + break; + + case 1: + YC += 8; + if (YC >= Height) + { + Pass++; + YC = 2; + } + break; + + case 2: + YC += 4; + if (YC >= Height) + { + Pass++; + YC = 1; + } + break; + + case 3: + YC += 2; + break; + + default: + break; + } + } + } +} + + +static int ColorDicking(Display *display) +{ + /* we've got the picture loaded, we know what colors are needed. get 'em */ + + register int i,j; + static byte lmasks[8] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; + byte lmask, *ptr; + int screen = DefaultScreen(display); + Colormap cmap = DefaultColormap(display,screen); + int dispcells = DisplayCells(display,screen); + + int strip = 0; + int nostrip = 0; + + if (!HasColormap) + return(GIF_Success); + /* no need to allocate any colors if no colormap in GIF file */ + + /* Allocate the X colors for this picture */ + + if (nostrip) + { + /* nostrip was set. try REAL hard to do it */ + for (i=j=0; i>8)) + + abs(g - (ctab[j].green>>8)) + + abs(b - (ctab[j].blue>>8)); + if (d=0; i--) + if (used[i]) + XFreeColors(display,cmap,cols+i,1,0L); + } + else + break; + } + +#ifdef DEBUG_GIF + if (j && strip<8) + fprintf(stderr,"%s: stripped %d bits\n",progname,strip); +#endif + + if (strip==8) + { + fprintf(stderr,"UTTERLY failed to allocate the desired colors.\n"); + for (i=0; idepth != depth) + { + XImage *old_image, *new_image; + Visual *visual = DefaultVisual(display,screen); + int width = (*image)->width; + int height = (*image)->height; + register int dwx, dwy; + byte *data; + + data = (byte *)malloc(width * height); + old_image = *image; + new_image = XCreateImage(display,visual,depth, + ZPixmap,0,data,width,height,8,0); + if (!new_image) + return(GIF_NoMemory); + + if (old_image->depth == 8 && new_image->depth == 4) + { + /* speedup for the most common format change */ + + register byte *sptr = (byte *)old_image->data; + register byte *dptr = (byte *)new_image->data; + + for (dwy=1; dwy<=height; dwy++) + { + for (dwx=1; dwx 4 bit */ + { + register unsigned long pixel_value; + + for (dwx=0; dwxdata); + old_image->data = NULL; + XDestroyImage(old_image); + + *image = new_image; + } + + return(GIF_Success); +} + + +static unsigned long be2long(unsigned char *be) /* big-endian -> long int */ +{ + return((be[0]<<24) | (be[1]<<16) | (be[2]<<8) | be[3]); +} + +static unsigned short be2short(unsigned char *be) /* big-endian -> short int */ +{ + return((be[0]<<8) | be[1]); +} + +static struct IFF_ILBM_BMHD *ConvertBMHD(unsigned char *header_data) +{ + struct IFF_ILBM_BMHD_big_endian *bmhd_be; + struct IFF_ILBM_BMHD *bmhd; + + bmhd_be = (struct IFF_ILBM_BMHD_big_endian *)header_data; + bmhd = (struct IFF_ILBM_BMHD *)malloc(sizeof(struct IFF_ILBM_BMHD)); + if (!bmhd) + return(NULL); + + bmhd->Width = be2short(bmhd_be->Width); + bmhd->Height = be2short(bmhd_be->Height); + bmhd->LeftEdge = be2short(bmhd_be->LeftEdge); + bmhd->TopEdge = be2short(bmhd_be->TopEdge); + bmhd->Depth = (int)bmhd_be->Depth; + bmhd->Mask = (int)bmhd_be->Mask; + bmhd->Compression = (int)bmhd_be->Compression; + bmhd->pad1 = bmhd_be->pad1; + bmhd->transparentColor = be2short(bmhd_be->transparentColor); + bmhd->xAspect = (int)bmhd_be->xAspect; + bmhd->yAspect = (int)bmhd_be->yAspect; + bmhd->pageWidth = be2short(bmhd_be->pageWidth); + bmhd->pageHeight = be2short(bmhd_be->pageHeight); + + return(bmhd); +} + +static unsigned char MSBitFirst2LSBitFirst(unsigned char msb_byte) +{ + unsigned char lsb_byte = 0; + int i; + + for(i=7;i>=0;i--) + { + lsb_byte |= (msb_byte & 1) << i; + msb_byte >>= 1; + } + + return(lsb_byte); +} + +int Read_ILBM_to_Bitmap(Display *display, char *filename, Pixmap *pixmap) +{ + Pixmap new_pixmap = 0; + int screen = DefaultScreen(display); + Drawable root = RootWindow(display,screen); + struct IFF_ILBM_FORM_big_endian *form_header; + struct IFF_ILBM_BMHD *bitmap_header; + unsigned long file_len, body_len; + unsigned char *file_data, *bitmap_data; + unsigned char *file_ptr, *bitmap_ptr, *body_ptr; + unsigned char byte_count, byte_value; + int i,x,y,z; + int width, height, depth; + int bytes_per_line, bitmap_size; + FILE *file; + + if (!(file = fopen(filename,"r"))) + return(ILBM_OpenFailed); + + if (fseek(file,0,SEEK_END) < 0) + { + fclose(file); + return(ILBM_ReadFailed); + } + + file_len = ftell(file); + rewind(file); + + if (!(file_data = (unsigned char *)malloc(file_len))) + { + fclose(file); + return(ILBM_NoMemory); + } + + if (fread(file_data,1,file_len,file) != file_len) + { + free(file_data); + fclose(file); + return(ILBM_ReadFailed); + } + + fclose(file); + + form_header = (struct IFF_ILBM_FORM_big_endian *)file_data; + + if (strncmp(form_header->magic_FORM,"FORM",4) || + file_len != be2long(form_header->chunk_size)+8 || + strncmp(form_header->magic_ILBM,"ILBM",4)) + { +#ifdef DEBUG_ILBM + printf("%s: IFF chunk 'FORM' and/or 'ILBM' not found.\n",filename); +#endif + free(file_data); + return(ILBM_FileInvalid); + } + + bitmap_header = NULL; + body_ptr = NULL; + file_ptr = file_data + 12; + + while(file_ptr < (unsigned char *)(file_data + file_len)) + { + if (!strncmp(file_ptr,"BMHD",4)) + { +#ifdef DEBUG_ILBM + printf("%s: IFF chunk 'BMHD' found.\n",filename); +#endif + bitmap_header = ConvertBMHD(file_ptr + 8); + file_ptr += be2long(file_ptr + 4) + 8; + continue; + } + else if (!strncmp(file_ptr,"BODY",4)) + { +#ifdef DEBUG_ILBM + printf("%s: IFF chunk 'BODY' found.\n",filename); +#endif + body_ptr = file_ptr + 8; + body_len = be2long(file_ptr + 4); + file_ptr += be2long(file_ptr + 4) + 8; + continue; + } + else + { +#ifdef DEBUG_ILBM + printf("%s: IFF chunk '%c%c%c%c' found (but not used).\n",filename, + file_ptr[0],file_ptr[1],file_ptr[2],file_ptr[3]); +#endif + /* other chunk not recognized here */ + file_ptr += be2long(file_ptr + 4) + 8; + continue; + } + } + + if (!bitmap_header || !body_ptr) + { +#ifdef DEBUG_ILBM + printf("%s: IFF chunk 'BMHD' and/or 'BODY' not found.\n",filename); +#endif + free(file_data); + return(ILBM_FileInvalid); + } + + width = bitmap_header->Width; + height = bitmap_header->Height; + depth = bitmap_header->Depth; + +#ifdef DEBUG_ILBM + if (depth > 1) + printf("%s: %d bitplanes found; using only the first plane.\n", + filename,depth); +#endif + + bytes_per_line = ((width + 15) / 16) * 2; + bitmap_size = bytes_per_line * height; + + bitmap_data = (char *)malloc(bitmap_size); + if (!bitmap_data) + { + free(file_data); + free(bitmap_header); + return(ILBM_NoMemory); + } + + bitmap_ptr = bitmap_data; + for(i=0;iCompression) + { + while(x++ < bytes_per_line) + *bitmap_ptr++ |= MSBitFirst2LSBitFirst(*body_ptr++); + } + else + { + while(x < bytes_per_line) + { + byte_count = *body_ptr++; + + if (byte_count <= 128) + { + for(i=0;i +#include +#include +#include +#include + +#define GIF_Success 0 +#define GIF_OpenFailed -1 +#define GIF_ReadFailed -2 +#define GIF_FileInvalid -3 +#define GIF_NoMemory -4 +#define GIF_ColorFailed -5 + +#define ILBM_Success 0 +#define ILBM_OpenFailed -1 +#define ILBM_ReadFailed -2 +#define ILBM_FileInvalid -3 +#define ILBM_NoMemory -4 +#define ILBM_ColorFailed -5 + +int Read_ILBM_to_Bitmap(Display *, char *, Pixmap *); +int Read_GIF_to_Bitmap(Display *, char *, Pixmap *); +int Read_GIF_to_Pixmap(Display *, char *, Pixmap *); +int Read_GIF_to_XImage(Display *, char *, XImage **); + +#endif diff --git a/src/init.c b/src/init.c index 2d9b3042..c9fc72c8 100644 --- a/src/init.c +++ b/src/init.c @@ -18,10 +18,40 @@ #include "screens.h" #include "tools.h" #include "files.h" +#include "joystick.h" +#include "gfxloader.h" + #include +#ifdef DEBUG +/* +#define DEBUG_TIMING +*/ +#endif + +struct PictureFileInfo +{ + char *picture_filename; + BOOL picture_with_mask; +}; + +struct IconFileInfo +{ + char *picture_filename; + char *picturemask_filename; +}; + static int sound_process_id = 0; +static void InitLevelAndPlayerInfo(void); +static void InitDisplay(int, char **); +static void InitSound(void); +static void InitSoundProcess(void); +static void InitWindow(int, char **); +static void InitGfx(void); +static void LoadGfx(int, struct PictureFileInfo *); +static void InitElementProperties(void); + void OpenAll(int argc, char *argv[]) { InitLevelAndPlayerInfo(); @@ -196,7 +226,7 @@ void InitWindow(int argc, char *argv[]) char *window_name = WINDOWTITLE_STRING; char *icon_name = WINDOWTITLE_STRING; long window_event_mask; - static struct PictureFile icon_pic = + static struct IconFileInfo icon_pic = { "rocks_icon.xbm", "rocks_iconmask.xbm" @@ -295,15 +325,21 @@ void InitGfx() int i,j; XGCValues clip_gc_values; unsigned long clip_gc_valuemask; - static struct PictureFile pic[NUM_PICTURES] = + static struct PictureFileInfo pic[NUM_PICTURES] = { - { "RocksScreen.xpm", "RocksScreenMaske.xbm" }, - { "RocksDoor.xpm", "RocksDoorMaske.xbm" }, - { "RocksToons.xpm", "RocksToonsMaske.xbm" }, - { "RocksFont.xpm", NULL }, - { "RocksFont2.xpm", NULL } + { "RocksScreen", TRUE }, + { "RocksDoor", TRUE }, + { "RocksHeroes", TRUE }, + { "RocksToons", TRUE }, + { "RocksFont", FALSE }, + { "RocksFont2", FALSE } }; +#ifdef DEBUG_TIMING + long count1, count2; + count1 = Counter(); +#endif + LoadGfx(PIX_SMALLFONT,&pic[PIX_SMALLFONT]); DrawInitText(WINDOWTITLE_STRING,20,FC_YELLOW); DrawInitText(COPYRIGHT_STRING,50,FC_RED); @@ -313,6 +349,12 @@ void InitGfx() if (i!=PIX_SMALLFONT) LoadGfx(i,&pic[i]); +#ifdef DEBUG_TIMING + count2 = Counter(); + printf("SUMMARY: %.2f SECONDS LOADING TIME\n",(float)(count2-count1)/100.0); +#endif + + pix[PIX_DB_BACK] = XCreatePixmap(display, window, WIN_XSIZE,WIN_YSIZE, XDefaultDepth(display,screen)); @@ -357,19 +399,40 @@ void InitGfx() redraw_mask=REDRAW_ALL; } -void LoadGfx(int pos, struct PictureFile *pic) +void LoadGfx(int pos, struct PictureFileInfo *pic) { + char basefilename[256]; + char filename[256]; + +#ifdef XPM_INCLUDE_FILE int xpm_err, xbm_err; unsigned int width,height; int hot_x,hot_y; - char filename[256]; Pixmap shapemask; + char *picture_ext = ".xpm"; + char *picturemask_ext = "Mask.xbm"; +#else + int gif_err, ilbm_err; + char *picture_ext = ".gif"; + char *picturemask_ext = "Mask.ilbm"; +#endif + +#ifdef DEBUG_TIMING + long count1, count2; +#endif /* Grafik laden */ if (pic->picture_filename) { - DrawInitText(pic->picture_filename,150,FC_YELLOW); - sprintf(filename,"%s/%s",GFX_PATH,pic->picture_filename); + sprintf(basefilename,"%s%s",pic->picture_filename,picture_ext); + DrawInitText(basefilename,150,FC_YELLOW); + sprintf(filename,"%s/%s",GFX_PATH,basefilename); + +#ifdef DEBUG_TIMING + count1 = Counter(); +#endif + +#ifdef XPM_INCLUDE_FILE xpm_att[pos].valuemask = XpmCloseness; xpm_att[pos].closeness = 20000; @@ -378,7 +441,7 @@ void LoadGfx(int pos, struct PictureFile *pic) switch(xpm_err) { case XpmOpenFailed: - fprintf(stderr,"Xpm file open failed on '%s' !\n",filename); + fprintf(stderr,"Cannot open Xpm file '%s' !\n",filename); CloseAll(); exit(-1); case XpmFileInvalid: @@ -386,20 +449,60 @@ void LoadGfx(int pos, struct PictureFile *pic) CloseAll(); exit(-1); case XpmNoMemory: - fprintf(stderr,"Not enough memory !\n"); + fprintf(stderr,"Not enough memory for Xpm file '%s'!\n",filename); CloseAll(); exit(1); case XpmColorFailed: - fprintf(stderr,"Can`t get any colors...\n"); + fprintf(stderr,"Can't get colors for Xpm file '%s'!\n",filename); CloseAll(); exit(-1); default: break; } +#else + + gif_err = Read_GIF_to_Pixmap(display,filename,&pix[pos]); + + switch(gif_err) + { + case GIF_Success: + break; + case GIF_OpenFailed: + fprintf(stderr,"Cannot open GIF file '%s' !\n",filename); + CloseAll(); + exit(-1); + case GIF_ReadFailed: + fprintf(stderr,"Cannot read GIF file '%s' !\n",filename); + CloseAll(); + exit(-1); + case GIF_FileInvalid: + fprintf(stderr,"Invalid GIF file '%s'!\n",filename); + CloseAll(); + exit(-1); + case GIF_NoMemory: + fprintf(stderr,"Not enough memory for GIF file '%s'!\n",filename); + CloseAll(); + exit(1); + case GIF_ColorFailed: + fprintf(stderr,"Can't get colors for GIF file '%s'!\n",filename); + CloseAll(); + exit(-1); + default: + break; + } + +#endif + +#ifdef DEBUG_TIMING + count2 = Counter(); + printf("LOADING %s IN %.2f SECONDS\n", + filename,(float)(count2-count1)/100.0); +#endif + if (!pix[pos]) { - fprintf(stderr, "%s: cannot read Xpm file '%s'.\n", + fprintf(stderr, "%s: cannot read graphics file '%s'.\n", progname,filename); CloseAll(); exit(-1); @@ -407,10 +510,17 @@ void LoadGfx(int pos, struct PictureFile *pic) } /* zugehörige Maske laden (wenn vorhanden) */ - if (pic->picturemask_filename) + if (pic->picture_with_mask) { - DrawInitText(pic->picturemask_filename,150,FC_YELLOW); - sprintf(filename,"%s/%s",GFX_PATH,pic->picturemask_filename); + sprintf(basefilename,"%s%s",pic->picture_filename,picturemask_ext); + DrawInitText(basefilename,150,FC_YELLOW); + sprintf(filename,"%s/%s",GFX_PATH,basefilename); + +#ifdef DEBUG_TIMING + count1 = Counter(); +#endif + +#ifdef XPM_INCLUDE_FILE xbm_err = XReadBitmapFile(display,window,filename, &width,&height,&clipmask[pos],&hot_x,&hot_y); @@ -437,9 +547,45 @@ void LoadGfx(int pos, struct PictureFile *pic) break; } +#else + + ilbm_err = Read_ILBM_to_Bitmap(display,filename,&clipmask[pos]); + + switch(ilbm_err) + { + case ILBM_Success: + break; + case ILBM_OpenFailed: + fprintf(stderr,"Cannot open ILBM file '%s' !\n",filename); + CloseAll(); + exit(-1); + case ILBM_ReadFailed: + fprintf(stderr,"Cannot read ILBM file '%s' !\n",filename); + CloseAll(); + exit(-1); + case ILBM_FileInvalid: + fprintf(stderr,"Invalid ILBM file '%s'!\n",filename); + CloseAll(); + exit(-1); + case ILBM_NoMemory: + fprintf(stderr,"Not enough memory for ILBM file '%s'!\n",filename); + CloseAll(); + exit(1); + default: + break; + } + +#endif + +#ifdef DEBUG_TIMING + count2 = Counter(); + printf("LOADING %s IN %.2f SECONDS\n", + filename,(float)(count2-count1)/100.0); +#endif + if (!clipmask[pos]) { - fprintf(stderr, "%s: cannot read X11 bitmap file '%s'.\n", + fprintf(stderr, "%s: cannot read graphics file '%s'.\n", progname,filename); CloseAll(); exit(-1); @@ -470,16 +616,6 @@ void InitElementProperties() }; static int ep_amoeboid_num = sizeof(ep_amoeboid)/sizeof(int); - static int ep_badewannoid[] = - { - EL_BADEWANNE1, - EL_BADEWANNE2, - EL_BADEWANNE3, - EL_BADEWANNE4, - EL_BADEWANNE5 - }; - static int ep_badewannoid_num = sizeof(ep_badewannoid)/sizeof(int); - static int ep_schluessel[] = { EL_SCHLUESSEL1, @@ -573,7 +709,8 @@ void InitElementProperties() EL_BIRNE_EIN, EL_BIRNE_AUS, EL_BADEWANNE1, - EL_BADEWANNE2 + EL_BADEWANNE2, + EL_SONDE }; static int ep_slippery_num = sizeof(ep_slippery)/sizeof(int); @@ -585,7 +722,7 @@ void InitElementProperties() EL_FIREFLY, EL_MAMPFER, EL_MAMPFER2, - EL_ZOMBIE, + EL_ROBOT, EL_PACMAN }; static int ep_enemy_num = sizeof(ep_enemy)/sizeof(int); @@ -672,8 +809,13 @@ void InitElementProperties() EL_FIREFLY, EL_MAMPFER, EL_MAMPFER2, - EL_ZOMBIE, - EL_PACMAN + EL_ROBOT, + EL_PACMAN, + EL_MAULWURF, + EL_PINGUIN, + EL_SCHWEIN, + EL_DRACHE, + EL_SONDE }; static int ep_can_move_num = sizeof(ep_can_move)/sizeof(int); @@ -719,7 +861,7 @@ void InitElementProperties() EL_FIREFLY, EL_MAMPFER, EL_MAMPFER2, - EL_ZOMBIE, + EL_ROBOT, EL_PACMAN, EL_TROPFEN, EL_SALZSAEURE @@ -734,7 +876,7 @@ void InitElementProperties() EL_BUTTERFLY, EL_FIREFLY, EL_MAMPFER, - EL_ZOMBIE, + EL_ROBOT, EL_PACMAN, EL_TROPFEN, EL_AMOEBE_TOT, @@ -852,11 +994,51 @@ void InitElementProperties() }; static int ep_inactive_num = sizeof(ep_inactive)/sizeof(int); + static int ep_explosive[] = + { + EL_BOMBE, + EL_DYNAMIT, + EL_DYNAMIT_AUS, + EL_DYNABOMB, + EL_DYNABOMB_NR, + EL_DYNABOMB_SZ, + EL_DYNABOMB_XL, + EL_KAEFER, + EL_MAULWURF, + EL_PINGUIN, + EL_SCHWEIN, + EL_DRACHE, + EL_SONDE + }; + static int ep_explosive_num = sizeof(ep_explosive)/sizeof(int); + + static int ep_mampf3[] = + { + EL_EDELSTEIN, + EL_EDELSTEIN_BD, + EL_EDELSTEIN_GELB, + EL_EDELSTEIN_ROT, + EL_EDELSTEIN_LILA, + EL_DIAMANT + }; + static int ep_mampf3_num = sizeof(ep_mampf3)/sizeof(int); + + static int ep_pushable[] = + { + EL_FELSBROCKEN, + EL_BOMBE, + EL_KOKOSNUSS, + EL_ZEIT_LEER, + EL_SOKOBAN_FELD_VOLL, + EL_SOKOBAN_OBJEKT, + EL_SONDE + }; + static int ep_pushable_num = sizeof(ep_pushable)/sizeof(int); + static long ep_bit[] = { EP_BIT_AMOEBALIVE, EP_BIT_AMOEBOID, - EP_BIT_BADEWANNOID, EP_BIT_SCHLUESSEL, EP_BIT_PFORTE, EP_BIT_SOLID, @@ -875,13 +1057,15 @@ void InitElementProperties() EP_BIT_BD_ELEMENT, EP_BIT_SB_ELEMENT, EP_BIT_GEM, - EP_BIT_INACTIVE + EP_BIT_INACTIVE, + EP_BIT_EXPLOSIVE, + EP_BIT_MAMPF3, + EP_BIT_PUSHABLE }; static int *ep_array[] = { ep_amoebalive, ep_amoeboid, - ep_badewannoid, ep_schluessel, ep_pforte, ep_solid, @@ -900,13 +1084,15 @@ void InitElementProperties() ep_bd_element, ep_sb_element, ep_gem, - ep_inactive + ep_inactive, + ep_explosive, + ep_mampf3, + ep_pushable }; static int *ep_num[] = { &ep_amoebalive_num, &ep_amoeboid_num, - &ep_badewannoid_num, &ep_schluessel_num, &ep_pforte_num, &ep_solid_num, @@ -925,7 +1111,10 @@ void InitElementProperties() &ep_bd_element_num, &ep_sb_element_num, &ep_gem_num, - &ep_inactive_num + &ep_inactive_num, + &ep_explosive_num, + &ep_mampf3_num, + &ep_pushable_num }; static int num_properties = sizeof(ep_num)/sizeof(int *); @@ -954,12 +1143,14 @@ void CloseAll() { if (pix[i]) { +#ifdef XPM_INCLUDE_FILE if (i +#endif + +#include "joystick.h" + +/* +#include "tools.h" +#include "game.h" +#include "events.h" +#include "sound.h" +#include "misc.h" +#include "buttons.h" +#include +*/ + +void CheckJoystickData() +{ + int i; + int distance = 100; + + for(i=0;i<2;i++) + { + if (joystick[i].xmiddle <= distance) + joystick[i].xmiddle = distance; + if (joystick[i].ymiddle <= distance) + joystick[i].ymiddle = distance; + + if (joystick[i].xleft >= joystick[i].xmiddle) + joystick[i].xleft = joystick[i].xmiddle-distance; + if (joystick[i].xright <= joystick[i].xmiddle) + joystick[i].xright = joystick[i].xmiddle+distance; + + if (joystick[i].yupper >= joystick[i].ymiddle) + joystick[i].yupper = joystick[i].ymiddle-distance; + if (joystick[i].ylower <= joystick[i].ymiddle) + joystick[i].ylower = joystick[i].ymiddle+distance; + } +} + +int JoystickPosition(int middle, int margin, int actual) +{ + long range, pos; + int percentage; + + if (marginmiddle) + return(0); + if (margin>middle && actual100) + percentage = 100; + + return(percentage); +} + +int Joystick() +{ +#ifdef __FreeBSD__ + struct joystick joy_ctrl; +#else + struct joystick_control + { + int buttons; + int x; + int y; + } joy_ctrl; +#endif + + int js_x,js_y, js_b1,js_b2; + int left, right, up, down; + int result=0; + + if (joystick_status==JOYSTICK_OFF) + return(0); + + if (read(joystick_device, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl)) + { + fprintf(stderr,"%s: cannot read joystick settings - no joystick support\n", + progname); + joystick_status = JOYSTICK_OFF; + return(0); + } + + js_x = joy_ctrl.x; + js_y = joy_ctrl.y; +#ifdef __FreeBSD__ + js_b1 = joy_ctrl.b1; + js_b2 = joy_ctrl.b2; +#else + js_b1 = joy_ctrl.buttons & 1; + js_b2 = joy_ctrl.buttons & 2; +#endif + + left = JoystickPosition(joystick[joystick_nr].xmiddle, + joystick[joystick_nr].xleft, js_x); + right = JoystickPosition(joystick[joystick_nr].xmiddle, + joystick[joystick_nr].xright, js_x); + up = JoystickPosition(joystick[joystick_nr].ymiddle, + joystick[joystick_nr].yupper, js_y); + down = JoystickPosition(joystick[joystick_nr].ymiddle, + joystick[joystick_nr].ylower, js_y); + + if (left>JOYSTICK_PERCENT) + result |= JOY_LEFT; + else if (right>JOYSTICK_PERCENT) + result |= JOY_RIGHT; + if (up>JOYSTICK_PERCENT) + result |= JOY_UP; + else if (down>JOYSTICK_PERCENT) + result |= JOY_DOWN; + if (js_b1) + result |= JOY_BUTTON_1; + if (js_b2) + result |= JOY_BUTTON_2; + + return(result); +} + +int JoystickButton() +{ + static int last_joy_button = 0; + int joy_button = (Joystick() & JOY_BUTTON); + int result; + + if (joy_button) + { + if (last_joy_button) + result = JOY_BUTTON_PRESSED; + else + result = JOY_BUTTON_NEW_PRESSED; + } + else + { + if (last_joy_button) + result = JOY_BUTTON_NEW_RELEASED; + else + result = JOY_BUTTON_NOT_PRESSED; + } + + last_joy_button = joy_button; + return(result); +} diff --git a/src/joystick.h b/src/joystick.h new file mode 100644 index 00000000..64a8166d --- /dev/null +++ b/src/joystick.h @@ -0,0 +1,64 @@ +/*********************************************************** +* Rocks'n'Diamonds -- McDuffin Strikes Back! * +*----------------------------------------------------------* +* ©1997 Artsoft Development * +* Holger Schemel * +* 33604 Bielefeld * +* Telefon: (0521) 290471 * +* eMail: aeglos@valinor.owl.de * +* aeglos@uni-paderborn.de * +*----------------------------------------------------------* +* joystick.h * +***********************************************************/ + +#ifndef JOYSTICK_H +#define JOYSTICK_H + +#include "main.h" + +/* values for the joystick */ +#define JOYSTICK_OFF 0 +#define JOYSTICK_AVAILABLE 1 +#ifdef __FreeBSD__ +#include +#define DEV_JOYSTICK_0 "/dev/joy0" +#define DEV_JOYSTICK_1 "/dev/joy1" +#else +#define DEV_JOYSTICK_0 "/dev/js0" +#define DEV_JOYSTICK_1 "/dev/js1" +#endif + +/* get these values from the program 'js' from the joystick package, */ +/* set JOYSTICK_PERCENT to a threshold appropriate for your joystick */ +#define JOYSTICK_XLEFT 30 +#define JOYSTICK_XRIGHT 1250 +#define JOYSTICK_XMIDDLE 530 +#define JOYSTICK_YUPPER 40 +#define JOYSTICK_YLOWER 1440 +#define JOYSTICK_YMIDDLE 680 +#define JOYSTICK_PERCENT 25 +#define JOY_LEFT MV_LEFT +#define JOY_RIGHT MV_RIGHT +#define JOY_UP MV_UP +#define JOY_DOWN MV_DOWN +#define JOY_BUTTON_1 16 +#define JOY_BUTTON_2 32 +#define JOY_BUTTON (JOY_BUTTON_1 | JOY_BUTTON_2) +#define JOY_BUTTON_NOT_PRESSED 0 +#define JOY_BUTTON_PRESSED 1 +#define JOY_BUTTON_NEW_PRESSED 2 +#define JOY_BUTTON_NEW_RELEASED 3 + +#ifdef NO_JOYSTICK +#define JOYSTICK_STATUS JOYSTICK_OFF +#else +#define JOYSTICK_STATUS JOYSTICK_AVAILABLE +#endif + + +void CheckJoystickData(void); +int JoystickPosition(int, int, int); +int Joystick(void); +int JoystickButton(void); + +#endif diff --git a/src/main.c b/src/main.c index 0c9d1f18..2db25f2e 100644 --- a/src/main.c +++ b/src/main.c @@ -16,6 +16,7 @@ #include "init.h" #include "events.h" #include "sound.h" +#include "joystick.h" Display *display; int screen; @@ -23,7 +24,11 @@ Window window; GC gc, clip_gc[NUM_PIXMAPS]; Pixmap pix[NUM_PIXMAPS]; Pixmap clipmask[NUM_PIXMAPS]; + +#ifdef XPM_INCLUDE_FILE XpmAttributes xpm_att[NUM_PICTURES]; +#endif + Drawable drawto, drawto_field, backbuffer; Colormap cmap; @@ -75,9 +80,12 @@ long Elementeigenschaften[MAX_ELEMENTS]; int level_nr, leveldir_nr, num_leveldirs; int lev_fieldx,lev_fieldy, scroll_x,scroll_y; -int LevelSolved,GameOver, JX,JY, ZX,ZY; +int JX,JY, ZX,ZY, ExitX,ExitY; +int PlayerMovDir, PlayerFrame, PlayerPushing; +int PlayerGone,LevelSolved,GameOver; int FrameCounter,TimeFrames,TimeLeft,Score; -int Gems,SokobanFields,Lights,Dynamite,Key[4],MampferNr; +int Gems,SokobanFields,Lights,Friends; +int Dynamite,Key[4],MampferNr; int DynaBombCount, DynaBombSize, DynaBombsLeft, DynaBombXL; int SiebAktiv; diff --git a/src/main.h b/src/main.h index 6cf2bb23..36c0978d 100644 --- a/src/main.h +++ b/src/main.h @@ -26,8 +26,6 @@ #ifdef XPM_INCLUDE_FILE #include XPM_INCLUDE_FILE -#else -#include "YOU HAVE TO SET 'XPM_INCLUDE_FILE' IN THE 'Makefile'!!!" #endif #include @@ -75,31 +73,32 @@ typedef int BOOL; #define EP_BIT_AMOEBALIVE (1<<0) #define EP_BIT_AMOEBOID (1<<1) -#define EP_BIT_BADEWANNOID (1<<2) -#define EP_BIT_SCHLUESSEL (1<<3) -#define EP_BIT_PFORTE (1<<4) -#define EP_BIT_SOLID (1<<5) -#define EP_BIT_MASSIV (1<<6) -#define EP_BIT_SLIPPERY (1<<7) -#define EP_BIT_ENEMY (1<<8) -#define EP_BIT_MAUER (1<<9) -#define EP_BIT_CAN_FALL (1<<10) -#define EP_BIT_CAN_SMASH (1<<11) -#define EP_BIT_CAN_CHANGE (1<<12) -#define EP_BIT_CAN_MOVE (1<<13) -#define EP_BIT_COULD_MOVE (1<<14) -#define EP_BIT_DONT_TOUCH (1<<15) -#define EP_BIT_DONT_GO_TO (1<<16) -#define EP_BIT_MAMPF2 (1<<17) -#define EP_BIT_CHAR (1<<18) -#define EP_BIT_BD_ELEMENT (1<<19) -#define EP_BIT_SB_ELEMENT (1<<20) -#define EP_BIT_GEM (1<<21) -#define EP_BIT_INACTIVE (1<<22) +#define EP_BIT_SCHLUESSEL (1<<2) +#define EP_BIT_PFORTE (1<<3) +#define EP_BIT_SOLID (1<<4) +#define EP_BIT_MASSIV (1<<5) +#define EP_BIT_SLIPPERY (1<<6) +#define EP_BIT_ENEMY (1<<7) +#define EP_BIT_MAUER (1<<8) +#define EP_BIT_CAN_FALL (1<<9) +#define EP_BIT_CAN_SMASH (1<<10) +#define EP_BIT_CAN_CHANGE (1<<11) +#define EP_BIT_CAN_MOVE (1<<12) +#define EP_BIT_COULD_MOVE (1<<13) +#define EP_BIT_DONT_TOUCH (1<<14) +#define EP_BIT_DONT_GO_TO (1<<15) +#define EP_BIT_MAMPF2 (1<<16) +#define EP_BIT_CHAR (1<<17) +#define EP_BIT_BD_ELEMENT (1<<18) +#define EP_BIT_SB_ELEMENT (1<<19) +#define EP_BIT_GEM (1<<20) +#define EP_BIT_INACTIVE (1<<21) +#define EP_BIT_EXPLOSIVE (1<<22) +#define EP_BIT_MAMPF3 (1<<23) +#define EP_BIT_PUSHABLE (1<<24) #define IS_AMOEBALIVE(e) (Elementeigenschaften[e] & EP_BIT_AMOEBALIVE) #define IS_AMOEBOID(e) (Elementeigenschaften[e] & EP_BIT_AMOEBOID) -#define IS_BADEWANNOID(e) (Elementeigenschaften[e] & EP_BIT_BADEWANNOID) #define IS_SCHLUESSEL(e) (Elementeigenschaften[e] & EP_BIT_SCHLUESSEL) #define IS_PFORTE(e) (Elementeigenschaften[e] & EP_BIT_PFORTE) #define IS_SOLID(e) (Elementeigenschaften[e] & EP_BIT_SOLID) @@ -120,6 +119,9 @@ typedef int BOOL; #define IS_SB_ELEMENT(e) (Elementeigenschaften[e] & EP_BIT_SB_ELEMENT) #define IS_GEM(e) (Elementeigenschaften[e] & EP_BIT_GEM) #define IS_INACTIVE(e) (Elementeigenschaften[e] & EP_BIT_INACTIVE) +#define IS_EXPLOSIVE(e) (Elementeigenschaften[e] & EP_BIT_EXPLOSIVE) +#define IS_MAMPF3(e) (Elementeigenschaften[e] & EP_BIT_MAMPF3) +#define IS_PUSHABLE(e) (Elementeigenschaften[e] & EP_BIT_PUSHABLE) #define EL_CHANGED(e) ((e)==EL_FELSBROCKEN ? EL_EDELSTEIN : \ (e)==EL_EDELSTEIN ? EL_DIAMANT : \ @@ -138,15 +140,16 @@ typedef int BOOL; /* Pixmaps with Xpm or X11 Bitmap files */ #define PIX_BACK 0 #define PIX_DOOR 1 -#define PIX_TOONS 2 -#define PIX_BIGFONT 3 -#define PIX_SMALLFONT 4 +#define PIX_HEROES 2 +#define PIX_TOONS 3 +#define PIX_BIGFONT 4 +#define PIX_SMALLFONT 5 /* Pixmaps without them */ -#define PIX_DB_BACK 5 -#define PIX_DB_DOOR 6 +#define PIX_DB_BACK 6 +#define PIX_DB_DOOR 7 -#define NUM_PICTURES 5 -#define NUM_PIXMAPS 7 +#define NUM_PICTURES 6 +#define NUM_PIXMAPS 8 /* boundaries of arrays etc. */ #define MAX_NAMELEN (10+1) @@ -165,12 +168,6 @@ typedef int BOOL; #define MAX_NUM_AMOEBA 100 #define MAX_ELEMENTS 512 -struct PictureFile -{ - char *picture_filename; - char *picturemask_filename; -}; - struct HiScore { char Name[MAX_NAMELEN]; @@ -220,9 +217,9 @@ struct RecordingInfo unsigned long length_seconds; unsigned int delay_played; BOOL pause_before_death; - BOOL changed; BOOL recording, playing, pausing; BOOL fast_forward; + BOOL changed; struct { unsigned char joystickdata; @@ -243,7 +240,11 @@ extern GC gc, clip_gc[]; extern XImage *image[]; extern Pixmap clipmask[]; extern Pixmap pix[]; + +#ifdef XPM_INCLUDE_FILE extern XpmAttributes xpm_att[]; +#endif + extern Drawable drawto, drawto_field, backbuffer; extern Colormap cmap; @@ -294,9 +295,12 @@ extern long Elementeigenschaften[MAX_ELEMENTS]; extern int level_nr, leveldir_nr, num_leveldirs; extern int lev_fieldx,lev_fieldy, scroll_x,scroll_y; -extern int LevelSolved,GameOver, JX,JY, ZX,ZY; +extern int JX,JY, ZX,ZY, ExitX,ExitY; +extern int PlayerMovDir, PlayerFrame, PlayerPushing; +extern int PlayerGone,LevelSolved,GameOver; extern int FrameCounter,TimeFrames,TimeLeft,Score; -extern int Gems,SokobanFields,Lights,Dynamite,Key[4],MampferNr; +extern int Gems,SokobanFields,Lights,Friends; +extern int Dynamite,Key[4],MampferNr; extern int DynaBombCount, DynaBombSize, DynaBombsLeft, DynaBombXL; extern int SiebAktiv; @@ -305,8 +309,10 @@ extern struct LevelInfo level; extern struct PlayerInfo player; extern struct HiScore highscore[]; extern struct RecordingInfo tape; +extern struct SoundInfo Sound[]; extern struct JoystickInfo joystick[]; +extern char *sound_name[]; extern int background_loop[]; extern int num_bg_loops; @@ -361,6 +367,7 @@ extern char *progname; #define GFX_PER_LINE 16 #define MINI_GFX_PER_LINE 32 #define MICRO_GFX_PER_LINE 128 +#define HEROES_PER_LINE 16 #define FONT_CHARS_PER_LINE 16 #define FONT_LINES_PER_FONT 4 @@ -381,7 +388,7 @@ extern char *progname; #define EL_KAEFER 9 #define EL_FLIEGER 10 #define EL_MAMPFER 11 -#define EL_ZOMBIE 12 +#define EL_ROBOT 12 #define EL_BETON 13 #define EL_DIAMANT 14 #define EL_AMOEBE_TOT 15 @@ -487,6 +494,17 @@ extern char *progname; #define EL_AUSGANG_AUF 107 #define EL_SIEB2_TOT 108 #define EL_AMOEBA2DIAM 109 +#define EL_MAULWURF 110 +#define EL_PINGUIN 111 +#define EL_SONDE 112 +#define EL_PFEIL_L 113 +#define EL_PFEIL_R 114 +#define EL_PFEIL_O 115 +#define EL_PFEIL_U 116 +#define EL_SCHWEIN 117 +#define EL_DRACHE 118 + +#define EL_UNUSED_119 119 #define EL_CHAR_START 120 #define EL_CHAR_ASCII0 (EL_CHAR_START-32) @@ -519,6 +537,10 @@ extern char *progname; #define EL_CHAR_COPY (EL_CHAR_ASCII0+94) #define EL_CHAR_END (EL_CHAR_START+79) +#define EL_UNUSED_200 200 +/* ... */ +#define EL_UNUSED_255 255 + /* "unreal" runtime elements */ #define EL_BLOCKED 300 #define EL_EXPLODING 301 @@ -527,8 +549,22 @@ extern char *progname; #define EL_BLURB_RIGHT 304 #define EL_AMOEBING 305 #define EL_MAUERND 306 +#define EL_BURNING 307 + +/* game graphics: +** 0 - 255: graphics from "RocksScreen" +** 256 - 511: graphics from "RocksFont" +** 512 - 767: graphics from "RocksHeroes" +*/ -/* names for the graphic objects */ +#define GFX_START_ROCKSSCREEN 0 +#define GFX_END_ROCKSSCREEN 255 +#define GFX_START_ROCKSFONT 256 +#define GFX_END_ROCKSFONT 511 +#define GFX_START_ROCKSHEROES 512 +#define GFX_END_ROCKSHEROES 767 + +/* graphics from "RocksScreen" */ /* Zeile 0 (0) */ #define GFX_LEERRAUM (-1) #define GFX_ERDREICH 0 @@ -560,7 +596,7 @@ extern char *progname; #define GFX_BADEWANNE3 32 #define GFX_BADEWANNE4 33 #define GFX_BADEWANNE5 34 -#define GFX_SPIELFIGUR 35 +#define GFX_SMILEY 35 #define GFX_PFORTE1 36 #define GFX_PFORTE2 37 #define GFX_PFORTE3 38 @@ -586,7 +622,7 @@ extern char *progname; #define GFX_KAEFER_U 75 /* Zeile 5 (80) */ #define GFX_MAMPFER 80 -#define GFX_ZOMBIE 84 +#define GFX_ROBOT 84 #define GFX_PACMAN 88 #define GFX_PACMAN_R 88 #define GFX_PACMAN_O 89 @@ -608,6 +644,10 @@ extern char *progname; #define GFX_BIRNE_EIN 113 #define GFX_ZEIT_VOLL 114 #define GFX_ZEIT_LEER 115 +#define GFX_SPIELER1 116 +#define GFX_SPIELER2 117 +#define GFX_SPIELER3 118 +#define GFX_SPIELER4 119 #define GFX_AMOEBE_VOLL 120 #define GFX_AMOEBE_BD GFX_AMOEBE_VOLL #define GFX_SOKOBAN_OBJEKT 121 @@ -630,11 +670,14 @@ extern char *progname; #define GFX_KUGEL_GELB 142 #define GFX_KUGEL_GRAU 143 /* Zeile 9 (144) */ -#define GFX_BLURB_LEFT 144 -#define GFX_BLURB_RIGHT 148 +#define GFX_PINGUIN 144 +#define GFX_MAULWURF 145 +#define GFX_SCHWEIN 146 +#define GFX_DRACHE 147 #define GFX_EDELSTEIN_ROT 152 #define GFX_EDELSTEIN_LILA 154 #define GFX_DYNABOMB_XL 156 +#define GFX_SONDE 159 /* Zeile 10 (160) */ #define GFX_EDELSTEIN_BD 163 #define GFX_MAUER_R1 165 @@ -669,15 +712,44 @@ extern char *progname; #define GFX_FIREFLY_L 206 #define GFX_FIREFLY_U 207 -#define GFX_SCHLUESSEL GFX_SCHLUESSEL1 - -#define GFX_SPIELER1 116 -#define GFX_SPIELER2 117 -#define GFX_SPIELER3 118 -#define GFX_SPIELER4 119 - -/* nicht in "RocksScreen" sondern woanders :) */ -#define GFX_CHAR_START 256 +#define GFX_SCHLUESSEL GFX_SCHLUESSEL1 +#define GFX_SPIELFIGUR GFX_SPIELER1 + + +/* graphics from "RocksHeroes" */ + +#define GFX_SPIELER_DOWN (GFX_START_ROCKSHEROES + 0*HEROES_PER_LINE + 0) +#define GFX_SPIELER_UP (GFX_START_ROCKSHEROES + 0*HEROES_PER_LINE + 4) +#define GFX_SPIELER_LEFT (GFX_START_ROCKSHEROES + 1*HEROES_PER_LINE + 0) +#define GFX_SPIELER_RIGHT (GFX_START_ROCKSHEROES + 1*HEROES_PER_LINE + 4) +#define GFX_SPIELER_PUSH_RIGHT (GFX_START_ROCKSHEROES + 2*HEROES_PER_LINE + 0) +#define GFX_SPIELER_PUSH_LEFT (GFX_START_ROCKSHEROES + 2*HEROES_PER_LINE + 4) +#define GFX_SONDE_START (GFX_START_ROCKSHEROES + 7*HEROES_PER_LINE + 0) +#define GFX_SCHWEIN_DOWN (GFX_START_ROCKSHEROES + 0*HEROES_PER_LINE + 8) +#define GFX_SCHWEIN_UP (GFX_START_ROCKSHEROES + 0*HEROES_PER_LINE +12) +#define GFX_SCHWEIN_LEFT (GFX_START_ROCKSHEROES + 1*HEROES_PER_LINE + 8) +#define GFX_SCHWEIN_RIGHT (GFX_START_ROCKSHEROES + 1*HEROES_PER_LINE +12) +#define GFX_DRACHE_DOWN (GFX_START_ROCKSHEROES + 2*HEROES_PER_LINE + 8) +#define GFX_DRACHE_UP (GFX_START_ROCKSHEROES + 2*HEROES_PER_LINE +12) +#define GFX_DRACHE_LEFT (GFX_START_ROCKSHEROES + 3*HEROES_PER_LINE + 8) +#define GFX_DRACHE_RIGHT (GFX_START_ROCKSHEROES + 3*HEROES_PER_LINE +12) +#define GFX_MAULWURF_DOWN (GFX_START_ROCKSHEROES + 4*HEROES_PER_LINE + 8) +#define GFX_MAULWURF_UP (GFX_START_ROCKSHEROES + 4*HEROES_PER_LINE +12) +#define GFX_MAULWURF_LEFT (GFX_START_ROCKSHEROES + 5*HEROES_PER_LINE + 8) +#define GFX_MAULWURF_RIGHT (GFX_START_ROCKSHEROES + 5*HEROES_PER_LINE +12) +#define GFX_PINGUIN_DOWN (GFX_START_ROCKSHEROES + 7*HEROES_PER_LINE + 8) +#define GFX_PINGUIN_UP (GFX_START_ROCKSHEROES + 7*HEROES_PER_LINE +12) +#define GFX_PINGUIN_LEFT (GFX_START_ROCKSHEROES + 8*HEROES_PER_LINE + 8) +#define GFX_PINGUIN_RIGHT (GFX_START_ROCKSHEROES + 8*HEROES_PER_LINE +12) +#define GFX_BLURB_LEFT (GFX_START_ROCKSHEROES + 9*HEROES_PER_LINE + 8) +#define GFX_BLURB_RIGHT (GFX_START_ROCKSHEROES + 9*HEROES_PER_LINE +12) +#define GFX_FLAMMEN_LEFT (GFX_START_ROCKSHEROES + 8*HEROES_PER_LINE + 0) +#define GFX_FLAMMEN_RIGHT (GFX_START_ROCKSHEROES + 9*HEROES_PER_LINE + 0) +#define GFX_FLAMMEN_UP (GFX_START_ROCKSHEROES +10*HEROES_PER_LINE + 0) +#define GFX_FLAMMEN_DOWN (GFX_START_ROCKSHEROES +11*HEROES_PER_LINE + 0) + +/* graphics from "RocksFont" */ +#define GFX_CHAR_START (GFX_START_ROCKSFONT) #define GFX_CHAR_ASCII0 (GFX_CHAR_START-32) #define GFX_CHAR_AUSRUF (GFX_CHAR_ASCII0+33) #define GFX_CHAR_ZOLL (GFX_CHAR_ASCII0+34) @@ -714,7 +786,7 @@ extern char *progname; #define SC_KAEFER 2 #define SC_FLIEGER 3 #define SC_MAMPFER 4 -#define SC_ZOMBIE 5 +#define SC_ROBOT 5 #define SC_PACMAN 6 #define SC_KOKOSNUSS 7 #define SC_DYNAMIT 8 @@ -783,10 +855,7 @@ extern char *progname; (s)==SND_NETWORK || (s)==SND_CZARDASZ || \ (s)==SND_TYGER || (s)==SND_VOYAGER || \ (s)==SND_TWILIGHT) -extern char *sound_name[NUM_SOUNDS]; -/* this structure contains the sound data for the sound server */ -extern struct SoundInfo Sound[NUM_SOUNDS]; /* directions for moving */ #define MV_NO_MOVING 0 @@ -822,44 +891,6 @@ extern struct SoundInfo Sound[NUM_SOUNDS]; #define EMU_BOULDERDASH 1 #define EMU_SOKOBAN 2 -/* values for the joystick */ -#define JOYSTICK_OFF 0 -#define JOYSTICK_AVAILABLE 1 -#ifdef __FreeBSD__ -#include -#define DEV_JOYSTICK_0 "/dev/joy0" -#define DEV_JOYSTICK_1 "/dev/joy1" -#else -#define DEV_JOYSTICK_0 "/dev/js0" -#define DEV_JOYSTICK_1 "/dev/js1" -#endif - -/* get these values from the program 'js' from the joystick package, */ -/* set JOYSTICK_PERCENT to a threshold appropriate for your joystick */ -#define JOYSTICK_XLEFT 30 -#define JOYSTICK_XRIGHT 1250 -#define JOYSTICK_XMIDDLE 530 -#define JOYSTICK_YUPPER 40 -#define JOYSTICK_YLOWER 1440 -#define JOYSTICK_YMIDDLE 680 -#define JOYSTICK_PERCENT 25 -#define JOY_LEFT MV_LEFT -#define JOY_RIGHT MV_RIGHT -#define JOY_UP MV_UP -#define JOY_DOWN MV_DOWN -#define JOY_BUTTON_1 16 -#define JOY_BUTTON_2 32 -#define JOY_BUTTON (JOY_BUTTON_1 | JOY_BUTTON_2) -#define JOY_BUTTON_NOT_PRESSED 0 -#define JOY_BUTTON_PRESSED 1 -#define JOY_BUTTON_NEW_PRESSED 2 -#define JOY_BUTTON_NEW_RELEASED 3 - -#ifdef NO_JOYSTICK -#define JOYSTICK_STATUS JOYSTICK_OFF -#else -#define JOYSTICK_STATUS JOYSTICK_AVAILABLE -#endif #ifndef GAME_DIR #define GAME_DIR "." @@ -932,6 +963,7 @@ extern struct SoundInfo Sound[NUM_SOUNDS]; #define MB_PRESSED TRUE #define MB_MENU_CHOICE FALSE #define MB_MENU_MARK TRUE +#define MB_MENU_INITIALIZE (-1) #define MB_LEFT 1 #define MB_MIDDLE 2 #define MB_RIGHT 3 @@ -941,10 +973,6 @@ extern struct SoundInfo Sound[NUM_SOUNDS]; #define KEY_RELEASED FALSE #define KEY_PRESSED TRUE -/* values for focus_status */ -#define FOCUS_OUT FALSE -#define FOCUS_IN TRUE - /* values for redraw_mask */ #define REDRAW_ALL (1L<<0) #define REDRAW_FIELD (1L<<1) @@ -1003,4 +1031,8 @@ extern struct SoundInfo Sound[NUM_SOUNDS]; #define DOOR_GFX_PAGEY1 0 #define DOOR_GFX_PAGEY2 DYSIZE +/* für DrawGraphicAnimation (tools.c) und AnimateToon (cartoons.c) */ +#define ANIM_NORMAL 0 +#define ANIM_OSCILLATE 1 + #endif diff --git a/src/misc.c b/src/misc.c index 61683e6c..b9127322 100644 --- a/src/misc.c +++ b/src/misc.c @@ -15,6 +15,8 @@ #include "misc.h" #include "tools.h" #include "sound.h" +#include "random.h" + #include #include #include @@ -116,13 +118,6 @@ BOOL FrameReached(long *frame_counter_var, int frame_delay) return(FALSE); } -unsigned long be2long(unsigned long *be) /* big-endian -> longword */ -{ - unsigned char *ptr = (unsigned char *)be; - - return(ptr[0]<<24 | ptr[1]<<16 | ptr[2]<<8 | ptr[3]); -} - char *int2str(int ct, int nr) { static char str[20]; @@ -143,7 +138,7 @@ unsigned int SimpleRND(unsigned int max) unsigned int RND(unsigned int max) { - return(rand() % max); + return(random_linux_libc() % max); } unsigned int InitRND(long seed) @@ -153,12 +148,12 @@ unsigned int InitRND(long seed) if (seed==NEW_RANDOMIZE) { gettimeofday(¤t_time,NULL); - srand((unsigned int) current_time.tv_usec); + srandom_linux_libc((unsigned int) current_time.tv_usec); return((unsigned int) current_time.tv_usec); } else { - srand((unsigned int) seed); + srandom_linux_libc((unsigned int) seed); return((unsigned int) seed); } } @@ -172,329 +167,3 @@ char *GetLoginName() else return(pwd->pw_name); } - -void InitAnimation() -{ - HandleAnimation(ANIM_START); -} - -void StopAnimation() -{ - HandleAnimation(ANIM_STOP); -} - -void DoAnimation() -{ - HandleAnimation(ANIM_CONTINUE); -} - -void HandleAnimation(int mode) -{ - static long animstart_delay = -1; - static long animstart_delay_value = 0; - static BOOL anim_restart = TRUE; - static BOOL reset_delay = TRUE; - static int toon_nr = 0; - int draw_mode; - -/* - if (!toons_on || game_status==PLAYING) - return; -*/ - -/* - if (!toons_on || tape.playing || tape.recording) - return; -*/ - - if (!toons_on) - return; - - switch(mode) - { - case ANIM_START: - anim_restart = TRUE; - reset_delay = TRUE; - - /* Fill empty backbuffer for animation functions */ - if (direct_draw_on && game_status==PLAYING) - { - int xx,yy; - - drawto_field = backbuffer; - - for(xx=0;xxdirection & (ANIMDIR_LEFT | ANIMDIR_RIGHT)); - vert_move = (anim->direction & (ANIMDIR_UP | ANIMDIR_DOWN)); - anim_delay_value = 100/anim->frames_per_second; - frame = 0; - - if (horiz_move) - { - if (anim->position==ANIMPOS_UP) - pos_y = 0; - else if (anim->position==ANIMPOS_DOWN) - pos_y = FULL_SYSIZE-anim->height; - else if (anim->position==ANIMPOS_UPPER) - pos_y = SimpleRND((FULL_SYSIZE-anim->height)/2); - else - pos_y = SimpleRND(FULL_SYSIZE-anim->height); - - if (anim->direction==ANIMDIR_RIGHT) - { - delta_x = anim->stepsize; - pos_x = -anim->width+delta_x; - } - else - { - delta_x = -anim->stepsize; - pos_x = FULL_SXSIZE+delta_x; - } - delta_y = 0; - } - else - { - if (anim->position==ANIMPOS_LEFT) - pos_x = 0; - else if (anim->position==ANIMPOS_RIGHT) - pos_x = FULL_SXSIZE-anim->width; - else - pos_x = SimpleRND(FULL_SXSIZE-anim->width); - - if (anim->direction==ANIMDIR_DOWN) - { - delta_y = anim->stepsize; - pos_y = -anim->height+delta_y; - } - else - { - delta_y = -anim->stepsize; - pos_y = FULL_SYSIZE+delta_y; - } - delta_x = 0; - } - } - - if (pos_x <= -anim->width - anim->stepsize || - pos_x >= FULL_SXSIZE + anim->stepsize || - pos_y <= -anim->height - anim->stepsize || - pos_y >= FULL_SYSIZE + anim->stepsize) - return(TRUE); - - if (!DelayReached(&anim_delay,anim_delay_value)) - { - if (game_status==HELPSCREEN && !restart) - DrawAnim(src_x+cut_x,src_y+cut_y, width,height, - REAL_SX+dest_x,REAL_SY+dest_y, pad_x,pad_y); - - return(FALSE); - } - - if (pos_x<-anim->width) - pos_x = -anim->width; - else if (pos_x>FULL_SXSIZE) - pos_x = FULL_SXSIZE; - if (pos_y<-anim->height) - pos_y = -anim->height; - else if (pos_y>FULL_SYSIZE) - pos_y = FULL_SYSIZE; - - pad_x = (horiz_move ? anim->stepsize : 0); - pad_y = (vert_move ? anim->stepsize : 0); - src_x = anim->src_x + frame * anim->width; - src_y = anim->src_y; - dest_x = pos_x; - dest_y = pos_y; - cut_x = cut_y = 0; - width = anim->width; - height = anim->height; - - if (pos_x<0) - { - dest_x = 0; - width += pos_x; - cut_x = -pos_x; - } - else if (pos_x>FULL_SXSIZE-anim->width) - width -= (pos_x - (FULL_SXSIZE-anim->width)); - - if (pos_y<0) - { - dest_y = 0; - height += pos_y; - cut_y = -pos_y; - } - else if (pos_y>FULL_SYSIZE-anim->height) - height -= (pos_y - (FULL_SYSIZE-anim->height)); - - DrawAnim(src_x+cut_x,src_y+cut_y, width,height, - REAL_SX+dest_x,REAL_SY+dest_y, pad_x,pad_y); - - pos_x += delta_x; - pos_y += delta_y; - frame += frame_step; - - if (frame<0 || frame>=anim->frames) - { - if (anim->pingpong) - { - frame_step *= -1; - frame = (frame<0 ? 1 : anim->frames-2); - } - else - frame = (frame<0 ? anim->frames-1 : 0); - } - - return(FALSE); -} - -void DrawAnim(int src_x, int src_y, int width, int height, - int dest_x, int dest_y, int pad_x, int pad_y) -{ - int buf_x = DOOR_GFX_PAGEX3, buf_y = DOOR_GFX_PAGEY1; - -#if 1 - /* special method to avoid flickering interference with BackToFront() */ - XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,dest_x-pad_x,dest_y-pad_y, - width+2*pad_x,height+2*pad_y, buf_x,buf_y); - XSetClipOrigin(display,clip_gc[PIX_TOONS],dest_x-src_x,dest_y-src_y); - XCopyArea(display,pix[PIX_TOONS],backbuffer,clip_gc[PIX_TOONS], - src_x,src_y, width,height, dest_x,dest_y); - XCopyArea(display,backbuffer,window,gc, dest_x-pad_x,dest_y-pad_y, - width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y); - BackToFront(); - XCopyArea(display,pix[PIX_DB_DOOR],backbuffer,gc, buf_x,buf_y, - width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y); -#else - /* normal method, causing flickering interference with BackToFront() */ - XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,dest_x-pad_x,dest_y-pad_y, - width+2*pad_x,height+2*pad_y, buf_x,buf_y); - XSetClipOrigin(display,clip_gc[PIX_TOONS], - buf_x-src_x+pad_x,buf_y-src_y+pad_y); - XCopyArea(display,pix[PIX_TOONS],pix[PIX_DB_DOOR],clip_gc[PIX_TOONS], - src_x,src_y, width,height, buf_x+pad_x,buf_y+pad_y); - XCopyArea(display,pix[PIX_DB_DOOR],window,gc, buf_x,buf_y, - width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y); -#endif - - XFlush(display); -} diff --git a/src/misc.h b/src/misc.h index 685c2b83..1a2f29f0 100644 --- a/src/misc.h +++ b/src/misc.h @@ -17,69 +17,6 @@ #include "main.h" -/* values for cartoon figures */ -#define NUM_TOONS 6 - -#define DWARF_XSIZE 40 -#define DWARF_YSIZE 48 -#define DWARF_X 2 -#define DWARF_Y 72 -#define DWARF2_Y 186 -#define DWARF_FRAMES 8 -#define DWARF_FPS 10 -#define DWARF_STEPSIZE 4 -#define JUMPER_XSIZE 48 -#define JUMPER_YSIZE 56 -#define JUMPER_X 2 -#define JUMPER_Y 125 -#define JUMPER_FRAMES 8 -#define JUMPER_FPS 10 -#define JUMPER_STEPSIZE 4 -#define CLOWN_XSIZE 80 -#define CLOWN_YSIZE 110 -#define CLOWN_X 327 -#define CLOWN_Y 10 -#define CLOWN_FRAMES 1 -#define CLOWN_FPS 10 -#define CLOWN_STEPSIZE 4 -#define BIRD_XSIZE 32 -#define BIRD_YSIZE 30 -#define BIRD1_X 2 -#define BIRD1_Y 2 -#define BIRD2_X 2 -#define BIRD2_Y 37 -#define BIRD_FRAMES 8 -#define BIRD_FPS 20 -#define BIRD_STEPSIZE 4 - -#define ANIMDIR_LEFT 1 -#define ANIMDIR_RIGHT 2 -#define ANIMDIR_UP 4 -#define ANIMDIR_DOWN 8 - -#define ANIMPOS_ANY 0 -#define ANIMPOS_LEFT 1 -#define ANIMPOS_RIGHT 2 -#define ANIMPOS_UP 4 -#define ANIMPOS_DOWN 8 -#define ANIMPOS_UPPER 16 - -#define ANIM_START 0 -#define ANIM_CONTINUE 1 -#define ANIM_STOP 2 - -struct AnimInfo -{ - int width, height; - int src_x, src_y; - int frames; - int frames_per_second; - int stepsize; - BOOL pingpong; - int direction; - int position; -}; - #define INIT_COUNTER 0 #define READ_COUNTER_100 1 #define READ_COUNTER_1000 2 @@ -96,18 +33,10 @@ void WaitCounter2(long); void Delay(long); BOOL DelayReached(long *, int); BOOL FrameReached(long *, int); -unsigned long be2long(unsigned long *); char *int2str(int, int); unsigned int SimpleRND(unsigned int); unsigned int RND(unsigned int); unsigned int InitRND(long); char *GetLoginName(void); -void InitAnimation(void); -void StopAnimation(void); -void DoAnimation(void); -void HandleAnimation(int); -BOOL AnimateToon(int, BOOL); -void DrawAnim(int, int, int, int, int, int, int, int); - #endif diff --git a/src/random.c b/src/random.c new file mode 100644 index 00000000..bbac6e5b --- /dev/null +++ b/src/random.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * This is derived from the Berkeley source: + * @(#)random.c 5.5 (Berkeley) 7/6/88 + * It was reworked for the GNU C Library by Roland McGrath. + */ + +#include +#include +#include +#include +#include + +#include "random.h" + + +/* An improved random number generation package. In addition to the standard + rand()/srand() like interface, this package also has a special state info + interface. The initstate() routine is called with a seed, an array of + bytes, and a count of how many bytes are being passed in; this array is + then initialized to contain information for random number generation with + that much state information. Good sizes for the amount of state + information are 32, 64, 128, and 256 bytes. The state can be switched by + calling the setstate() function with the same array as was initiallized + with initstate(). By default, the package runs with 128 bytes of state + information and generates far better random numbers than a linear + congruential generator. If the amount of state information is less than + 32 bytes, a simple linear congruential R.N.G. is used. Internally, the + state information is treated as an array of longs; the zeroeth element of + the array is the type of R.N.G. being used (small integer); the remainder + of the array is the state information for the R.N.G. Thus, 32 bytes of + state information will give 7 longs worth of state information, which will + allow a degree seven polynomial. (Note: The zeroeth word of state + information also has some other information stored in it; see setstate + for details). The random number generation technique is a linear feedback + shift register approach, employing trinomials (since there are fewer terms + to sum up that way). In this approach, the least significant bit of all + the numbers in the state table will act as a linear feedback shift register, + and will have period 2^deg - 1 (where deg is the degree of the polynomial + being used, assuming that the polynomial is irreducible and primitive). + The higher order bits will have longer periods, since their values are + also influenced by pseudo-random carries out of the lower bits. The + total period of the generator is approximately deg*(2**deg - 1); thus + doubling the amount of state information has a vast influence on the + period of the generator. Note: The deg*(2**deg - 1) is an approximation + only good for large deg, when the period of the shift register is the + dominant factor. With deg equal to seven, the period is actually much + longer than the 7*(2**7 - 1) predicted by this formula. */ + + + +/* For each of the currently supported random number generators, we have a + break value on the amount of state information (you need at least thi + bytes of state info to support this random number generator), a degree for + the polynomial (actually a trinomial) that the R.N.G. is based on, and + separation between the two lower order coefficients of the trinomial. */ + +/* Linear congruential. */ +#define TYPE_0 0 +#define BREAK_0 8 +#define DEG_0 0 +#define SEP_0 0 + +/* x**7 + x**3 + 1. */ +#define TYPE_1 1 +#define BREAK_1 32 +#define DEG_1 7 +#define SEP_1 3 + +/* x**15 + x + 1. */ +#define TYPE_2 2 +#define BREAK_2 64 +#define DEG_2 15 +#define SEP_2 1 + +/* x**31 + x**3 + 1. */ +#define TYPE_3 3 +#define BREAK_3 128 +#define DEG_3 31 +#define SEP_3 3 + +/* x**63 + x + 1. */ +#define TYPE_4 4 +#define BREAK_4 256 +#define DEG_4 63 +#define SEP_4 1 + + +/* Array versions of the above information to make code run faster. + Relies on fact that TYPE_i == i. */ + +#define MAX_TYPES 5 /* Max number of types above. */ + + + +/* Initially, everything is set up as if from: + initstate(1, randtbl, 128); + Note that this initialization takes advantage of the fact that srandom + advances the front and rear pointers 10*rand_deg times, and hence the + rear pointer which starts at 0 will also end up at zero; thus the zeroeth + element of the state information, which contains info about the current + position of the rear pointer is just + (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */ + +static long int randtbl[DEG_3 + 1] = +{ + TYPE_3, + -851904987, -43806228, -2029755270, 1390239686, -1912102820, + -485608943, 1969813258, -1590463333, -1944053249, 455935928, 508023712, + -1714531963, 1800685987, -2015299881, 654595283, -1149023258, + -1470005550, -1143256056, -1325577603, -1568001885, 1275120390, + -607508183, -205999574, -1696891592, 1492211999, -1528267240, + -952028296, -189082757, 362343714, 1424981831, 2039449641, +}; + +/* FPTR and RPTR are two pointers into the state info, a front and a rear + pointer. These two pointers are always rand_sep places aparts, as they + cycle through the state information. (Yes, this does mean we could get + away with just one pointer, but the code for random is more efficient + this way). The pointers are left positioned as they would be from the call: + initstate(1, randtbl, 128); + (The position of the rear pointer, rptr, is really 0 (as explained above + in the initialization of randtbl) because the state table pointer is set + to point to randtbl[1] (as explained below).) */ + +static long int *fptr = &randtbl[SEP_3 + 1]; +static long int *rptr = &randtbl[1]; + + + +/* The following things are the pointer to the state information table, + the type of the current generator, the degree of the current polynomial + being used, and the separation between the two pointers. + Note that for efficiency of random, we remember the first location of + the state information, not the zeroeth. Hence it is valid to access + state[-1], which is used to store the type of the R.N.G. + Also, we remember the last location, since this is more efficient than + indexing every time to find the address of the last element to see if + the front and rear pointers have wrapped. */ + +static long int *state = &randtbl[1]; + +static int rand_type = TYPE_3; +static int rand_deg = DEG_3; +static int rand_sep = SEP_3; + +static long int *end_ptr = &randtbl[sizeof(randtbl) / sizeof(randtbl[0])]; + +/* Initialize the random number generator based on the given seed. If the + type is the trivial no-state-information type, just remember the seed. + Otherwise, initializes state[] based on the given "seed" via a linear + congruential generator. Then, the pointers are set to known locations + that are exactly rand_sep places apart. Lastly, it cycles the state + information a given number of times to get rid of any initial dependencies + introduced by the L.C.R.N.G. Note that the initialization of randtbl[] + for default usage relies on values produced by this routine. */ + +void srandom_linux_libc(unsigned int x) +{ + state[0] = x; + if (rand_type != TYPE_0) + { + register long int i; + for (i = 1; i < rand_deg; ++i) + state[i] = (1103515145 * state[i - 1]) + 12345; + fptr = &state[rand_sep]; + rptr = &state[0]; + for (i = 0; i < 10 * rand_deg; ++i) + (void) random_linux_libc(); + } +} + +/* If we are using the trivial TYPE_0 R.N.G., just do the old linear + congruential bit. Otherwise, we do our fancy trinomial stuff, which is the + same in all ther other cases due to all the global variables that have been + set up. The basic operation is to add the number at the rear pointer into + the one at the front pointer. Then both pointers are advanced to the next + location cyclically in the table. The value returned is the sum generated, + reduced to 31 bits by throwing away the "least random" low bit. + Note: The code takes advantage of the fact that both the front and + rear pointers can't wrap on the same call by not testing the rear + pointer if the front one has wrapped. Returns a 31-bit random number. */ + +long int random_linux_libc() +{ + if (rand_type == TYPE_0) + { + state[0] = ((state[0] * 1103515245) + 12345) & LONG_MAX; + return state[0]; + } + else + { + long int i; + *fptr += *rptr; + /* Chucking least random bit. */ + i = (*fptr >> 1) & LONG_MAX; + ++fptr; + if (fptr >= end_ptr) + { + fptr = state; + ++rptr; + } + else + { + ++rptr; + if (rptr >= end_ptr) + rptr = state; + } + return i; + } +} diff --git a/src/random.h b/src/random.h new file mode 100644 index 00000000..0f99fffd --- /dev/null +++ b/src/random.h @@ -0,0 +1,21 @@ +/*********************************************************** +* Rocks'n'Diamonds -- McDuffin Strikes Back! * +*----------------------------------------------------------* +* ©1995 Artsoft Development * +* Holger Schemel * +* 33659 Bielefeld-Senne * +* Telefon: (0521) 493245 * +* eMail: aeglos@valinor.owl.de * +* aeglos@uni-paderborn.de * +* q99492@pbhrzx.uni-paderborn.de * +*----------------------------------------------------------* +* random.h * +***********************************************************/ + +#ifndef RANDOM_H +#define RANDOM_H + +void srandom_linux_libc(unsigned int); +long int random_linux_libc(void); + +#endif diff --git a/src/screens.c b/src/screens.c index 3a8f0bb5..bfb4f117 100644 --- a/src/screens.c +++ b/src/screens.c @@ -22,6 +22,8 @@ #include "files.h" #include "buttons.h" #include "tape.h" +#include "joystick.h" +#include "cartoons.h" void DrawHeadline() { @@ -71,7 +73,7 @@ void DrawMainMenu() FadeToFront(); InitAnimation(); - HandleMainMenu(0,0,0,0,MB_MENU_MARK); + HandleMainMenu(0,0,0,0,MB_MENU_INITIALIZE); TapeStop(); if (TAPE_IS_EMPTY(tape)) @@ -80,6 +82,7 @@ void DrawMainMenu() OpenDoor(DOOR_CLOSE_1 | DOOR_OPEN_2); + ClearEventQueue(); XAutoRepeatOn(display); } @@ -89,12 +92,15 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) static int redraw = TRUE; int x = (mx+32-SX)/32, y = (my+32-SY)/32; - if (redraw || (!mx && !my && !dx && !dy)) + if (redraw || button == MB_MENU_INITIALIZE) { DrawGraphic(0,choice-1,GFX_KUGEL_ROT); redraw = FALSE; } + if (button == MB_MENU_INITIALIZE) + return; + if (dx || dy) { if (dx && choice==4) @@ -223,7 +229,8 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) game_status = EXITGAME; } - redraw = TRUE; + if (!button) + redraw = TRUE; } } BackToFront(); @@ -244,7 +251,12 @@ static int helpscreen_frame[MAX_HELPSCREEN_ELS]; static int helpscreen_delay[MAX_HELPSCREEN_ELS]; static int helpscreen_action[] = { - GFX_SPIELFIGUR,1,100, HA_NEXT, + GFX_SPIELER_DOWN,4,2, + GFX_SPIELER_UP,4,2, + GFX_SPIELER_LEFT,4,2, + GFX_SPIELER_RIGHT,4,2, + GFX_SPIELER_PUSH_LEFT,4,2, + GFX_SPIELER_PUSH_RIGHT,4,2, HA_NEXT, GFX_ERDREICH,1,100, HA_NEXT, GFX_LEERRAUM,1,100, HA_NEXT, GFX_MORAST_LEER,1,100, HA_NEXT, @@ -254,7 +266,7 @@ static int helpscreen_action[] = GFX_MAUER_L1,3,4, GFX_MAUERWERK,1,20, GFX_LEERRAUM,1,10, HA_NEXT, GFX_UNSICHTBAR,1,100, HA_NEXT, GFX_FELSBODEN,1,100, HA_NEXT, - GFX_CHAR_A,30,3, GFX_CHAR_AUSRUF,32,3, HA_NEXT, + GFX_CHAR_A,30,4, GFX_CHAR_AUSRUF,32,4, HA_NEXT, GFX_EDELSTEIN,2,5, HA_NEXT, GFX_DIAMANT,2,5, HA_NEXT, GFX_EDELSTEIN_BD,2,5, HA_NEXT, @@ -272,9 +284,9 @@ static int helpscreen_action[] = GFX_ERZ_EDEL_LILA,1,50, GFX_EXPLOSION,8,1, GFX_EDELSTEIN_LILA,1,10, HA_NEXT, GFX_GEBLUBBER,4,4, HA_NEXT, - GFX_SCHLUESSEL1,4,33, HA_NEXT, - GFX_PFORTE1,4,33, HA_NEXT, - GFX_PFORTE1X,4,33, HA_NEXT, + GFX_SCHLUESSEL1,4,25, HA_NEXT, + GFX_PFORTE1,4,25, HA_NEXT, + GFX_PFORTE1X,4,25, HA_NEXT, GFX_DYNAMIT_AUS,1,100, HA_NEXT, GFX_DYNAMIT,7,6, GFX_EXPLOSION,8,1, GFX_LEERRAUM,1,10, HA_NEXT, GFX_DYNABOMB+0,4,3, GFX_DYNABOMB+3,1,3, GFX_DYNABOMB+2,1,3, @@ -290,36 +302,53 @@ static int helpscreen_action[] = GFX_KAEFER+5,1,1, GFX_KAEFER+1,1,1, GFX_KAEFER+5,1,1, GFX_KAEFER+6,1,1, GFX_KAEFER+2,1,1, GFX_KAEFER+6,1,1, GFX_KAEFER+7,1,1, GFX_KAEFER+3,1,1, GFX_KAEFER+7,1,1, HA_NEXT, - GFX_BUTTERFLY,1,1, GFX_BUTTERFLY+1,1,1, HA_NEXT, - GFX_FIREFLY,1,1, GFX_FIREFLY+1,1,1, HA_NEXT, + GFX_BUTTERFLY,2,2, HA_NEXT, + GFX_FIREFLY,2,2, HA_NEXT, GFX_PACMAN+0,1,3, GFX_PACMAN+4,1,2, GFX_PACMAN+0,1,3, GFX_PACMAN+1,1,3, GFX_PACMAN+5,1,2, GFX_PACMAN+1,1,3, GFX_PACMAN+2,1,3, GFX_PACMAN+6,1,2, GFX_PACMAN+2,1,3, GFX_PACMAN+3,1,3, GFX_PACMAN+7,1,2, GFX_PACMAN+3,1,3, HA_NEXT, - GFX_MAMPFER+0,4,0, GFX_MAMPFER+3,1,0, GFX_MAMPFER+2,1,0, - GFX_MAMPFER+1,1,0, GFX_MAMPFER+0,1,0, HA_NEXT, - GFX_MAMPFER2+0,4,0, GFX_MAMPFER2+3,1,0, GFX_MAMPFER2+2,1,0, - GFX_MAMPFER2+1,1,0, GFX_MAMPFER2+0,1,0, HA_NEXT, - GFX_ZOMBIE+0,4,0, GFX_ZOMBIE+3,1,0, GFX_ZOMBIE+2,1,0, - GFX_ZOMBIE+1,1,0, GFX_ZOMBIE+0,1,0, HA_NEXT, + GFX_MAMPFER+0,4,1, GFX_MAMPFER+3,1,1, GFX_MAMPFER+2,1,1, + GFX_MAMPFER+1,1,1, GFX_MAMPFER+0,1,1, HA_NEXT, + GFX_MAMPFER2+0,4,1, GFX_MAMPFER2+3,1,1, GFX_MAMPFER2+2,1,1, + GFX_MAMPFER2+1,1,1, GFX_MAMPFER2+0,1,1, HA_NEXT, + GFX_ROBOT+0,4,1, GFX_ROBOT+3,1,1, GFX_ROBOT+2,1,1, + GFX_ROBOT+1,1,1, GFX_ROBOT+0,1,1, HA_NEXT, + GFX_MAULWURF_DOWN,4,2, + GFX_MAULWURF_UP,4,2, + GFX_MAULWURF_LEFT,4,2, + GFX_MAULWURF_RIGHT,4,2, HA_NEXT, + GFX_PINGUIN_DOWN,4,2, + GFX_PINGUIN_UP,4,2, + GFX_PINGUIN_LEFT,4,2, + GFX_PINGUIN_RIGHT,4,2, HA_NEXT, + GFX_SCHWEIN_DOWN,4,2, + GFX_SCHWEIN_UP,4,2, + GFX_SCHWEIN_LEFT,4,2, + GFX_SCHWEIN_RIGHT,4,2, HA_NEXT, + GFX_DRACHE_DOWN,4,2, + GFX_DRACHE_UP,4,2, + GFX_DRACHE_LEFT,4,2, + GFX_DRACHE_RIGHT,4,2, HA_NEXT, + GFX_SONDE_START,8,1, HA_NEXT, GFX_ABLENK,4,1, HA_NEXT, - GFX_BIRNE_AUS,1,33, GFX_BIRNE_EIN,1,33, HA_NEXT, - GFX_ZEIT_VOLL,1,33, GFX_ZEIT_LEER,1,33, HA_NEXT, - GFX_TROPFEN,1,33, GFX_AMOEBING,4,1, GFX_AMOEBE_LEBT,1,10, HA_NEXT, + GFX_BIRNE_AUS,1,25, GFX_BIRNE_EIN,1,25, HA_NEXT, + GFX_ZEIT_VOLL,1,25, GFX_ZEIT_LEER,1,25, HA_NEXT, + GFX_TROPFEN,1,25, GFX_AMOEBING,4,1, GFX_AMOEBE_LEBT,1,10, HA_NEXT, GFX_AMOEBE_TOT+2,2,50, GFX_AMOEBE_TOT,2,50, HA_NEXT, GFX_AMOEBE_LEBT,4,40, HA_NEXT, GFX_AMOEBE_LEBT,1,10, GFX_AMOEBING,4,2, HA_NEXT, - GFX_AMOEBE_LEBT,1,33, GFX_AMOEBE_TOT,1,33, GFX_EXPLOSION,8,1, + GFX_AMOEBE_LEBT,1,25, GFX_AMOEBE_TOT,1,25, GFX_EXPLOSION,8,1, GFX_DIAMANT,1,10, HA_NEXT, GFX_LIFE,1,100, HA_NEXT, GFX_LIFE_ASYNC,1,100, HA_NEXT, GFX_SIEB_LEER,4,2, HA_NEXT, GFX_SIEB2_LEER,4,2, HA_NEXT, GFX_AUSGANG_ZU,1,100, GFX_AUSGANG_ACT,4,2, - GFX_AUSGANG_AUF+0,4,1, GFX_AUSGANG_AUF+3,1,1, - GFX_AUSGANG_AUF+2,1,1, GFX_AUSGANG_AUF+1,1,1, HA_NEXT, - GFX_AUSGANG_AUF+0,4,1, GFX_AUSGANG_AUF+3,1,1, - GFX_AUSGANG_AUF+2,1,1, GFX_AUSGANG_AUF+1,1,1, HA_NEXT, + GFX_AUSGANG_AUF+0,4,2, GFX_AUSGANG_AUF+3,1,2, + GFX_AUSGANG_AUF+2,1,2, GFX_AUSGANG_AUF+1,1,2, HA_NEXT, + GFX_AUSGANG_AUF+0,4,2, GFX_AUSGANG_AUF+3,1,2, + GFX_AUSGANG_AUF+2,1,2, GFX_AUSGANG_AUF+1,1,2, HA_NEXT, HA_END }; static char *helpscreen_eltext[][2] = @@ -362,6 +391,11 @@ static char *helpscreen_eltext[][2] = {"Cruncher: Eats diamonds and you,", "if you're not careful"}, {"Cruncher (BD style):", "Eats almost everything"}, {"Robot: Tries to kill the player", ""}, + {"The mole: You must guide him savely","to the exit; he will follow you"}, + {"The penguin: Guide him to the exit,","but keep him away from monsters!"}, + {"The Pig: Harmless, but eats all", "gems it can get"}, + {"The Dragon: Breathes fire,", "especially to some monsters"}, + {"Sonde: Follows you everywhere;", "harmless, but may block your way"}, {"Magic Wheel: Touch it to get rid of","the robots for some seconds"}, {"Light Bulb: All of them must be", "switched on to finish a level"}, {"Extra Time Orb: Adds some seconds", "to the time available for the level"}, @@ -394,7 +428,7 @@ static int helpscreen_musicpos; void DrawHelpScreenElAction(int start) { int i = 0, j = 0; - int frame, delay, graphic; + int frame, graphic; int xstart = SX+16, ystart = SY+64+2*32, ystep = TILEY+4; while(helpscreen_action[j] != HA_END) @@ -427,8 +461,7 @@ void DrawHelpScreenElAction(int start) helpscreen_frame[i-start] = helpscreen_action[j++]-1; } - delay = helpscreen_action[j++]; - helpscreen_delay[i-start] = delay; + helpscreen_delay[i-start] = helpscreen_action[j++] - 1; if (helpscreen_action[j] == HA_NEXT) { @@ -628,7 +661,7 @@ void HandleHelpScreen(int button) } else { - if (DelayReached(&hs_delay,3)) + if (DelayReached(&hs_delay,GAME_FRAME_DELAY)) { if (helpscreen_state0) + else if ((key==XK_Delete || key==XK_BackSpace) && xpos>0) { xpos--; player.alias_name[xpos] = 0; @@ -721,7 +754,7 @@ void DrawChooseLevel() FadeToFront(); InitAnimation(); - HandleChooseLevel(0,0,0,0,MB_MENU_MARK); + HandleChooseLevel(0,0,0,0,MB_MENU_INITIALIZE); } void HandleChooseLevel(int mx, int my, int dx, int dy, int button) @@ -730,12 +763,21 @@ void HandleChooseLevel(int mx, int my, int dx, int dy, int button) static int redraw = TRUE; int x = (mx+32-SX)/32, y = (my+32-SY)/32; + if (button == MB_MENU_INITIALIZE) + { + redraw = TRUE; + choice = leveldir_nr + 3; + } + if (redraw) { DrawGraphic(0,choice-1,GFX_KUGEL_ROT); redraw = FALSE; } + if (button == MB_MENU_INITIALIZE) + return; + if (dx || dy) { if (dy) @@ -885,7 +927,7 @@ void DrawSetupScreen() FadeToFront(); InitAnimation(); - HandleSetupScreen(0,0,0,0,MB_MENU_MARK); + HandleSetupScreen(0,0,0,0,MB_MENU_INITIALIZE); } void HandleSetupScreen(int mx, int my, int dx, int dy, int button) @@ -897,12 +939,18 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button) int pos_empty = SETUP_SCREEN_POS_EMPTY + 1; int pos_end = SETUP_SCREEN_POS_END + 1; + if (button == MB_MENU_INITIALIZE) + redraw = TRUE; + if (redraw) { DrawGraphic(0,choice-1,GFX_KUGEL_ROT); redraw = FALSE; } + if (button == MB_MENU_INITIALIZE) + return; + if (dx || dy) { if (dy) @@ -1197,7 +1245,7 @@ void HandleGameActions() if (LevelSolved) GameWon(); - if (GameOver && !TAPE_IS_STOPPED(tape)) + if (PlayerGone && !TAPE_IS_STOPPED(tape)) TapeStop(); GameActions(); @@ -1246,6 +1294,7 @@ void HandleVideoButtons(int mx, int my, int button) tape.pos[tape.counter].delay = tape.delay_played; tape.playing = FALSE; tape.recording = TRUE; + tape.changed = TRUE; DrawVideoDisplay(VIDEO_STATE_PLAY_OFF | VIDEO_STATE_REC_ON,0); } diff --git a/src/sound.c b/src/sound.c index dc14ad55..3ee23f30 100644 --- a/src/sound.c +++ b/src/sound.c @@ -563,12 +563,19 @@ int ulaw_to_linear(unsigned char ulawbyte) /*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/ +static unsigned long be2long(unsigned long *be) /* big-endian -> longword */ +{ + unsigned char *ptr = (unsigned char *)be; + + return(ptr[0]<<24 | ptr[1]<<16 | ptr[2]<<8 | ptr[3]); +} + BOOL LoadSound(struct SoundInfo *snd_info) { FILE *file; char filename[256]; char *sound_ext = "8svx"; - struct SoundHeader_8SVX *snd_hdr; + struct SoundHeader_8SVX *sound_header; unsigned char *ptr; sprintf(filename,"%s/%s.%s",SND_PATH,snd_info->name,sound_ext); @@ -609,40 +616,48 @@ BOOL LoadSound(struct SoundInfo *snd_info) fclose(file); - snd_hdr = (struct SoundHeader_8SVX *)snd_info->file_ptr; + sound_header = (struct SoundHeader_8SVX *)snd_info->file_ptr; - if (strncmp(snd_hdr->magic_FORM,"FORM",4) || - snd_info->file_len!=be2long(&snd_hdr->chunk_size)+8 || - strncmp(snd_hdr->magic_8SVX,"8SVX",4)) + if (strncmp(sound_header->magic_FORM,"FORM",4) || + snd_info->file_len != be2long(&sound_header->chunk_size)+8 || + strncmp(sound_header->magic_8SVX,"8SVX",4)) { fprintf(stderr,"%s: '%s' is not an IFF/8SVX file or broken- no sounds\n", progname,filename); return(FALSE); } - ptr = (unsigned char *)snd_info->file_ptr; + ptr = snd_info->file_ptr + 12; - while(ptr<(unsigned char *)snd_info->file_ptr+snd_info->file_len) + while(ptr < (unsigned char *)(snd_info->file_ptr + snd_info->file_len)) { if (!strncmp(ptr,"VHDR",4)) { - ptr+=be2long((unsigned long *)(ptr+4)); + ptr += be2long((unsigned long *)(ptr + 4)) + 8; + continue; } - if (!strncmp(ptr,"ANNO",4)) + else if (!strncmp(ptr,"ANNO",4)) { - ptr+=be2long((unsigned long *)(ptr+4)); + ptr += be2long((unsigned long *)(ptr + 4)) + 8; + continue; } - if (!strncmp(ptr,"CHAN",4)) + else if (!strncmp(ptr,"CHAN",4)) { - ptr+=be2long((unsigned long *)(ptr+4)); + ptr += be2long((unsigned long *)(ptr + 4)) + 8; + continue; } - if (!strncmp(ptr,"BODY",4)) + else if (!strncmp(ptr,"BODY",4)) { - snd_info->data_ptr = ptr+8; - snd_info->data_len = be2long((unsigned long *)(ptr+4)); + snd_info->data_ptr = ptr + 8; + snd_info->data_len = be2long((unsigned long *)(ptr + 4)); return(TRUE); } - ptr++; + else + { + /* other chunk not recognized here */ + ptr += be2long((unsigned long *)(ptr + 4)) + 8; + continue; + } } return(FALSE); diff --git a/src/sound.h b/src/sound.h index 384f77cf..089c44fb 100644 --- a/src/sound.h +++ b/src/sound.h @@ -110,8 +110,9 @@ struct SoundHeader_8SVX struct SoundInfo { - char *name; - char *file_ptr, *data_ptr; + unsigned char *name; + unsigned char *file_ptr; + char *data_ptr; long file_len, data_len; }; @@ -131,9 +132,6 @@ struct SoundControl char *data_ptr; }; -/* function from "misc.c" */ -unsigned long be2long(unsigned long *); - /* sound server functions */ void SoundServer(void); void SoundServer_InsertNewSound(struct SoundControl); diff --git a/src/tape.c b/src/tape.c index 35929e88..33713069 100644 --- a/src/tape.c +++ b/src/tape.c @@ -28,10 +28,10 @@ void TapeStartRecording() tape.length = 0; tape.counter = 0; tape.pos[tape.counter].delay = 0; - tape.changed = TRUE; tape.recording = TRUE; tape.playing = FALSE; tape.pausing = FALSE; + tape.changed = TRUE; tape.date = 10000*(zeit2->tm_year%100) + 100*zeit2->tm_mon + zeit2->tm_mday; tape.random_seed = InitRND(NEW_RANDOMIZE); @@ -146,7 +146,7 @@ int TapePlayAction() if (tape.counter>=tape.length) { - TapeStopPlaying(); + TapeStop(); return(0); } @@ -184,7 +184,7 @@ BOOL TapePlayDelay() if (tape.counter>=tape.length) { - TapeStopPlaying(); + TapeStop(); return(TRUE); } diff --git a/src/tools.c b/src/tools.c index 63c027fa..7ffa3c19 100644 --- a/src/tools.c +++ b/src/tools.c @@ -22,6 +22,9 @@ #include "sound.h" #include "misc.h" #include "buttons.h" +#include "joystick.h" +#include "cartoons.h" + #include void BackToFront() @@ -251,9 +254,116 @@ void DrawTextExt(Drawable d, GC gc, int x, int y, } } +void DrawPlayerField() +{ + int x = JX, y = JY; + int sx = SCROLLX(x), sy = SCROLLY(y); + int element = Feld[x][y]; + int graphic, phase; + BOOL draw_thru_mask = FALSE; + + if (PlayerGone) + return; + +#if DEBUG + if (!IN_LEV_FIELD(x,y) || !IN_SCR_FIELD(sx,sy)) + { + printf("DrawPlayerField(): x = %d, y = %d\n",x,y); + printf("DrawPlayerField(): This should never happen!\n"); + return; + } +#endif + + if (element == EL_EXPLODING) + return; + + if (direct_draw_on) + drawto_field = backbuffer; + + /* draw things behind the player (EL_PFORTE* || mole/penguin/pig/dragon) */ + + if (Store[x][y]) + { + DrawGraphic(sx,sy, el2gfx(Store[x][y])); + draw_thru_mask = TRUE; + } + else if (element!=EL_LEERRAUM && element!=EL_DYNAMIT && element!=EL_DYNABOMB) + { + DrawLevelField(x,y); + draw_thru_mask = TRUE; + } + + /* draw player himself */ + + if (PlayerMovDir==MV_LEFT) + graphic = (PlayerPushing ? GFX_SPIELER_PUSH_LEFT : GFX_SPIELER_LEFT); + else if (PlayerMovDir==MV_RIGHT) + graphic = (PlayerPushing ? GFX_SPIELER_PUSH_RIGHT : GFX_SPIELER_RIGHT); + else if (PlayerMovDir==MV_UP) + graphic = GFX_SPIELER_UP; + else /* MV_DOWN || MV_NO_MOVING */ + graphic = GFX_SPIELER_DOWN; + + graphic += PlayerFrame; + + if (draw_thru_mask) + DrawGraphicThruMask(sx,sy, graphic); + else + DrawGraphic(sx,sy, graphic); + + /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */ + + if (element == EL_DYNAMIT || element == EL_DYNABOMB) + { + graphic = el2gfx(element); + + if (element == EL_DYNAMIT) + { + if ((phase = (48-MovDelay[x][y])/6) > 6) + phase = 6; + } + else + { + if ((phase = ((48-MovDelay[x][y])/3) % 8) > 3) + phase = 7-phase; + } + + DrawGraphicThruMask(sx,sy, graphic + phase); + } + + if (direct_draw_on) + { + int dest_x = SX+SCROLLX(x)*TILEX; + int dest_y = SY+SCROLLY(y)*TILEY; + + XCopyArea(display,backbuffer,window,gc, + dest_x,dest_y, TILEX,TILEY, dest_x,dest_y); + drawto_field = window; + } +} + +static int getGraphicAnimationPhase(int frames, int delay, int mode) +{ + int phase; + + if (mode == ANIM_OSCILLATE) + { + int max_anim_frames = frames*2 - 2; + phase = (FrameCounter % (delay * max_anim_frames)) / delay; + phase = (phase < frames ? phase : max_anim_frames - phase); + } + else + phase = (FrameCounter % (delay * frames)) / delay; + + return(phase); +} + void DrawGraphicAnimation(int x, int y, int graphic, int frames, int delay, int mode) { + int phase = getGraphicAnimationPhase(frames, delay, mode); + +/* int phase; if (mode == ANIM_OSCILLATE) @@ -264,6 +374,7 @@ void DrawGraphicAnimation(int x, int y, int graphic, } else phase = (FrameCounter % (delay * frames)) / delay; +*/ if (!(FrameCounter % delay) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y))) DrawGraphic(SCROLLX(x),SCROLLY(y), graphic + phase); @@ -271,6 +382,16 @@ void DrawGraphicAnimation(int x, int y, int graphic, void DrawGraphic(int x, int y, int graphic) { + +#if DEBUG + if (!IN_SCR_FIELD(x,y)) + { + printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic); + printf("DrawGraphic(): This should never happen!\n"); + return; + } +#endif + DrawGraphicExt(drawto_field, gc, x, y, graphic); redraw_tiles++; redraw[x][y] = TRUE; @@ -284,42 +405,77 @@ void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic) void DrawGraphicExtHiRes(Drawable d, GC gc, int x, int y, int graphic) { - if (graphic<0) - XFillRectangle(display,d,gc, x,y, TILEX,TILEY); - else if (graphic<256) + if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN) + { + graphic -= GFX_START_ROCKSSCREEN; XCopyArea(display,pix[PIX_BACK],d,gc, SX+(graphic % GFX_PER_LINE)*TILEX, SY+(graphic / GFX_PER_LINE)*TILEY, TILEX,TILEY, x,y); - else + } + else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES) { - graphic -= 256; + graphic -= GFX_START_ROCKSHEROES; + XCopyArea(display,pix[PIX_HEROES],d,gc, + (graphic % HEROES_PER_LINE)*TILEX, + (graphic / HEROES_PER_LINE)*TILEY, + TILEX,TILEY, x,y); + } + else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT) + { + graphic -= GFX_START_ROCKSFONT; XCopyArea(display,pix[PIX_BIGFONT],d,gc, (graphic % FONT_CHARS_PER_LINE)*TILEX, (graphic / FONT_CHARS_PER_LINE)*TILEY + FC_SPECIAL1*TILEY*FONT_LINES_PER_FONT, TILEX,TILEY, x,y); } + else + XFillRectangle(display,d,gc, x,y, TILEX,TILEY); } void DrawGraphicThruMask(int x, int y, int graphic) { int src_x,src_y, dest_x,dest_y; - if (graphic<0 || graphic>255) +#if DEBUG + if (!IN_SCR_FIELD(x,y)) { - DrawGraphic(x,y,graphic); + printf("DrawGraphicThruMask(): x = %d, y = %d\n",x,y); + printf("DrawGraphicThruMask(): This should never happen!\n"); return; } +#endif - src_x = SX+(graphic % GFX_PER_LINE)*TILEX; - src_y = SY+(graphic / GFX_PER_LINE)*TILEY; - dest_x = SX+x*TILEX; - dest_y = SY+y*TILEY; - - XSetClipOrigin(display,clip_gc[PIX_BACK],dest_x-src_x,dest_y-src_y); - XCopyArea(display,pix[PIX_BACK],drawto_field,clip_gc[PIX_BACK], src_x,src_y, - TILEX,TILEY, dest_x,dest_y); + if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN) + { + graphic -= GFX_START_ROCKSSCREEN; + src_x = SX+(graphic % GFX_PER_LINE)*TILEX; + src_y = SY+(graphic / GFX_PER_LINE)*TILEY; + dest_x = SX+x*TILEX; + dest_y = SY+y*TILEY; + + XSetClipOrigin(display,clip_gc[PIX_BACK],dest_x-src_x,dest_y-src_y); + XCopyArea(display,pix[PIX_BACK],drawto_field,clip_gc[PIX_BACK], + src_x,src_y, TILEX,TILEY, dest_x,dest_y); + } + else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES) + { + graphic -= GFX_START_ROCKSHEROES; + src_x = (graphic % HEROES_PER_LINE)*TILEX; + src_y = (graphic / HEROES_PER_LINE)*TILEY; + dest_x = SX+x*TILEX; + dest_y = SY+y*TILEY; + + XSetClipOrigin(display,clip_gc[PIX_HEROES],dest_x-src_x,dest_y-src_y); + XCopyArea(display,pix[PIX_HEROES],drawto_field,clip_gc[PIX_HEROES], + src_x,src_y, TILEX,TILEY, dest_x,dest_y); + } + else + { + DrawGraphic(x,y,graphic); + return; + } redraw_tiles++; redraw[x][y]=TRUE; @@ -346,22 +502,25 @@ void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic) void DrawMiniGraphicExtHiRes(Drawable d, GC gc, int x, int y, int graphic) { - if (graphic<0) - XFillRectangle(display,d,gc, x,y, MINI_TILEX,MINI_TILEY); - else if (graphic<256) + if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN) + { + graphic -= GFX_START_ROCKSSCREEN; XCopyArea(display,pix[PIX_BACK],d,gc, MINI_GFX_STARTX+(graphic % MINI_GFX_PER_LINE)*MINI_TILEX, MINI_GFX_STARTY+(graphic / MINI_GFX_PER_LINE)*MINI_TILEY, MINI_TILEX,MINI_TILEY, x,y); - else + } + else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT) { - graphic -= 256; + graphic -= GFX_START_ROCKSFONT; XCopyArea(display,pix[PIX_SMALLFONT],d,gc, (graphic % FONT_CHARS_PER_LINE)*FONT4_XSIZE, (graphic / FONT_CHARS_PER_LINE)*FONT4_YSIZE + FC_SPECIAL2*FONT2_YSIZE*FONT_LINES_PER_FONT, MINI_TILEX,MINI_TILEY, x,y); } + else + XFillRectangle(display,d,gc, x,y, MINI_TILEX,MINI_TILEY); } void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int cut_mode) @@ -439,10 +598,31 @@ void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int cut_mode) redraw[x][y+SIGN(dy)]=TRUE; } - XCopyArea(display,pix[PIX_BACK],drawto_field,gc, - SX+(graphic % GFX_PER_LINE)*TILEX+cx, - SY+(graphic / GFX_PER_LINE)*TILEY+cy, - width,height, SX+x*TILEX+dx,SY+y*TILEY+dy); + if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN) + { + graphic -= GFX_START_ROCKSSCREEN; + XCopyArea(display,pix[PIX_BACK],drawto_field,gc, + SX+(graphic % GFX_PER_LINE)*TILEX+cx, + SY+(graphic / GFX_PER_LINE)*TILEY+cy, + width,height, SX+x*TILEX+dx,SY+y*TILEY+dy); + } + else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES) + { + graphic -= GFX_START_ROCKSHEROES; + XCopyArea(display,pix[PIX_HEROES],drawto_field,gc, + (graphic % HEROES_PER_LINE)*TILEX+cx, + (graphic / HEROES_PER_LINE)*TILEY+cy, + width,height, SX+x*TILEX+dx,SY+y*TILEY+dy); + } + +#if DEBUG + if (!IN_SCR_FIELD(x,y)) + { + printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic); + printf("DrawGraphicShifted(): This should never happen!\n"); + return; + } +#endif redraw_tiles++; redraw[x][y]=TRUE; @@ -453,32 +633,50 @@ void DrawElementShifted(int x, int y, int dx, int dy, int element,int cut_mode) { int ux = UNSCROLLX(x), uy = UNSCROLLY(y); int graphic = el2gfx(element); - int phase = ABS(MovPos[ux][uy])/(TILEX/2); + int phase4 = ABS(MovPos[ux][uy])/(TILEX/4); + int phase = phase4 / 2; int dir = MovDir[ux][uy]; -/* - int horiz_move = (dir==MV_LEFT || dir==MV_RIGHT); -*/ - - if (element==EL_PACMAN || - element==EL_KAEFER || - element==EL_FLIEGER || - element==EL_BUTTERFLY || - element==EL_FIREFLY) + if (element==EL_PACMAN || element==EL_KAEFER || element==EL_FLIEGER) { - if (element==EL_BUTTERFLY || element==EL_FIREFLY) - graphic += !phase; + graphic += 4*!phase; + + if (dir==MV_UP) + graphic += 1; + else if (dir==MV_LEFT) + graphic += 2; + else if (dir==MV_DOWN) + graphic += 3; + } + else if (element==EL_MAULWURF || element==EL_PINGUIN || + element==EL_SCHWEIN || element==EL_DRACHE) + { + if (dir==MV_LEFT) + graphic = (element==EL_MAULWURF ? GFX_MAULWURF_LEFT : + element==EL_PINGUIN ? GFX_PINGUIN_LEFT : + element==EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT); + else if (dir==MV_RIGHT) + graphic = (element==EL_MAULWURF ? GFX_MAULWURF_RIGHT : + element==EL_PINGUIN ? GFX_PINGUIN_RIGHT : + element==EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT); + else if (dir==MV_UP) + graphic = (element==EL_MAULWURF ? GFX_MAULWURF_UP : + element==EL_PINGUIN ? GFX_PINGUIN_UP : + element==EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP); else - { - graphic += 4*!phase; - - if (dir==MV_UP) - graphic += 1; - else if (dir==MV_LEFT) - graphic += 2; - else if (dir==MV_DOWN) - graphic += 3; - } + graphic = (element==EL_MAULWURF ? GFX_MAULWURF_DOWN : + element==EL_PINGUIN ? GFX_PINGUIN_DOWN : + element==EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN); + + graphic += phase4; + } + else if (element==EL_SONDE) + { + graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL); + } + else if (element==EL_BUTTERFLY || element==EL_FIREFLY) + { + graphic += !phase; } else if ((element==EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode) { @@ -998,10 +1196,8 @@ BOOL AreYouSure(char *text, unsigned int ays_state) } break; case FocusIn: - HandleFocusEvent(FOCUS_IN); - break; case FocusOut: - HandleFocusEvent(FOCUS_OUT); + HandleFocusEvent((XFocusChangeEvent *) &event); break; default: break; @@ -1213,137 +1409,6 @@ int ReadPixel(Drawable d, int x, int y) return(XGetPixel(pixelimage,0,0)); } -void CheckJoystickData() -{ - int i; - int distance = 100; - - for(i=0;i<2;i++) - { - if (joystick[i].xmiddle <= distance) - joystick[i].xmiddle = distance; - if (joystick[i].ymiddle <= distance) - joystick[i].ymiddle = distance; - - if (joystick[i].xleft >= joystick[i].xmiddle) - joystick[i].xleft = joystick[i].xmiddle-distance; - if (joystick[i].xright <= joystick[i].xmiddle) - joystick[i].xright = joystick[i].xmiddle+distance; - - if (joystick[i].yupper >= joystick[i].ymiddle) - joystick[i].yupper = joystick[i].ymiddle-distance; - if (joystick[i].ylower <= joystick[i].ymiddle) - joystick[i].ylower = joystick[i].ymiddle+distance; - } -} - -int JoystickPosition(int middle, int margin, int actual) -{ - long range, pos; - int percentage; - - if (marginmiddle) - return(0); - if (margin>middle && actual100) - percentage = 100; - - return(percentage); -} - -int Joystick() -{ -#ifdef __FreeBSD__ - struct joystick joy_ctrl; -#else - struct joystick_control - { - int buttons; - int x; - int y; - } joy_ctrl; -#endif - - int js_x,js_y, js_b1,js_b2; - int left, right, up, down; - int result=0; - - if (joystick_status==JOYSTICK_OFF) - return(0); - - if (read(joystick_device, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl)) - { - fprintf(stderr,"%s: cannot read joystick settings - no joystick support\n", - progname); - joystick_status = JOYSTICK_OFF; - return(0); - } - - js_x = joy_ctrl.x; - js_y = joy_ctrl.y; -#ifdef __FreeBSD__ - js_b1 = joy_ctrl.b1; - js_b2 = joy_ctrl.b2; -#else - js_b1 = joy_ctrl.buttons & 1; - js_b2 = joy_ctrl.buttons & 2; -#endif - - left = JoystickPosition(joystick[joystick_nr].xmiddle, - joystick[joystick_nr].xleft, js_x); - right = JoystickPosition(joystick[joystick_nr].xmiddle, - joystick[joystick_nr].xright, js_x); - up = JoystickPosition(joystick[joystick_nr].ymiddle, - joystick[joystick_nr].yupper, js_y); - down = JoystickPosition(joystick[joystick_nr].ymiddle, - joystick[joystick_nr].ylower, js_y); - - if (left>JOYSTICK_PERCENT) - result |= JOY_LEFT; - else if (right>JOYSTICK_PERCENT) - result |= JOY_RIGHT; - if (up>JOYSTICK_PERCENT) - result |= JOY_UP; - else if (down>JOYSTICK_PERCENT) - result |= JOY_DOWN; - if (js_b1) - result |= JOY_BUTTON_1; - if (js_b2) - result |= JOY_BUTTON_2; - - return(result); -} - -int JoystickButton() -{ - static int last_joy_button = 0; - int joy_button = (Joystick() & JOY_BUTTON); - int result; - - if (joy_button) - { - if (last_joy_button) - result = JOY_BUTTON_PRESSED; - else - result = JOY_BUTTON_NEW_PRESSED; - } - else - { - if (last_joy_button) - result = JOY_BUTTON_NEW_RELEASED; - else - result = JOY_BUTTON_NOT_PRESSED; - } - - last_joy_button = joy_button; - return(result); -} - int el2gfx(int element) { switch(element) @@ -1384,7 +1449,7 @@ int el2gfx(int element) case EL_FIREFLY_L: return(GFX_FIREFLY_L); case EL_FIREFLY_U: return(GFX_FIREFLY_U); case EL_MAMPFER: return(GFX_MAMPFER); - case EL_ZOMBIE: return(GFX_ZOMBIE); + case EL_ROBOT: return(GFX_ROBOT); case EL_BETON: return(GFX_BETON); case EL_DIAMANT: return(GFX_DIAMANT); case EL_MORAST_LEER: return(GFX_MORAST_LEER); @@ -1458,6 +1523,15 @@ int el2gfx(int element) case EL_SOKOBAN_OBJEKT: return(GFX_SOKOBAN_OBJEKT); case EL_SOKOBAN_FELD_LEER: return(GFX_SOKOBAN_FELD_LEER); case EL_SOKOBAN_FELD_VOLL: return(GFX_SOKOBAN_FELD_VOLL); + case EL_MAULWURF: return(GFX_MAULWURF); + case EL_PINGUIN: return(GFX_PINGUIN); + case EL_SCHWEIN: return(GFX_SCHWEIN); + case EL_DRACHE: return(GFX_DRACHE); + case EL_SONDE: return(GFX_SONDE); + case EL_PFEIL_L: return(GFX_PFEIL_L); + case EL_PFEIL_R: return(GFX_PFEIL_R); + case EL_PFEIL_O: return(GFX_PFEIL_O); + case EL_PFEIL_U: return(GFX_PFEIL_U); default: { if (IS_CHAR(element)) diff --git a/src/tools.h b/src/tools.h index ce4ab0f2..43dcf1e0 100644 --- a/src/tools.h +++ b/src/tools.h @@ -19,10 +19,6 @@ #include -/* für DrawGraphicAnimation */ -#define ANIM_NORMAL 0 -#define ANIM_OSCILLATE 1 - /* für DrawElementShifted */ #define CUT_NO_CUTTING 0 #define CUT_ABOVE 1 @@ -57,6 +53,7 @@ void FadeToFront(); void ClearWindow(); void DrawText(int, int, char *, int, int); void DrawTextExt(Drawable, GC, int, int, char *, int, int); +void DrawPlayerField(void); void DrawGraphicAnimation(int, int, int, int, int, int); void DrawGraphic(int, int, int); void DrawGraphicExt(Drawable, GC, int, int, int); @@ -85,10 +82,6 @@ unsigned int CloseDoor(unsigned int); unsigned int GetDoorState(void); unsigned int MoveDoor(unsigned int); int ReadPixel(Drawable, int, int); -void CheckJoystickData(void); -int JoystickPosition(int, int, int); -int Joystick(void); -int JoystickButton(void); int el2gfx(int); #endif