#include "stdhdr.h"
#include "Sound.h"
#include "Logic.h"
EGameState g_nGameState = Initialising;
DWORD g_dwLevelScreenStartTime;
BYTE Grid[YBLOCKS][XBLOCKS];
int g_nBalls;
CEnemySprite **g_spriteBalls;
int g_nLevel;
int g_nLives;
int g_nPercentFilled;
BOOL g_bHasDied;
double g_nPlayerVelocity;
CPlayerSprite *g_spritePlayer;
extern IDirectMusicSegment8 *g_pLevelUp, *g_pDie, *g_pFill;
void InitPlayer()
{
DeletePlayer();
g_bHasDied = FALSE;
g_nPlayerVelocity = 2;
g_spritePlayer = new CPlayerSprite(g_nPlayerVelocity);
}
void DeletePlayer()
{
if (g_spritePlayer)
delete g_spritePlayer;
g_spritePlayer = NULL;
}
void InitLevel()
{
DeleteLevel();
g_nBalls = g_nLevel + 1;
g_nPercentFilled = 0;
g_spriteBalls = new CEnemySprite*[g_nBalls];
int nEnemiesDown = (int)sqrt(g_nBalls);
int nEnemiesAcross = g_nBalls / nEnemiesDown;
int i;
for (i = 0; i < g_nBalls; i++)
{
g_spriteBalls[i] = new CEnemySprite;
g_spriteBalls[i]->m_x = ((i / nEnemiesDown + 1) * (XBLOCKS - 4) / (nEnemiesAcross + 1) + 2) * BLOCKSIZE;
g_spriteBalls[i]->m_y = ((i % nEnemiesDown + 1) * (YBLOCKS - 4) / (nEnemiesDown + 1) + 2) * BLOCKSIZE;
}
memset(Grid, GRID_EMPTY, sizeof(Grid));
memset(Grid[0], GRID_FULL, sizeof(Grid[0]) * 2);
memset(Grid[YBLOCKS - 2], GRID_FULL, sizeof(Grid[0]) * 2);
for (i = 0; i < YBLOCKS; i++)
Grid[i][0] = Grid[i][1] = Grid[i][XBLOCKS - 1] = Grid[i][XBLOCKS - 2] = GRID_FULL;
ChangeToGameState(LevelScreen);
}
void DeleteLevel()
{
int i;
for (i = 0; i < g_nBalls; i++)
delete g_spriteBalls[i];
g_nBalls = 0;
if (g_spriteBalls)
delete [] g_spriteBalls;
g_spriteBalls = NULL;
}
void FillGrid()
{
HDC hDC;
hDC = CreateCompatibleDC(NULL);
HBITMAP hBitmap;
LPBYTE pBitmap = new BYTE[XBLOCKS * YBLOCKS / 8];
int x, y, i;
UINT nMask;
memset(pBitmap, 0, XBLOCKS * YBLOCKS / 8);
for (y = 0; y < YBLOCKS; y++)
{
for (x = 0; x < XBLOCKS; )
{
for (nMask = 0x80; nMask; nMask >>= 1, x++)
{
if (Grid[y][x] != GRID_EMPTY)
pBitmap[(y * XBLOCKS + x) / 8] |= nMask;
}
}
}
hBitmap = CreateBitmap(XBLOCKS, YBLOCKS, 1, 1, pBitmap);
SelectObject(hDC, hBitmap);
for (i = 0; i < g_nBalls; i++)
ExtFloodFill(hDC, (int)g_spriteBalls[i]->m_x / BLOCKSIZE, (int)g_spriteBalls[i]->m_y / BLOCKSIZE,
0, FLOODFILLSURFACE);
GetBitmapBits(hBitmap, XBLOCKS * YBLOCKS / 8, pBitmap);
int nFill = 0;
for (y = 0; y < YBLOCKS; y++)
{
for (x = 0; x < XBLOCKS; )
{
for (nMask = 0x80; nMask; nMask >>= 1, x++)
{
if ((pBitmap[(y * XBLOCKS + x) / 8] & nMask) == 0)
Grid[y][x] = GRID_FULL;
if (Grid[y][x] == GRID_FULL)
nFill++;
}
}
}
nFill -= XBLOCKS * 4 + YBLOCKS * 4;
g_nPercentFilled = (nFill * 100) / ((XBLOCKS - 4) * (YBLOCKS - 4));
DeleteObject(hBitmap);
delete pBitmap;
}
void ResetGame()
{
g_nLives = 3;
g_nLevel = 1;
InitLevel();
InitPlayer();
}
void UpdateGameState()
{
int x, y, i;
if (g_bHasDied)
{
PlaySound(g_pDie, DMUS_SEGF_SECONDARY);
g_nLives--;
if (g_nLives <= 0)
{
ChangeToGameState(Intro);
return;
}
else
{
for (y = 0; y < YBLOCKS; y++)
{
for (x = 0; x < XBLOCKS; x++)
{
if (Grid[y][x] == GRID_MID)
Grid[y][x] = GRID_EMPTY;
}
}
InitPlayer();
}
}
else if (g_nPercentFilled >= 75)
{
g_nLevel++;
g_nLives++;
InitLevel();
InitPlayer();
PlaySound(g_pLevelUp, DMUS_SEGF_SECONDARY);
}
for (i = 0; i < g_nBalls; i++)
g_spriteBalls[i]->Move();
CPlayerSprite::Direction nOldDirection = g_spritePlayer->m_nDirection;
g_spritePlayer->Move();
if (g_spritePlayer->m_bAtGrid)
{
x = (int)g_spritePlayer->m_x / BLOCKSIZE;
y = (int)g_spritePlayer->m_y / BLOCKSIZE;
int xNew = x, yNew = y;
switch (g_spritePlayer->m_nDirection)
{
case CPlayerSprite::Direction::UP:
if (yNew > 0)
yNew--;
break;
case CPlayerSprite::Direction::DOWN:
if (yNew < (YBLOCKS - 1))
yNew++;
break;
case CPlayerSprite::Direction::LEFT:
if (xNew > 0)
xNew--;
break;
case CPlayerSprite::Direction::RIGHT:
if (xNew < (XBLOCKS - 1))
xNew++;
break;
case CPlayerSprite::Direction::STOPPED:
break;
}
switch (Grid[yNew][xNew])
{
case GRID_FULL:
if (Grid[y][x] == GRID_EMPTY)
{
Grid[y][x] = GRID_MID;
for (int y = 0; y < YBLOCKS; y++)
{
for (int x = 0; x < XBLOCKS; x++)
{
if (Grid[y][x] == GRID_MID)
Grid[y][x] = GRID_FULL;
}
}
PlaySound(g_pFill, DMUS_SEGF_SECONDARY);
FillGrid();
g_spritePlayer->m_nNextDirection = CPlayerSprite::Direction::STOPPED;
}
break;
case GRID_EMPTY:
if (Grid[y][x] == GRID_FULL)
{
if (nOldDirection != CPlayerSprite::Direction::STOPPED)
g_spritePlayer->m_nDirection =
g_spritePlayer->m_nNextDirection =
CPlayerSprite::Direction::STOPPED;
}
else
Grid[y][x] = GRID_MID;
break;
case GRID_MID:
g_bHasDied = TRUE;
break;
}
}
}
void PlayBackgroundMusic();
void ChangeToGameState(EGameState nNewState)
{
switch (nNewState)
{
case Intro:
break;
case LevelScreen:
g_dwLevelScreenStartTime = GetTickCount();
break;
}
g_nGameState = nNewState;
PlayBackgroundMusic();
}