Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
402 lines (344 sloc) 7.89 KB
#define OLC_PGE_APPLICATION
#include "pge.h"
#include <iostream>
#include <string>
#include <algorithm>
#include <chrono>
class Game : public olc::PixelGameEngine
{
private:
class Gem
{
public:
short color;
bool exists;
bool isBomb;
bool removed;
};
std::wstring gemSpr;
std::wstring bombSpr;
Gem gems[8][8];
olc::Pixel colors[8];
void drawGem(int x, int y, olc::Pixel &color, bool isBomb, bool removed)
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
if (removed)
{
color.a = 128;
}
else
{
color.a = 255;
}
if (!isBomb)
{
if (gemSpr[j*8+i] != L'.')
Draw(x*8+i, y*8+j, color);
}
else
{
if (bombSpr[j*8+i] != L'.')
Draw(x*8+i, y*8+j, color);
}
}
}
}
float fDelayTime;
enum STATES
{
USER,
SWAP,
CHECK,
ERASE,
COMPRESS,
NEW
} gameState, nextGameState;
int cursorX = 0, cursorY = 0;
int swapX = 0, swapY = 0;
bool bSwapFail = false;
bool bGemsToRemove = false;
int totalGems = 0;
int score = 0;
struct Fragment
{
float x;
float y;
float vx;
float vy;
short color;
};
std::list<Fragment> fragments;
public:
Game()
{
sAppName = "Test";
}
bool OnUserCreate()
{
colors[0] = olc::RED;
colors[1] = olc::BLUE;
colors[2] = olc::GREY;
colors[3] = olc::GREEN;
colors[4] = olc::YELLOW;
colors[5] = olc::MAGENTA;
colors[6] = olc::CYAN;
// colors[7] = olc::;
gemSpr += L"..XXXX..";
gemSpr += L".XXXXXX.";
gemSpr += L"XXXXXXXX";
gemSpr += L"XXX..XXX";
gemSpr += L"XXX..XXX";
gemSpr += L"XXXXXXXX";
gemSpr += L".XXXXXX.";
gemSpr += L"..XXXX..";
bombSpr += L"...X..X.";
bombSpr += L"X.X.X...";
bombSpr += L"...XX.X.";
bombSpr += L".XXXXX.X";
bombSpr += L"X.XXXXX.";
bombSpr += L".X.XX...";
bombSpr += L"...X.X.X";
bombSpr += L".X..X...";
for (int x = 0; x < 8; x++)
{
for (int y = 0; y < 8; y++)
{
gems[x][y].color = rand()%7;
gems[x][y].exists = false;
gems[x][y].removed = false;
gems[x][y].isBomb = false;
}
}
gameState = USER;
return true;
}
bool OnUserUpdate(float fElapsedTime)
{
std::this_thread::sleep_for(std::chrono::milliseconds(5));
if (fDelayTime > 0.0f)
{
fDelayTime -= fElapsedTime;
}
else
{
auto boom = [&](int x, int y, int size, short color){
auto random_float = [&](float min, float max){
return ((float)rand()/(float)RAND_MAX) * (max - min) + min;
};
for (int i = 0; i < size; i++)
{
float a = random_float(0, 2.0f*M_PI);
Fragment f = {(float)x, (float)y, std::cos(a)*random_float(30.0f, 75.0), std::sin(a)*random_float(30.0f, 75.0), color};
fragments.push_back(f);
}
};
switch(gameState)
{
case USER:
if (totalGems < 64)
{
nextGameState = COMPRESS;
}
else {
if (!GetKey(olc::Key::SPACE).bHeld)
{
if (GetKey(olc::Key::LEFT).bPressed) cursorX--;
if (GetKey(olc::Key::RIGHT).bPressed) cursorX++;
if (GetKey(olc::Key::UP).bPressed) cursorY--;
if (GetKey(olc::Key::DOWN).bPressed) cursorY++;
if (cursorX < 0) cursorX = 0;
if (cursorY < 0) cursorY = 0;
if (cursorX > 7) cursorX = 7;
if (cursorY > 7) cursorY = 7;
}
else {
swapX = cursorX;
swapY = cursorY;
if (GetKey(olc::Key::LEFT).bPressed && cursorX > 0) swapX = cursorX-1;
if (GetKey(olc::Key::RIGHT).bPressed && cursorX < 7) swapX = cursorX+1;
if (GetKey(olc::Key::UP).bPressed && cursorY > 0) swapY = cursorY-1;
if (GetKey(olc::Key::DOWN).bPressed && cursorY < 7) swapY = cursorY+1;
if (swapX != cursorX || swapY != cursorY) nextGameState = SWAP;
}
}
cursorX %= 8;
cursorY %= 8;
break;
case SWAP:
bSwapFail = true;
std::swap(gems[cursorX][cursorY], gems[swapX][swapY]);
fDelayTime = 0.5f;
nextGameState = CHECK;
break;
case CHECK:
nextGameState = ERASE;
fDelayTime = 0.5f;
bGemsToRemove = false;
for (int x = 0; x < 8; x++)
{
for (int y = 0; y < 8; y++)
{
if (!gems[x][y].removed)
{
int chain = 1;
bool bPlaceBomb = false;
while (gems[x][y].color == gems[x + chain][y].color && (chain + x) < 8) chain++;
if (chain >= 3)
{
score += 100 * chain;
if (chain >= 4) bPlaceBomb = true;
while (chain > 0)
{
if (gems[x + chain - 1][y].isBomb)
{
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
int m = std::min(std::max(i + (x + chain - 1), 0), 7);
int n = std::min(std::max(j + y, 0), 7);
gems[m][n].removed = true;
}
}
score += 1000;
}
gems[x + chain - 1][y].removed = true;
chain--;
bSwapFail = false;
bGemsToRemove = true;
}
}
chain = 1;
while (gems[x][y].color == gems[x][y + chain].color && (chain + y) < 8) chain++;
if (chain >= 3)
{
score += 100 * chain;
if (chain >= 4) bPlaceBomb = true;
while (chain > 0)
{
if (gems[x][y + chain - 1].isBomb)
{
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
int m = std::min(std::max(i + x, 0), 7);
int n = std::min(std::max(j + (y + chain - 1), 0), 7);
gems[m][n].removed = true;
}
}
score += 1000;
}
gems[x][y + chain - 1].removed = true;
chain--;
bSwapFail = false;
bGemsToRemove = true;
}
}
if (bPlaceBomb)
{
gems[x][y].isBomb = true;
gems[x][y].removed = false;
}
}
}
}
break;
case ERASE:
nextGameState = COMPRESS;
if (!bGemsToRemove)
{
if (bSwapFail)
{
std::swap(gems[cursorX][cursorY], gems[swapX][swapY]);
}
nextGameState = USER;
}
for (int x = 0; x < 8; x++)
{
for (int y = 0; y < 8; y++)
{
if (gems[x][y].removed)
{
gems[x][y].exists = false;
gems[x][y].isBomb = false;
boom(x*8+4, y*8+4, 50, gems[x][y].color);
totalGems--;
}
}
}
break;
case COMPRESS:
for (int y = 6; y >= 0; y--)
{
for (int x = 0; x < 8; x++)
{
if (gems[x][y].exists && !gems[x][y+1].exists)
std::swap(gems[x][y], gems[x][y+1]);
}
}
fDelayTime = 0.1f;
nextGameState = NEW;
break;
case NEW:
for (int x = 0; x < 8; x++)
{
if (!gems[x][0].exists)
{
gems[x][0].exists = true;
gems[x][0].removed = false;
gems[x][0].color = rand()%7;
totalGems++;
}
}
if (totalGems < 64)
{
fDelayTime = 0.1f;
nextGameState = COMPRESS;
}
else {
nextGameState = CHECK;
}
break;
}
gameState = nextGameState;
}
FillRect(0, 0, ScreenWidth(), ScreenHeight(), olc::BLACK);
SetPixelMode(olc::Pixel::Mode::ALPHA);
for (int x = 0; x < 8; x++)
{
for (int y = 0; y < 8; y++)
{
if (gems[x][y].exists)
this->drawGem(x, y, colors[gems[x][y].color], gems[x][y].isBomb, gems[x][y].removed);
}
}
DrawRect(cursorX*8, cursorY*8, 7, 7);
if (GetKey(olc::Key::SPACE).bHeld)
{
DrawRect(swapX*8, swapY*8, 7, 7, olc::BLUE);
}
DrawString(0, 64, std::to_string(score));
for (auto &p : fragments)
{
Draw(p.x, p.y, colors[p.color]);
p.vy += 100*fElapsedTime;
p.x += p.vx*fElapsedTime;
p.y += p.vy*fElapsedTime;
}
std::remove_if(fragments.begin(), fragments.end(), [&](Fragment &f){
return f.x < 0 || f.x > ScreenWidth() || f.y < 0 || f.y > ScreenHeight();
});
return true;
}
};
int main()
{
Game game;
if (game.Construct(64, 64+8, 8, 8))
game.Start();
return 0;
};
You can’t perform that action at this time.