home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d115
/
marketroid.lha
/
Marketroid
/
src
/
anim.c
next >
Wrap
C/C++ Source or Header
|
1987-11-22
|
9KB
|
413 lines
/* :ts=8 bk=0
*
* anim.c: Animation drivers.
*
* Leo L. Schwab 8710.2 (415) 456-3960
*/
#include <exec/types.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <graphics/rastport.h>
#include "marketroid.h"
extern struct object ob_grunt; /* Special case for movement */
extern struct BitMap *sbm;
struct BitMap *getxpmap();
struct List guys;
static int opened;
int leftbound, rightbound, topbound, bottombound;
struct obcontrol *
addobject (ob, pri, dir, x, y)
register struct object *ob;
int pri, dir, x, y;
{
register struct obcontrol *oc;
if (!(oc = AllocMem ((long) sizeof (*oc), MEMF_CLEAR)))
return (0);
oc -> node.ln_Pri = pri;
oc -> ob = ob;
oc -> x = x;
oc -> y = y;
oc -> frame = 0;
oc -> delay = 1;
if (oc->x + ob->width > rightbound ||
oc->x < leftbound ||
oc->y + ob->height > bottombound ||
oc->y < topbound)
oc -> flags |= OFFSCREEN;
setdir (oc, dir);
Enqueue (&guys, oc);
return (oc);
}
removeobject (oc)
register struct obcontrol *oc;
{
register struct object *ob = oc -> ob;
register struct BitMap *bm;
/* Pull it out of the list */
Remove (oc);
/* Erase the image from the screen */
if (!(oc -> flags & OFFSCREEN))
BltBitMap (ob -> bitmap, 0L, 0L,
sbm, (long) oc -> x, (long) oc -> y,
(long) ob -> width, (long) ob -> height,
0L, 0xffL, NULL);
/* Free dynamically allocated stuff */
if (bm = (struct BitMap *) oc -> node.ln_Name) {
if (bm -> Planes[0])
FreeRaster (bm -> Planes[0],
(long) ob->width, bm->Rows * 4L);
FreeMem (bm, (long) sizeof (*bm));
}
FreeMem (oc, (long) sizeof (*oc));
}
deleteallof (ob)
register struct object *ob;
{
register struct obcontrol *oc;
oc = (struct obcontrol *) guys.lh_Head;
while (oc -> node.ln_Succ) {
oc = (struct obcontrol *) oc -> node.ln_Succ;
if (((struct obcontrol *) oc -> node.ln_Pred) -> ob == ob)
removeobject (oc -> node.ln_Pred);
}
}
setdir (oc, dir)
register struct obcontrol *oc;
int dir;
{
switch (dir) {
case UP:
oc -> dx = 0;
oc -> dy = -(oc -> ob -> incr);
oc -> xoff = oc->ob->upx;
oc -> yoff = oc->ob->upy;
break;
case DOWN:
oc -> dx = 0;
oc -> dy = oc -> ob -> incr;
oc -> xoff = oc->ob->downx;
oc -> yoff = oc->ob->downy;
break;
case LEFT:
oc -> dy = 0;
oc -> dx = -2 * oc->ob->incr;
oc -> xoff = oc->ob->leftx;
oc -> yoff = oc->ob->lefty;
break;
case RIGHT:
oc -> dy = 0;
oc -> dx = 2 * oc->ob->incr;
oc -> xoff = oc->ob->rightx;
oc -> yoff = oc->ob->righty;
break;
}
oc -> dir = dir;
}
setbounds (lb, rb, tb, bb)
{
leftbound = lb;
rightbound = rb;
topbound = tb;
bottombound = bb;
}
setexplode (oc)
register struct obcontrol *oc;
{
oc -> flags |= EXPLODING;
oc -> dir = 1;
oc -> frame = 0;
oc -> delay = 1;
}
cls (rp)
struct RastPort *rp;
{
register BYTE pensav = rp -> FgPen;
SetAPen (rp, 0L);
RectFill (rp, (long) leftbound, (long) topbound,
rightbound - 1L, bottombound - 1L);
SetAPen (rp, (long) pensav);
}
animate ()
{
register struct obcontrol *oc;
for (oc = (struct obcontrol *) guys.lh_Head;
oc -> node.ln_Succ;
oc = (struct obcontrol *) oc -> node.ln_Succ) {
if (!--(oc->delay)) {
/* Countdown ran out, update image */
moveobject (oc);
if (oc -> flags & EXPLODING)
/* Special mod. for exploding stuff */
oc -> delay = 2;
else if (oc -> ob == &ob_grunt)
/* Grunts move randomly */
oc -> delay = rnd (oc->ob->framerate) +
oc -> ob -> framerate;
else
oc -> delay = oc -> ob -> framerate;
}
}
}
moveobject (oc)
register struct obcontrol *oc;
{
register struct object *ob = oc -> ob;
long ex, ey, sizx, sizy;
long yoff;
yoff = oc -> yoff;
if (oc -> flags & FREEZE) /* Don't move it, just draw it */
goto frozen; /* Up yours, Djikstra :-) */
if (oc -> flags & EXPLODING) {
explode (oc);
return;
}
switch (oc -> dir) {
case UP:
oc -> y += oc -> dy;
ex = oc -> x;
ey = oc -> y + ob -> height;
sizx = ob -> width;
sizy = -oc -> dy;
break;
case DOWN:
ex = oc -> x;
ey = oc -> y;
sizx = ob -> width;
sizy = oc -> dy;
oc -> y += oc -> dy;
break;
case LEFT:
oc -> x += oc -> dx;
ex = oc -> x + ob -> width;
ey = oc -> y;
sizx = -oc -> dx;
sizy = ob -> height;
break;
case RIGHT:
ex = oc -> x;
ey = oc -> y;
sizx = oc -> dx;
sizy = ob -> height;
oc -> x += oc -> dx;
break;
}
/*
* This next 'if' is tricky. If the object wanders off the screen
* in any way, we mark it as OFFSCREEN and don't render it. If,
* during the last animation pass, it was onscreen, we erase it at
* it's last known position.
*/
if (oc->x + ob->width > rightbound ||
oc->x < leftbound ||
oc->y + ob->height > bottombound ||
oc->y < topbound) {
if (!(oc -> flags & OFFSCREEN))
BltBitMap
(ob -> bitmap, 0L, 0L,
sbm, (long) oc->x - oc->dx, (long) oc->y - oc->dy,
(long) ob -> width, (long) ob -> height,
0L, 0xffL, NULL);
oc -> flags |= OFFSCREEN;
return;
}
/* Do erasure only if it really moved and was onscreen last time */
if (sizx && sizy && !(oc->flags & OFFSCREEN))
BltBitMap (ob -> bitmap, 0L, 0L, sbm, ex, ey, sizx, sizy,
0L, 0xffL, NULL);
/* Calculate new frame, if multiframed object */
if (ob -> animseq)
yoff += (ob -> animseq)[oc -> frame];
frozen:
/* Draw new guy */
BltBitMap (ob -> bitmap, (long) oc -> xoff, yoff,
sbm, (long) oc -> x, (long) oc -> y,
(long) ob -> width, (long) ob -> height,
0xc0L, 0xffL, NULL);
if (++oc -> frame >= ob -> nframes)
oc -> frame = 0;
oc -> flags &= ~OFFSCREEN;
}
explode (oc)
register struct obcontrol *oc;
{
/* Pray.... */
register struct object *ob = oc -> ob;
register struct BitMap *bm;
register long y, by, high;
UWORD bpr;
if (oc -> frame < 0 || oc -> flags & OFFSCREEN)
return;
if (!oc -> node.ln_Name)
/* No explosion bitmap has been allocated, go get one. */
if (!(oc -> node.ln_Name = (char *) getxpmap (oc)))
die ("Explosion allocation failed.\n");
bm = (struct BitMap *) oc -> node.ln_Name;
/* Clear previous instance of explosion from screen */
high = oc -> frame * (ob -> height - 1) + 1;
y = oc->y - high/2 + ob->height/2;
if (y < topbound) {
by = -(y - topbound);
high -= by;
y = topbound;
} else
by = 0;
if (y + high >= bottombound)
high -= y + high - bottombound;
BltBitMap (bm, 0L, by,
sbm, (long) oc -> x, y,
(long) ob -> width, high,
0x20L, 0xffL, NULL);
/* Clear intermediate bitmap */
BltBitMap (ob -> bitmap, 0L, 0L,
bm, 0L, 0L,
(long) ob -> width, (long) ob -> height * 10L,
0L, 0xffL, NULL);
/* Check to see if explosion is done */
if ((oc->frame += oc->dir) > 10 || oc->frame < 1) {
oc -> frame = -1;
return;
}
/* Expand image vertically by raping intermediate BitMap */
bpr = bm -> BytesPerRow;
bm -> BytesPerRow *= oc -> frame; /* Make it look wider */
BltBitMap (ob -> bitmap, (long) oc -> xoff, (long) oc -> yoff,
bm, 0L, 0L,
(long) ob -> width, (long) ob -> height,
0xc0L, 0xffL, NULL);
/*
* We have vertically expanded the bitmap. We now copy it into
* the main screen bitmap.
*/
bm -> BytesPerRow = bpr; /* Fix it */
high = oc -> frame * (ob -> height - 1) + 1;
y = oc->y - high/2 + ob->height/2;
if (y < topbound) {
by = -(y - topbound);
high -= by;
y = topbound;
} else
by = 0;
if (y + high >= bottombound)
high -= y + high - bottombound;
BltBitMap (bm, 0L, by,
sbm, (long) oc -> x, y,
(long) ob -> width, high,
0xe0L, 0xffL, NULL);
}
struct BitMap *
getxpmap (oc)
register struct obcontrol *oc;
{
register struct object *ob = oc -> ob;
register struct BitMap *bm;
register UWORD *planes;
int high;
high = ob -> height * 10;
if (!(planes = AllocRaster ((long) ob -> width, high * 4L)))
return (0);
if (!(bm = AllocMem ((long) sizeof (*bm), NULL)))
return (0);
InitBitMap (bm, 4L, (long) ob -> width, (long) high);
high *= bm -> BytesPerRow >> 1;
bm -> Planes[0] = (PLANEPTR) planes;
bm -> Planes[1] = (PLANEPTR) (planes + high);
bm -> Planes[2] = (PLANEPTR) (planes + high + high);
bm -> Planes[3] = (PLANEPTR) (planes + high + high + high);
/* Clear this intermediate bitmap */
BltBitMap (ob -> bitmap, 0L, 0L,
bm, 0L, 0L,
(long) ob -> width, ob -> height * 10L,
0L, 0xffL, NULL);
/* Return on-screen object to known state */
if (oc -> dir > 0) /* Only if exploding positively */
BltBitMap (ob->bitmap, (long) oc -> xoff, (long) oc -> yoff,
sbm, (long) oc -> x, (long) oc -> y,
(long) ob -> width, (long) ob -> height,
0xc0L, 0xffL, NULL);
return (bm);
}
/* Housekeeping */
openanim ()
{
NewList (&guys);
opened = 1;
}
closeanim ()
{
register struct obcontrol *oc;
register struct BitMap *bm;
int high;
if (!opened)
return;
while (oc = RemHead (&guys)) {
if (bm = (struct BitMap *) oc -> node.ln_Name) {
if (bm -> Planes[0])
/*- - - - - - - - - - - - - - -*/
FreeRaster (bm -> Planes[0], (long) oc->ob->width, oc->ob->height * 10 * 4L);
/*- - - - - - - - - - - - - - -*/
FreeMem (bm, (long) sizeof (*bm));
}
FreeMem (oc, (long) sizeof (*oc));
}
}