home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus Extra 1996 #3
/
AmigaPlus_CD-ROM-EXTRA_Nr.3.bin
/
spiele-demos
/
aqua
/
aqua.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-15
|
20KB
|
694 lines
/* Aqua demo by John Enright. Graphics (c) Mike Alkan */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/memory.h>
#include <exec/types.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#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 22 /* 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<<BMDEPTH]; /* color table with 2 to the power of BMDEPTH entries */
int dlist=-1; /* display list handle for anims */
int rs_offset=0,window,reset=0;
/* ---- the anim object array pointers ---- */
struct anim_struct *rollcrab=NULL,*coral1=NULL,*coral2=NULL,*coral3=NULL;
struct anim_cplx *fish1=NULL,*fish2=NULL,*fish3=NULL;
struct anim_cplx *aquadino=NULL;
/*-------------------------------------------------------------------------*/
BitMapHeader bmh;
struct loadILBM_struct loadpic =
{
"gfx/aqua.pic", /* ptr to picture name string */
NULL, /* ptr to 1st bitmap */
NULL, /* ptr to 2nd bitmap (if any) */
color, /* ptr to color table array */
(1<<BMDEPTH), /* # colors in color table */
NULL, /* height of image in pixels (filled by load call) */
NULL, /* width of image in pixels (filled) */
NULL, /* x display offset (filled) */
NULL, /* y display offset (filled) */
NULL, /* pic mode (filled) */
BMOFFSET/8, /* x load offset (from left) in bytes */
0, /* y load offset (from top) in rows */
ILBM_COLOR, /* flags (fill color table) */
0xff, /* bitplane fill mask */
0xff, /* bitplane load mask */
&bmh /* address of BitMapHeader to fill */
};
unsigned short copper_list[]= {
UC_NOSPRITES, /* turn off sprite DMA */
UC_END /* end custom copper list */
};
struct copper_struct copper =
{
copper_list,
NULL,
NULL
};
struct gs_viewport vp =
{
NULL, /* ptr to next viewport */
color, /* ptr to color table */
(1<<BMDEPTH), /* number of colors in table */
&copper, /* ptr to user copper list */
BMHEIGHT,DISPLAY_SIZE,BMDEPTH,BMHEIGHT,BMWIDTH, /* height, width, depth, bmheight, bmwidth */
0,0, /* top & left viewport offsets */
BMOFFSET,0, /* X & Y bitmap offsets */
GSVP_ALLOCBM, /* flags (allocate bitmaps) */
NULL,NULL, /* 2.xx & above compatibility stuff */
NULL,NULL, /* bitmap pointers */
NULL, /* future expansion */
0,0,0,0 /* display clip (MinX,MinY,MaxX,MaxY) */
};
struct display_struct display =
{
NULL, /* ptr to previous display view */
NULL,NULL, /* 2.xx & above compatibility stuff */
0,0, /* X and Y display offsets (1.3 style) */
0, /* display mode ID */
GSV_DOUBLE|GSV_SCROLLABLE, /* flags (scrollable double buffered) */
&vp, /* ptr to 1st viewport */
NULL /* future expansion */
};
/***************************************************************************/
main(argc,argv)
int argc;
char *argv[];
{
int err,end=0;
if (gs_open_libs(DOS|GRAPHICS,0)) /* open AmigaDOS libs, latest versions */
exit(01); /* if can't open libs, abort */
if (err=setup()) /* if couldn't get set up... abort program */
{
printf("\nSetup error: %d\n",err);
gs_close_libs(); /* close all libraries */
exit(02);
}
Forbid(); /* take over the entire machine */
while (!end) /* this shows off speed */
{
move_creatures(); /* animate everything */
end=check_close(); /* end when user hits left mouse button */
}
Permit(); /* OK, let other things run while we clean up */
cleanup(); /* close & deallocate everything */
gs_close_libs(); /* close all libraries */
}
/***************************************************************************/
/*
This is the scroll handler which runs as a vertical blank server routine
and handles scrolling of the bitmap. This is the reason for its ultra-
smooth performance, regardless of what the animation system is doing.
The "__interrupt" is a SAS convention used to make sure that the function
does NOT do stack checking. The "__saveds" is also a SAS convention, and
loads the near data pointer at the beginning of the function.
*/
void __interrupt __saveds scroll()
{
int stick,x=0,diff,velocity=1,shift=0;
static int x_offset=0,dir_right=1,flop=0;
flop++;
if (flop < FRAME_RATE) /* check against frame rate */
return; /* if not time to scroll, abort */
flop=0;
stick = _gs_joystick(1); /* poll joystick */
if (stick & (JOY_LEFT|JOY_RIGHT|JOY_BUTTON1))
{ /* if joystick value we're concerned with */
velocity*=3; /* increase velocity */
if (stick & JOY_BUTTON1) /* button holds display */
velocity=0;
if (stick & JOY_LEFT)
x=-velocity;
else if (stick & JOY_RIGHT)
x=velocity;
}
else
{
if (dir_right) /* if scrolling right */
{
x=velocity;
}
else /* else scrolll left */
{
x=-velocity;
}
}
x_offset+=x;
if ((x_offset + DISPLAY_SIZE) >= 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 */
} /* 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 */
}
}
else if (diff >= (PAGE_SIZE-DISPLAY_SIZE))
{
x=-((PAGE_SIZE-DISPLAY_SIZE)-x);
shift=1;
}
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 */
}
}
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;
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); /* 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)
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);
}