Compare commits
3 Commits
024b893d2d
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2377006ba | ||
|
|
6e1a625102 | ||
|
|
33acb24e20 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,3 +2,5 @@ cmake-build-debug
|
|||||||
CandyCrush
|
CandyCrush
|
||||||
*.data
|
*.data
|
||||||
build
|
build
|
||||||
|
.idea
|
||||||
|
*.zip
|
||||||
|
|||||||
24
CMakeLists.txt
Normal file
24
CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.21)
|
||||||
|
project(CandyCrush LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
|
set(SFML_USE_STATIC_STD_LIBS ON)
|
||||||
|
set(SFML_BUILD_AUDIO ON)
|
||||||
|
set(SFML_BUILD_GRAPHICS ON)
|
||||||
|
set(SFML_BUILD_NETWORK OFF)
|
||||||
|
set(SFML_USE_SYSTEM_DEPS OFF)
|
||||||
|
set(SFML_BUILD_EXAMPLES OFF)
|
||||||
|
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(SFML
|
||||||
|
GIT_REPOSITORY https://github.com/SFML/SFML.git
|
||||||
|
GIT_TAG 3.0.2
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(SFML)
|
||||||
|
|
||||||
|
add_executable(CandyCrush src/main.cpp)
|
||||||
|
target_link_libraries(CandyCrush PRIVATE sfml-graphics sfml-audio)
|
||||||
|
|
||||||
|
|
||||||
16
README.md
Normal file
16
README.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Candy Crush
|
||||||
|
## Наш ответ буржуйским игрушкам
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Установка зависимостей
|
||||||
|
```
|
||||||
|
sudo apt-get install libX11-devel libudev-devel libGL-devel libopenal-devel libvorbis-devel libflac-devel libXrandr-devel libXcursor-devel libXi-devel libfreetype-devel
|
||||||
|
```
|
||||||
|
|
||||||
|
## Сборка
|
||||||
|
```bash
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake ..
|
||||||
|
cmake --build .
|
||||||
|
```
|
||||||
BIN
assets/fonts/Inter-Black.ttf
Normal file
BIN
assets/fonts/Inter-Black.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/Inter-Regular.ttf
Normal file
BIN
assets/fonts/Inter-Regular.ttf
Normal file
Binary file not shown.
BIN
assets/images/background.png
Normal file
BIN
assets/images/background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 323 KiB |
BIN
assets/images/button_bg.png
Normal file
BIN
assets/images/button_bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1022 B |
BIN
assets/images/candys.png
Normal file
BIN
assets/images/candys.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 222 KiB |
BIN
assets/music/background.ogg
Normal file
BIN
assets/music/background.ogg
Normal file
Binary file not shown.
54
src/checkCombinations.hpp
Normal file
54
src/checkCombinations.hpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "structCandy.hpp"
|
||||||
|
#include "move.hpp"
|
||||||
|
|
||||||
|
void check(candy map[][10])
|
||||||
|
{
|
||||||
|
for(int i = 1;i <= 8;i++)
|
||||||
|
for(int j = 1;j <= 8;j++)
|
||||||
|
{
|
||||||
|
if (map[i][j].kind == map[i+1][j].kind || map[i+1][j].kind > 4 || map[i][j].kind > 4)
|
||||||
|
if (map[i][j].kind == map[i-1][j].kind || map[i-1][j].kind > 4 || map[i][j].kind > 4)
|
||||||
|
if (map[i-1][j].kind == map[i+1][j].kind || map[i-1][j].kind > 4 || map[i+1][j].kind > 4)
|
||||||
|
for(int k = -1; k <= 1; k++)
|
||||||
|
{
|
||||||
|
if (map[i + k][j].kind == 6) for(int n = 0; n <= 8; n++) map[i + k][n].combination++;
|
||||||
|
if (map[i + k][j].kind == 5) for(int n = -1; n <= 1; n++) for(int m = -1; m <= 1; m++) if(i + k + n >= 0 && i + k + n <= 8 && j + m >= 0 && j + m <= 8) map[i + k + n][j + m].combination++;
|
||||||
|
map[i + k][j].combination++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map[i][j].kind == map[i][j+1].kind || map[i][j+1].kind > 4 || map[i][j].kind > 4)
|
||||||
|
if (map[i][j].kind == map[i][j-1].kind || map[i][j-1].kind > 4 || map[i][j].kind > 4)
|
||||||
|
if (map[i][j-1].kind == map[i][j+1].kind || map[i][j-1].kind > 4 || map[i][j+1].kind > 4)
|
||||||
|
for(int k = -1; k <= 1; k++)
|
||||||
|
{
|
||||||
|
if (map[i][j + k].kind == 6) for(int n = 0; n <= 8; n++) map[i][n].combination++;
|
||||||
|
if (map[i][j + k].kind == 5) for(int n = -1; n <= 1; n++) for(int m = -1; m <= 1; m++) if(i + n >= 0 && i + n <= 8 && j + k + m >= 0 && j + k + m <= 8) map[i + n][j + k + m].combination++;
|
||||||
|
map[i][j + k].combination++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(bool &isMoving, candy map[][10], int &points)
|
||||||
|
{
|
||||||
|
if (!isMoving)
|
||||||
|
{
|
||||||
|
for(int i = 8;i > 0; i--)
|
||||||
|
for(int j = 1;j <= 8;j++)
|
||||||
|
if (map[i][j].combination)
|
||||||
|
for(int n = i;n > 0; n--)
|
||||||
|
if (!map[n][j].combination) {swap(map[n][j], map[i][j], map); break;};
|
||||||
|
|
||||||
|
for(int j = 1; j <= 8;j++)
|
||||||
|
for(int i = 8,n = 0; i > 0; i--)
|
||||||
|
if (map[i][j].combination)
|
||||||
|
{
|
||||||
|
points++;
|
||||||
|
map[i][j].kind = rand() % 5;
|
||||||
|
if (rand() % 100 < 5) map[i][j].kind = 5 + rand() % 2;
|
||||||
|
map[i][j].y = -tile_size * n++;
|
||||||
|
map[i][j].combination=0;
|
||||||
|
map[i][j].alpha = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/generationCandys.hpp
Normal file
14
src/generationCandys.hpp
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "structCandy.hpp"
|
||||||
|
void generation(candy map[][10])
|
||||||
|
{
|
||||||
|
for (int i = 1;i <= 8; i++)
|
||||||
|
for (int j = 1; j <= 8; j++)
|
||||||
|
{
|
||||||
|
map[i][j].kind = rand() % 5;
|
||||||
|
map[i][j].column = j;
|
||||||
|
map[i][j].row = i;
|
||||||
|
map[i][j].x = j * tile_size;
|
||||||
|
map[i][j].y = i * tile_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
198
src/main.cpp
Normal file
198
src/main.cpp
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include <ctime>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "mouseClickHandler.hpp"
|
||||||
|
#include "structCandy.hpp"
|
||||||
|
#include "generationCandys.hpp"
|
||||||
|
#include "checkCombinations.hpp"
|
||||||
|
#include "move.hpp"
|
||||||
|
#include <SFML/Audio.hpp>
|
||||||
|
|
||||||
|
candy map[10][10];
|
||||||
|
|
||||||
|
void playMusic()
|
||||||
|
{
|
||||||
|
static sf::Music background_music;
|
||||||
|
if (!background_music.openFromFile("assets/music/background.ogg"))
|
||||||
|
{
|
||||||
|
std::cerr << "Ошибка загрузки музыки" << std::endl;
|
||||||
|
}
|
||||||
|
background_music.setLooping(true);
|
||||||
|
background_music.setVolume(100);
|
||||||
|
background_music.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace sf;
|
||||||
|
|
||||||
|
int seed;
|
||||||
|
srand(seed);
|
||||||
|
|
||||||
|
|
||||||
|
sf::RenderWindow window(sf::VideoMode({1280u, 720u}), "Candy Crush");
|
||||||
|
window.setFramerateLimit(120);
|
||||||
|
playMusic();
|
||||||
|
|
||||||
|
Texture bg_texture, candys_texture, button_texture;
|
||||||
|
if (!bg_texture.loadFromFile("assets/images/background.png")) return -1;
|
||||||
|
if (!candys_texture.loadFromFile("assets/images/candys.png")) return -1;
|
||||||
|
if (!button_texture.loadFromFile("assets/images/button_bg.png")) return -1;
|
||||||
|
|
||||||
|
candys_texture.setSmooth(false);
|
||||||
|
|
||||||
|
Sprite background(bg_texture), candys(candys_texture), button_bg(button_texture);
|
||||||
|
button_bg.setPosition({490, 150});
|
||||||
|
|
||||||
|
Font font_regular, font_black;
|
||||||
|
if (!font_regular.openFromFile("assets/fonts/Inter-Regular.ttf")) return -1;
|
||||||
|
if (!font_black.openFromFile("assets/fonts/Inter-Black.ttf")) return -1;
|
||||||
|
|
||||||
|
Text points_text(font_regular, "0", 20);
|
||||||
|
points_text.setPosition({10, 5});
|
||||||
|
Text rating_text(font_regular, "", 28);
|
||||||
|
rating_text.setPosition({500, 260});
|
||||||
|
Text newgame_button_text(font_black, "NEW GAME", 48);
|
||||||
|
newgame_button_text.setPosition({500, 160});
|
||||||
|
Text endgame_button_text(font_black, "END GAME", 24);
|
||||||
|
endgame_button_text.setPosition({1110, 655});
|
||||||
|
|
||||||
|
generation(map);
|
||||||
|
|
||||||
|
int x0, y0, x, y;
|
||||||
|
int click = 0;
|
||||||
|
Vector2i position;
|
||||||
|
bool isSwap = false;
|
||||||
|
bool isMoving = false;
|
||||||
|
int points = 0;
|
||||||
|
int scene = 0;
|
||||||
|
|
||||||
|
if (std::filesystem::exists("last_game.data"))
|
||||||
|
{
|
||||||
|
std::ifstream points_file("last_game.data");
|
||||||
|
points_file >> points;
|
||||||
|
points_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> rating;
|
||||||
|
for(int i = 0; i < 5; i++) rating.push_back(0);
|
||||||
|
if (std::filesystem::exists("rating.data"))
|
||||||
|
{
|
||||||
|
std::ifstream rating_file("rating.data");
|
||||||
|
rating_file >> rating[0] >> rating[1] >> rating[2] >> rating[3] >> rating[4];
|
||||||
|
rating_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
String rating_str;
|
||||||
|
for(int i = 0; i < 5; i++) rating_str += std::to_string(i + 1) + " - " + std::to_string(rating[i]) + " points\n";
|
||||||
|
rating_text.setString(rating_str);
|
||||||
|
|
||||||
|
if (points > 0) {
|
||||||
|
newgame_button_text.setString("CONTINUE");
|
||||||
|
newgame_button_text.setPosition({510, 160});
|
||||||
|
}
|
||||||
|
|
||||||
|
while (window.isOpen())
|
||||||
|
{
|
||||||
|
while (const std::optional event = window.pollEvent())
|
||||||
|
{
|
||||||
|
if (event->is<Event::Closed>())
|
||||||
|
{
|
||||||
|
std::ofstream points_file("last_game.data");
|
||||||
|
points_file << points;
|
||||||
|
points_file.close();
|
||||||
|
|
||||||
|
std::ofstream rating_file("rating.data");
|
||||||
|
rating_file << rating[0] << " " << rating[1] << " " << rating[2] << " " << rating[3] << " " << rating[4];
|
||||||
|
rating_file.close();
|
||||||
|
|
||||||
|
window.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto* mousePressed = event->getIf<Event::MouseButtonPressed>())
|
||||||
|
{
|
||||||
|
if (mousePressed->button == Mouse::Button::Left)
|
||||||
|
{
|
||||||
|
if (scene == 0)
|
||||||
|
{
|
||||||
|
position = Mouse::getPosition(window);
|
||||||
|
if (position.x >= 490 && position.x <= 790 && position.y >= 150 && position.y <= 230)
|
||||||
|
{
|
||||||
|
scene = 1;
|
||||||
|
button_bg.setScale({0.5f, 0.5f});
|
||||||
|
button_bg.setPosition({1100, 650});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
position = Mouse::getPosition(window);
|
||||||
|
if (position.x >= 1100 && position.x <= 1250 && position.y >= 650 && position.y <= 690)
|
||||||
|
{
|
||||||
|
if (points > rating[4]) rating[4] = points;
|
||||||
|
std::sort(rating.begin(), rating.end(), std::greater<int>());
|
||||||
|
|
||||||
|
rating_str = "";
|
||||||
|
for(int i = 0; i < 5; i++) rating_str += std::to_string(i + 1) + " - " + std::to_string(rating[i]) + " points\n";
|
||||||
|
rating_text.setString(rating_str);
|
||||||
|
|
||||||
|
scene = 0;
|
||||||
|
points = 0;
|
||||||
|
|
||||||
|
newgame_button_text.setString("NEW GAME");
|
||||||
|
newgame_button_text.setPosition({500, 160});
|
||||||
|
|
||||||
|
button_bg.setScale({1, 1});
|
||||||
|
button_bg.setPosition({490, 150});
|
||||||
|
}
|
||||||
|
if (!isSwap && !isMoving) click++;
|
||||||
|
position -= offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scene == 0)
|
||||||
|
{
|
||||||
|
window.draw(background);
|
||||||
|
window.draw(button_bg);
|
||||||
|
window.draw(newgame_button_text);
|
||||||
|
window.draw(rating_text);
|
||||||
|
}
|
||||||
|
else if (scene == 1)
|
||||||
|
{
|
||||||
|
mouse_click(click, x0, y0, tile_size, position, isSwap, x, y, map);
|
||||||
|
check(map);
|
||||||
|
move(isMoving, map);
|
||||||
|
deleting(isMoving, map);
|
||||||
|
antiswap(isMoving, isSwap, map, y0, x0, y, x);
|
||||||
|
update(isMoving, map, points);
|
||||||
|
|
||||||
|
window.draw(background);
|
||||||
|
|
||||||
|
window.draw(button_bg);
|
||||||
|
window.draw(endgame_button_text);
|
||||||
|
|
||||||
|
points_text.setString("Points: " + std::to_string(points));
|
||||||
|
window.draw(points_text);
|
||||||
|
|
||||||
|
for (int i = 1; i <= 8; i++)
|
||||||
|
for (int j = 1; j <= 8; j++)
|
||||||
|
{
|
||||||
|
candy element = map[i][j];
|
||||||
|
candys.setTextureRect(IntRect({element.kind * 98*2, 0}, {98*2, 98*2}));
|
||||||
|
candys.setScale({70 / candys.getLocalBounds().size.y, 70 / candys.getLocalBounds().size.x});
|
||||||
|
candys.setColor(Color(255, 255, 255, element.alpha));
|
||||||
|
candys.setPosition({static_cast<float>(element.x), static_cast<float>(element.y)});
|
||||||
|
candys.move({static_cast<float>(offset.x - tile_size), static_cast<float>(offset.y - tile_size)});
|
||||||
|
window.draw(candys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.display();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
23
src/mouseClickHandler.hpp
Normal file
23
src/mouseClickHandler.hpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <math.h>
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include "structCandy.hpp"
|
||||||
|
#include "move.hpp"
|
||||||
|
|
||||||
|
void mouse_click(int &click, int &x0, int &y0, int tile_size, sf::Vector2i pos, bool &isSwap, int &x, int &y, candy map[][10]){
|
||||||
|
if (click == 1)
|
||||||
|
{
|
||||||
|
x0 = pos.x / tile_size + 1;
|
||||||
|
y0 = pos.y / tile_size + 1;
|
||||||
|
}
|
||||||
|
if (click == 2)
|
||||||
|
{
|
||||||
|
x = pos.x / tile_size + 1;
|
||||||
|
y = pos.y / tile_size + 1;
|
||||||
|
if (abs(x - x0)+ abs(y - y0) == 1)
|
||||||
|
{
|
||||||
|
swap(map[y0][x0], map[y][x], map); isSwap = 1; click = 0;
|
||||||
|
}
|
||||||
|
else click = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
src/move.hpp
Normal file
48
src/move.hpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
#include "structCandy.hpp"
|
||||||
|
|
||||||
|
void swap(candy first, candy second, candy map[][10])
|
||||||
|
{
|
||||||
|
std::swap(first.column,second.column);
|
||||||
|
std::swap(first.row,second.row);
|
||||||
|
|
||||||
|
map[first.row][first.column] = first;
|
||||||
|
map[second.row][second.column] = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void move(bool &isMoving, candy map[][10])
|
||||||
|
{
|
||||||
|
isMoving=false;
|
||||||
|
for (int i = 1;i <= 8;i++)
|
||||||
|
for (int j = 1;j <= 8;j++)
|
||||||
|
{
|
||||||
|
candy &element = map[i][j];
|
||||||
|
int dx, dy;
|
||||||
|
for(int n = 0; n < 4; n++)
|
||||||
|
{
|
||||||
|
dx = element.x - element.column * tile_size;
|
||||||
|
dy = element.y - element.row * tile_size;
|
||||||
|
if (dx) element.x -= dx/abs(dx);
|
||||||
|
if (dy) element.y -= dy/abs(dy);
|
||||||
|
}
|
||||||
|
if (dx||dy) isMoving = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleting(bool &isMoving, candy map[][10])
|
||||||
|
{
|
||||||
|
if (!isMoving)
|
||||||
|
for (int i = 1; i <= 8; i++)
|
||||||
|
for (int j = 1;j <= 8; j++)
|
||||||
|
if (map[i][j].combination) if (map[i][j].alpha>10) {map[i][j].alpha -= 10; isMoving=true;}
|
||||||
|
}
|
||||||
|
|
||||||
|
void antiswap(bool &isMoving, bool &isSwap, candy map[][10], int y0, int x0, int y, int x)
|
||||||
|
{
|
||||||
|
int score = 0;
|
||||||
|
for (int i = 1;i <= 8;i++)
|
||||||
|
for (int j = 1;j <= 8;j++)
|
||||||
|
score += map[i][j].combination;
|
||||||
|
if (isSwap && !isMoving) {if (!score) swap(map[y0][x0], map[y][x], map); isSwap=0;}
|
||||||
|
}
|
||||||
19
src/structCandy.hpp
Normal file
19
src/structCandy.hpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
|
constexpr int tile_size = 80;
|
||||||
|
sf::Vector2i offset(320, 40);
|
||||||
|
|
||||||
|
struct candy
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
int column, row;
|
||||||
|
int kind;
|
||||||
|
int combination;
|
||||||
|
int alpha;
|
||||||
|
candy()
|
||||||
|
{
|
||||||
|
combination = 0;
|
||||||
|
alpha = 255;
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user