/* ** BETATRON high level library for platform and action arcade games. ** Copyright (C) 1997 Liouros Thanasis, liouros@hotmail.com ** ** FAR.CC: This file is part of the BETATRON library and can be used ** and/or distributed only under the terms of the GNU Library ** General Public License. See doc/readme.1st for details. */ #include "world.h" #include "plvga.h" short TOworld::howfarD(TOobject *spr,unsigned short howmany) { register unsigned short downy= spr->y + spr->shei -1; unsigned short diff; register unsigned short counter=0; unsigned short ty,tx; register unsigned short *lay; diff=(height<<4)-1 - downy; if (howmany > diff) howmany=diff; if (!Pbackattr) return howmany; counter= 0xf- (downy & 0xf); // posa pixel mporei na kinithei pros ta kato // xoris na allaksei tile register unsigned short step=length; ty= ( downy >> 4) +1; // to kato meros tou sprite tx= (spr->x + (spr->slen >> 1)) >> 4; lay=Pbackattr+ty*step+tx; for (;howmany>counter;counter+=16) { if ( (*lay) & 32768) break; lay+=step; } if (counter>howmany) counter=howmany; return counter; } short TOworld::howfarSD(TOobject *spr,unsigned short howmany) { register unsigned short downy; register unsigned short counter=0; unsigned short diff; unsigned short tx,ty; unsigned short layadd; register unsigned short *lay; unsigned short *lay2; unsigned short nowy,sno; // surfaceno unsigned short sprx; unsigned short surfsx,surfex,surfsy,surfy; Tsurface *surf; if (!surfaces || !Pbackattr2) // den iparxoun plagies epifaneies return howfarD(spr,howmany); downy= spr->y + spr->shei -1; diff=(height<<4)-1 - downy; if (howmany > diff) howmany=diff; if (!Pbackattr || !howmany) return howmany; sprx=spr->x+(spr->slen >> 1); tx=sprx >> 4; // i mesi tou sprite // iparxoun kai plagies epifaneies ty=downy>>4; layadd=ty*length+tx; lay2=Pbackattr2+layadd; lay=Pbackattr+layadd; nowy=downy; if ( ! ( (*lay) & 32768) ) // den iparxei epifaneia s'auto to tile nowy|=0xF; // proxora to nowy sto telos autou tou tile else { sno=(*lay2)&SURFBITSMASK; // einai i epifaneia orizontio tmima stin korifi tou tile ? if (sno==SURFBITSMASK) nowy|=0xF; else { surf=surfaces+sno; surfsx=surf->sx; surfsy=surf->sy; surfex=surfsx+surf->sl-1; //elegkse an to simeio anikei stin epifaneia kata tin orizontia dieuthinsi if ( surfsx > sprx || surfex < sprx) nowy|=0xF; else { surfy=surf->data[sprx-surfsx]+surfsy; // des an anikei to simeio tis epifaneias sto tile if (surfy>>4 != ty) nowy|=0xF; // proxora to nowy sto telos autou tou tile else { // to simeio tis epifaneias anikei sto tile if (surfy>nowy) { nowy=surfy-1; return ((nowy-downy)>howmany?howmany:nowy-downy); } else nowy|=0xF; // proxora to nowy sto telos autou tou tile } } } } lay+=length;lay2+=length;ty++; counter=nowy-downy; for (;howmany>counter;lay+=length,lay2+=length,ty++,counter+=16) { if ( ! ( (*lay) & 32768) ) // den iparxei epifaneia s'auto to tile continue; // diaforetika iparxei epifaneia sno=(*lay2)&SURFBITSMASK; if (sno==SURFBITSMASK) break; // terma ftasame se empodio surf=surfaces+sno; surfsx=surf->sx; surfsy=surf->sy; surfex=surfsx+surf->sl-1; //elegkse an to simeio anikei stin epifaneia kata tin orizontia dieuthinsi if ( surfsx > sprx || surfex < sprx) continue; surfy=surf->data[sprx-surfsx]+surfsy; // des an anikei to simeio tis epifaneias sto tile if (surfy>>4 != ty) continue; // to simeio tis epifaneias anikei sto tile if (surfy>downy+counter) { counter=(surfy-1)-downy; break; } } // for return (counter>howmany?howmany:counter); } short TOworld::howfarU(TOobject *spr,unsigned short howmany) { register unsigned short upy= spr->y; register unsigned short counter=0; unsigned short starttilex,starttiley; if (upy < howmany) howmany=upy; if (!Pbackattr) return howmany; counter=(upy & 0xf); // posa pixel pros ta pano xoris na allaksei tile starttilex= ((spr->x+(spr->slen >> 1)) >> 4); starttiley= ( upy >> 4) -1; register unsigned short step=length; register unsigned short *lay=Pbackattr+starttiley*step+starttilex; for (;howmany>counter;counter+=16) { if ( (*lay) & 16384) break; lay-=step; } if (counter>howmany) counter=howmany; return counter; } Tdxy TOworld::howfarSR(TOobject *spr,unsigned short howmany) { static Tdxy t; unsigned short startx,endx; unsigned short ty1,ty2; unsigned short oldty1,oldty2; unsigned short nowy1,nowy2; // ta oria tou sprite katakorifa unsigned short starty2; long nowx; // mi tixon kai iperxilisei pera apo to 65535 unsigned short tx,oldtx; long diff; unsigned short *lay,*lay2,*laytmp,*lay3,*lay4; long layval; unsigned short *surfar; // surfarray long xlimit,xlimit2; // ena deksi orio se broxo unsigned short surfsx,surfex,surfsy,surfy,sno; long i; Tsurface *surf; long oldsurfy; // pairnei kai tin timi -1; unsigned short tmpty; t.fall=0; // arxika to sprite den eftase sto telos tis epifaneias if (!Pbackattr2 || !surfaces) { t.dy=0; t.dx=howfarR(spr,howmany); return t; } diff = (length << 4)- (long)(spr->x + spr->slen); if (diff < howmany) howmany=diff; if (!Pbackattr || !howmany) { t.dy=0; t.dx=howmany; return t; } /* 2 periptoseis i) to sprite brisketai idi pano se kapoia epifaneia. Se auti tin periptosi i howfarSR prospathei na akolouthisei auti tin epifaneia pros ta deksia howmany pixels. ii) to sprite den brisketai pano se epifaneia. Se auti tin periptosi i howfarSL proxoraei pros ta deksia stin orizontia dieuthinsi howmany pixels mexri na xtipisei ena solid tile i mia epifaneia. Periptosi i) Algorithmos ty1,ty2: einai ta katheta oria tou sprite oldty1: einai ta proigoumena katheta oria nowx=startx; ektelese ena vroxo apo startx mexri startx+howmany - vres an to sprite (nowx,nowy2) vrisketai pano se epifaneia An oxi pida stin periptosi ii) - vres to tmima tis epifaneias kata tin orizontia dieuthinsi apo to nowx mexri to startx+howmany, esto stlen (stlen<=howmany) ektelese ena vroxo apo nowx mexri nowx+stlen - Ean ty1 howmany break; ekso apo to vroxo nowx--; afairese ena apo to deikti tis epifaneias gia na vreis to proigoumeno surfy kai na ipologiseis apo kei to nowy2=surfy-1 epestrepse tous arithmous Periptosi ii) Algorithmos gia kathe tile ekteloume ena vroxo howmany fores gia to nowx apo nowx mexri nowx+howmany; Me ta oldtx kai tx elegxoume an allaksame tile. sto telos kathe broxou: - to nowx|=0xf ,nowx++ - tx++ - Ean nowx-startx > howmany break; 1) - Ean tx!=oldtx elegkse an mporoume na perasoume to tx katheto block ton tiles apo ty1 mexri ty2 kai these (oldtx=tx) An oxi telos - Ean *lay & 32768 continue - Ean iparxei epifaneia kai einai arithmou 0 (diladi top solid tile) continue - Ean iparxei epifaneia kai teleionei prin to nowx continue - Ean iparxei epifaneia kai surfx > nowx,nowx=surfx; these surfyold=surfy kai nowx++, 2) bres apo to nowx mexri to telos tou tile pio tmima tis epifaneias einai mesa sto tile , esto stlen - Gia ola ta simeia apo to nowx mexri to nowx+stlen kane ta eksis - an i diafora einai mi arnitiki diladi einai nowy >= surfy tote an i diafora nowy-oldsurfy einai mi thetiki diladi nowy<=oldsurfy exoume sigkrousi opote break; 3) nowx--; kai vres posa tha epistrepseis */ startx=nowx=spr->x+(spr->slen >> 1); endx=startx+howmany; nowy1=spr->y; nowy2=starty2=spr->y+spr->shei-1; ty1=oldty1=nowy1>>4; ty2=oldty2=nowy2>>4; tx=oldtx=startx >> 4; lay=Pbackattr+ty2*length+tx; /////////////////////////// if ( (tmpty=(nowy2+1) >> 4 ) >= height) goto NotOnSurfaceInit; layval=tmpty*length+tx; // psakse gia epifaneia 1 pixel kato apo // to trexon y2 lay4=Pbackattr+layval; //////////////////// Elegxos gia ton an to sprite einai pano se epifaneia //// if (! ((*lay4) & 32768) ) // den iparxei epifaneia se auto to tile goto NotOnSurfaceInit; // pigaine stin periptosi ii) lay3=Pbackattr2+layval; sno=(*lay3)&SURFBITSMASK; if (sno==SURFBITSMASK) goto NotOnSurfaceInit; surf=surfaces+sno; surfsx=surf->sx; surfsy=surf->sy; surfex=surfsx+surf->sl-1; //elegkse an to simeio anikei stin epifaneia kata tin orizontia dieuthinsi if ( surfex < nowx || surfsx > nowx) goto NotOnSurfaceInit; surfar=surf->data+(nowx-surfsx); surfy=(*surfar)+surfsy; // des an to sprite brisketai pano stin epifaneia if (nowy2!=surfy-1) goto NotOnSurfaceInit; ///////////////////////////// Apo edo to sprite vrisketai pano se epifaneia /////////Bres to tmima tis epifaneias apo nowx mexri startx+howmany if (surfex>=endx) xlimit=endx; else xlimit=surfex; /////////Broxos apo nowx mexri xlimit nowx++; tx=nowx>>4; //////// Algorithmos periptosis i) for (;nowx<=xlimit;nowx++,tx=nowx>>4) { surfar++; nowy2=surfsy+(*surfar)-1; // akoloutha tin epifaneia nowy1=nowy2-spr->shei+1; ty1=nowy1>>4; ty2=nowy2>>4; layval=(ty2-oldty2)*length + (tx-oldtx); lay+=layval; // elegkse mipos iparxei sigkrousi pros ta pano if (ty1=ty1;i--,laytmp-=length) if ( (*laytmp) & 8192) { nowy2=surfsy+(*(surfar-1))-1; goto OnSurfaceExit; } oldty1=ty1; oldtx=tx; oldty2=ty2; //// } // for if (nowx<=endx) // prepei na proxorisoume kai allo { t.fall=1; // to sprite eftase sto telos tis epifaneias lay+=tx-oldtx; // tin teleutaia fora mono to x allakse goto NotOnSurface; } OnSurfaceExit: nowx--; // meiose to nowx giati exei auksithei kata 1 t.dx=nowx-startx; t.dy=nowy2-starty2; return t; //////////////////////////////////////////////////////////////////////////// ////////// apo edo kai kato einai i deuteri periptosi ////////////////////// //////////////////////////////////////////////////////////////////////////// NotOnSurfaceInit: nowx++; // proxora sto epomeno pixel tx=nowx>>4; // enimerose kai to tx lay+=(tx-oldtx); // kai to lay NotOnSurface: lay2=Pbackattr2+ty2*length+tx; // ipologise to lay2 // vroxos for (;nowx<=(long)endx;nowx|=0xf,nowx++,tx=nowx>>4,lay++,lay2++) { // elegxos gia sigkrousi pros ta deksia if (tx!=oldtx) for (i=ty2,laytmp=lay;i>=ty1;i--,laytmp-=length) if ( (*laytmp) & 8192) goto NotOnSurfaceExit; oldtx=tx; /// elegkse mipos den iparxei epifaneia if ( ! ((*lay) & 32768) ) continue; // mideniki epifaneia diladi top solid tile sno=(*lay2)&SURFBITSMASK; if (sno==SURFBITSMASK) continue; surf=surfaces+sno; surfsx=surf->sx; surfsy=surf->sy; surfex=surfsx+surf->sl-1; //elegkse an i epifaneia teleionei prin to nowx if ( surfex < nowx) continue; // elegkse an i epifaneia arxizei meta to nowx surfar=surf->data; if ( surfsx >= nowx) { nowx=surfsx; // pida stin arxi tis epifaneias oldsurfy=-1; // -1 gia na min iparxei periptosi sigkrousis } else { surfar+=(nowx-surfsx); oldsurfy=*(surfar-1)+surfsy; // to oldsurfy deixnei sto proigoumeno pixel } // vres pio tmima tis epifaneias einai mesa sto tile if ( surfex >= (nowx|0xf)) xlimit=nowx|0xf; else xlimit=surfex; // broxos for (;nowx<=xlimit;nowx++,surfar++) { surfy=surfsy+(*surfar); if (nowy2>=surfy) if ( (long)nowy2<=oldsurfy ) goto NotOnSurfaceExit; oldsurfy=surfy; } // elegkse tin periptosi pou allazoume tile kai // to surfy paei se diaforetiko tile apo to nowy2 // eno i diafora surfy-oldsurfy >= 2 // auti i periptosi mporei na dimiourgisei provlima // an den antimetopistei eidika if (nowx<=surfex) if (nowy2>=(surfsy+(*surfar)) ) if ( (long)nowy2<=oldsurfy ) goto NotOnSurfaceExit; }//for NotOnSurfaceExit: nowx--; t.dx=((nowx-startx)>=howmany?howmany:(nowx-startx)); t.dy=nowy2-starty2; return t; } short TOworld::howfarR(TOobject *spr,unsigned short howmany) { unsigned short rightx=spr->x+(spr->slen >> 1); register unsigned short counter=0; register unsigned short starttiley,endtiley; unsigned short starttilex; unsigned short diff; diff = (length << 4)- spr->x - spr->slen; if (diff < howmany) howmany=diff; if (!Pbackattr) return howmany; counter= 0xf- (rightx & 0xf); // posa pixel mporei na kinithei pros ta deksia // xoris na allaksei tile starttilex= (rightx >> 4) +1; starttiley= (spr->y >> 4); endtiley = (spr->y + spr->shei - 1) >> 4; register unsigned short step=length; register unsigned short *lay=Pbackattr+starttiley*step+starttilex; register unsigned short *laytmp; register unsigned short i; for (;howmany>counter;counter+=16,lay++) for (laytmp=lay,i=starttiley;i<=endtiley;i++,laytmp+=step) if ( (*laytmp) & 8192 ) { if (counter>howmany) counter=howmany; return counter; } return (counter>howmany)?howmany:counter; } short TOworld::howfarL(TOobject *spr,unsigned short howmany) { unsigned short leftx=spr->x+(spr->slen >> 1); register unsigned short counter=0; register unsigned short starttiley,endtiley; unsigned short starttilex; short diff; if (spr->x < howmany) howmany=spr->x; if (!Pbackattr) return howmany; counter= (leftx & 0xf); // posa pixel mporei na kinithei pros ta aristera // xoris na allaksei tile starttilex= (leftx >> 4) - 1; starttiley= (spr->y >> 4); endtiley = (spr->y + spr->shei - 1) >> 4; register unsigned short step=length; register unsigned short *lay=Pbackattr+starttiley*step+starttilex; register unsigned short *laytmp; register unsigned short i; for (;howmany>counter;counter+=16,lay--) for (laytmp=lay,i=starttiley;i<=endtiley;i++,laytmp+=step) if ( (*laytmp) & 4096 ) { if (counter>howmany) counter=howmany; return counter; } return (counter>howmany)?howmany:counter; } Tdxy TOworld::howfarSL(TOobject *spr,unsigned short howmany) { static Tdxy t; unsigned short startx; unsigned short endx; unsigned short ty1,ty2; unsigned short oldty1,oldty2; unsigned short nowy1,nowy2; // ta oria tou sprite katakorifa unsigned short starty2; long nowx; // mi tixon kai iperxilisei pera apo to 0 unsigned short tx,oldtx; unsigned short diff; unsigned short *lay,*lay2,*laytmp,*lay3,*lay4; long layval; unsigned short *surfar; // surfarray long xlimit,xlimit2; // ena deksi orio se broxo unsigned short surfsx,surfex,surfsy,surfy,sno; long i; Tsurface *surf; long oldsurfy; // pairnei kai tin timi -1; unsigned short tmpty; t.fall=0; // arxika to sprite den eftase sto telos tis epifaneias if ( !Pbackattr2 || !surfaces) { t.dy=0; t.dx=howfarL(spr,howmany); return t; } if (spr->x < howmany) howmany=spr->x; if (!Pbackattr || !howmany) { t.dy=0; t.dx=howmany; return t; } startx=nowx=spr->x+(spr->slen >> 1); endx=startx-howmany; nowy1=spr->y; nowy2=starty2=spr->y+spr->shei-1; ty1=oldty1=nowy1>>4; ty2=oldty2=nowy2>>4; tx=oldtx=startx >> 4; lay=Pbackattr+ty2*length+tx; /////////////////////////// if ( (tmpty=(nowy2+1) >> 4 ) >= height) goto NotOnSurfaceInitL; layval=tmpty*length+tx; // psakse gia epifaneia 1 pixel kato apo // to trexon y2 lay4=Pbackattr+layval; //////////////////// Elegxos gia ton an to sprite einai pano se epifaneia //// if (! ((*lay4) & 32768) ) // den iparxei epifaneia se auto to tile goto NotOnSurfaceInitL; // pigaine stin periptosi ii) lay3=Pbackattr2+layval; sno=(*lay3)&SURFBITSMASK; if (sno==SURFBITSMASK) goto NotOnSurfaceInitL; surf=surfaces+sno; surfsx=surf->sx; surfsy=surf->sy; surfex=surfsx+surf->sl-1; //elegkse an to simeio anikei stin epifaneia kata tin orizontia dieuthinsi if ( surfex < nowx || surfsx > nowx) goto NotOnSurfaceInitL; surfar=surf->data+(nowx-surfsx); surfy=(*surfar)+surfsy; // des an to sprite brisketai pano stin epifaneia if (nowy2!=surfy-1) goto NotOnSurfaceInitL; ///////////////////////////// Apo edo to sprite vrisketai pano se epifaneia /////////Bres to tmima tis epifaneias apo nowx mexri startx+howmany if (surfsx<=endx) xlimit=endx; else xlimit=surfsx; /////////Broxos apo nowx mexri xlimit nowx--; tx=nowx>>4; //////// Algorithmos periptosis i) for (;nowx>=xlimit;nowx--,tx=nowx>>4) { surfar--; nowy2=surfsy+(*surfar)-1; // akoloutha tin epifaneia nowy1=nowy2-spr->shei+1; ty1=nowy1>>4; ty2=nowy2>>4; layval=(ty2-oldty2)*length + (tx-oldtx); lay+=layval; // elegkse mipos iparxei sigkrousi pros ta pano if (ty1=ty1;i--,laytmp-=length) if ( (*laytmp) & 4096) { nowy2=surfsy+(*(surfar-1))-1; goto OnSurfaceExitL; } oldty1=ty1; oldtx=tx; oldty2=ty2; //// } // for if (nowx>=endx) // prepei na proxorisoume kai allo ?? { t.fall=1; // to sprite eftase stin arxi tis epifaneias lay+=tx-oldtx; // tin teleutaia fora mono to x allakse goto NotOnSurfaceL; } OnSurfaceExitL: nowx++; t.dx=startx-nowx; t.dy=nowy2-starty2; return t; //////////////////////////////////////////////////////////////////////////// ////////// apo edo kai kato einai i deuteri periptosi ////////////////////// //////////////////////////////////////////////////////////////////////////// NotOnSurfaceInitL: nowx--; // proxora sto epomeno pixel tx=nowx>>4; // enimerose kai to tx lay+=(tx-oldtx); // kai to lay NotOnSurfaceL: lay2=Pbackattr2+ty2*length+tx; // ipologise to lay2 // vroxos for (;nowx>=(long)endx;nowx&=(~0xf),nowx--,tx=nowx>>4,lay--,lay2--) { //*-------------------*/ printf("nowx: %d endx: %d\n",nowx,endx); // elegxos gia sigkrousi pros ta aristera if (tx!=oldtx) for (i=ty2,laytmp=lay;i>=ty1;i--,laytmp-=length) if ( (*laytmp) & 4096) goto NotOnSurfaceExitL; oldtx=tx; /// elegkse mipos den iparxei epifaneia if ( ! ((*lay) & 32768) ) continue; // mideniki epifaneia diladi top solid tile sno=(*lay2)&SURFBITSMASK; if (sno==SURFBITSMASK) continue; surf=surfaces+sno; surfsx=surf->sx; surfsy=surf->sy; surfex=surfsx+surf->sl-1; //elegkse an i epifaneia arxizei meta to nowx if ( surfsx > nowx) continue; // elegkse an i epifaneia teleionei prin to nowx surfar=surf->data; if ( surfex <= nowx) { nowx=surfex; // pida stin arxi tis epifaneias oldsurfy=-1; // -1 gia na min iparxei periptosi sigkrousis } else { surfar+=(nowx-surfsx); oldsurfy=*(surfar+1)+surfsy; // to oldsurfy deixnei sto proigoumeno pixel } // vres pio tmima tis epifaneias einai mesa sto tile if ( surfsx < nowx&(~0xf) ) xlimit=nowx&(~0xf); else xlimit=surfsx; // broxos for (;nowx>=xlimit;nowx--,surfar--) { surfy=surfsy+(*surfar); if (nowy2>=surfy) if ( (long)nowy2<=oldsurfy ) goto NotOnSurfaceExitL; oldsurfy=surfy; } // elegkse tin periptosi pou allazoume tile kai // to surfy paei se diaforetiko tile apo to nowy2 // eno i diafora surfy-oldsurfy >= 2 // auti i periptosi mporei na dimiourgisei provlima // an den antimetopistei eidika if (nowx>=surfsx) if (nowy2>=(surfsy+(*surfar)) ) if ( (long)nowy2<=oldsurfy ) goto NotOnSurfaceExitL; }//for NotOnSurfaceExitL: nowx++; t.dx=((startx-nowx)>=howmany?howmany:(startx-nowx)); t.dy=nowy2-starty2; return t; }