/* Aqua demo by John Enright. Graphics (c) Mike Alkan */ #include #include #include #include #include #include #include #include #include #include #include "GameSmith:GameSmith.h" #include "GameSmith:include/proto/all_regargs.h" #include "GameSmith:include/libraries/libptrs.h" #define DISPLAY_SIZE 320 /* lores display resolution horizontal */ #define PAGE_SIZE (DISPLAY_SIZE*4) /* actual scrollable bitmap size */ #define BMDEPTH 4 /* depth of bitmap (16 color) */ #define BMOFFSET 48 /* buffer amount (in pixels) for anims & display offset */ #define BMWIDTH (PAGE_SIZE+(BMOFFSET*2)) /* actual width of bitmap */ #define BMHEIGHT 192 /* height of bitmap. All of this is visible */ #define VS_X (PAGE_SIZE*10) /* width of virtual space for object traversal */ #define LEFT_BOUNDS BMOFFSET /* left boundary for anim objects */ #define RIGHT_BOUNDS (VS_X+BMOFFSET) /* right boundary for anim objects */ #define TOP_BOUNDS 16 /* top boundary for anim objects */ #define BOTTOM_BOUNDS 184 /* bottom boundary for anim objects */ #define BOTTOM_SPACE 16 /* vertical rows on sea bottom for obj placement */ #define ANIM_SPEED 4 /* pixel speed for object movement */ #define ANIM_COUNT 18 /* number of objects in each array */ #define VB_DELAY 5 /* the fastest objects are allowed to animate */ #define FRAME_RATE 1 /* scroll rate in vertical blank intervals */ /*-------------------------------------------------------------------------*/ /* Function Prototypes */ void scroll(void); int setup(void); int place_anim_bottom(struct anim_struct *); int place_cplx_bottom(struct anim_cplx *); int place_cplx(struct anim_cplx *); void move_creatures(void); void move_anim(struct anim_struct *); void move_cplx(struct anim_cplx *); void check_bounds(void); void check_anim_bounds(struct anim_struct *); void check_cplx_bounds(struct anim_cplx *); int check_close(void); void cleanup(void); /*-------------------------------------------------------------------------*/ /* some global variables */ struct Interrupt *scroller=NULL; unsigned long color[1<= VS_X) /* check against scroll boundaries */ { /* don't go past virtual space used by anims */ dir_right=0; x_offset=VS_X-DISPLAY_SIZE;; x=0; } else if (x_offset < 0) { dir_right=1; x_offset=0; x=0; } if (x) { diff=vp.xoff+x-BMOFFSET; if (diff < 0) /* if past beginning of actual bitmap */ { x=(PAGE_SIZE-DISPLAY_SIZE)+x; /* shift to end of bitmap & keep scrolling */ shift=1; /* this provides a seemless transition, and */ if (!page) { reset=1; rs_offset-=PAGE_SIZE-DISPLAY_SIZE; window=PAGE_SIZE-DISPLAY_SIZE; /* adjust real space window */ } page=0; } /* gives the illusion of an infinite horizon */ else if (((diff-velocity) < 0)) /* early warning system. :) */ { /* notify main program of upcoming bitmap shift */ if ((x_offset-velocity) > 0) { rs_offset-=PAGE_SIZE-DISPLAY_SIZE; window=PAGE_SIZE-DISPLAY_SIZE; /* adjust real space window */ reset=1; /* flag to reset bitmap pointers */ page=1; } } else if (diff >= (PAGE_SIZE-DISPLAY_SIZE)) { x=-((PAGE_SIZE-DISPLAY_SIZE)-x); shift=1; if (!page) { reset=1; rs_offset+=PAGE_SIZE-DISPLAY_SIZE; window=0; /* adjust real space window */ } page=0; } else if ((diff+velocity) >= (PAGE_SIZE-DISPLAY_SIZE)) { /* notify main program of upcoming bitmap shift */ if ((x_offset+velocity+DISPLAY_SIZE) < VS_X) { rs_offset+=PAGE_SIZE-DISPLAY_SIZE; window=0; /* adjust real space window */ reset=1; /* flag to reset bitmap pointers */ page=1; } } if (!shift) gs_rs_window(dlist,diff,0); /* scroll real space window over bitmap */ gs_scroll_vp(&display,0,x,0,1); /* scroll the display during next VB */ } } /***************************************************************************/ /* This function creates the display, loads the background picture, loads all anim objects, allocates a display list for the animation system, adds all objects to the list, draws the objects in the display, shows the GDS display, and then installs the scroller. */ int setup() { int cnt=0; struct anim_load_struct load; switch (gs_chiprev()) /* set hard left display offset depending on chipset */ { case AGA_CHIPREV: if (GfxBase->LibNode.lib_Version >= 36) /* if WB 2.0 or higher */ display.DxOffset=0x87; else display.DxOffset=0; break; default: if (GfxBase->LibNode.lib_Version >= 36) /* if WB 2.0 or higher */ display.DxOffset=0x77; else display.DxOffset=0; break; } gs_get_ILBM_bm(&loadpic); /* load color table from picture file */ #ifdef NTSC_MONITOR_ID if (GfxBase->LibNode.lib_Version >= 36) /* if WB 2.0 or higher */ { /* this defeats mode promotion on AGA machines */ if (ModeNotAvailable(NTSC_MONITOR_ID)) { display.modes = PAL_MONITOR_ID; } else { display.modes = NTSC_MONITOR_ID; } } #endif if (gs_create_display(&display)) { return(-1); } loadpic.bitmap1=vp.bitmap1; /* tell picture loader where to put picture */ loadpic.bitmap2=vp.bitmap2; /* fill both bitmaps with background picture */ while (cnt < PAGE_SIZE) /* stagger the picture continously across bitmap width */ { loadpic.loadx=(BMOFFSET+cnt)/8; if (gs_loadILBM(&loadpic)) { gs_remove_display(&display); return(-2); } cnt+=bmh.w; /* add width of picture to load offset */ } load.flags=ANIMLOAD_NOCOLOR; /* don't allocate a color table */ load.cmap_size=8; /* number of bits per color value */ load.array_elements=ANIM_COUNT; /* number of array elements desired */ load.filename="anim/rollcrab.anim"; /* name of anim file */ if (gs_load_anim(&load)) /* load the anim object */ { cleanup(); return(-3); } rollcrab=load.anim_ptr.anim; /* ptr to anim object */ load.filename="anim/coral1.anim"; /* name of anim file */ if (gs_load_anim(&load)) /* load the anim object */ { cleanup(); return(-3); } coral1=load.anim_ptr.anim; /* ptr to anim object */ load.filename="anim/coral2.anim"; /* name of anim file */ if (gs_load_anim(&load)) /* load the anim object */ { cleanup(); return(-3); } coral2=load.anim_ptr.anim; /* ptr to anim object */ // load.filename="anim/coral3.anim"; /* name of anim file */ // if (gs_load_anim(&load)) /* load the anim object */ // { // cleanup(); // return(-3); // } // coral3=load.anim_ptr.anim; /* ptr to anim object */ load.filename="cplx/fish1.cplx"; /* name of anim file */ if (gs_load_anim(&load)) /* load the anim object */ { cleanup(); return(-4); } fish1=load.anim_ptr.cplx; /* ptr to anim object */ load.filename="cplx/fish2.cplx"; /* name of anim file */ if (gs_load_anim(&load)) /* load the anim object */ { cleanup(); return(-5); } fish2=load.anim_ptr.cplx; /* ptr to anim object */ load.filename="cplx/fish3.cplx"; /* name of anim file */ if (gs_load_anim(&load)) /* load the anim object */ { cleanup(); return(-6); } fish3=load.anim_ptr.cplx; /* ptr to anim object */ load.filename="cplx/aquadino.cplx"; /* name of anim file */ if (gs_load_anim(&load)) /* load the anim object */ { cleanup(); return(-7); } aquadino=load.anim_ptr.cplx; /* ptr to anim object */ if ((dlist=gs_get_display_list()) < 0) /* allocate a display list for anims */ { cleanup(); return(-8); } gs_init_anim(dlist,vp.bitmap1,vp.bitmap2,NULL); /* tell anim system about bitmaps */ gs_rs_dim(dlist,DISPLAY_SIZE+(BMOFFSET*2),BMHEIGHT); /* set new real space dimensions */ /* define area in which anim objects will be allowed to wander */ gs_set_anim_bounds(dlist,LEFT_BOUNDS,TOP_BOUNDS,RIGHT_BOUNDS,BOTTOM_BOUNDS); if (place_anim_bottom(rollcrab)) /* now place all anim objects in the virtual area */ { cleanup(); return(-10); } if (place_anim_bottom(coral1)) { cleanup(); return(-11); } if (place_anim_bottom(coral2)) { cleanup(); return(-12); } // if (place_anim_bottom(coral3)) // { // cleanup(); // return(-13); // } if (place_cplx_bottom(aquadino)) { cleanup(); return(-14); } if (place_cplx(fish1)) { cleanup(); return(-15); } if (place_cplx(fish2)) { cleanup(); return(-16); } if (place_cplx(fish3)) { cleanup(); return(-17); } gs_draw_anims(dlist); /* actually draw anims in 2nd bitmap */ check_bounds(); /* check to see if any need to turn around */ gs_next_anim_page(dlist); /* tell animation system to use other bitmap next time */ gs_show_display(&display,1); /* show the display */ gs_flip_display(&display,1); /* flip to next bitmap page during next vertical blank */ gs_open_vb_timer(); /* open the super efficient GDS vertical blank timer */ gs_vb_timer_reset(); while (!gs_vb_time()); /* sync gfx with display */ gs_vb_timer_reset(); /* reset counter to zero */ scroller=gs_add_vb_server(&scroll,0); /* add scroller function to vertical blank server chain */ if (!scroller) { cleanup(); return(-9); } return(0); /* all went well */ } /***************************************************************************/ /* Place a simple anim object on the see bottom */ int place_anim_bottom(anim) struct anim_struct *anim; { int cnt; for (cnt=0; cnt < ANIM_COUNT; cnt++) { anim[cnt].x = gs_random(VS_X); /* random X,Y coords */ anim[cnt].y = gs_random(BOTTOM_SPACE)+(BOTTOM_BOUNDS-BOTTOM_SPACE)-anim[cnt].height; anim[cnt].xa = gs_random(ANIM_SPEED) +1; /* use xa field for object speed */ /* we can do this since object is not attached to */ /* anything, and the field would go unused otherwise */ if (cnt&1) { anim[cnt].xa=-anim[cnt].xa; } anim[cnt].prio = anim[cnt].y+anim[cnt].height; /* obj priority setting */ if (gs_add_anim(dlist,(struct anim_struct *)&anim[cnt],anim[cnt].x,anim[cnt].y)) { /* if can't add object to display list */ return(-1); /* return failure */ } gs_set_anim_cell((struct anim_struct *)&anim[cnt],gs_random(anim[cnt].count)); } return(0); } /***************************************************************************/ int place_cplx_bottom(cplx) struct anim_cplx *cplx; { int cnt,seq,x,y; for (cnt=0; cnt < ANIM_COUNT; cnt++) { x = gs_random(VS_X); /* random X,Y coords */ y = gs_random(BOTTOM_SPACE)+(BOTTOM_BOUNDS-BOTTOM_SPACE) -cplx[cnt].height; seq=1; cplx[cnt].list->xa = gs_random(ANIM_SPEED) +1; /* use xa field for object speed */ if (cnt&1) { seq=0; cplx[cnt].list->xa=-cplx[cnt].list->xa; } if (gs_add_anim_cplx(dlist,(struct anim_cplx *)&cplx[cnt],x,y,seq,y+cplx[cnt].height)) { /* if can't add object to display list */ return(-1); /* return failure */ } gs_set_cplx_cell((struct anim_cplx *)&cplx[cnt], gs_random(cplx[cnt].list->count)); } return(0); } /***************************************************************************/ int place_cplx(cplx) struct anim_cplx *cplx; { int cnt,seq,x,y,pre_y; pre_y = BOTTOM_BOUNDS-TOP_BOUNDS+12-cplx->height; for (cnt=0; cnt < ANIM_COUNT; cnt++) { x = gs_random(VS_X); /* random X,Y coords */ y = gs_random(pre_y)+TOP_BOUNDS; seq=1; cplx[cnt].list->xa = gs_random(ANIM_SPEED) +1; /* use xa field for object speed */ if (cnt&1) { seq=0; cplx[cnt].list->xa=-cplx[cnt].list->xa; } if (gs_add_anim_cplx(dlist,(struct anim_cplx *)&cplx[cnt],x,y,seq,y+cplx[cnt].height)) { /* if can't add object to display list */ return(-1); /* return failure */ } gs_set_cplx_cell((struct anim_cplx *)&cplx[cnt], gs_random(cplx[cnt].list->count)); } return(0); } /***************************************************************************/ /* This handles movement & animation of all objects. It also continuously redraws all objects in case the bitmap pointers have been reset (see the scroll routine). */ void move_creatures() /* move & animate everything */ { unsigned long time; if (reset) /* if bitmap pointers being reset */ { reset=0; gs_rs_offset(dlist,rs_offset,0); /* adjust real space offset for anims */ gs_rs_window(dlist,window,0); /* adjust real space window over bitmap */ } time = gs_vb_time(); /* get value of vertical blank timer */ if (time >= VB_DELAY) /* don't go too fast */ { gs_vb_timer_reset(); /* reset vertical blank timer */ move_anim(rollcrab); move_cplx(aquadino); move_cplx(fish1); move_cplx(fish2); move_cplx(fish3); while (display.flags & GSV_FLIP); /* while page not flipped yet */ gs_draw_anims(dlist); /* draw them anim objects! */ gs_flip_display(&display,1); /* switch to other display, sync */ gs_next_anim_page(dlist); /* tell anim sys to use other bitmap */ check_bounds(); /* turn around at virtual space bounds */ } else { while (display.flags & GSV_FLIP); /* while page not flipped yet */ gs_draw_anims(dlist); /* draw them anim objects! */ gs_flip_display(&display,1); /* switch to other display, sync */ gs_next_anim_page(dlist); /* tell anim sys to use other bitmap */ } } /***************************************************************************/ void move_anim(anim) struct anim_struct *anim; { int cnt; for (cnt=0; cnt < ANIM_COUNT; cnt++) { anim[cnt].y+=anim[cnt].xa; gs_anim_obj((struct anim_struct *)&anim[cnt],anim[cnt].x,anim[cnt].y); } } /***************************************************************************/ void move_cplx(cplx) struct anim_cplx *cplx; { int cnt,x; for (cnt=0; cnt < ANIM_COUNT; cnt++) { x=cplx[cnt].anim->x+cplx[cnt].list->xa; /* move the object */ gs_anim_cplx((struct anim_cplx *)&cplx[cnt],x,cplx[cnt].anim->y); } } /***************************************************************************/ void check_bounds() { check_anim_bounds(rollcrab); check_cplx_bounds(aquadino); check_cplx_bounds(fish1); check_cplx_bounds(fish2); check_cplx_bounds(fish3); } /***************************************************************************/ /* This function checks against top & bottom boundaries for the rollcrab, and reverses direction accordingly. */ void check_anim_bounds(anim) struct anim_struct *anim; { int cnt; for (cnt=0; cnt < ANIM_COUNT; cnt++) { if (anim[cnt].flags & (ANIM_BOUNDS_Y1|ANIM_BOUNDS_Y2)) { anim[cnt].xa=-anim[cnt].xa; /* reverse X direction */ } } } /***************************************************************************/ /* This function checks against left & right boundaries for all other creatures, and reverses direction accordingly. */ void check_cplx_bounds(cplx) struct anim_cplx *cplx; { int cnt; for (cnt=0; cnt < ANIM_COUNT; cnt++) { if (cplx[cnt].anim->flags & (ANIM_BOUNDS_X1|ANIM_BOUNDS_X2)) { cplx[cnt].list->xa=-cplx[cnt].list->xa; /* reverse X direction */ gs_set_cplx_seq((struct anim_cplx *)&cplx[cnt],cplx[cnt].seq^1, cplx[cnt].anim->x,cplx[cnt].anim->y); } } } /***************************************************************************/ int check_close() /* check for left mouse button click */ { if (gs_joystick(0) & (JOY_BUTTON1|JOY_BUTTON2)) return(1); return(0); } /***************************************************************************/ void cleanup() /* release all resources and memory */ { gs_close_vb_timer(); if (dlist > -1) gs_free_display_list(dlist); if (scroller) gs_remove_vb_server(scroller); if (rollcrab) gs_free_anim(rollcrab,ANIM_COUNT); if (coral1) gs_free_anim(coral1,ANIM_COUNT); if (coral2) gs_free_anim(coral2,ANIM_COUNT); if (coral3) gs_free_anim(coral3,ANIM_COUNT); if (fish1) gs_free_cplx(fish1,ANIM_COUNT); if (fish2) gs_free_cplx(fish2,ANIM_COUNT); if (fish3) gs_free_cplx(fish3,ANIM_COUNT); if (aquadino) gs_free_cplx(aquadino,ANIM_COUNT); gs_remove_display(&display); }