1
0
kolibrios/programs/games/fara/trunk/gameWnd.cpp
2014-01-19 17:00:32 +00:00

1584 lines
35 KiB
C++
Raw Blame History

//
#include "kosSyst.h"
#include "KosFile.h"
#include "gfxdef.h"
#include "gameWnd.h"
#include "mcarray.h"
#include "lang.h"
//
#define EMPTY_PLACE 0
#define LEVEL_PROGRESS_LEFT (132+1)
#define LEVEL_PROGRESS_TOP (388+21)
#define LEVEL_PROGRESS_HEIGHT 4
#define LEVEL_PROGRESS_WIDTH 329
#define LEVEL_PROGRESS_COLOUR 0xDF2933
#define BONUS_SOMEBLOCK_TOP (120+21)
#define BONUS_SOMEBLOCK_LEFT (46+1)
#define BONUS_FREEBLOCK_TOP (163+21)
#define BONUS_FREEBLOCK_LEFT (9+1)
#define BONUS_DIAGBLOCK_TOP (213+21)
#define BONUS_DIAGBLOCK_LEFT (48+1)
#define BONUS_PROGRESS_HEIGHT 37
#define BONUS_PROGRESS_WIDTH 4
#define LEVEL_SCORE_BASE 50
//
CKosBitmap gameFace;
CKosBitmap gameBlocks;
CKosBitmap gameNumbers;
CKosBitmap gameBlocksZ[4];
//
CFishka *fishki[blocksNum];
//
char *gameWndTitle;
#if LANG == RUS
char gameWndTitle1[] = "” à ®­ ¦¤ñâ ⥡ï :)\0";
char gameWndTitle2[] = "<EFBFBD>ã ¢®â...\0";
char gameOverText[] = "„ «ìè¥ ¤®à®£¨ ­¥â!";
#else
char gameWndTitle1[] = "Pharaoh waits for you :)\0";
char gameWndTitle2[] = "Well...\0";
char gameOverText[] = "No further way!";
#endif
//
Word gcx, gcy;
//
#define mapSize 8
//
//
#define blocksLeft (134+2)
#define blocksTop (43+22)
//
#define blockTypesNum 10
//
Byte gameMap[mapSize * mapSize];
// óðîâåíü
int gameLevel;
//
int maxGameLevel;
int startGameLevel;
// ñ÷¸ò
Dword playerScore;
// ñ÷¸ò÷èê äîáàâëåííûõ áëîêîâ
int insertedBlocksCount;
// êîëè÷åñòâî áëîêîâ äëÿ ïåðåõîäà íà ñëåäóþùèé óðîâåíü
int levelBlocksLimit;
// íîìåð âûäåëåííîãî áëîêà
int selectedBlock;
// ïðèáàâëåíèå øàãà äëÿ èíäèêàòîðà ïðîõîæäåíèÿ óðîâíÿ * 1024
int levelProgressStep;
// çàí÷åíèå èíäèêàòîðà ïðîõîæäåíèÿ óðîâíÿ
int levelProgressCount;
// áëîêè äëÿ óäàëåíèÿ
struct sRemoveBlock
{
short int ndx;
short int value;
sRemoveBlock()
{
this->ndx = 0;
this->value = 0;
};
sRemoveBlock( int pNdx, int pValue )
{
this->ndx = pNdx;
this->value = pValue;
};
};
bool operator == ( const sRemoveBlock &b1, const sRemoveBlock &b2 )
{
return b1.ndx == b2.ndx;
};
MCArray<sRemoveBlock> toRemoveList;
// ïàäàþùèå áëîêè
MCArray<int> toFallList;
//
bool mouseButtonDisabled;
//
bool freezeBonuses = false;
//
int bonusSomeBlockProgressStep;
int bonusSomeBlockProgressCount;
//
int bonusFreeBlockProgressStep;
int bonusFreeBlockProgressCount;
//
int bonusDiagBlockProgressStep;
int bonusDiagBlockProgressCount;
#define SELECTED_BLOCK_NONE -1
// áîíóñ âêëþ÷åí
int bonusSomeBlock;
// ñ÷¸ò÷èê áëîêîâ äëÿ áîíóñà
int bonusSomeBlockCount;
// êîëè÷åñòâî áëîêîâ, êîòîðîå íàäî óáðàòü, ÷òîáû ïîëó÷èòü áîíóñ
int bonusSomeBlockEdge;
#define BONUS_SOMEBLOCK_SELECTED -2
//
bool bonusFreeBlock;
int bonusFreeBlockCount;
int bonusFreeBlockEdge;
#define BONUS_FREEBLOCK_SELECTED -3
//
int bonusDiagBlock;
int bonusDiagBlockCount;
int bonusDiagBlockEdge;
#define BONUS_DIAGBLOCK_SELECTED -4
//
void drawScore();
// îòîáðàçèòü áëîêè áîíóñîâ
void drawBonuses();
//
void drawLevelNum();
//
void fadeOutBlocks();
//
void fallDownBlocks();
void ClearGameMeters()
{
// èíäèêàòîð ïðîõîæäåíèå óðîâíÿ
kos_DrawBar(
LEVEL_PROGRESS_LEFT,
LEVEL_PROGRESS_TOP,
LEVEL_PROGRESS_WIDTH,
LEVEL_PROGRESS_HEIGHT,
0
);
// èíäèêàòîðû áîíóñîâ
// some
kos_DrawBar(
33+1,
118+21,
BONUS_PROGRESS_WIDTH,
BONUS_PROGRESS_HEIGHT,
0
);
// free
kos_DrawBar(
58+1,
166+21,
BONUS_PROGRESS_WIDTH,
BONUS_PROGRESS_HEIGHT,
0
);
// diag
kos_DrawBar(
37+1,
213+21,
BONUS_PROGRESS_WIDTH,
BONUS_PROGRESS_HEIGHT,
0
);
}
//
void drawGameMeters()
{
//
ClearGameMeters();
// èíäèêàòîð ïðîõîæäåíèå óðîâíÿ
kos_DrawBar(
LEVEL_PROGRESS_LEFT,
LEVEL_PROGRESS_TOP,
levelProgressCount,
LEVEL_PROGRESS_HEIGHT,
LEVEL_PROGRESS_COLOUR
);
//
if ( bonusSomeBlockProgressCount > 0 )
// some
kos_DrawBar(
33+1,
118+21+BONUS_PROGRESS_HEIGHT-bonusSomeBlockProgressCount,
BONUS_PROGRESS_WIDTH,
bonusSomeBlockProgressCount,
LEVEL_PROGRESS_COLOUR
);
//
if ( bonusFreeBlockProgressCount > 0 )
// free
kos_DrawBar(
58+1,
166+21+BONUS_PROGRESS_HEIGHT-bonusFreeBlockProgressCount,
BONUS_PROGRESS_WIDTH,
bonusFreeBlockProgressCount,
LEVEL_PROGRESS_COLOUR
);
//
if ( bonusDiagBlockProgressCount > 0 )
// diag
kos_DrawBar(
37+1,
213+21+BONUS_PROGRESS_HEIGHT-bonusDiagBlockProgressCount,
BONUS_PROGRESS_WIDTH,
bonusDiagBlockProgressCount,
LEVEL_PROGRESS_COLOUR
);
}
////////////////////////////////////////////////////////////////////////////////
void SetLevelVariables()
{
selectedBlock = -1;
levelBlocksLimit = ( gameLevel > 5 ) ? LEVEL_SCORE_BASE * ( gameLevel + 1 ) : LEVEL_SCORE_BASE * ( 11 - gameLevel );
insertedBlocksCount = 0;
//
levelProgressCount = 0;
levelProgressStep = ( LEVEL_PROGRESS_WIDTH * 1024 ) / levelBlocksLimit;
//
bonusSomeBlockEdge = levelBlocksLimit / 4;
bonusFreeBlockEdge = levelBlocksLimit / 3;
bonusDiagBlockEdge = levelBlocksLimit / 2;
//
bonusSomeBlockProgressStep = ( BONUS_PROGRESS_HEIGHT * 1024 ) / bonusSomeBlockEdge;
bonusSomeBlockProgressCount = ( ( ( bonusSomeBlockCount > bonusSomeBlockEdge ) ? bonusSomeBlockEdge : bonusSomeBlockCount ) * bonusSomeBlockProgressStep ) / 1024;
//
bonusFreeBlockProgressStep = ( BONUS_PROGRESS_HEIGHT * 1024 ) / bonusFreeBlockEdge;
bonusFreeBlockProgressCount = ( ( ( bonusFreeBlockCount > bonusFreeBlockEdge ) ? bonusFreeBlockEdge : bonusFreeBlockCount ) * bonusFreeBlockProgressStep ) / 1024;
//
bonusDiagBlockProgressStep = ( BONUS_PROGRESS_HEIGHT * 1024 ) / bonusDiagBlockEdge;
bonusDiagBlockProgressCount = ( ( ( bonusDiagBlockCount > bonusDiagBlockEdge ) ? bonusDiagBlockEdge : bonusDiagBlockCount ) * bonusDiagBlockProgressStep ) / 1024;
}
//
int GetScoreByBlocks( int blocksCount )
{
int limit, update, i, j, acc;
//
if ( blocksCount < 3 ) return 0;
//
limit = 20 * blocksNum * gameLevel;
//
update = gameLevel;
acc = 1;
//
j = blocksCount - 3;
//
for ( i = 0; i < j; i++ )
{
//
acc *= gameLevel + 1;
//
if ( ( update + acc ) > limit ) return limit;
}
//
return update + acc;
}
//
int insertNewBlocks()
{
int i, j, k, ndx, result, btn;
//
toFallList.Clear();
//
result = 0;
//
btn = gameLevel > 5 ? blockTypesNum : 5 + gameLevel;
//
ndx = ( mapSize * mapSize ) - mapSize;
//
for ( i = 0; i < mapSize; i++ )
{
for ( j = 0; j < mapSize; j++ )
{
//
k = ndx + i - ( j * mapSize );
//
if ( gameMap[k] == EMPTY_PLACE )
{
//
for ( ; j < (mapSize-1); j++ )
{
//
gameMap[k] = gameMap[k-mapSize];
toFallList.AddExclusive( k );
k -= mapSize;
}
//
gameMap[i] = ( rtlRand() % btn ) + 1;
toFallList.AddExclusive( i );
//
result++;
//
break;
}
}
}
//
insertedBlocksCount += result;
//
return result;
}
// ïîèñê öåïî÷åê áëîêîâ äëÿ óäàëåíèÿ, óäàëåíèå áëîêîâ
// âîçâðàùàåò ïðèðàùåíèå ñ÷¸òà èãðîêà
int findBlockLines()
{
int x, y, ndx;
int removeCount = 0;
// î÷èñòèì ñïèñîê äëÿ çàïèñè ðåçóëüòàòîâ
toRemoveList.Clear();
//
for ( y = 0; y < mapSize; y++ )
{
//
for ( x = 0; x < mapSize; x++ )
{
//
ndx = x + ( y * mapSize );
//
if ( gameMap[ndx] == EMPTY_PLACE ) continue;
// ïðîâåðÿåì ãîðèçîíòàëüíóþ öåïî÷êó
if ( x < (mapSize - 2) )
{
//
if (
( gameMap[ndx] == gameMap[ndx+1] && gameMap[ndx] == gameMap[ndx+2] )
|| ( BONUS_FREE_BLOCK == gameMap[ndx] && gameMap[ndx+1] == gameMap[ndx+2] )
|| ( gameMap[ndx] == gameMap[ndx+1] && BONUS_FREE_BLOCK == gameMap[ndx+2] )
|| ( gameMap[ndx] == gameMap[ndx+2] && BONUS_FREE_BLOCK == gameMap[ndx+1] )
)
{
// íàøëè öåïî÷êó, çàïîìíèì
toRemoveList.AddExclusive( sRemoveBlock( ndx, gameMap[ndx] ) );
toRemoveList.AddExclusive( sRemoveBlock( ndx+1, gameMap[ndx+1] ) );
toRemoveList.AddExclusive( sRemoveBlock( ndx+2, gameMap[ndx+2] ) );
}
}
// ïðîâåðÿåì âåðòèêàëüíóþ öåïî÷êó
if ( y < (mapSize - 2) )
{
//
if (
( gameMap[ndx] == gameMap[ndx+mapSize] && gameMap[ndx] == gameMap[ndx+mapSize+mapSize] )
|| ( BONUS_FREE_BLOCK == gameMap[ndx] && gameMap[ndx+mapSize] == gameMap[ndx+mapSize+mapSize] )
|| ( gameMap[ndx] == gameMap[ndx+mapSize] && BONUS_FREE_BLOCK == gameMap[ndx+mapSize+mapSize] )
|| ( gameMap[ndx] == gameMap[ndx+mapSize+mapSize] && BONUS_FREE_BLOCK == gameMap[ndx+mapSize] )
)
{
// íàøëè öåïî÷êó, çàïîìíèì
toRemoveList.AddExclusive( sRemoveBlock( ndx, gameMap[ndx] ) );
toRemoveList.AddExclusive( sRemoveBlock( ndx+mapSize, gameMap[ndx+mapSize] ) );
toRemoveList.AddExclusive( sRemoveBlock( ndx+mapSize+mapSize, gameMap[ndx+mapSize+mapSize] ) );
}
}
}
}
//
return toRemoveList.GetCount();
}
// ïðîâåðêà íà íåâîçìîæíîñòü ñîáðàòü êàêóþ-íèáóäü ëèíèþ
bool checkGameOut()
{
int x, y, ndx;
//
ndx = 0;
//
for ( y = 0; y < mapSize; y++ )
{
//
for ( x = 0; x < mapSize; x++ )
{
// ïðîâåðÿåì ãîðèçîíòàëüíûå öåïî÷êè èç äâóõ ñèìâîëîâ
if ( x < (mapSize - 1) )
{
//
if ( gameMap[ndx] == gameMap[ndx+1] )
{
// íàøëè öåïî÷êó èç äâóõ áëîêîâ
// ïðîâåðêà áîíóñîâ
if ( bonusSomeBlock == gameMap[ndx] ) return false;
if ( bonusFreeBlock ) return false;
// ïðîâåðêà îáû÷íûõ ïåðåñòàíîâîê
if ( y > 0 )
{
//
if ( x > 0 )
{
//
if ( gameMap[ndx-mapSize-1] == gameMap[ndx] ) return false;
}
//
if ( x < (mapSize - 2) )
{
//
if ( gameMap[ndx-mapSize+2] == gameMap[ndx] ) return false;
}
}
//
if ( x > 1 )
{
//
if ( gameMap[ndx-2] == gameMap[ndx] ) return false;
}
//
if ( x < (mapSize - 3) )
{
//
if ( gameMap[ndx+3] == gameMap[ndx] ) return false;
}
//
if ( y < (mapSize - 1) )
{
//
if ( x > 0 )
{
//
if ( gameMap[ndx+mapSize-1] == gameMap[ndx] ) return false;
}
//
if ( x < (mapSize - 2) )
{
//
if ( gameMap[ndx+mapSize+2] == gameMap[ndx] ) return false;
}
}
// ïðîâåðêà äèàãîíàëüíûõ ïåðåñòàíîâîê
if ( bonusDiagBlock > 0 )
{
//
if ( y > 0 )
{
//
if ( x > 1 )
{
//
if ( gameMap[ndx-mapSize-2] == gameMap[ndx] ) return false;
}
//
if ( gameMap[ndx-mapSize] == gameMap[ndx] ) return false;
//
if ( x < (mapSize - 2) )
{
//
if ( gameMap[ndx-mapSize+1] == gameMap[ndx] ) return false;
}
//
if ( x < (mapSize - 3) )
{
//
if ( gameMap[ndx-mapSize+3] == gameMap[ndx] ) return false;
}
}
//
if ( y < (mapSize - 1) )
{
//
if ( x > 1 )
{
//
if ( gameMap[ndx+mapSize-2] == gameMap[ndx] ) return false;
}
//
if ( gameMap[ndx+mapSize] == gameMap[ndx] ) return false;
//
if ( x < (mapSize - 2) )
{
//
if ( gameMap[ndx+mapSize+1] == gameMap[ndx] ) return false;
}
//
if ( x < (mapSize - 3) )
{
//
if ( gameMap[ndx+mapSize+3] == gameMap[ndx] ) return false;
}
}
} // çàêîí÷åíà ïðîâåðêà äèàãîíàëüíûõ ïåðåñòàíîâîê
}
}
// ïðîâåðÿåì ãîðèçîíòàëüíûå öåïî÷êè èç äâóõ áëîêîâ ñ ïðîìåæóòêîì
if ( x < (mapSize - 2) )
{
//
if ( gameMap[ndx] == gameMap[ndx+2] )
{
// íàøëè äâà áëîêà ñ ïðîìåæóòêîì
// ïðîâåðêà áîíóñîâ
if ( bonusSomeBlock == gameMap[ndx] ) return false;
if ( bonusFreeBlock ) return false;
//
if ( y > 0 )
{
//
if ( gameMap[ndx-mapSize+1] == gameMap[ndx] ) return false;
}
//
if ( y < (mapSize-1) )
{
//
if ( gameMap[ndx+mapSize+1] == gameMap[ndx] ) return false;
}
// ïðîâåðêà äèàãîíàëüíûõ ïåðåñòàíîâîê
if ( bonusDiagBlock > 0 )
{
//
if ( y > 0 )
{
//
if ( gameMap[ndx-mapSize] == gameMap[ndx] ) return false;
//
if ( gameMap[ndx-mapSize+2] == gameMap[ndx] ) return false;
}
//
if ( y < (mapSize-1) )
{
//
if ( gameMap[ndx+mapSize] == gameMap[ndx] ) return false;
//
if ( gameMap[ndx+mapSize+2] == gameMap[ndx] ) return false;
}
}
}
}
// ïðîâåðÿåì âåðòèêàëüíûå öåïî÷êè èç äâóõ ñèìâîëîâ
if ( y < (mapSize - 1) )
{
//
if ( gameMap[ndx] == gameMap[ndx+mapSize] )
{
// íàøëè öåïî÷êó èç äâóõ áëîêîâ
// ïðîâåðêà áîíóñîâ
if ( bonusSomeBlock == gameMap[ndx] ) return false;
if ( bonusFreeBlock ) return false;
//
if ( x > 0 )
{
//
if ( y > 0 )
{
//
if ( gameMap[ndx-1-mapSize] == gameMap[ndx] ) return false;
}
//
if ( y < (mapSize - 2) )
{
//
if ( gameMap[ndx-1+(2*mapSize)] == gameMap[ndx] ) return false;
}
}
//
if ( y > 1 )
{
//
if ( gameMap[ndx-(2*mapSize)] == gameMap[ndx] ) return false;
}
//
if ( y < (mapSize - 3) )
{
//
if ( gameMap[ndx+(3*mapSize)] == gameMap[ndx] ) return false;
}
//
if ( x < (mapSize - 1) )
{
//
if ( y > 0 )
{
//
if ( gameMap[ndx+1-mapSize] == gameMap[ndx] ) return false;
}
//
if ( y < (mapSize - 2) )
{
//
if ( gameMap[ndx+1+(2*mapSize)] == gameMap[ndx] ) return false;
}
}
// ïðîâåðêà äèàãîíàëüíûõ ïåðåñòàíîâîê
if ( bonusDiagBlock > 0 )
{
//
if ( x > 0 )
{
//
if ( y > 1 )
{
//
if ( gameMap[ndx-1-(2*mapSize)] == gameMap[ndx] ) return false;
}
//
if ( gameMap[ndx-1] == gameMap[ndx] ) return false;
//
if ( y < (mapSize - 2) )
{
//
if ( gameMap[ndx-1+mapSize] == gameMap[ndx] ) return false;
}
//
if ( y < (mapSize - 3) )
{
//
if ( gameMap[ndx-1+(3*mapSize)] == gameMap[ndx] ) return false;
}
}
//
if ( x < (mapSize - 1) )
{
//
if ( y > 1 )
{
//
if ( gameMap[ndx+1-(2*mapSize)] == gameMap[ndx] ) return false;
}
//
if ( gameMap[ndx+1] == gameMap[ndx] ) return false;
//
if ( y < (mapSize - 2) )
{
//
if ( gameMap[ndx+1+mapSize] == gameMap[ndx] ) return false;
}
//
if ( y < (mapSize - 3) )
{
//
if ( gameMap[ndx+1+(3*mapSize)] == gameMap[ndx] ) return false;
}
}
} // çàêîí÷åíà ïðîâåðêà äèàãîíàëüíûõ ïåðåñòàíîâîê
}
}
// ïðîâåðÿåì âåðòèêàëüíûå öåïî÷êè èç äâóõ áëîêîâ ñ ïðîìåæóòêîì
if ( y < (mapSize - 2) )
{
//
if ( gameMap[ndx] == gameMap[ndx+(2*mapSize)] )
{
// íàøëè äâà áëîêà ñ ïðîìåæóòêîì
// ïðîâåðêà áîíóñîâ
if ( bonusSomeBlock == gameMap[ndx] ) return false;
if ( bonusFreeBlock ) return false;
//
if ( x > 0 )
{
//
if ( gameMap[ndx-1+mapSize] == gameMap[ndx] ) return false;
}
//
if ( x < (mapSize-1) )
{
//
if ( gameMap[ndx+1+mapSize] == gameMap[ndx] ) return false;
}
// ïðîâåðêà äèàãîíàëüíûõ ïåðåñòàíîâîê
if ( bonusDiagBlock > 0 )
{
//
if ( x > 0 )
{
//
if ( gameMap[ndx-1] == gameMap[ndx] ) return false;
//
if ( gameMap[ndx-1+(2*mapSize)] == gameMap[ndx] ) return false;
}
//
if ( x < (mapSize-1) )
{
//
if ( gameMap[ndx+1] == gameMap[ndx] ) return false;
//
if ( gameMap[ndx+1+(2*mapSize)] == gameMap[ndx] ) return false;
}
}
}
}
//
ndx++;
}
}
//
gameWndTitle = gameWndTitle2;
//
return true;
}
//
bool exterminateLines()
{
int deletedBlocks, btn, i, j;
bool needRedrawBonus = false;
//
btn = gameLevel > 5 ? blockTypesNum : 5 + gameLevel;
//
playerScore += GetScoreByBlocks( deletedBlocks = findBlockLines() );
//
if ( ! freezeBonuses )
{
//
if ( gameLevel >= 2 && bonusSomeBlock <= 0 ) bonusSomeBlockCount += deletedBlocks;
if ( gameLevel >= 3 && !bonusFreeBlock ) bonusFreeBlockCount += deletedBlocks;
if ( gameLevel >= 4 && bonusDiagBlock <= 0 ) bonusDiagBlockCount += deletedBlocks;
// ïåðâûé áîíóñ
if (
( bonusSomeBlockCount >= bonusSomeBlockEdge || ( gameLevel >= 2 && deletedBlocks >= 4 ) )
&& bonusSomeBlock <= 0
)
{
bonusSomeBlock = ( rtlRand() % btn ) + 1;
needRedrawBonus = true;
if ( bonusSomeBlockCount >= bonusSomeBlockEdge ) bonusSomeBlockCount = 0;
}
if ( bonusSomeBlockCount >= bonusSomeBlockEdge ) bonusSomeBlockCount = 0;
// âòîðîé áîíóñ
if ( bonusFreeBlockCount >= bonusFreeBlockEdge || ( gameLevel >=3 && deletedBlocks >= 5 ) )
{
bonusFreeBlock = true;
needRedrawBonus = true;
if ( bonusFreeBlockCount >= bonusFreeBlockEdge ) bonusFreeBlockCount = 0;
}
if ( bonusFreeBlockCount >= bonusFreeBlockEdge ) bonusFreeBlockCount = 0;
// òðåòèé áîíóñ
if ( bonusDiagBlockCount >= bonusDiagBlockEdge || ( gameLevel >= 4 && deletedBlocks >= 6 ) )
{
bonusDiagBlock = 3;
needRedrawBonus = true;
if ( bonusDiagBlockCount >= bonusDiagBlockEdge ) bonusDiagBlockCount = 0;
}
if ( bonusDiagBlockCount >= bonusDiagBlockEdge ) bonusDiagBlockCount = 0;
//
bonusSomeBlockProgressCount = ( ( ( bonusSomeBlockCount > bonusSomeBlockEdge ) ? bonusSomeBlockEdge : bonusSomeBlockCount ) * bonusSomeBlockProgressStep ) / 1024;
//
bonusFreeBlockProgressCount = ( ( ( bonusFreeBlockCount > bonusFreeBlockEdge ) ? bonusFreeBlockEdge : bonusFreeBlockCount ) * bonusFreeBlockProgressStep ) / 1024;
//
bonusDiagBlockProgressCount = ( ( ( bonusDiagBlockCount > bonusDiagBlockEdge ) ? bonusDiagBlockEdge : bonusDiagBlockCount ) * bonusDiagBlockProgressStep ) / 1024;
//
if ( needRedrawBonus ) drawBonuses();
}
//
j = toRemoveList.GetCount();
//
for ( i = 0; i < j; i++ )
{
gameMap[toRemoveList[i].ndx] = EMPTY_PLACE;
}
//
return toRemoveList.GetCount() > 0;
}
// çàïîëíåíèå èãðîâîãî ïîëÿ ñëó÷àéíîé êîìáèíàöèåé áëîêîâ
void initGameMap()
{
int i, localScore, localInserted, btn;
//
btn = gameLevel > 5 ? blockTypesNum : 5 + gameLevel;
//
for ( i = 0; i < (mapSize * mapSize); i++ )
{
gameMap[i] = ( rtlRand() % btn ) + 1;
}
//
localScore = playerScore;
localInserted = insertedBlocksCount;
//
freezeBonuses = true;
//
while ( exterminateLines() )
{
while ( insertNewBlocks() > 0 );
}
//
freezeBonuses = false;
//
playerScore = localScore;
insertedBlocksCount = localInserted;
}
// îòîáðàçèòü áëîêè áîíóñîâ
void drawBonuses()
{
//
kos_PutImage(
selectedBlock != BONUS_SOMEBLOCK_SELECTED ?
fishki[bonusSomeBlock]->GetBits() :
fishki[bonusSomeBlock]->GetHighlightedBits(),
blockSize, blockSize,
BONUS_SOMEBLOCK_LEFT, BONUS_SOMEBLOCK_TOP
);
//
kos_PutImage(
bonusFreeBlock ?
(
selectedBlock != BONUS_FREEBLOCK_SELECTED ?
fishki[BONUS_FREE_BLOCK]->GetBits() :
fishki[BONUS_FREE_BLOCK]->GetHighlightedBits()
) :
fishki[0]->GetBits(),
blockSize, blockSize,
BONUS_FREEBLOCK_LEFT, BONUS_FREEBLOCK_TOP
);
//
kos_PutImage(
bonusDiagBlock > 0 ?
fishki[bonusDiagBlock+BONUS_DIAG_BLOCK-1]->GetBits() :
fishki[0]->GetBits(),
blockSize, blockSize,
BONUS_DIAGBLOCK_LEFT, BONUS_DIAGBLOCK_TOP
);
}
// îòîáðàçèòü èãðîâîå ïîëå
void drawGameMap()
{
int i, j, ndx;
//
for ( i = 0; i < mapSize; i++ )
{
//
for ( j = 0; j < mapSize; j++ )
{
//
ndx = (i*mapSize) + j;
//
kos_PutImage(
ndx != selectedBlock ?
fishki[gameMap[ndx]]->GetBits() :
fishki[gameMap[ndx]]->GetHighlightedBits(),
blockSize, blockSize,
(j * blockSize) + blocksLeft,
(i * blockSize) + blocksTop
);
}
}
}
// êîîðäèíàòû êóðñîðà "ìûøè"
int mX, mY;
// ïðîâåðêà íà íàæàòèå ëåâîé êíîïêè "ìûøè"
bool mouseLButtonDown()
{
static bool isDown = false;
Dword buttons;
//
kos_GetMouseState( buttons, mX, mY );
//
if ( mouseButtonDisabled ) return false;
//
if ( ( buttons & 1 ) )
{
if ( isDown )
return false;
else
{
isDown = true;
return true;
}
}
else
{
if ( isDown )
{
isDown = false;
}
return false;
}
}
//
void flipTwoBlocks( int ndx1, int ndx2 )
{
Word blX, blY, selX, selY;
Byte fishCode;
//
blX = ( ndx1 % mapSize ) * blockSize + blocksLeft;
blY = ( ndx1 / mapSize ) * blockSize + blocksTop;
selX = ( ndx2 % mapSize ) * blockSize + blocksLeft;
selY = ( ndx2 / mapSize ) * blockSize + blocksTop;
// ïåðåñòàâèì áëîêè ìåñòàìè
fishCode = gameMap[ndx1];
gameMap[ndx1] = gameMap[ndx2];
gameMap[ndx2] = fishCode;
// èçîáðàæåíèå áëîêà
kos_PutImage(
fishki[gameMap[ndx1]]->GetBits(),
blockSize, blockSize,
blX,
blY
);
// èçîáðàæåíèå áëîêà
kos_PutImage(
fishki[gameMap[ndx2]]->GetBits(),
blockSize, blockSize,
selX,
selY
);
}
// èãðîâîé ïðîöåññ
int GameLoop()
{
int result, ndx, blX, blY, selX, selY, ddX, ddY, nSel;
Byte keyCode, mCode;
bool needDecBonus;
Dword buttonID;
//
gameWndTitle = gameWndTitle1;
gameFace.GetSize( gcx, gcy );
gameLevel = startGameLevel;
playerScore = 0;
bonusSomeBlock = 0;
bonusFreeBlock = false;
bonusDiagBlock = 0;
bonusSomeBlockCount = 0;
bonusFreeBlockCount = 0;
bonusDiagBlockCount = 0;
bonusSomeBlockProgressCount = 0;
bonusFreeBlockProgressCount = 0;
bonusDiagBlockProgressCount = 0;
SetLevelVariables();
mouseButtonDisabled = false;
initGameMap();
//
kos_ChangeWindow( -1, -1, gcx + 1, gcy + 21 );
//
for ( result = GM_NONE; result == GM_NONE; )
{
switch( kos_WaitForEvent() )
{
// íàäî ïîëíîñòüþ ïåðåðèñîâàòü îêíî
case 1:
DrawGameWindow();
break;
// êëàâèàòóðà
case 2:
if ( kos_GetKey( keyCode ) )
{
//
switch ( keyCode )
{
case 0x1B:
result = GM_ABORT;
break;
default:
break;
}
}
break;
// êíîïêè
case 3:
if ( kos_GetButtonID( buttonID ) )
{
switch ( buttonID )
{
case 1:
kos_ExitApp();
case 0xA:
result = GM_ABORT;
break;
default:
break;
}
}
// ñîáûòèå îò ìûøè
case 6:
// íàæàòèå ëåâîé êíîïêè?
if ( mouseLButtonDown() )
{
// ñ÷èòàåì êîîðäèíàòû îòíîñèòåëíî èãðîâîãî ïîëÿ
blX = mX - blocksLeft;
blY = mY - blocksTop;
// ïîïàëî â èãðîâîå ïîëå?
if ( blX >= 0 && blX < (mapSize * blockSize)
&& blY >= 0 && blY < (mapSize * blockSize) )
{
// ïîëó÷àåì êîîðäèíàòû â áëîêàõ
blX /= blockSize;
blY /= blockSize;
// ïîëó÷àåì íîìåð áëîêà íà êàðòå
ndx = blX + ( blY * mapSize );
// åù¸ îäíà ïðîâåðêà, ÷òîáû íå âûëåçòè çà ïðåäåëû êàðòû
if ( ndx >= 0 && ndx < (mapSize * mapSize) )
{
// íà÷èíàåì ïåðåðèñîâêó
kos_WindowRedrawStatus( WRS_BEGIN );
// åñëè íå áûëî âûáðàííîãî áëîêà
if ( selectedBlock == SELECTED_BLOCK_NONE )
{
// çàïîìíèì âûäåëåííûé áëîê
selectedBlock = ndx;
// îòìåòèì áëîê íà èãðîâîì ïîëå
kos_PutImage(
fishki[gameMap[selectedBlock]]->GetHighlightedBits(),
blockSize, blockSize,
( selectedBlock % mapSize ) * blockSize + blocksLeft,
( selectedBlock / mapSize ) * blockSize + blocksTop
);
}
else // ïîìå÷åííûé áëîê óæå åñòü
{
if ( selectedBlock >= 0 )
{
// êîîðäèíàòû ïîìå÷åííîãî áëîêà
selX = selectedBlock % mapSize;
selY = selectedBlock / mapSize;
// áûë âûáðàí äðóãîé áëîê?
if ( ndx != selectedBlock )
{
// ñ÷èòàåì ðàçíîñòü êîîðäèíàò äâóõ áëîêîâ
ddX = selX - blX;
ddY = selY - blY;
needDecBonus = ( bonusDiagBlock > 0 && abs(ddX) == 1 && abs(ddY) == 1 );
// åñëè ýòî ñîñåäíèé áëîê
if (
( abs(ddX) == 1 && ddY == 0 )
|| ( abs(ddY) == 1 && ddX == 0 )
|| needDecBonus
)
{
// ïåðåñòàâèì áëîêè ìåñòàìè
flipTwoBlocks( ndx, selectedBlock );
//
kos_Pause( 16 );
//
if ( findBlockLines() > 0 )
{
//
if ( needDecBonus )
{
//
--bonusDiagBlock;
//
drawBonuses();
}
// ñíèìàåì ïîìåòêó ñ áëîêà
selectedBlock = SELECTED_BLOCK_NONE;
//
while ( exterminateLines() )
{
//
fadeOutBlocks();
//
//drawGameMap();
//drawScore();
//
//kos_Pause( 25 );
//
while ( insertNewBlocks() > 0 )
{
//
fallDownBlocks();
//
//drawGameMap();
//kos_Pause( 30 );
}
}
//
drawScore();
//
levelProgressCount = ( ( ( insertedBlocksCount > levelBlocksLimit ) ? levelBlocksLimit : insertedBlocksCount ) * levelProgressStep ) / 1024;
//
drawGameMeters();
//
if ( insertedBlocksCount > levelBlocksLimit )
{
kos_Pause( 50 );
gameLevel++;
SetLevelVariables();
//
//initGameMap();
//
//DrawGameWindow();
//
drawGameMeters();
drawLevelNum();
}
else
//
if ( mouseButtonDisabled = checkGameOut() )
{
//
DrawGameWindow();
}
}
else
{
// íå ïîëó÷àåòñÿ ëèíèè, áëîêè ñòàâèì íà ìåñòî
flipTwoBlocks( ndx, selectedBlock );
// ñíèìàåì ïîìåòêó ñ áëîêà
selectedBlock = SELECTED_BLOCK_NONE;
}
}
else // âûáðàí íåñîñåäíèé áëîê
{
// ïåðåñòèì ìàðêåð
kos_PutImage(
fishki[gameMap[selectedBlock]]->GetBits(),
blockSize, blockSize,
selX * blockSize + blocksLeft,
selY * blockSize + blocksTop
);
// ïîìåòèì âûáðàííûé áëîê
selectedBlock = ndx;
// íà èãðîâîì ïîëå
kos_PutImage(
fishki[gameMap[selectedBlock]]->GetHighlightedBits(),
blockSize, blockSize,
blX * blockSize + blocksLeft,
blY * blockSize + blocksTop
);
}
}
else // âûáðàí òîò æå áëîê
{
// ñíèìàåì ïîìåòêó
kos_PutImage(
fishki[gameMap[selectedBlock]]->GetBits(),
blockSize, blockSize,
selX * blockSize + blocksLeft,
selY * blockSize + blocksTop
);
//
selectedBlock = SELECTED_BLOCK_NONE;
}
}
else
// òêíóëè â áëîê ïðè âûáðàííîì áîíóñå
{
//
mCode = gameMap[ndx];
//
switch ( selectedBlock )
{
case BONUS_SOMEBLOCK_SELECTED:
gameMap[ndx] = bonusSomeBlock;
break;
case BONUS_FREEBLOCK_SELECTED:
gameMap[ndx] = BONUS_FREE_BLOCK;
break;
default:
break;
}
//
if ( findBlockLines() > 0 )
{
// óáèðàåì èñïîëüçîâàííûé áîíóñ
switch ( selectedBlock )
{
case BONUS_SOMEBLOCK_SELECTED:
bonusSomeBlock = 0;
break;
case BONUS_FREEBLOCK_SELECTED:
bonusFreeBlock = false;
break;
default:
break;
}
// íà ýêðàíå òîæå
drawBonuses();
drawGameMap();
kos_Pause( 16 );
// óáèðàåì áëîêè
// ñíèìàåì ïîìåòêó ñ áëîêà
selectedBlock = SELECTED_BLOCK_NONE;
//
while ( exterminateLines() )
{
//
fadeOutBlocks();
//
//drawGameMap();
//drawScore();
//
//kos_Pause( 25 );
//
while ( insertNewBlocks() > 0 )
{
//
fallDownBlocks();
//
//drawGameMap();
//kos_Pause( 30 );
}
}
//
drawScore();
//
levelProgressCount = ( ( ( insertedBlocksCount > levelBlocksLimit ) ? levelBlocksLimit : insertedBlocksCount ) * levelProgressStep ) / 1024;
//
drawGameMeters();
//
if ( insertedBlocksCount > levelBlocksLimit )
{
kos_Pause( 50 );
gameLevel++;
SetLevelVariables();
//
//initGameMap();
//
//DrawGameWindow();
//
drawGameMeters();
drawLevelNum();
}
else
//
mouseButtonDisabled = checkGameOut();
}
else
// áîíóñ çäåñü íåïðèìåíèì
{
// âåðí¸ì âçàä
gameMap[ndx] = mCode;
// ïîìåòèì áëîê
selectedBlock = ndx;
// íà èãðîâîì ïîëå
kos_PutImage(
fishki[gameMap[selectedBlock]]->GetHighlightedBits(),
blockSize, blockSize,
blX * blockSize + blocksLeft,
blY * blockSize + blocksTop
);
// óáåð¸ì ïîìåòêó ñ áîíóñà
drawBonuses();
}
}
}
// îïðåäåëèì êíîïêó
kos_DefineButton(
444+1, 2+21,
54, 20,
0x6000000A,
0
);
// çàâåðøàåì ïåðåðèñîâêó
kos_WindowRedrawStatus( WRS_END );
}
}
else
// ïðîâåðèì ïîïàäàíèå â áîíóñû
{
nSel = 0;
//
if ( mX >= BONUS_SOMEBLOCK_LEFT && (mX - BONUS_SOMEBLOCK_LEFT) <= blockSize
&& mY >= BONUS_SOMEBLOCK_TOP && (mY - BONUS_SOMEBLOCK_TOP ) <= blockSize )
{
//
nSel = BONUS_SOMEBLOCK_SELECTED;
}
//
if ( mX >= BONUS_FREEBLOCK_LEFT && (mX - BONUS_FREEBLOCK_LEFT) <= blockSize
&& mY >= BONUS_FREEBLOCK_TOP && (mY - BONUS_FREEBLOCK_TOP ) <= blockSize )
{
//
nSel = BONUS_FREEBLOCK_SELECTED;
}
//
if ( mX >= BONUS_DIAGBLOCK_LEFT && (mX - BONUS_DIAGBLOCK_LEFT) <= blockSize
&& mY >= BONUS_DIAGBLOCK_TOP && (mY - BONUS_DIAGBLOCK_TOP ) <= blockSize )
{
//
nSel = BONUS_DIAGBLOCK_SELECTED;
}
//
if ( nSel != 0 )
{
//
if ( selectedBlock > 0 )
{
// ñíèìàåì ïîìåòêó
kos_PutImage(
fishki[gameMap[selectedBlock]]->GetBits(),
blockSize, blockSize,
(selectedBlock % mapSize) * blockSize + blocksLeft,
(selectedBlock / mapSize) * blockSize + blocksTop
);
}
//
if ( selectedBlock != nSel )
selectedBlock = nSel;
else
selectedBlock = SELECTED_BLOCK_NONE;
//
drawBonuses();
}
}
}
//
break;
default:
break;
}
}
// îòìåíèì êíîïêó
kos_DefineButton(
0, 0,
0, 0,
0x8000000A,
0
);
//
if ( gameLevel > maxGameLevel ) maxGameLevel = gameLevel;
//
return result;
}
//
void drawLevelNum()
{
Word startX;
//
if ( gameLevel > 9 )
{
//
startX = LEVEL_LEFT;
//
kos_PutImage(
gameNumbers.GetBits() + ( ( gameLevel / 10 ) * NUM_WIDTH * NUM_HEIGHT ),
NUM_WIDTH, NUM_HEIGHT,
startX, LEVEL_TOP
);
//
startX += NUM_WIDTH;
}
else
{
//
startX = LEVEL_LEFT + ( (LEVEL_WIDTH - NUM_WIDTH) / 2 );
}
//
kos_PutImage(
gameNumbers.GetBits() + ( ( gameLevel % 10 ) * NUM_WIDTH * NUM_HEIGHT ),
NUM_WIDTH, NUM_HEIGHT,
startX, LEVEL_TOP
);
}
//
void drawScore()
{
Word startX;
int i, j;
char strNum[8];
// ÷èñëî â òåêñòîâîì âèäå
sprintf( strNum, "%U", playerScore );
//
j = strlen( strNum );
//
startX = SCORE_LEFT + ( ( SCORE_WIDTH - ( NUM_WIDTH * j ) ) / 2 );
//
for ( i = 0; i < j; i++ )
{
//
kos_PutImage(
gameNumbers.GetBits() + ( ( strNum[i] - '0' ) * NUM_WIDTH * NUM_HEIGHT ),
NUM_WIDTH, NUM_HEIGHT,
startX, SCORE_TOP
);
//
startX += NUM_WIDTH;
}
}
//
void DrawGameWindow()
{
//
kos_WindowRedrawStatus( WRS_BEGIN );
// îêíî
kos_DefineAndDrawWindow(
WNDLEFT, WNDTOP,
gcx + 1, gcy + 21,
0x54, 0x0, // Skinned fixed size window, dont fill working area, window has caption
0, WNDHEADCOLOUR,
gameWndTitle
);
// çàãîëîâîê îêíà
kos_ChangeWindowCaption(gameWndTitle);
gameFace.Draw( 1, 21 );
drawGameMap();
drawGameMeters();
drawBonuses();
// íîìåð óðîâíÿ
drawLevelNum();
drawScore();
//
if ( mouseButtonDisabled )
{
//
kos_DrawBar(
( gcx + 1 - 160 ) / 2, ( gcy + 21 - 32 ) / 2,
160, 32,
0x2383B3
);
//
kos_WriteTextToWindow(
( gcx + 1 - sizeof( gameOverText ) * 6 ) / 2, ( gcy + 21 - 9 ) / 2,
0x0, 0xF7F7F7,
gameOverText,
sizeof( gameOverText )
);
}
// îïðåäåëèì êíîïêó
kos_DefineButton(
444+1, 2+21,
54, 20,
0x6000000A,
0
);
//
kos_WindowRedrawStatus( WRS_END );
}
//
void fadeOutBlocks()
{
int i, j, k, ndx, x, y;
//
j = toRemoveList.GetCount();
//
for ( k = 0; k < 4; k++ )
{
//
__asm{
push eax
push ebx
mov eax, 18
mov ebx, 14
int 0x40
pop eax
pop ebx
}
//
for ( i = 0; i < j; i++ )
{
//
ndx = toRemoveList[i].ndx;
y = ndx / mapSize;
x = ndx % mapSize;
//
kos_PutImage(
gameBlocksZ[k].GetBits() + ( (toRemoveList[i].value - 1) * blockSize * blockSize ),
blockSize, blockSize,
(x * blockSize) + blocksLeft,
(y * blockSize) + blocksTop
);
}
//
kos_Pause( 3 );
}
//clear
for ( i = 0; i < j; i++ )
{
//
ndx = toRemoveList[i].ndx;
y = ndx / mapSize;
x = ndx % mapSize;
//
kos_DrawBar(
(x * blockSize) + blocksLeft,
(y * blockSize) + blocksTop,
blockSize, blockSize, 0
);
}
//
kos_Pause( 16 );
}
//
void fallDownBlocks()
{
int i, j, k, ndx, x, y, height, offset;
//
j = toFallList.GetCount();
//
for ( k = 1; k <= blockSize; k += 2 )
{
//
__asm{
push eax
push ebx
mov eax, 18
mov ebx, 14
int 0x40
pop eax
pop ebx
}
//
for ( i = 0; i < j; i++ )
{
//
ndx = toFallList[i];
//
y = ( ( ( ndx / mapSize ) - 1 ) * blockSize ) + k;
if ( y < 0 )
{
y = 0;
height = k;
offset = blockSize - k;
}
else
{
offset = 0;
height = blockSize;
}
//
x = ( ndx % mapSize ) * blockSize;
//
kos_PutImage(
fishki[gameMap[ndx]]->GetBits() + ( offset * blockSize ),
blockSize, height,
x + blocksLeft,
y + blocksTop
);
}
//
kos_Pause( 1 );
}
}