- tile animation bugs in some levels of ep2 have been fixed git-svn-id: https://clonekeenplus.svn.sourceforge.net/svnroot/clonekeenplus/cgenius/trunk@196 4df4b0f3-56ce-47cb-b001-ed939b7d65a6
394 lines
11 KiB
C++
394 lines
11 KiB
C++
/* MAP.C
|
|
Functions that deal with the level map. Most notably in here
|
|
you'll find the 4-way scrolling engine.
|
|
*/
|
|
|
|
#include "keen.h"
|
|
#include "CGraphics.h"
|
|
|
|
unsigned long scroll_x = 0; // total amount of X scroll
|
|
unsigned int scrollx_buf = 0; // amount the scroll buffer is scrolled(x)
|
|
unsigned char scrollpix = 0; // (0-7) for tracking when to draw a stripe
|
|
unsigned int mapx = 0; // map X location shown at scrollbuffer row 0
|
|
unsigned int mapxstripepos = 0; // X pixel position of next stripe row
|
|
|
|
unsigned int scrolly_buf = 0; // amount the scroll buffer is scrolled(y)
|
|
unsigned char scrollpixy = 0; // (0-7) for tracking when to draw a stripe
|
|
unsigned int mapy = 0; // map Y location shown at scrollbuffer column 0
|
|
unsigned int mapystripepos = 0; // Y pixel position of next stripe column
|
|
|
|
// note that the scroll buffer is 512x512, this is where all the 511 and 512
|
|
// numbers come from.
|
|
|
|
// scrolls the map one pixel right
|
|
void map_scroll_right(void)
|
|
{
|
|
scroll_x++;
|
|
if(scrollx_buf>=511) scrollx_buf=0; else scrollx_buf++;
|
|
|
|
scrollpix++;
|
|
if (scrollpix>15)
|
|
{ // need to draw a new stripe
|
|
map_draw_vstripe(mapxstripepos, mapx + 32);
|
|
mapx++;
|
|
mapxstripepos += 16;
|
|
if (mapxstripepos >= 512) mapxstripepos = 0;
|
|
scrollpix = 0;
|
|
}
|
|
}
|
|
|
|
// scrolls the map one pixel left
|
|
void map_scroll_left(void)
|
|
{
|
|
scroll_x--;
|
|
if(scrollx_buf==0) scrollx_buf=511; else scrollx_buf--;
|
|
|
|
if (scrollpix==0)
|
|
{ // need to draw a new stripe
|
|
mapx--;
|
|
if (mapxstripepos == 0)
|
|
{
|
|
mapxstripepos = (512 - 16);
|
|
}
|
|
else
|
|
{
|
|
mapxstripepos -= 16;
|
|
}
|
|
map_draw_vstripe(mapxstripepos, mapx);
|
|
|
|
scrollpix = 15;
|
|
} else scrollpix--;
|
|
}
|
|
|
|
void map_scroll_down(void)
|
|
{
|
|
scroll_y++;
|
|
if(scrolly_buf>=511) scrolly_buf=0; else scrolly_buf++;
|
|
|
|
scrollpixy++;
|
|
if (scrollpixy>15)
|
|
{ // need to draw a new stripe
|
|
map_draw_hstripe(mapystripepos, mapy + 32);
|
|
mapy++;
|
|
mapystripepos += 16;
|
|
if (mapystripepos >= 512) mapystripepos = 0;
|
|
scrollpixy = 0;
|
|
}
|
|
}
|
|
|
|
void map_scroll_up(void)
|
|
{
|
|
scroll_y--;
|
|
if(scrolly_buf==0) scrolly_buf=511; else scrolly_buf--;
|
|
|
|
if (scrollpixy==0)
|
|
{ // need to draw a new stripe
|
|
mapy--;
|
|
if (mapystripepos == 0)
|
|
{
|
|
mapystripepos = (512 - 16);
|
|
}
|
|
else
|
|
{
|
|
mapystripepos -= 16;
|
|
}
|
|
map_draw_hstripe(mapystripepos, mapy);
|
|
|
|
scrollpixy = 15;
|
|
} else scrollpixy--;
|
|
}
|
|
|
|
|
|
// draws a vertical stripe from map position mapx to scrollbuffer position x
|
|
void map_draw_vstripe(unsigned int x, unsigned int mpx)
|
|
{
|
|
int i,y,c;
|
|
/*int xt=x>>4;*/
|
|
for(y=0;y<SCROLLBUF_NUMTILESY;y++)
|
|
{
|
|
c = map.mapdata[mpx][y+mapy];
|
|
g_pGraphics->drawTile(x, ((y<<4)+mapystripepos)&511, c);
|
|
|
|
if (AnimTileInUse[x>>4][(((y<<4)+mapystripepos)&511)>>4])
|
|
{ // we just drew over an animated tile which we must unregister
|
|
animtiles[AnimTileInUse[x>>4][(((y<<4)+mapystripepos)&511)>>4]].slotinuse = 0;
|
|
AnimTileInUse[x>>4][(((y<<4)+mapystripepos)&511)>>4] = 0;
|
|
}
|
|
//if (tiles[c].isAnimated)
|
|
if ( TileProperty[c][ANIMATION] > 1 )
|
|
{ // we just drew an animated tile which we will now register
|
|
for(i=1;i<MAX_ANIMTILES-1;i++)
|
|
{
|
|
if (!animtiles[i].slotinuse)
|
|
{ // we found an unused slot
|
|
animtiles[i].x = x;
|
|
animtiles[i].y = (((y<<4)+mapystripepos)&511);
|
|
animtiles[i].baseframe = c - tiles[c].animOffset;
|
|
animtiles[i].offset = tiles[c].animOffset;
|
|
animtiles[i].slotinuse = 1;
|
|
AnimTileInUse[x>>4][((((y<<4)+mapystripepos)&511))>>4] = i;
|
|
goto stop; // and drop out of the loop
|
|
}
|
|
}
|
|
stop: ;
|
|
}
|
|
}
|
|
}
|
|
// draw a horizontal stripe, for vertical scrolling
|
|
void map_draw_hstripe(unsigned int y, unsigned int mpy)
|
|
{
|
|
int i,x,c;
|
|
/*int xt;*/
|
|
for(x=0;x<SCROLLBUF_NUMTILESX;x++)
|
|
{
|
|
c = map.mapdata[x+mapx][mpy];
|
|
g_pGraphics->drawTile(((x<<4)+mapxstripepos)&511, y, c);
|
|
|
|
if (AnimTileInUse[(((x<<4)+mapxstripepos)&511)>>4][y>>4])
|
|
{ // we just drew over an animated tile which we must unregister
|
|
animtiles[AnimTileInUse[(((x<<4)+mapxstripepos)&511)>>4][y>>4]].slotinuse = 0;
|
|
AnimTileInUse[(((x<<4)+mapxstripepos)&511)>>4][y>>4] = 0;
|
|
}
|
|
if ( TileProperty[c][ANIMATION] > 1 )
|
|
{ // we just drew an animated tile which we will now register
|
|
|
|
for(i=1;i<MAX_ANIMTILES-1;i++)
|
|
{
|
|
if (!animtiles[i].slotinuse)
|
|
{ // we found an unused slot
|
|
animtiles[i].x = ((x<<4)+mapxstripepos)&511;
|
|
animtiles[i].y = y;
|
|
animtiles[i].baseframe = c - tiles[c].animOffset;
|
|
animtiles[i].offset = tiles[c].animOffset;
|
|
animtiles[i].slotinuse = 1;
|
|
AnimTileInUse[(((x<<4)+mapxstripepos)&511)>>4][y>>4] = i;
|
|
goto stop; // and drop out of the loop
|
|
}
|
|
}
|
|
stop: ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// returns the map tile at map position (x,y)
|
|
unsigned int getmaptileat(unsigned int x, unsigned int y)
|
|
{
|
|
int xa = x>>4;
|
|
int ya = y>>4;
|
|
|
|
if (xa<=255 && ya<=255)
|
|
{
|
|
return map.mapdata[xa][ya];
|
|
}
|
|
else
|
|
{
|
|
if(xa > 255)
|
|
{
|
|
xa = 255;
|
|
//player[cp].xa = 255;
|
|
}
|
|
if(ya > 254)
|
|
{
|
|
ya = 255;
|
|
//player[cp].ya = 255;
|
|
}
|
|
|
|
return map.mapdata[xa][ya];
|
|
//crashflag = 1;
|
|
//crashflag2 = x;
|
|
//crashflag3 = y;
|
|
//why_term_ptr = "getmaptileat(): OOB reading from mapdata.";
|
|
//return 0;
|
|
}
|
|
}
|
|
unsigned int getlevelat(unsigned int x, unsigned int y)
|
|
{
|
|
|
|
return map.objectlayer[x>>4][y>>4];
|
|
}
|
|
|
|
// called at start of level to draw the upper-left corner of the map
|
|
// onto the scrollbuffer...from then on the map will only be drawn
|
|
// in stripes as it scrolls around.
|
|
void drawmap(void)
|
|
{
|
|
int y;
|
|
for(y=0;y<SCROLLBUF_NUMTILESY;y++)
|
|
{
|
|
map_draw_hstripe(y<<4, y);
|
|
}
|
|
}
|
|
|
|
// changes the tile at (x,y) in real time
|
|
void map_chgtile(unsigned int x, unsigned int y, int newtile)
|
|
{
|
|
map.mapdata[x][y] = newtile;
|
|
|
|
if (x>=mapx && y>=mapy && x<mapx+64 && y<mapy+64)
|
|
g_pGraphics->drawTile(((mapxstripepos+((x-mapx)<<4))&511), ((mapystripepos+((y-mapy)<<4))&511), newtile);
|
|
}
|
|
|
|
// searches for animated tiles at the map position (X,Y) and
|
|
// unregisters them from animtiles
|
|
void map_deanimate(int x, int y)
|
|
{
|
|
int px,py;
|
|
int i;
|
|
// figure out pixel position of map tile (x,y)
|
|
px = ((mapxstripepos+((x-mapx)<<4))&511);
|
|
py = ((mapystripepos+((y-mapy)<<4))&511);
|
|
|
|
//TileProperty[map.mapdata[x][y]][ANIMATION] = 1;
|
|
|
|
// find it!
|
|
for(i=1;i<MAX_ANIMTILES-1;i++)
|
|
{
|
|
if (animtiles[i].x == px && animtiles[i].y == py)
|
|
{
|
|
animtiles[i].slotinuse = 0;
|
|
AnimTileInUse[px>>4][py>>4] = 0;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// tells if the object is animating at a given position
|
|
int map_isanimated(int x, int y)
|
|
{
|
|
int px,py;
|
|
int i;
|
|
// figure out pixel position of map tile (x,y)
|
|
px = ((mapxstripepos+((x-mapx)<<4))&511);
|
|
py = ((mapystripepos+((y-mapy)<<4))&511);
|
|
|
|
// find it!
|
|
for(i=1;i<MAX_ANIMTILES-1;i++)
|
|
{
|
|
if (animtiles[i].x == px && animtiles[i].y == py)
|
|
{
|
|
if(animtiles[i].slotinuse != 0)
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0; // no
|
|
}
|
|
|
|
void map_unregister_all_animtiles(void)
|
|
{
|
|
int i;
|
|
for(i=0;i<MAX_ANIMTILES-1;i++) animtiles[i].slotinuse = 0;
|
|
}
|
|
|
|
// after changing a map tile in real time with map_chgtile()
|
|
// from an unanimated to an animated tile, you must call this
|
|
// function to register the new animated tile.
|
|
void map_animate(int x, int y)
|
|
{
|
|
int px,py;
|
|
int c, i;
|
|
|
|
// figure out pixel position of map tile (x,y)
|
|
px = ((mapxstripepos+((x-mapx)<<4))&511);
|
|
py = ((mapystripepos+((y-mapy)<<4))&511);
|
|
c = map.mapdata[x][y];
|
|
if ( TileProperty[c][ANIMATION] == 1 ) // In case the tile mustn't be animated
|
|
{
|
|
crashflag = x;
|
|
crashflag2 = y;
|
|
why_term_ptr = "sorry, but tile at x/y=crashflag1/2 isn't supposed to be animated!";
|
|
crashflag = 0;
|
|
crashflag2 = 0;
|
|
// TODO: Try to remove the crashflags. They really mess up the system!
|
|
|
|
return;
|
|
}
|
|
|
|
// don't reanimate a tile that's already registered--then we'd
|
|
// have multiple entries for it in animtiles[] (that's not good).
|
|
if (AnimTileInUse[px>>4][py>>4])
|
|
return;
|
|
|
|
// find an unused slot in animtiles
|
|
for(i=1;i<MAX_ANIMTILES-1;i++)
|
|
{
|
|
if (!animtiles[i].slotinuse)
|
|
{ // we found an unused slot
|
|
animtiles[i].x = px;
|
|
animtiles[i].y = py;
|
|
animtiles[i].baseframe = c - tiles[c].animOffset;
|
|
animtiles[i].offset = tiles[c].animOffset;
|
|
animtiles[i].slotinuse = 1;
|
|
AnimTileInUse[px>>4][py>>4] = i;
|
|
return;
|
|
}
|
|
}
|
|
|
|
crashflag = 1;
|
|
crashflag2 = x;
|
|
crashflag3 = y;
|
|
why_term_ptr = "Unable to animate tile at x/y=crashflag1/2";
|
|
}
|
|
|
|
// searches the map's object layer for object OBJ.
|
|
// if it is found returns nonzero and places the
|
|
// coordinates of the first occurance of the object
|
|
// in (xout,yout)
|
|
char map_findobject(unsigned int obj, int *xout, int *yout)
|
|
{
|
|
unsigned int x,y;
|
|
|
|
for(y=2;y<map.ysize-2;y++)
|
|
{
|
|
for(x=2;x<map.xsize-2;x++)
|
|
{
|
|
if (map.objectlayer[x][y]==obj)
|
|
{
|
|
*xout = x;
|
|
*yout = y;
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// searches the map's tile layer for tile TILE.
|
|
// if it is found returns nonzero and places the
|
|
// coordinates of the first occurance of the tile
|
|
// in (xout,yout)
|
|
char map_findtile(unsigned int tile, int *xout, int *yout)
|
|
{
|
|
unsigned int x,y;
|
|
|
|
for(y=2;y<map.ysize-2;y++)
|
|
{
|
|
for(x=2;x<map.xsize-2;x++)
|
|
{
|
|
if (map.mapdata[x][y]==tile)
|
|
{
|
|
*xout = x;
|
|
*yout = y;
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// refreshes the map at the current scroll position
|
|
// (unlike drawmap() which does not honor the scroll and will
|
|
// glitch up if scrollx/y is != 0)
|
|
void map_redraw(void)
|
|
{
|
|
int x,mpx;
|
|
|
|
x = mapxstripepos;
|
|
for(mpx=0;mpx<32;mpx++)
|
|
{
|
|
map_draw_vstripe(x,mpx+mapx);
|
|
x+=16;
|
|
x&=511;
|
|
}
|
|
}
|