12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769 |
- /**
- * ideas, ...
- * hexafield with rotate
- * different kind of block-checks, ... row-like, neuralplay like.
- *
- * seven kind of game with changing target sum, .. generated from the level so correct answer is always there.
- *
- * NOTES:
- * ::randomBlock defines a random block in the selected space.
- *
- */
- #define EMPTY_CARD 100
- #define JOKER_CARD 101
- #define DECK_POSITION_X (52000)
- #define DECK_POSITION_Y (14000)
- #define TILE_SIZE_ADD 3000
- #define DESTROYINGSPEED 1024 // 256 = 1
- #define ALLOW_VOID_MOVES // Allow moves that do not result destroying
- #define SQUARE_BASED // square-based or hexagon-based
- //#include <qdebug>
- #include "npclevel.h"
- #include <math.h> // for cosine.
- #include <memory.h> // for memcpy and memset
- #include <stdio.h> // for debug.
- #include <stdlib.h> // for random, can be changed if needed.
- #include <string.h> // for strlen
- #ifndef __int64
- #define __int64 long long int
- #endif
- CNpcLevel::CNpcLevel(ITileRenderer *renderer, CParticleEngine *pengine, int width, int height ) : m_renderer(renderer) {
- m_pengine = pengine;
- m_deckVisibility = 0;
- m_destroyingRound = 0;
- m_dragBegan = 0;
- m_hint1 = 0;
- m_hint2 = 0;
- m_levelScore = 0;
- m_levelProgressChange = 0;
- //m_wasDropping = 0;
- m_grid = 0;
- m_difficulty = 1;
- m_gridWidth = 0;
- m_gridHeight = 0;
- m_floatingAngle = 0;
- m_state = eLEVELSTATE_IDLE;
- m_levelScore = 0;
- m_levelProgressChange = 0;
- m_currentLevel = 0;
- m_hasMoves = 0;
- m_changing[0] = 0;
- m_changing[1] = 0;
- setGameArea( 0,0, 65536, 65536 );
- m_changingCounter = 0;
- m_illegalMoveCounter = 0;
- for (int f=0; f<4096; f++) {
- m_cosineTable[f] = (int)( cos( (float)f/4096.0f * 3.14159f*2.0f ) * 65536.0f );
- };
- resetGrid( width, height );
- // Reset sprays
- pengine->createSprayType( &m_scoreSpray, (TexFont<<16)+10, 0, 0,0,65535,0, 65536/8, 0,0,0, scoreParticleRenderFunction, this );
- pengine->createSprayType( &m_smokeSpray, (TexParticle<<16),0, 0,0, 65536/4,65536/4, 65536/16,65536/16, 65536/4,65536/8,0,0,0,65536,0,8000 );
- pengine->createSprayType( &m_sparkleSpray, (TexParticle<<16)+2,0, 80000,3000, 32536,80536, 65536/20,65536/16, -9000,6000,0,0,0,65536,-32000,32000, 1 );
- pengine->createSprayType( &m_fruitSpray, (TexPieces<<16),8, 164000,4000, 65536,65536, 65536/10,65536/10, -5500,4000,0,0,0,65536,-90000,180000, 0 );
- pengine->createSprayType( &m_morphSpray, (TexParticle<<16)+3, 0,
- 0,2000, 65536/3,65536/8, 65536/2,0, -32000,0,0,0,0,65536,0,16000, 1 );
- };
- CNpcLevel::~CNpcLevel() {
- resetGrid(0,0); // release
- };
- void CNpcLevel::scoreParticleRenderFunction( void *data, SParticle *p ) {
- CNpcLevel *l = (CNpcLevel*)data;
- int x = p->x;// - p->size/2;
- int y = p->y; // - p->size/2;
- char testr[20];
- int size = 120000 + 65536-p->lifeTime/2;
- size/=14;
- y-=size/2;
- if ((p->userData>>16)==0) {
- size/=2;
- int val = (p->userData&255);
- int type = ((p->userData>>8)&255);
- switch (type) {
- case 0:
- default:
- sprintf(testr, "%d of a kind", val );
- break;
- case 1:
- sprintf(testr, "flush of %d", val );
- break;
- case 2:
- sprintf(testr, "straight of %d", val );
- break;
- }
- } else {
- int j =((p->userData>>16)&255);
- if (j==50) {
- size/=2;
- strcpy( testr, "solve bonus");
- } else {
- if (j==51) {
- size/=2;
- strcpy( testr, "taptap");
- } else
- sprintf(testr, "x%d", j );
- }
- };
- char *text = testr;
- x-= strlen(testr)*size*3/5/2;
- char ch;
- // end fade
- int fade =255-(p->lifeTime>>6);
- if (fade<0) fade = 0;
- if (fade==0) { // START FADE
- fade = (65536-p->lifeTime)/20;
- if (fade<0) fade = 0;
- //fade = (p->lifeTime>>7);
- //if (fade>255) fade = 255;
- fade>>=8;
- };
- while (*text!=0) {
- if (*text!=' ') {
- ch = *text-32;
- l->m_renderer->renderTile( x,y,size,size, 0, 0, (TexFont<<16) | ch | (fade<<24), 0 );
- }
- x+=size*3/5;
- text++;
- };
- };
- void CNpcLevel::setLevelState( eLEVELSTATE newState ) {
- m_state = newState;
- switch (m_state) {
- case eLEVELSTATE_BEGINNING:
- zeroMask( GRIDFLAG_CALCULATION_TEMP );
- m_renderer->effectNotify( eEFFECT_NEWLEVEL, 0,0 );
- m_startupCounter = 65536*5;
- break;
- case eLEVELSTATE_GAMEOVER:
- m_startupCounter = (m_gridWidth*m_gridHeight)*65536 ;
- break;
- case eLEVELSTATE_LEVELCOMPLETED:
- zeroMask( GRIDFLAG_CALCULATION_TEMP );
- m_startupCounter = 65536*5;
- break;
- };
- };
- int CNpcLevel::randomBlock() {
- int amount_of_numbers = 7;
- int rval = (rand()&3)*13 + ((13-amount_of_numbers)+(rand()%amount_of_numbers));
- //return (rand()&3)*13 + (4+(rand()%9));
- //return (rand()&3)*13 + (4+(rand()%9));
- int empty_prob = -2+m_currentLevel * 3;
- if (empty_prob>38) empty_prob = 48;
- if ((rand() & 255) < empty_prob) rval = EMPTY_CARD;
- //if ((rand() & 255) < 32) rval = JOKER_CARD;
- return rval;
- //return (rand()%(13*4));
- };
- void CNpcLevel::createLevel( int levelIndex ) {
- m_currentLevel = levelIndex;
- m_hint1 = 0;
- m_hint2 = 0;
- int tecount = 0;
- do {
- // "plant the seeds"
- for (int f=0; f<m_gridWidth*m_gridHeight; f++) {
- m_grid[f].index = randomBlock();
- m_grid[f].flags = 0;
- m_grid[f].animationCount = (rand()&65535)*8;
- m_grid[f].destroying = -1;
- m_grid[f].dropping = -1;
- m_grid[f].wobble = 0;
- m_grid[f].wobbleinc = 0;
- }
- tecount++;
- } while (checkDestroyWholeLevel(0) != 0 || hasMovesLeft() != 1);
- m_hasMoves = 1;
- zeroMask( 0xFFFFFFFF );
- m_changing[0] = 0;
- m_changing[1] = 0;
- m_levelScore = 0;
- m_levelProgressChange = 0;
- cancelSelection(0);
- cancelSelection(1);
- m_destroyingRound = 0;
- hasMovesLeft(); // update hint
- setLevelState( eLEVELSTATE_BEGINNING );
- };
- void CNpcLevel::resetGrid( int width, int height ) {
- if (m_grid) {
- delete [] m_grid;
- m_grid = 0;
- };
- m_hint1 = 0;
- m_hint2 = 0;
- m_gridWidth = width;
- m_gridHeight = height;
- if (m_gridHeight<1 || m_gridWidth<1) return;
- m_grid = new SNpcGridItem[ m_gridWidth * m_gridHeight ];
- m_itemWidth = 65536 / m_gridWidth;
- m_itemHeight = 65536 / m_gridHeight;
- int w = m_itemWidth;
- int h = m_itemHeight;
- int x,y;
- // (re)calculate coordinates
- for (int g=0; g<m_gridWidth; g++) {
- x = (g<<16)/m_gridWidth + (65536/2)/m_gridWidth;
- #ifdef SQUARE_BASED
- int yoff= (65536/2)/m_gridHeight; // + (65536/2)/m_gridHeight;
- #else
- int yoff = (g&1)*h/2;
- #endif
- SNpcGridItem *i = m_grid + g;
- for (int f=0; f<m_gridHeight; f++ ) {
- i->gridxpos = g;
- i->gridypos = f;
- y = ((f)<<16)/m_gridHeight + yoff;
- i->lposx = x - (w>>1);
- i->lposy = y - (h>>1);
- i->genCount = 0;
- i->destroying = -1;
- i->dropping = -1;
- i->animationCount = 0;
- i->wobble = 0;
- i->wobbleinc = 0;
- i+=m_gridWidth;
- };
- };
- };
- // PUZZLEPOKER LOGIC.
- int CNpcLevel::calculateSimilar( int index, int x, int y, int checkmode, int dir ) {
- switch (dir) {
- case 0: y--; break;
- case 1: y++; break;
- case 2: x--; break;
- case 3: x++; break;
- };
- SNpcGridItem *i = getGridItemAt(x,y);
- if (!i) return 0;
- if (i->index==EMPTY_CARD) return 0;
- if (i->index==-1) return 0;
- if (i->dropping!=-1) return 0;
- if (i->destroying>0) return 0; // 0 is correct,... NOT -1
- //if (i->flags&GRIDFLAG_MARKED) return 0;
- //if (i==0 || i->index!=index) return 0;
- int earth_index = i->index/13;
- int number_index = i->index-earth_index*13;
- switch (checkmode) {
- default:
- case 0: // similar earth
- if ((i->flags & GRIDFLAG_SAME_EARTH) != 0) return 0;
- if ((earth_index != index/13)) return 0;
- i->flags |= GRIDFLAG_SAME_EARTH;
- break;
- case 1: // similar number
- if ((i->flags & GRIDFLAG_SAME_NUMBER) != 0) return 0;
- if (number_index != (index-index/13*13)) return 0;
- i->flags |= GRIDFLAG_SAME_NUMBER;
- break;
- case 2: // "normal" minus straight
- if ((i->flags & GRIDFLAG_MINUS_STRAIGHT) != 0) return 0;
- if ((dir&1)==0) { // backwards
- if (number_index!=(index-index/13*13)-1) return 0;
- } else {
- if (number_index!=(index-index/13*13)+1) return 0;
- };
- i->flags |= GRIDFLAG_MINUS_STRAIGHT;
- break;
- case 3: // "reverse" plus straight
- if ((i->flags & GRIDFLAG_PLUS_STRAIGHT) != 0) return 0;
- if ((dir&1)==0) { // backwards
- if (number_index!=(index-index/13*13)+1) return 0;
- } else {
- if (number_index!=(index-index/13*13)-1) return 0;
- };
- i->flags |= GRIDFLAG_PLUS_STRAIGHT;
- break;
- };
- return 1+calculateSimilar(i->index, x,y, checkmode, dir );
- };
- int CNpcLevel::checkDestroyAt( int blockx, int blocky, char apply ) {
- SNpcGridItem *i = getGridItemAt( blockx, blocky);
- int rval = 0;
- int sim_earth;
- int sim_number;
- int minus_straight;
- int plus_straight;
- if (i->index!=-1 && i->index!=EMPTY_CARD) {
- for (int dir = 0; dir<2; dir++) {
- zeroMask( GRIDFLAG_PLUS_STRAIGHT | GRIDFLAG_MINUS_STRAIGHT | GRIDFLAG_SAME_EARTH | GRIDFLAG_SAME_NUMBER | GRIDFLAG_CALCULATION_TEMP);
- minus_straight = calculateSimilar( i->index, blockx, blocky, 2, dir*2) +
- calculateSimilar( i->index, blockx, blocky, 2, dir*2+1) + 1;
- if (minus_straight>3) {
- i->flags |= GRIDFLAG_MINUS_STRAIGHT;
- if (apply) applyDestroy( GRIDFLAG_MINUS_STRAIGHT );
- rval = 1;
- };
- plus_straight = calculateSimilar( i->index, blockx, blocky, 3, dir*2) +
- calculateSimilar( i->index, blockx, blocky, 3, dir*2+1) + 1;
- if (plus_straight>3) {
- i->flags |= GRIDFLAG_PLUS_STRAIGHT;
- if (apply) applyDestroy( GRIDFLAG_PLUS_STRAIGHT );
- rval = 1;
- };
- // similar earth
- sim_earth = calculateSimilar( i->index, blockx, blocky, 0, dir*2) +
- calculateSimilar( i->index, blockx, blocky, 0, dir*2+1) + 1;
- if (sim_earth>=4) {
- i->flags |= GRIDFLAG_SAME_EARTH;
- if (apply) applyDestroy( GRIDFLAG_SAME_EARTH );
- rval = 1;
- };
- sim_number = calculateSimilar( i->index, blockx, blocky, 1, dir*2) +
- calculateSimilar( i->index, blockx, blocky, 1, dir*2+1) + 1;
- if (sim_number>2) {
- i->flags |= GRIDFLAG_SAME_NUMBER;
- if (apply) applyDestroy( GRIDFLAG_SAME_NUMBER );
- rval = 1;
- };
- }
- }
- return rval;
- };
- /*
- // basic match3 -> fruitcake logic
- int CNpcLevel::calculateSimilar( int index, int x, int y, int checkmode, int dir ) {
- int rval = 0;
- SNpcGridItem *i = getGridItemAt(x,y);
- if (i==0 || i->index==0xFFFFFFFF) return 0;
- // seek the beginning ...
- int x2=x;
- int y2=y;
- while (1) {
- #ifdef SQUARE_BASED
- if (dir==0) {x2--;} else {y2--;}
- #else
- if (dir==0) { y2+=(x2&1); x2--; }
- else if (dir==1) { x2--; y2-=(x2&1); }
- else { y2--; }
- #endif
- i = getGridItemAt( x2,y2 );
- if (!i) break;
- if (i->index != index) break;
- x = x2;
- y = y2;
- };
- while (1) {
- i = getGridItemAt( x,y );
- if (!i) break;
- if (i->index != index ) break;
- rval++;
- i->flags |= GRIDFLAG_CALCULATION_TEMP;
- #ifdef SQUARE_BASED
- if (dir==0) x++; else y++;
- #else
- if (dir==0) { x++; y-=(x&1); }
- else if (dir==1) { y+=(x&1); x++; }
- else { y++; }
- #endif
- };
- return rval;
- };
- int CNpcLevel::checkDestroyAt( int blockx, int blocky, char apply ) {
- SNpcGridItem *i = getGridItemAt( blockx, blocky);
- int rval = 0;
- int a = 0;
- if (i->index!=0xFFFFFFFF) {
- zeroMask( GRIDFLAG_CALCULATION_TEMP );
- a = calculateSimilar( i->index, blockx,blocky,0,0 );
- if (a>=3) { if (apply) applyDestroy(GRIDFLAG_CALCULATION_TEMP); rval = 1; } else zeroMask( GRIDFLAG_CALCULATION_TEMP );
- a = calculateSimilar( i->index, blockx,blocky,0,1 );
- if (a>=3) { if (apply) applyDestroy(GRIDFLAG_CALCULATION_TEMP); rval = 1; } else zeroMask( GRIDFLAG_CALCULATION_TEMP );
- #ifndef SQUARE_BASED // check the thrid direction with hexagons.
- a = calculateSimilar( i->index, blockx,blocky,0,2 );
- if (a>=3) { if (apply) applyDestroy(GRIDFLAG_CALCULATION_TEMP); rval = 1; }
- #endif
- }
- return rval;
- };
- */
- int CNpcLevel::checkDestroyWholeLevel(char apply) {
- int rval = 0;
- for (int f=0; f<m_gridHeight; f++)
- for (int g=0; g<m_gridWidth; g++)
- if (checkDestroyAt( g,f,apply ) != 0) rval = 1;
- return rval;
- };
- void CNpcLevel::wobbleHint() {
- //return; // TODO, BACK ON
- if (m_hint1==0 || m_hint2==0) return; // error
- m_hint1->wobbleinc = -65535/16;
- m_hint2->wobbleinc = -65535/15;
- if (m_currentLevel==0) { // switch us
- int x= xtoGameArea((65536/m_gridWidth+m_hint1->lposx+m_hint2->lposx)/2 );
- int y= ytoGameArea((65536/m_gridHeight+m_hint1->lposy+m_hint2->lposy)/2 );
- int dx= xtoGameArea(65536/2)-x;
- int dy= ytoGameArea(65536/2)-y;
- m_pengine->spray( 1, x,y,0, dx/4,dy/4,0, 51<<16, &m_scoreSpray );
- }
- };
- int CNpcLevel::tryMoveWith( SNpcGridItem *i1, SNpcGridItem *i2 ) {
- //qdebug() << "trymovewith start";
- if (i1==0 || i2==0) return 0;
- int ctemp = i1->index;
- i1->index = i2->index;
- i2->index = ctemp;
- int rval = 0;
- if (checkDestroyAt( i1->gridxpos, i1->gridypos, 0 ) == 1 ||
- checkDestroyAt( i2->gridxpos, i2->gridypos, 0 ) == 1) {
- rval = 1;
- };
- ctemp = i1->index; // change back
- i1->index = i2->index;
- i2->index = ctemp;
- //qdebug() << "trymovewith end";
- return rval;
- };
- int CNpcLevel::hasMovesLeft() {
- m_hint1 = 0;
- m_hint2 = 0;
- //qdebug()<<"hasmovesleft start";
- // seek through moves
- for (int y=m_gridHeight-1; y>1; y--) {
- SNpcGridItem *i1 = (m_grid+m_gridWidth*y);
- for (int x=0; x<m_gridWidth; x++) {
- // simulate the moves..
- #ifdef SQUARE_BASED
- if (tryMoveWith( i1,getGridItemAt( x,y+1 ) ) == 1) {
- //i1->flags |= GRIDFLAG_SELECTED;
- m_hint1 = i1;
- m_hint2 = getGridItemAt( x,y+1 );
- //qdebug()<<"hasmovesleft end";
- return 1;
- }
- if (tryMoveWith( i1,getGridItemAt( x+1,y ) ) == 1) {
- //i1->flags |= GRIDFLAG_SELECTED;
- m_hint1 = i1;
- m_hint2 = getGridItemAt( x+1,y );
- //qdebug()<<"hasmovesleft end";
- return 1;
- }
- #else
- if (tryMoveWith( i1,getGridItemAt( x,y+1 ) ) == 1) {
- //i1->flags |= GRIDFLAG_SELECTED;
- m_hint1 = i1;
- m_hint2 = getGridItemAt( x,y+1 );
- //qdebug()<<"hasmovesleft end";
- return 1;
- }
- if (tryMoveWith( i1,getGridItemAt( x+1,y-1+(x&1) ) ) == 1) {
- //i1->flags |= GRIDFLAG_SELECTED;
- m_hint1 = i1;
- m_hint2 = getGridItemAt( x+1,y-1+(x&1) );
- //qdebug()<<"hasmovesleft end";
- return 1;
- }
- if (tryMoveWith( i1,getGridItemAt( x+1,y-1+(x&1)+1 ) ) == 1) {
- //i1->flags |= GRIDFLAG_SELECTED;
- m_hint1 = i1;
- m_hint2 = getGridItemAt( x+1,y-1+(x&1)+1 );
- //qdebug()<<"hasmovesleft end";
- return 1;
- }
- #endif
- i1++;
- };
- };
- //qdebug()<<"hasmovesleft end";
- return 0;
- };
- void CNpcLevel::applyDestroy(unsigned int flag) {
- char wasFirst = 0;
- int width = m_itemWidth;
- int height = m_itemHeight;
- m_doingNothing = false;
- int blocks = 0;
- int mx = 0;
- int my = 0;
- SNpcGridItem *i = m_grid;
- SNpcGridItem *i_target = i+m_gridWidth*m_gridHeight;
- while (i!=i_target) {
- // just destoy the ones that are not already destroying
- if (i->index!=-1 && (i->flags&flag) && (i->destroying==-1)) {
- // at least one of the line wasnt marked before, .. this was first found. mark for scores
- if (!(i->flags&GRIDFLAG_MARKED)) wasFirst = 1;
- mx += i->lposx;
- my += i->lposy;
- blocks++;
- i->flags |=GRIDFLAG_MARKED;
- i->destroying = 0; // start destroying.
- // stop dropping when destroynig?
- //if (i->dropping!=-1) {
- // i->dropping = -1;
- // i->posoffsety = 0;
- //};
- //i->flags &= 0xFFFFFFFF^GRIDFLAG_CALCULATION_TEMP;
- };
- i++;
- };
- if (blocks<1) return;
- if (wasFirst==1) {
- //if (1) {
- //int m = (3-m_destroyingRound);
- //if (m<1) m = 1;
- //int scoreAdd = 1+(((blocks-2)*(blocks-2))*10) / (m_destroyingRound+1);
- //blocks = 5;
- //int scoreAdd = (((blocks-REQUIRED_BLOCKS)+1) * (blocks));
- int scoreAdd = (blocks*blocks*2) / (m_destroyingRound+1); // TODO, CHANGE THIS
- //scoreAdd *= (m_destroyingRound+1);
- int sind = 0;
- int scoreMul = 1;
- switch (flag) {
- case GRIDFLAG_MINUS_STRAIGHT:
- case GRIDFLAG_PLUS_STRAIGHT:
- sind = 2;
- scoreMul = 11;
- break;
- case GRIDFLAG_SAME_EARTH:
- sind = 1;
- scoreMul = 3;
- break;
- case GRIDFLAG_SAME_NUMBER:
- sind = 0;
- scoreMul = 7;
- break;
- };
- if (scoreAdd<1) scoreAdd = 1;
- scoreAdd = (scoreAdd*scoreMul)/3; // most scores fropm straights, then from earth, then from number
-
- m_levelProgressChange += (scoreAdd);// / (m_destroyingRound+1));
- int x= xtoGameArea(mx/blocks+width/2);
- int y = ytoGameArea( my/blocks+height/2 );
- int dx= xtoGameArea(65536/2)-x;
- int dy= ytoGameArea(65536/2)-y;
- m_pengine->spray(1, x, y,0, dx,dy, 0, sind*256 + blocks, &m_scoreSpray );
- //scoreAdd = scoreAdd*(m_destroyingRound+3)/3;
- m_levelScore += scoreAdd;
- }
- };
- int CNpcLevel::tryApplyChange( SNpcGridItem *i ) {
- // cannot select another peace when other than in normal mode
- if ( m_state!=eLEVELSTATE_NORMAL ) {
- m_renderer->effectNotify(eILLEGAL_MOVE, 0, 0);
- cancelSelection(0);
- cancelSelection(1);
- return 0; // cannot continue, level is processing itself.
- };
- char allowChange = 0;
- if (m_difficulty==0) allowChange = 1; // for kids.
- if (allowChange==0) {
- // must be next to changing[0] to be allowed
- #ifdef SQUARE_BASED
- if ((abs( m_changing[0]->gridxpos - i->gridxpos ) +
- abs( m_changing[0]->gridypos - i->gridypos )) <= 1) allowChange = 1;
- #else
- int yofs = (m_changing[0]->gridxpos&1);
- int dx = m_changing[0]->gridxpos - i->gridxpos;
- int dy = m_changing[0]->gridypos - i->gridypos;
- if (dx==0 && abs(dy)<=1) allowChange = 1;
- dy += yofs;
- if (dx==1 || dx==-1) if (dy==0 || dy==1) allowChange = 1;
- #endif
- }
- if (allowChange) {
- m_renderer->effectNotify(eCHANGING, 0, 0);
- m_changing[1] = i;
- m_changingCounter = 65536;
- m_illegalMoveCounter = 0;
- // changing is now enabled
- i->flags ^= GRIDFLAG_SELECTED; // flip the first bit
- }
- else
- {
- m_renderer->effectNotify(eILLEGAL_MOVE, 0, 0);
- cancelSelection(0);
- return 0;
- }
- return 1;
- };
- void CNpcLevel::cancelSelection( int index ) {
- if (m_changing[index]!=0) {
- m_changing[index]->posoffsetx = 0;
- m_changing[index]->posoffsety = 0;
- m_changing[index]->flags &= 0xFFFFFFFF^GRIDFLAG_SELECTED;
- m_changing[index] = 0;
- }
- };
- void CNpcLevel::click( int fixedx, int fixedy, int type ) {
- // dont process these.
- if (m_state==eLEVELSTATE_BEGINNING || m_state==eLEVELSTATE_LEVELCOMPLETED || m_state==eLEVELSTATE_GAMEOVER) return;
- if (m_changingCounter>0) return; // we are currently changing.
- fixedx = ((fixedx-m_areaX)<<12)/(m_areaWidth>>4);
- fixedy = ((fixedy-m_areaY)<<12)/(m_areaHeight>>4);
- if (fixedx<0 || fixedy<0 || fixedx>65535 || fixedy>65535) return; // not inside gamelevel
- int gx = ((fixedx*m_gridWidth)>>16);
- #ifdef SQUARE_BASED
- int gy = ((fixedy*m_gridHeight)>>16);
- #else
- int gyoff = (65536/m_gridHeight/2) -(65536/m_gridHeight/2) * (gx&1);
- int gy = (((fixedy+gyoff)*m_gridHeight)>>16);
- #endif
- if (gy<0) return;
- SNpcGridItem *i = getGridItemAt( gx, gy );
- switch (type) {
- case 1:
- if (m_changing[0]!=0) {
- if (m_difficulty>0) {
- //float fx = (fixedx-m_changing[0]->lposx)-(m_areaWidth/m_gridWidth/2);
- //float fy = (fixedy-m_changing[0]->lposy)-(m_areaHeight/m_gridHeight/2);
- float fx = (fixedx-m_changing[0]->lposx)-(65536/m_gridWidth/2);
- float fy = (fixedy-m_changing[0]->lposy)-(65536/m_gridHeight/2);
- float le = sqrtf( fx*fx+fy*fy );
- if (le>6000.0f) {
- fx=fx/le*6000.0f;
- fy=fy/le*6000.0f;
- }
- m_changing[0]->posoffsetx = fx;
- m_changing[0]->posoffsety = fy;
- //m_changing[0]->posoffsetx = 10000;
- // place absolute position under the cursor
- //m_changing[0]->posoffsetx = (fixedx-m_changing[0]->lposx)-(65536/m_gridWidth/2);
- //m_changing[0]->posoffsety = (fixedy-m_changing[0]->lposy)-(65536/m_gridHeight/2);
- gx = m_changing[0]->lposx + m_changing[0]->posoffsetx + (65536/m_gridWidth/2);
- gy = m_changing[0]->lposy + m_changing[0]->posoffsety + (65536/m_gridHeight/2);
- gx = ((gx*m_gridWidth)>>16);
- #ifdef SQUARE_BASED
- gy = ((gy*m_gridHeight)>>16);
- #else
- int gyoff = (65536/m_gridHeight/2) -(65536/m_gridHeight/2) * (gx&1);
- gy = (((gy+gyoff)*m_gridHeight)>>16);
- if (gy<0) return;
- #endif
- i = getGridItemAt(gx,gy);
- } else {
- m_changing[0]->posoffsetx = (fixedx-m_changing[0]->lposx)-(65536/m_gridWidth/2);
- m_changing[0]->posoffsety = (fixedy-m_changing[0]->lposy)-(65536/m_gridHeight/2);
- }
- /*
- if (m_dragBegan==0) {
- m_changing[0]->posoffsetx = 0;
- m_changing[0]->posoffsety = 0;
- };
- */
- if (i!=m_changing[0]) {
- if (m_changing[1]!=i) {
- //if (m_changing[1]) m_changing[1]->flags ^= GRIDFLAG_SELECTED;
- m_changing[1] = i;
- //if (i) i->flags ^= GRIDFLAG_SELECTED; // flip the first bit
- };
- m_dragBegan = 1;
- };
- } else return;
- break;
- case 2:
- if (m_difficulty>0 && m_dragBegan && m_changing[1]) i = m_changing[1];
- if (m_changing[0]!=0 && m_changing[0]!=i && i->destroying==-1 && i->dropping==-1) {
- tryApplyChange(i);
- } else {
- if (m_dragBegan) {
- cancelSelection(0);
- cancelSelection(1);
- };
- }
- m_dragBegan = 0;
- break;
- case 0:
- m_dragBegan = 0;
- if (!i) return;
- if (i==m_changing[0]) { // was already selected and now we are cancelling it.
- m_renderer->effectNotify(eCLICK, 0, 0);
- cancelSelection(0);
- } else {
- if (i->destroying==-1 && i->dropping==-1) {
- if (m_changing[0]==0)
- {
- // click empty card..
- if (i->index == EMPTY_CARD) {
- m_renderer->effectNotify(eCHANGE_COMPLETED, 0, 0);
- while (i->index == EMPTY_CARD) i->index = randomBlock();
- m_levelProgressChange -= 20;
- m_pengine->spray(1,
- xtoGameArea(i->lposx + m_itemWidth/2),
- ytoGameArea(i->lposy+m_itemHeight/2),
- 200, 0, 0, 0, 0, &m_morphSpray );
- m_pengine->spray(20,
- xtoGameArea(i->lposx + m_itemWidth/2),
- ytoGameArea(i->lposy+m_itemHeight/2),
- 8000, 0, -16000, 64000, 0, &m_sparkleSpray );
- checkDestroyAt(i->gridxpos, i->gridypos );
- } else {
- m_renderer->effectNotify(eCLICK, 0, 0);
- m_changing[0] = i;
- i->flags ^= GRIDFLAG_SELECTED; // flip the first bit
- }
- }
- else {
- tryApplyChange( i );
- };
- }
- }
- break;
- }
- };
- SNpcGridItem *CNpcLevel::getGridItemAt( int blockx, int blocky ) {
- if (blockx<0 || blocky<0 || blockx>=m_gridWidth || blocky>=m_gridHeight) return 0;
- return m_grid + blocky*m_gridWidth + blockx;
- };
- void CNpcLevel::zeroMask( unsigned int maskToZero ) {
- for (int f=0; f<m_gridWidth*m_gridHeight; f++) {
- m_grid [f].flags &= (0xFFFFFFFF^maskToZero );
- };
- };
- void CNpcLevel::run( int fixedFrameTime16Bit ) {
- //fixedFrameTime16Bit/= 10;
- if (m_state == eLEVELSTATE_BEGINNING)
- m_deckVisibility += ((65536 - m_deckVisibility)*(fixedFrameTime16Bit>>4))>>10;
- else
- m_deckVisibility -= ((m_deckVisibility)*(fixedFrameTime16Bit>>4))>>10;
- if (m_state == eLEVELSTATE_IDLE) return;
- if (fixedFrameTime16Bit>8000) fixedFrameTime16Bit = 8000;
- int f,g;
- m_floatingAngle += fixedFrameTime16Bit;
- int width = 65536 / m_gridWidth;
- int height = 65536 / m_gridHeight;
- m_doingNothing = true;
- int something_destroyed = 0;
- int something_dropped = 0;
- int something_destroying = 0;
- int something_dropping = 0;
- int something_created = 0;
- int ind = 0;
- SNpcGridItem *i = m_grid;
- SNpcGridItem *i_target = i + m_gridWidth*m_gridHeight;
- while (i!=i_target) {
- if (ind<m_gridWidth && i->index == -1) {
- int safeCount = 0;
- do { // try a block as long as required
- i->index = randomBlock();
- safeCount++;
- } while (safeCount<1000 && checkDestroyAt(ind,0,0)!=0);
- something_created = 1;
- m_doingNothing = false;
- };
- if (i->destroying>=0) {
- something_destroying = 1;
- f = i->destroying;
- i->destroying+=((fixedFrameTime16Bit*DESTROYINGSPEED)>>8); // destroying speed
- if (f<=(65536+65536/2) && i->destroying>(65536+65536/2)) {
- /*
- m_pengine->spray(10, xtoGameArea(i->lposx+width/2), ytoGameArea(i->lposy+height/2),4000,
- 0,0, 8000, 0, &m_smokeSpray );
- */
- m_pengine->spray(10, xtoGameArea(i->lposx+width/2), ytoGameArea(i->lposy+height/2),8000,
- 0,-10000, 16000, 0, &m_sparkleSpray );
- m_pengine->spray(6+(rand()&3), xtoGameArea(i->lposx+width/2), ytoGameArea(i->lposy+height/2),6000,
- 0,-40000, 50000, 0, &m_fruitSpray );
- };
- if (i->destroying>=65536*2) { // destroy, finally.
- if (i==m_changing[0] || i==m_changing[1]) {
- cancelSelection(0);
- cancelSelection(1);
- m_changingCounter = 0;
- }
- i->index=-1;
- i->destroying = -1;
- i->dropping = -1;
- i->posoffsetx = 0;
- i->posoffsety = 0;
- i->flags = 0;
- i->animationCount = 0;
- something_destroyed = 1;
- };
- };
- i->animationCount += fixedFrameTime16Bit;
- i->animationCount&=(65536*16-1);
- g = ((i->wobble * fixedFrameTime16Bit)>>12); // string effect
- i->wobbleinc-=g;
- g = ((i->wobbleinc * fixedFrameTime16Bit)>>13); // slowdown
- i->wobbleinc -= g;
- g = ((i->wobbleinc * fixedFrameTime16Bit)>>13); // add
- i->wobble+=g;
- if (m_state!=eLEVELSTATE_GAMEOVER) {
- if (i->flags&GRIDFLAG_SELECTED) {
- i->genCount += (((8000-i->genCount) * fixedFrameTime16Bit) >> 14);
- } else {
- // TEST
- //int g = (m_cosineTable[ ((m_floatingAngle>>4) + (ind/(m_gridWidth-1)<<6))&4095 ]>>6);
- int g = (m_cosineTable[ ((m_floatingAngle>>4) + (ind<<10))&4095 ]>>6);
- i->genCount += (((g-i->genCount)*fixedFrameTime16Bit)>>13);
- // gameovereffect
- i->genCount += (((-i->genCount) * fixedFrameTime16Bit) >> 14);
- //i->genCount = 0;
- }
- }
- i++;
- ind++;
- };
- if (something_destroyed==1) {
- m_renderer->effectNotify(eEFFECT_DESTROYING, m_destroyingRound,0);
- m_destroyingRound++;
- };
- int count = 0;
- i = m_grid;
- i_target = i + m_gridWidth*(m_gridHeight-1);
- while (i!=i_target) {
- if (i->dropping==-1 && i->index!=-1) {
- /*
- // destroying pieces wont drop
- if (i->destroying==-1 && (i[m_gridWidth].index==-1 || i[m_gridWidth].dropping!=-1)) {
- i->dropping = 5000; // enable dropping.
- i->posoffsety=0;
- };
- */
- // destroying pieces will drop
- if ((i[m_gridWidth].index==-1 || i[m_gridWidth].dropping!=-1)) {
- i->dropping = 5000; // enable dropping.
- something_dropping = 1;
- i->posoffsety=0;
- };
- } else {
- something_dropping = 1;
- i->dropping+=fixedFrameTime16Bit*4;
- i->posoffsety+=((i->dropping*fixedFrameTime16Bit)>>16);
- if (i->posoffsety>=height) {
- if (i[m_gridWidth].index==-1) {
- //i->posoffsety = 0;
- i->posoffsety-=height;
- i[m_gridWidth].animationCount = i->animationCount;
- i[m_gridWidth].destroying = i->destroying;
- i[m_gridWidth].flags = i->flags;
- i[m_gridWidth].index = i->index;
- i[m_gridWidth].posoffsetx = i->posoffsetx;
- i[m_gridWidth].posoffsety = i->posoffsety;
- i[m_gridWidth].dropping = i->dropping;
- i[m_gridWidth].wobble = i->wobble;
- i[m_gridWidth].wobbleinc = i->wobbleinc;
- i->index = -1;
- i->dropping = -1;
- i->wobble = 0;
- i->wobbleinc = 0;
- }
- }
- if (i[m_gridWidth].index!=-1 && i[m_gridWidth].dropping==-1) {
- // stop dropping...
- f = count/m_gridWidth;
- checkDestroyAt( count-f*m_gridWidth, f, 1 );
- something_dropped = 1;
- i->dropping = -1;
- i->wobbleinc = 4000;
- i->posoffsety = 0;
- };
- };
- count++;
- i++;
- };
- // stop the last line
- i = m_grid + m_gridWidth*(m_gridHeight-1);
- i_target=i+m_gridWidth;
- while (i!=i_target) {
- if (i->dropping!=-1) {
- i->dropping = -1;
- i->posoffsety =0;
- };
- i++;
- };
- if (something_destroyed != 0 || something_dropped != 0 ||
- something_destroying != 0 || something_dropping != 0)
- m_doingNothing = false;
- switch (m_state) {
- case eLEVELSTATE_BEGINNING:
- {
- m_startupCounter -= fixedFrameTime16Bit;
- if (m_startupCounter<=0) {
- m_startupCounter = 0;
- setLevelState( eLEVELSTATE_NORMAL );
- };
- int amount = m_gridWidth * m_gridHeight;
- SNpcGridItem *i = m_grid;
- for (int f=0; f<m_gridWidth*m_gridHeight; f++) {
- int g = m_startupCounter - ((f<<16)*4/amount);
- if (g<0) {
- g = 0;
- if ((i->flags&GRIDFLAG_CALCULATION_TEMP) == 0) {
- i->flags|=GRIDFLAG_CALCULATION_TEMP;
- // do something when block is in place
- m_renderer->effectNotify( eEFFECT_BLOCK_BEGIN_FINISHED, 0,0 );
- };
- } else i->wobble = -1000;
- g>>=4;
- if (g>1024) g = 1024;
- //i->posoffsetx = -(65536-m_cosineTable[ ((g>>9)) & 4095 ])>>4;
- //i->posoffsety = -(g>>5);
- //i->posoffsetx = (m_areaX + m_areaWidth/2) - i->lposx;
- //i->posoffsety = (m_areaY + m_areaHeight/2) - i->lposy;
- i->posoffsetx = DECK_POSITION_X-i->lposx -m_itemWidth/2;
- i->posoffsety = DECK_POSITION_Y-i->lposy - m_itemHeight/2;
- i->posoffsetx = (i->posoffsetx * g)>>10;
- i->posoffsety = (i->posoffsety * g)>>10;
- i->genCount = g*48;
- i++;
- };
- }
- break;
- case eLEVELSTATE_LEVELCOMPLETED:
- {
- m_startupCounter -= fixedFrameTime16Bit;
- if (m_startupCounter<=0) {
- m_startupCounter = 0;
- setLevelState( eLEVELSTATE_IDLE );
- };
- int amount = m_gridWidth * m_gridHeight;
- SNpcGridItem *i = m_grid;
- for (int f=0; f<m_gridWidth*m_gridHeight; f++) {
- int g = ((f<<16)*4/amount) - m_startupCounter;
- g>>=4;
- if (g>1024) g = 1024;
- if (g<=0)
- g = 0;
- else {
- if ((i->flags&GRIDFLAG_CALCULATION_TEMP) == 0) {
- i->flags|=GRIDFLAG_CALCULATION_TEMP;
- // do something when block is taken from its place
- //if (((f)) == 0)
- m_renderer->effectNotify( eEFFECT_BLOCK_VANISH_STARTED, 0,0 );
- };
- }
- //i->posoffsetx = -(65536-m_cosineTable[ ((g>>9)) & 4095 ])>>4;
- //i->posoffsety = -(g>>5);
- //i->posoffsetx = (m_areaX + m_areaWidth/2) - i->lposx;
- //i->posoffsety = (m_areaY + m_areaHeight/2) - i->lposy;
- //i->posoffsetx = DECK_POSITION_X-i->lposx -m_itemWidth/2;
- //i->posoffsety = DECK_POSITION_Y-i->lposy - m_itemHeight/2;
- i->posoffsetx = ((65536-i->lposx + m_itemWidth) * g)>>10;
- i->posoffsety = ((65536-i->lposy + m_itemHeight) * g)>>10;
- i->genCount = g*48;
- i++;
- };
- break;
- }
- case eLEVELSTATE_GAMEOVER:
- {
- int jj = ((m_gridWidth*m_gridHeight)<<16) - m_startupCounter/2;
- if (jj<65536) jj=65536;
- jj = (__int64)(( jj * (__int64)fixedFrameTime16Bit ) >>16 );
- m_startupCounter -= jj;
- if (m_startupCounter<=-65536*32) {
- m_startupCounter=-65536*32;
- setLevelState( eLEVELSTATE_IDLE );
- //setLevelState( eLEVELSTATE_NORMAL );
- // wait and do nothing... until the game changes levelstate to something else.
- };
- SNpcGridItem *i = m_grid;
- for (int f=0; f<m_gridWidth*m_gridHeight; f++) {
- int g = (f<<16)-m_startupCounter;
- if (g<0) g = 0;
- if (g>65536*28) g = 65536*28;
- i->genCount=-(g>>5);
- //
- //i->posoffsetx = +(g>>5);
- //i->posoffsety = +(g>>5);
- i++;
- };
- }
- break;
- case eLEVELSTATE_NORMAL:
- {
- if (something_created)
- checkDestroyWholeLevel();
- // check if the level have moves left and update the hint
- if (something_destroyed || something_dropped || something_created) {
- m_hint1 = 0;
- m_hint2 = 0;
- if (something_destroying==0 && something_dropping==0) {
- if (hasMovesLeft()) {
- } else {
- // NO MOVES LEFT!!
- // give scores
- m_pengine->spray(1, xtoGameArea(65536/2),
- ytoGameArea( 65536/4 ),
- 0, 0, 8000, 0, (50<<16), &m_scoreSpray );
- m_levelScore += 800;
- m_levelProgressChange += 40;
- // destroy randomly?
- int dcount = m_gridHeight;
- int safeCount = 0;
- while (dcount>0 && safeCount<2000) {
- SNpcGridItem *i = getGridItemAt( (rand()&255)*m_gridWidth/256, (rand()&255)*m_gridHeight/256 );
- if (i->index!=-1 && ((i->flags&GRIDFLAG_MARKED) == 0) && i!=m_changing[0] && i!=m_changing[1]) {
- i->flags |= GRIDFLAG_MARKED;
- dcount--;
- };
- safeCount++;
- }
- applyDestroy(GRIDFLAG_MARKED);
- };
- }
- };
- // combo
- if (m_destroyingRound>3 && m_doingNothing) {
- //m_pengine->spray(10, xtoGameArea(65536/2), ytoGameArea( 65536/2 ), 2000,0,0, 8000, 0, &m_destroySpray );
- m_pengine->spray(1, xtoGameArea(65536/2),
- ytoGameArea( 65536/2 ),
- 0, 0, 8000, 0, ((m_destroyingRound-1)<<16), &m_scoreSpray );
- m_renderer->effectNotify( eEFFECT_XBONUS, 0,0 );
- m_levelProgressChange += m_destroyingRound*3;
- m_levelScore += (m_destroyingRound*30);
- m_destroyingRound = 0;
- }
- if (m_changingCounter>0) {
- m_changingCounter -= fixedFrameTime16Bit*6; // CHANGE THIS, WAS 6
- // do the change with m_changing[0] and [1]
- if (m_changingCounter<=0) {
- int temp = m_changing[0]->index;
- m_changing[0]->index = m_changing[1]->index;
- m_changing[1]->index = temp;
- // reset the destroying rounds.
- m_destroyingRound = 0;
- int allow_move = 0;
- // check destroy.
- if (checkDestroyAt( m_changing[0]->gridxpos, m_changing[0]->gridypos )!=0) allow_move = 1;
- if (checkDestroyAt( m_changing[1]->gridxpos, m_changing[1]->gridypos )!=0) allow_move = 1;
- #ifdef ALLOW_VOID_MOVES
- if (allow_move == 0) {
- allow_move = 1; // subtract some scores
- m_levelProgressChange -= 15;
- }
- #endif
- if (allow_move!=0) {
- m_renderer->effectNotify( eCHANGE_COMPLETED, 0 ,0 );
- m_changingCounter = 0;
- } else {
- // ILLEGAL MOVE
- // was a bad move .. change back
- if (m_illegalMoveCounter == 0) {
- m_changingCounter = 65536;
- m_illegalMoveCounter++;
- m_renderer->effectNotify( eILLEGAL_MOVE, 0, 0);
- } else {
- // this was a "backwards" move.
- m_changingCounter = 0; // stay still.
- };
- };
- if (m_changingCounter==0) {
- m_changing[0]->flags &= 0xFFFFFFFF^GRIDFLAG_SELECTED;
- m_changing[1]->flags &= 0xFFFFFFFF^GRIDFLAG_SELECTED;
- m_changing[0]->posoffsetx = 0;
- m_changing[0]->posoffsety = 0;
- m_changing[1]->posoffsetx = 0;
- m_changing[1]->posoffsety = 0;
- m_changing[0] = 0;
- m_changing[1] = 0;
- }
- } else {
- int dx,dy;
- if (m_changing[0] && m_changing[1]) {
- dx = (m_changing[1]->lposx - m_changing[0]->lposx);
- dy = (m_changing[1]->lposy - m_changing[0]->lposy);
- int i = 65536-m_changingCounter;
- dx = ((dx*(i>>4))>>12);
- dy = ((dy*(i>>4))>>12);
- i >>=6;
- i&=4095;
- int ndx = (((dy) * (m_cosineTable[i]>>2)) >> 14);
- int ndy = (((-dx) * (m_cosineTable[i]>>2)) >> 14);
- m_changing[0]->posoffsetx = dx+ndx*3/2;
- m_changing[0]->posoffsety = dy+ndy;
- m_changing[1]->posoffsetx = -dx-ndx*3/2;
- m_changing[1]->posoffsety = -dy-ndy;
- } else {
- cancelSelection(0);
- cancelSelection(1);
- m_changingCounter = 0;
- }
- };
- break; // dont continue.
- };
- }
- break;
- };
- };
- int CNpcLevel::xtoGameArea( const int sourcex ) {
- return m_areaX + ((sourcex*(m_areaWidth>>6))>>10);
- };
- int CNpcLevel::ytoGameArea( const int sourcey ) {
- return m_areaY + ((sourcey*(m_areaHeight>>6))>>10);
- };
- const char num_letters[]={28,29,30,31,32,33,34,35,26,9,16,10,0 };
- void CNpcLevel::renderTileCaller( SNpcGridItem *i, ITileRenderer &renderer ) {
- // change size from i's gencount
- int sizeAdd = TILE_SIZE_ADD + (i->genCount>>2);
- int fade = 0;
- int width = m_itemWidth;
- int height = m_itemHeight;
- int tex = TexPieces;
- int earth_index =i->index/13;
- int num_index = i->index - earth_index*13;
- num_index++;
- if (num_index>12) {
- num_index = 0;
- }
- if (i->index == JOKER_CARD) {
- earth_index = rand() & 3;
- num_index = 6+ (rand()&7);
- };
- if (i->destroying!=-1) {
- tex = TexPiecesSelected;
- //sizeAdd -= i->destroying/8;
- };
- if (i->flags&GRIDFLAG_MARKED) { // marked
- tex = TexPiecesSelected;
- };
- if (i->flags&GRIDFLAG_SELECTED) {
- tex = TexPiecesSelected;
- };
- //int wadd = (((sizeAdd>>2)* (256*m_itemWidth/m_itemHeight)) >>8); // aspect here
- int wadd = ((sizeAdd*5)>>3) + m_itemWidth / 2;
- int hadd = (sizeAdd>>2);
- int rx = i->lposx + i->posoffsetx - (wadd>>1);
- //int ry = i->lposy + i->posoffsety - hadd; //- (hadd>>1); // align to bottom
- int ry = i->lposy + i->posoffsety - (hadd>>1); //- (hadd>>1); // align to bottom
- ry+=i->wobble;
- width += wadd;
- height += hadd;
- if (width<=0 || height<=0) return;
- // convert
- if (m_state == eLEVELSTATE_GAMEOVER) {
- fade = -i->genCount / 200;
- };
- if (fade<0) fade = 0;
- if (fade>255) fade = 255;
- int rx2 = xtoGameArea( rx+width );
- int ry2 = ytoGameArea( ry+height );
- rx = xtoGameArea( rx );
- ry = ytoGameArea( ry );
- width = rx2-rx;
- height = ry2-ry;
- if (i->destroying!=-1) {
- fade = ((i->destroying>>1)-65536*4/5);
- if (fade<0) fade = 0; else fade*=10;
- };
- if (fade<255) {
- if (i->index != EMPTY_CARD) {
- // base
- renderer.renderTile(
- rx,
- ry,
- width,
- height,
- 0,0,
- 1 | (tex<<16) | (fade<<24), 0 );
- // "earth"
- renderer.renderTile(
- rx+(width>>2),
- ry+(height>>4),
- (width*4)>>3,
- height>>1,
- 0,0,
- (earth_index+2) | (tex<<16) | (fade<<24), 0 );
- if (num_index==13) num_index = 0;
- //num
- renderer.renderTile(
- rx+(width>>2),
- ry+(height>>1),
- (width*4)>>3,
- (height>>1),
- 0,0,
- (num_index+6) | (tex<<16) | (fade<<24), 0 );
- } else {
- // empty card
- renderer.renderTile(
- rx,
- ry,
- width,
- height,
- 0,0,
- 0 | (tex<<16) | (fade<<24), 0 );
- };
- /*
- if (i->backVisibility>0) {
- renderer.renderTile(
- rx,
- ry,
- width,
- height,
- 0,0,
- 0 | (tex<<16) | ((i->backVisibility>>8)<<24), 0 );
- };
- */
- }
- // draw flare
- if (i->destroying!=-1) {
- //fade = 255-(((i->destroying>>8) * (i->destroying>>8))>>10);
- fade = 255-(i->destroying>>9)*5/4;
- if (fade<0) fade=-fade*5;
- if (fade<0) fade = 0;
- int size = 4000 + (((i->destroying>>8) * (i->destroying>>8))>>4);
- //int size = 40000 + (255-fade)*20;
- if (fade<255)
- renderer.renderTile(
- rx-size,
- ry-size,
- width+size*2,
- height+size*2,
- i->animationCount>>4,1,2 | (TexParticle<<16) | (fade<<24), 0 );
- }
- }
- void CNpcLevel::draw (ITileRenderer &renderer ) {
- if (m_state == eLEVELSTATE_IDLE) return;
- SNpcGridItem *i = m_grid;
- SNpcGridItem *i_target = i+m_gridWidth * m_gridHeight;
- // first draw.
- while (i!=i_target) {
- if (i->index!=0xFFFFFFFF && //i->index!=8 &&
- !(i->flags&GRIDFLAG_HIDDEN) &&
- !(i->flags&GRIDFLAG_SELECTED) &&
- !(i->flags&GRIDFLAG_MARKED) &&
- (i->genCount<1000)) {
- renderTileCaller( i, renderer );
- }
- i++;
- };
- // second draw.
- i = m_grid;
- while (i!=i_target) {
- if (i->index!=0xFFFFFFFF &&
- !(i->flags&GRIDFLAG_HIDDEN)) {
- if (i->flags&(GRIDFLAG_SELECTED|GRIDFLAG_MARKED) || i->genCount>=1000) {
- renderTileCaller(i, renderer );
- };
- }
- i++;
- };
- if (m_deckVisibility>1024) {
- // deck draw
- for (int f=0; f<3; f++) {
- int ysize = m_itemHeight*3;
- int xsize = m_itemWidth*3;
- int amount = 256;
- //if (m_startupCounter<65536*4) amount = 0;
- int a = (m_startupCounter>>4) + (f*650);
- renderer.renderTile( DECK_POSITION_X -xsize/2 + ((((((m_cosineTable[ a& 4095 ]>>6)*(m_cosineTable[ (a*2+1500)&4095]>>8))>>8))*amount)>>8),
- DECK_POSITION_Y -ysize/2 + (((m_cosineTable[ (a+1200)& 4095 ]>>6)*amount)>>8),
- xsize,
- ysize,
- 0, 0, 0|(TexPieces<<16) | ((255-(m_deckVisibility>>8))<<24), 0 );
- };
- };
- };
- void CNpcLevel::saveToFile( FILE *file ) {
- SNpcGridItem *i = m_grid;
- SNpcGridItem *i_target = m_grid + m_gridWidth * m_gridHeight;
- while (i!=i_target) {
- fwrite( &i->index, sizeof(int), 1, file );
- i++;
- };
- };
- void CNpcLevel::loadFromFile( FILE *file ) {
- createLevel(0); // just create something so flags etc are ok
- SNpcGridItem *i = m_grid;
- SNpcGridItem *i_target = m_grid + m_gridWidth * m_gridHeight;
- while (i!=i_target) {
- fread( &i->index, sizeof(int), 1, file );
- i->posoffsetx = 0;
- i->posoffsety = 0;
- i++;
- };
- if (checkDestroyWholeLevel()!=0) {
- }
- hasMovesLeft(); // update hint
- m_destroyingRound = 0;
- };
|