home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
029.lha
/
Vsprite
/
vsprite.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-04-02
|
17KB
|
607 lines
/* vsprite.final.c, merged with its support files */
/* execute makesimple vsprite.final ; Amiga C 1.1 (Lattice 3.03) */
#include "exec/types.h"
#include "intuition/intuition.h"
#include "graphics/sprite.h"
#include "exec/memory.h"
#include "graphics/gels.h"
/* ask system to create and manage MAXSP vsprites */
#define MAXSP 28
/* define possible speeds for vsprites in counts per vblank */
SHORT speed[] = { 1, 2, -1, -2 };
SHORT xmove[MAXSP], ymove[MAXSP];
/* sprite directions of movement */
struct VSprite *vsprite[MAXSP]; /* MAXSP simple sprites */
struct VSprite *vspr; /* pointer to a sprite */
short maxgot; /* max # of sprites we created */
struct GelsInfo mygelsinfo; /* the window's RastPort needs one
* of these in order to do VSprites */
struct Window *w; /* pointer to a Window */
struct RastPort *rp; /* pointer to a RastPort */
struct Screen *s; /* a pointer to a Screen */
struct ViewPort *vp; /* pointer to a ViewPort */
struct Window *OpenWindow();
struct Screen *OpenScreen();
LONG GfxBase;
LONG IntuitionBase;
/* 18 words of sprite data = 9 lines of sprite data */
UWORD sprite_data[ ] = {
0x0fc3, 0x0000, /* image data line 1*/
0x3ff3, 0x0000, /* image data line 2*/
0x30c3, 0x0000, /* image data line 3*/
0x0000, 0x3c03, /* image data line 4*/
0x0000, 0x3fc3, /* image data line 5*/
0x0000, 0x03c3, /* image data line 6*/
0xc033, 0xc033, /* image data line 7*/
0xffc0, 0xffc0, /* image data line 8*/
0x3f03, 0x3f03, /* image data line 9*/
};
UWORD *sprdata;
void movesprites()
{
short i;
for (i=0; i<maxgot; i++)
{
vspr = vsprite[i];
vspr->X = xmove[i]+vspr->X;
vspr->Y = ymove[i]+vspr->Y;
/* move the sprites ... here. */
if(vspr->X >= 300 || vspr->X <= 0) xmove[i]=-xmove[i];
if(vspr->Y >= 190 || vspr->Y <= 0) ymove[i]=-ymove[i];
}
SortGList(rp); /* get the list in order */
DrawGList(rp, vp); /* create the sprite instructions */
MakeScreen(s); /* ask Intuition to pull it all together */
RethinkDisplay(); /* and to show us what we have now. */
}
#define AZCOLOR 1
#define WHITECOLOR 2
#define WC WINDOWCLOSE
#define WS WINDOWSIZING
#define WDP WINDOWDEPTH
#define WDR WINDOWDRAG
#define NORMALFLAGS (WC|WS|WDP)
/* Did not use windowdrag because dont want screen to be moved. */
/* Allow window sizing so user can decrease size of window, then
* increase it again, thus erasing the background text and more
* easily see that some vsprites wink out and into existence when
* too many sprites are on a single horizontal plane and the
* vsprite machine runs out of sprites to assign.
*/
/* myfont1 specifies characteristics of the default font;
* this case selects the 80 column font that displays as
* 40 columns in low resolution mode.
*/
struct TextAttr myfont1 = { "topaz.font", 8, 0, 0 };
struct NewScreen myscreen1 = {
0, 0, /* LeftEdge, TopEdge ... where to put screen */
320, 200, /* Width, Height ... size of the screen */
5, /* 5 planes Depth, means 2 to the 5th or
* 32 different colors to choose from once
* the screen is opened.
*/
1, 0, /* DetailPen, BlockPen */
SPRITES, /* ViewModes ... value of 0 = low resolution */
CUSTOMSCREEN, /* Type of screen */
&myfont1, /* Font to be used as default for this screen */
"32 Color Test", /* DefaultTitle for its title bar */
NULL, /* screens user-gadgets, always NULL, ignored */
NULL };
/* address of custom bitmap for screen,
* not used in this example
*/
struct NewWindow myWindow = {
0, /* LeftEdge for window measured in pixels,
at the current horizontal resolution,
from the leftmost edge of the Screen */
0, /* TopEdge for window is measured in lines
from the top of the current Screen. */
320, 185, /* Width, Height of this window */
0, /* DetailPen - what pen number is to be
used to draw the borders of the window */
1, /* BlockPen - what pen number is to be
used to draw system generated window
gadgets */
/* (for DetailPen and BlockPen, the value
of -1 says "use the default value") */
CLOSEWINDOW, /* simplesprite program used INTUITICKS also */
/* IDCMP Flags */
NORMALFLAGS | GIMMEZEROZERO | ACTIVATE,
/* Window Flags: (see below for more info) */
NULL, /* FirstGadget */
NULL, /* CheckMark */
"Click Close Gadget To Stop", /* Window title */
NULL, /* Pointer to Screen if not workbench */
NULL, /* Pointer to BitMap if a SUPERBITMAP window */
320, 10, /* minimum width, minimum height */
320, 200, /* maximum width, maximum height */
CUSTOMSCREEN
};
#include "graphics/gfxmacros.h"
/* #include "event1.c" */
/* gets the event handler */
/* event1.c */
HandleEvent(code)
LONG code; /* provided by main */
{
switch(code)
{
case CLOSEWINDOW:
return(0);
break;
case INTUITICKS: /* could have done much faster
* but what the heck, this is
* shorter for test purposes
*/
movesprites(); /* 10 moves per second; test */
default:
break;
}
return(1);
}
UWORD mycolortable[] = {
0x0000, 0x0e30, 0x0fff, 0x0b40, 0x0fb0, 0x0bf0,
0x05d0, 0x0ed0, 0x07df, 0x069f, 0x0c0e,
0x0f2e, 0x0feb, 0x0c98, 0x0bbb, 0x07df,
0x0000, 0x0e30, 0x0fff, 0x0b40,
0x0fb0, 0x0bf0, 0x05d0, 0x0ed0,
0x07df, 0x069f, 0x0c0e, 0x0f2e,
0x0feb, 0x0c98, 0x0bbb, 0x07df
};
/* black, red, white, fire-engine red, orange, yellow,
lime green, green, aqua, dark blue, purple,
violet, tan, brown, gray, skyblue, (everything again) */
UWORD colorset0[ ] = { 0x0e30, 0xffff, 0x0b40 }; /* same as colors 17-19 */
UWORD colorset1[ ] = { 0x0bf0, 0x05d0, 0x0ed0 }; /* 21-23 */
UWORD colorset2[ ] = { 0x069f, 0x0c0e, 0x0f2e }; /* 25-27 */
UWORD colorset3[ ] = { 0x0c98, 0x0bbb, 0x07df }; /* 29-31 */
UWORD *colorset[ ] = {
colorset0, colorset1,
colorset2, colorset3 };
int choice;
char *numbers[] = { "17","18","19",
"20","21","22","23",
"24","25","26","27",
"28","29","30","31" };
/* #include "ram:purgegels.c" */
/* purgegels.c */
/*
* Use this to get rid of the gels stuff when it is not needed any more.
* You must have allocated the gels info stuff (use the ReadyGels routine).
*/
void PurgeGels(g)
struct GelsInfo *g;
{
if (g->collHandler != NULL)
FreeMem(g->collHandler, sizeof(struct collTable));
if (g->lastColor != NULL)
FreeMem(g->lastColor, sizeof(LONG) * 8);
if (g->nextLine != NULL)
FreeMem(g->nextLine, sizeof(WORD) * 8);
if (g->gelHead != NULL)
FreeMem(g->gelHead, sizeof(struct VSprite));
if (g->gelTail != NULL)
FreeMem(g->gelTail, sizeof(struct VSprite));
}
/* Deallocate memory which has been allocated by the routines Makexxx. */
/* Assumes images and imageshadow deallocated elsewhere. */
void DeleteGel(v)
struct VSprite *v;
{
if (v != NULL) {
if (v->VSBob != NULL) {
if (v->VSBob->SaveBuffer != NULL) {
FreeMem(v->VSBob->SaveBuffer, sizeof(SHORT) * v->Width
* v->Height * v->Depth);
}
if (v->VSBob->DBuffer != NULL) {
if (v->VSBob->DBuffer->BufBuffer != 0) {
FreeMem(v->VSBob->DBuffer->BufBuffer,
sizeof(SHORT) * v->Width * v->Height * v->Depth);
}
FreeMem(v->VSBob->DBuffer, sizeof(struct DBufPacket));
}
FreeMem( v->VSBob, sizeof(struct Bob));
}
if (v->CollMask != NULL) {
FreeMem(v->CollMask, sizeof(WORD) * v->Height * v->Width);
}
if (v->BorderLine != NULL) {
FreeMem(v->BorderLine, sizeof(WORD) * v->Width);
}
FreeMem(v, sizeof(struct VSprite));
}
}
/* end of purgegels.c */
/* #include "ram:readygels.c" */
/* readygels.c */
struct VSprite *SpriteHead = NULL;
struct VSprite *SpriteTail = NULL;
void border_dummy() /* a dummy collision routine */
{
return;
}
ReadyGels(g, r)
struct RastPort *r;
struct GelsInfo *g;
{
/* Allocate head and tail of list. */
if ((SpriteHead = (struct VSprite *)AllocMem(sizeof
(struct VSprite), MEMF_PUBLIC | MEMF_CLEAR)) == 0)
{
return(-1);
}
if ((SpriteTail = (struct VSprite *)AllocMem(sizeof
(struct VSprite), MEMF_PUBLIC | MEMF_CLEAR)) == 0)
{
FreeMem(SpriteHead, sizeof(struct VSprite));
return(-2);
}
g->sprRsrvd = 0xFC; /* do not use sprites 0 or 1. */
if ((g->nextLine = (WORD *)AllocMem(sizeof(WORD) * 8,
MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
{
FreeMem(SpriteHead, sizeof(struct VSprite));
FreeMem(SpriteTail, sizeof(struct VSprite));
return(-3);
}
if ((g->lastColor = (WORD **)AllocMem(sizeof(LONG) * 8,
MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
{
FreeMem(g->nextLine,8 * sizeof(WORD));
FreeMem(SpriteHead, sizeof(struct VSprite));
FreeMem(SpriteTail, sizeof(struct VSprite));
return(-4);
}
/* Next we prepare a table of pointers to the routines which should
* be performed when DoCollision senses a collision. This
* declaration may not be necessary for a basic vsprite with
* no collision detection implemented, but then it makes for
* a complete example.
*/
if ((g->collHandler = (struct collTable *)AllocMem(sizeof(struct
collTable), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
{
FreeMem(g->lastColor, 8 * sizeof(LONG));
FreeMem(g->nextLine,8 * sizeof(WORD));
FreeMem(SpriteHead, sizeof(struct VSprite));
FreeMem(SpriteTail, sizeof(struct VSprite));
return(-5);
}
/* When any part of the object touches or passes across
* this boundary, it will cause the boundary collision
* routine to be called. This is at smash[0] in the
* collision handler table and is called only if
* DoCollision is called.
*/
g->leftmost = 0;
g->rightmost = r->BitMap->BytesPerRow * 8 - 1;
g->topmost = 0;
g->bottommost = r->BitMap->Rows - 1;
r->GelsInfo = g; /* Link together the two structures */
InitGels(SpriteHead, SpriteTail, g );
/* Pointers initialized to the dummy sprites which will be
* used by the system to keep track of the animation system.
*/
SetCollision(0, border_dummy, g);
WaitTOF();
return(0); /* a return value of 0 says all ok, any
* negative value tells you when it failed.
* (see the listing as to what the routine
* was trying to do... all failures are
* due to out of memory conditions).
*/
}
/* end of readygels.c */
/* #include "ram:MakeVSprite.c" */
/* MakeVSprite.c */
struct VSprite *MakeVSprite(lineheight, image, colorset, x, y,
wordwidth, imagedepth, flags)
SHORT lineheight; /* How tall is this vsprite? */
WORD *image; /* Where is the vsprite image data, should be
twice as many words as the value of lineheight */
WORD *colorset; /* Where is the set of three words which describes
the colors that this vsprite can take on? */
SHORT x, y; /* What is its initial onscreen position? */
SHORT wordwidth, imagedepth, flags;
{
struct VSprite *v; /* Make a pointer to the vsprite structure which
this routine dynamically allocates */
if ((v = (struct VSprite *)AllocMem(sizeof(struct VSprite),
MEMF_PUBLIC | MEMF_CLEAR)) == 0)
{
return(0);
}
v->Flags = flags; /* Is this a vsprite, not a bob? */
v->Y = y; /* Establish initial position relative to */
v->X = x; /* the Display coordinates. */
v->Height = lineheight; /* The Caller says how high it is. */
v->Width = wordwidth; /* A vsprite is always 1 word (16 bits) wide. */
/* There are two kinds of depth... the depth of the image itself, and the
* depth of the playfield into which it will be drawn. The image depth
* says how much data space will be needed to store an image if it's
* dynamically allocated. The playfield depth establishes how much space
* will be needed to save and restore the background when a bob is drawn.
* A vsprite is always 2 planes deep, but if it's being used to make a
* bob, it may be deeper...
*/
v->Depth = imagedepth;
/* Assume that the caller at least has a default boundary collision
* routine.... bit 1 of this mask is reserved for boundary collision
* detect during DoCollision(). The only collisions reported will be
* with the borders. The caller can change all this later.
*/
v->MeMask = 1;
v->HitMask = 1;
v->ImageData = image; /* Caller says where to find the image. */
/* Show system where to find a mask which is a squished down version
* of the vsprite (allows for fast horizontal border collision detect).
*/
if ((v->BorderLine = (WORD *)AllocMem((sizeof(WORD)*wordwidth),
MEMF_PUBLIC | MEMF_CLEAR)) == 0)
{
FreeMem(v, sizeof(struct VSprite));
return(0);
}
/* Show system where to find the mask which contains a 1 bit for any
* position in the object in any plane where there is a 1 bit (all planes
* OR'ed together).
*/
if ((v->CollMask = (WORD *)AllocMem(sizeof(WORD)*lineheight*wordwidth,
MEMF_CHIP | MEMF_CLEAR)) == 0)
{
FreeMem(v, sizeof(struct VSprite));
FreeMem(v->BorderLine, wordwidth * sizeof(WORD));
return(0);
}
/* This isn't used for a Bob, just a VSprite. It's where the
* Caller says where to find the VSprites colors.
*/
v->SprColors = colorset;
/* These aren't used for a VSprite, and MakeBob'll do set up for Bob. */
v->PlanePick = 0x00;
v->PlaneOnOff = 0x00;
InitMasks(v); /* Create the collMask and borderLine */
return(v);
}
/* end of MakeVSprite.c */
int main()
{
struct IntuiMessage *msg;
LONG result;
SHORT k, j, x, y, error;
UWORD *src, *dest; /* for copying sprite data to RAM */
GfxBase = OpenLibrary("graphics.library",0);
IntuitionBase = OpenLibrary("intuition.library",0);
/* (error checking left out for brevity here) */
s = OpenScreen(&myscreen1); /* try to open it */
if(s == 0)
{
printf("Can't open myscreen1\n");
exit(10);
}
myWindow.Screen = s; /* say where screen is located */
ShowTitle(s, FALSE); /* Dont let screen be dragged down...*/
w = OpenWindow(&myWindow);
if(w == 0)
{
printf("Window didn't open!\n");
CloseScreen(s);
exit(20);
}
vp = &(s->ViewPort);
/* set the colors for this viewport */
LoadRGB4(vp, &mycolortable[0], 32);
rp = w->RPort;
/* Now wait for a message to arrive from Intuition
* (task goes to sleep while waiting for the message)
*/
/* Write Text using sprite colors so that demo can show
* how the vsprite machine stuffs the colors as it goes
* down the screen. Thus if using vsprites, user should
* avoid using the color registers that the vsprites use.
*/
/* Notice also that color numbers 17-19 are untouched.
* That is because of the sprResrvd=0xFC in ReadyGels.
* (Doesn't allow the virtual sprite machine to access
* either sprite 0 or 1... 0 is used by mouse cursor and
* shares its colors with 1, so I reserved both of them.
*/
for(j=8; j<180; j+=50)
{
for(k=0; k<15; k++)
{
Move(rp,k*20,j);
SetAPen(rp,k+17); /* show 17-31 */
/* 16, 20, 24, 28 are unaffected by vsprites
* because they are not used by hardware sprites */
Text(rp,numbers[k],2);
}
}
/* *************************************** */
/* VSPRITE DEMO SECTION */
/* *************************************** */
/* Allocate CHIP memory to hold the actual sprite data */
/* (necessary if ever to run on an expanded RAM Amiga) */
sprdata = (UWORD *)AllocMem(36, MEMF_CHIP);
if(sprdata == NULL)
{
/* not enough memory for sprite */
}
/* now copy the sprite data into the CHIP RAM. */
src = sprite_data;
dest = sprdata; /* source, destination */
for( j=0; j<18; j++)
{
*dest++ = *src++;
}
choice = 0;
maxgot = 0;
/* Prepare the GELS system to work with VSPRITE or BOBS */
error = ReadyGels(&mygelsinfo, rp);
for(k=0; k<MAXSP; k++) /* whatever maximum number of vsprites */
{
xmove[k]=speed[RangeRand(4)];
ymove[k]=speed[RangeRand(4)];
/* establish a position for the sprite */
x = 10 + RangeRand(280);
y = 10 + RangeRand(170);
/* create a vsprite */
vsprite[k] = MakeVSprite( 9, sprdata, colorset[choice],
x, y, 1, 2, VSPRITE);
/* 9 lines high, using MEMF_CHIP image of a sprite,
* with a particular set of colors, at an X,Y location
* 1 word wide, 2 planes deep (all vsprites are 2 deep)
* and it is a VSPRITE */
if(vsprite[k] == 0)
{
break; /* ran out of memory! */
}
AddVSprite(vsprite[k], rp);
maxgot++;
choice++; /* choose a different color set */
if(choice >= 4)
{
choice = 0; /* wrap around on colorsets */
}
}
while(1) /* forever */
{
WaitTOF();
movesprites();
result = -1; /* now see if CLOSEWINDOW is waiting */
msg = (struct IntuiMessage *)GetMsg(w->UserPort);
if(msg != 0)
{
result = HandleEvent(msg->Class);
/* Let Intuition reuse the msg */
ReplyMsg(msg);
}
if(result == 0)
{
break; /* got a CLOSEWINDOW */
}
}
/* DONE, now cleanup */
/* Free however many vsprites we actually managed to create */
for(k=0; k<maxgot; k++)
{
DeleteGel(vsprite[k]);
}
/* delete what ReadyGels created */
PurgeGels(&mygelsinfo);
FreeMem(sprdata, 36); /* free what we allocated. */
CloseWindow(w);
CloseScreen(s);
return (0);
}