Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
524 changes: 524 additions & 0 deletions Board.cpp

Large diffs are not rendered by default.

131 changes: 131 additions & 0 deletions Board.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#pragma once

#include <vector>
#include <set>
#include <random>
#include <SFML/Graphics.hpp>
#include "Gem.h"
#include "Config.h"
#include <memory>
class IdleState : public GameStateBase {
public:
void enter(Board& board) override;
GameStateBase* update(Board& board) override;
void exit(Board& board) override;
bool isIdle() const override;
};

class GemSelectedState : public GameStateBase {
public:
void enter(Board& board) override;
GameStateBase* update(Board& board) override;
void exit(Board& board) override;
};

class SwappingState : public GameStateBase {
public:
void enter(Board& board) override;
GameStateBase* update(Board& board) override;
void exit(Board& board) override;
};

class CheckingState : public GameStateBase {
public:
void enter(Board& board) override;
GameStateBase* update(Board& board) override;
void exit(Board& board) override;
};

class DestroyingState : public GameStateBase {
public:
void enter(Board& board) override;
GameStateBase* update(Board& board) override;
void exit(Board& board) override;
};

class FallingState : public GameStateBase {
public:
void enter(Board& board) override;
GameStateBase* update(Board& board) override;
void exit(Board& board) override;
};

class RefillingState : public GameStateBase {
public:
void enter(Board& board) override;
GameStateBase* update(Board& board) override;
void exit(Board& board) override;
};

class ApplyingBonusState : public GameStateBase {
public:
void enter(Board& board) override;
GameStateBase* update(Board& board) override;
void exit(Board& board) override;
};


class Board {
public:
Board(int width, int height, sf::Texture& textureSheet);
Board(const Board&) = delete;
Board& operator=(const Board&) = delete;

void draw(sf::RenderWindow& window);
bool update();
bool handleMouseClick(sf::Vector2i pixelCoords);
bool isIdle() const;
void setState(std::unique_ptr<GameStateBase> newState);
GridCoord getSelectedGemCoords() const { return selectedGemCoords; }
void setSelectedGemCoords(GridCoord coords) { selectedGemCoords = coords; }
bool isGemSelected() const { return gemSelected; }
void setGemSelected(bool selected) { gemSelected = selected; }

bool isValidCoords(int r, int c) const;
bool isValidCoords(GridCoord coords) const;
bool areAdjacent(GridCoord p1, GridCoord p2) const;
void swapGems(GridCoord p1, GridCoord p2);
std::set<GridCoord> findMatches();
std::pair<int, std::vector<std::pair<GridCoord, int>>> destroyGems(const std::set<GridCoord>& coordsToDestroy);
bool applyGravity();
bool refillBoard();
void trySpawnBonus(const std::vector<std::pair<GridCoord, int>>& destroyedGemsInfo);
void applyRepaintBonus(GridCoord targetPos, int sourceColorIndex);
void applyBombBonus(GridCoord targetPos);
void createGem(int r, int c, std::unique_ptr<GemColorBase> color);
void createRandomGem(int r, int c);
std::vector<std::vector<std::unique_ptr<Gem>>>& getGrid() { return grid; }
const std::vector<std::vector<std::unique_ptr<Gem>>>& getGrid() const { return grid; }
sf::Texture& getTextureSheet() { return textureSheetRef; }
std::mt19937& getRNG() { return rng; }
std::uniform_int_distribution<int>& getGemColorDist() { return gemColorDist; }
std::uniform_real_distribution<float>& getBonusChanceDist() { return bonusChanceDist; }
std::uniform_int_distribution<int>& getBonusTypeDist() { return bonusTypeDist; }
std::uniform_int_distribution<int>& getGridXDist() { return gridXDist; }
std::uniform_int_distribution<int>& getGridYDist() { return gridYDist; }
int getWidth() const { return width; }
int getHeight() const { return height; }
std::vector<std::pair<GridCoord, int>> recentlyDestroyedGems;

bool hasPossibleMoves() const;


private:
int width;
int height;
sf::Texture& textureSheetRef;
std::vector<std::vector<std::unique_ptr<Gem>>> grid;
GridCoord selectedGemCoords;
bool gemSelected;

std::mt19937 rng;
std::uniform_int_distribution<int> gemColorDist;
std::uniform_real_distribution<float> bonusChanceDist;
std::uniform_int_distribution<int> bonusTypeDist;
std::uniform_int_distribution<int> gridXDist;
std::uniform_int_distribution<int> gridYDist;

std::unique_ptr<GameStateBase> currentState;

void initializeBoard();
};
124 changes: 124 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
set(PROJECT_NAME GEMS_3)

################################################################################
# Source groups
################################################################################
set(Source_Files
"Board.cpp"
"Board.h"
"Config.h"
"Game.cpp"
"Game.h"
"Gem.cpp"
"Gem.h"
"main.cpp"
)
source_group("Source Files" FILES ${Source_Files})

set(ALL_FILES
${Source_Files}
)

################################################################################
# Target
################################################################################
add_executable(${PROJECT_NAME} ${ALL_FILES})

use_props(${PROJECT_NAME} "${CMAKE_CONFIGURATION_TYPES}" "${DEFAULT_CXX_PROPS}")
set(ROOT_NAMESPACE GEMS3)

set_target_properties(${PROJECT_NAME} PROPERTIES
VS_GLOBAL_KEYWORD "Win32Proj"
)
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
set_target_properties(${PROJECT_NAME} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE "TRUE"
)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86")
set_target_properties(${PROJECT_NAME} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE "TRUE"
)
endif()
################################################################################
# Compile definitions
################################################################################
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
target_compile_definitions(${PROJECT_NAME} PRIVATE
"$<$<CONFIG:Debug>:"
"_DEBUG"
">"
"$<$<CONFIG:Release>:"
"NDEBUG"
">"
"_CONSOLE;"
"UNICODE;"
"_UNICODE"
)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86")
target_compile_definitions(${PROJECT_NAME} PRIVATE
"$<$<CONFIG:Debug>:"
"_DEBUG"
">"
"$<$<CONFIG:Release>:"
"NDEBUG"
">"
"WIN32;"
"_CONSOLE;"
"UNICODE;"
"_UNICODE"
)
endif()

################################################################################
# Compile and link options
################################################################################
if(MSVC)
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Debug>:
/std:c++17
>
$<$<CONFIG:Release>:
/Oi;
/Gy
>
/permissive-;
/sdl;
/W3;
${DEFAULT_CXX_DEBUG_INFORMATION_FORMAT};
${DEFAULT_CXX_EXCEPTION_HANDLING}
)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86")
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Release>:
/Oi;
/Gy
>
/permissive-;
/sdl;
/W3;
${DEFAULT_CXX_DEBUG_INFORMATION_FORMAT};
${DEFAULT_CXX_EXCEPTION_HANDLING}
)
endif()
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
target_link_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Release>:
/OPT:REF;
/OPT:ICF
>
/DEBUG;
/SUBSYSTEM:CONSOLE
)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86")
target_link_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Release>:
/OPT:REF;
/OPT:ICF
>
/DEBUG;
/SUBSYSTEM:CONSOLE
)
endif()
endif()

96 changes: 96 additions & 0 deletions Config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#pragma once

#include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/Color.hpp>
#include <map>
#include <memory>

constexpr int GRID_WIDTH = 8;
constexpr int GRID_HEIGHT = 8;
constexpr int GEM_SIZE = 64;
constexpr unsigned int WINDOW_WIDTH = GRID_WIDTH * GEM_SIZE;
constexpr unsigned int WINDOW_HEIGHT = GRID_HEIGHT * GEM_SIZE;
const int NUM_GEM_COLORS = 6;
const float BONUS_CHANCE = 0.1f;
const int REPAINT_BONUS_RADIUS = 3;
const int BOMB_BONUS_COUNT = 5;
class GemColorBase {
public:
virtual ~GemColorBase() = default;
virtual int getIndex() const = 0;
virtual sf::Color getSFMLColor() const = 0;
};
class RedGemColor : public GemColorBase {
public:
int getIndex() const override { return 0; }
sf::Color getSFMLColor() const override { return sf::Color::Red; }
};

class GreenGemColor : public GemColorBase {
public:
int getIndex() const override { return 1; }
sf::Color getSFMLColor() const override { return sf::Color::Green; }
};

class BlueGemColor : public GemColorBase {
public:
int getIndex() const override { return 2; }
sf::Color getSFMLColor() const override { return sf::Color::Blue; }
};

class YellowGemColor : public GemColorBase {
public:
int getIndex() const override { return 3; }
sf::Color getSFMLColor() const override { return sf::Color::Yellow; }
};

class PurpleGemColor : public GemColorBase {
public:
int getIndex() const override { return 4; }
sf::Color getSFMLColor() const override { return sf::Color::Magenta; }
};

class OrangeGemColor : public GemColorBase {
public:
int getIndex() const override { return 5; }
sf::Color getSFMLColor() const override { return sf::Color(255, 165, 0); }
};

class NoneGemColor : public GemColorBase {
public:
int getIndex() const override { return -1; }
sf::Color getSFMLColor() const override { return sf::Color::Black; }
};
class GameStateBase {
public:
virtual ~GameStateBase() = default;
virtual void enter(class Board& board) = 0;
virtual GameStateBase* update(class Board& board) = 0;
virtual void exit(class Board& board) = 0;
virtual bool isIdle() const { return false; }
};
struct GridCoord {
int x;
int y;

GridCoord() : x(0), y(0) {}
GridCoord(int x, int y) : x(x), y(y) {}
bool operator<(const GridCoord& other) const {
if (y == other.y) {
return x < other.x;
}
return y < other.y;
}

bool operator==(const GridCoord& other) const {
return x == other.x && y == other.y;
}
};
namespace sf {
inline bool operator<(const Vector2i& a, const Vector2i& b) {
if (a.x == b.x) {
return a.y < b.y;
}
return a.x < b.x;
}
}
Loading