SFML и C++ Уроки \ Разработка игр › Форумы › Логика игр › логика и графика Match3 game( три в ряд)
В этой теме 7 ответов, 3 участника, последнее обновление LastikPro 7 года/лет, 8 мес. назад.
-
АвторСообщения
-
Доброго времени суток уважаемые форумчане.Вынужден писать (курсовая работа) так называемую игру “Три в ряд” суть которой заключается в том, чтобы на поле 9х9 из шариков разных цветов составить три шарика одинакового цвета в ряд чтобы они исчезли. Разработать игру нужно с использованием ООП. В связи с этим возник ряд проблем которые заключаются в том, что я
хреногоне очень хорошо понимаю как должна строится структура программы(игры) (сколько классов, как взаимодействовать с объектами и.т.д) и как в этой игре реализовать построение поля 9х9 с помощью классов и взаимодействие шаров. Возникнет вопрос почему я собственно приперся на форум по SFML, а потому что игру нужно писать на с++, а наиболее удобная библиотека по работе с графикой и для создания игр, судя по отзывам, это SFML. Я не прошу написать за меня курсовую, я просто ищу наставника, который знаком с SFML,поможет и подтолкнет мое понимание ООП в нужное русло. Приведу код который я с горем пополам написал это класс одного шарика и главная функция которая его отрисовывает. Одна из проблем которая возникла это шарик не отрисовывается на фоне и как создать поле 9х9 из этих шаров с разными цветами (зачатки рандомного распределения цветов уже есть в классе). Над полем есть несколько идей это использовать матрицу, использовать вектор (Vector2i), использовать двумерный массив (думаю что Vector2 i и двумерный массив это одно и тоже ) Связаться со мной можно тут и в вк (https://vk.com/dude_postal)C++1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071#include <SFML/Graphics.hpp>#include <time.h>using namespace sf;const int BallSize = 64;class bubble{//private:public:float x, y, w, h;Texture texture;//сфмл текстураSprite sprite;//сфмл спрайтColor color;Image image;String File;bubble(String F){File = F;//имя файла+расширениеimage.loadFromFile("images/" + File);//запихиваем в image наше изображение вместо File мы передадим то, что пропишем при создании объекта. В нашем случае "hero.png" и получится запись идентичная image.loadFromFile("images/hero/png");texture.loadFromImage(image);//закидываем наше изображение в текстуруsprite.setTexture(texture);//заливаем спрайт текстурой}static Color SetRandomColor(){const sf::Color colorArray[5] = { sf::Color::Cyan, sf::Color::Blue, sf::Color::Green, sf::Color::Red, sf::Color::Yellow };srand(time(NULL));return(colorArray[rand() % 5]);}};int main(){RenderWindow app(VideoMode(800, 600), "Bubbles");app.setFramerateLimit(60);//все для фонаbubble b("gray.png");//создаем объект p класса player,задаем "hero.png" как имя файла+расширение, далее координата Х,У, ширина, высота.//Texture t1;//t1.loadFromFile("images/background.png");//Sprite background(t1);//базовый цикл для отрисовки и всей фигни (это от бибилиотеки )while (app.isOpen()){sf::Event event;while (app.pollEvent(event)){if (event.type == sf::Event::Closed ||(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape))app.close();}app.clear();app.draw(b.sprite);//app.draw(background);app.display();}}Вложения:
You must be logged in to view attached files.Я когда то писал клон игры Lines, если хочешь могу тебе сорцы скинуть. Там правда нет ООП, но думаю будет не сложно внедрить, там всего лишь 300 строчек. На счёт Vector2 i ты не прав, это аналог одномерного массива из 2х чисел типа int. На счёт того что не отображается спрайт, перепроверь, правильны ли пути.
Спасибо за ответ. По моему Lines это не совсем то, что нужно (возможно я не уверен, просто видел на хабре решение по игре Lines, но это было не то) У меня есть пример таких “шариков” без ООП, но то ли я чутка туговат (а это скорее всего так), то ли написать “шарики” с помощью ООП гораздо труднее чем без. Просто проблема в том что мозг еще не заточен в понимании ООП и в этом и причина моей тугости. Класс одного шарика я создал. Теперь нужно создать поле 9х9 из таких шариков с рандомной генерацией цвета. А потом и логика пойдет. Приведу код тех шариков без ООП.( не знаю зачем )
C++123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167using namespace sf;int ts = 64; //tile sizeVector2i offset(48, 24);struct piece{int x, y, col, row, kind, match, alpha;piece(){ match = 0; alpha = 255; }} grid[10][10];void swap(piece p1, piece p2){std::swap(p1.col, p2.col);std::swap(p1.row, p2.row);grid[p1.row][p1.col] = p1;grid[p2.row][p2.col] = p2;}int main(){srand(time(0));RenderWindow app(VideoMode(800, 600), "Match-3 Game!");app.setFramerateLimit(60);Texture t1, t2;t1.loadFromFile("images/background.png");t2.loadFromFile("images/gray.png");Sprite background(t1), gems(t2);for (int i = 1; i <= 9; i++)for (int j = 1; j <= 9; j++){grid[i][j].kind = rand() % 3;grid[i][j].col = j;grid[i][j].row = i;grid[i][j].x = j*ts;grid[i][j].y = i*ts;}int x0, y0, x, y; int click = 0; Vector2i pos;bool isSwap = false, isMoving = false;while (app.isOpen()){Event e;while (app.pollEvent(e)){if (e.type == Event::Closed)app.close();if (e.type == Event::MouseButtonPressed)if (e.key.code == Mouse::Left){if (!isSwap && !isMoving) click++;pos = Mouse::getPosition(app) - offset;}}// mouse clickif (click == 1){x0 = pos.x / ts + 1;y0 = pos.y / ts + 1;}if (click == 2){x = pos.x / ts + 1;y = pos.y / ts + 1;if (abs(x - x0) + abs(y - y0) == 1){swap(grid[y0][x0], grid[y][x]); isSwap = 1; click = 0;}else click = 1;}//Match findingfor (int i = 1; i <= 8; i++)for (int j = 1; j <= 8; j++){if (grid[i][j].kind == grid[i + 1][j].kind)if (grid[i][j].kind == grid[i - 1][j].kind)for (int n = -1; n <= 1; n++) grid[i + n][j].match++;if (grid[i][j].kind == grid[i][j + 1].kind)if (grid[i][j].kind == grid[i][j - 1].kind)for (int n = -1; n <= 1; n++) grid[i][j + n].match++;}//Moving animationisMoving = false;for (int i = 1; i <= 8; i++)for (int j = 1; j <= 8; j++){piece &p = grid[i][j];int dx, dy;for (int n = 0; n<4; n++) // 4 - speed{dx = p.x - p.col*ts;dy = p.y - p.row*ts;if (dx) p.x -= dx / abs(dx);if (dy) p.y -= dy / abs(dy);}if (dx || dy) isMoving = 1;}//Deleting amimationif (!isMoving)for (int i = 1; i <= 8; i++)for (int j = 1; j <= 8; j++)if (grid[i][j].match) if (grid[i][j].alpha>10) { grid[i][j].alpha -= 10; isMoving = true; }//Get scoreint score = 0;for (int i = 1; i <= 8; i++)for (int j = 1; j <= 8; j++)score += grid[i][j].match;//Second swap if no matchif (isSwap && !isMoving){if (!score) swap(grid[y0][x0], grid[y][x]); isSwap = 0;}//Update gridif (!isMoving){for (int i = 8; i>0; i--)for (int j = 1; j <= 8; j++)if (grid[i][j].match)for (int n = i; n>0; n--)if (!grid[n][j].match) { swap(grid[n][j], grid[i][j]); break; };for (int j = 1; j <= 8; j++)for (int i = 8, n = 0; i>0; i--)if (grid[i][j].match){grid[i][j].kind = rand() % 7;grid[i][j].y = -ts*n++;grid[i][j].match = 0;grid[i][j].alpha = 255;}}//////draw///////app.draw(background);for (int i = 1; i <= 8; i++)for (int j = 1; j <= 8; j++){piece p = grid[i][j];//gems.setTextureRect(IntRect(p.kind * 49, 0, 49, 49));gems.setColor(sf::Color::Cyan);gems.setPosition(p.x, p.y);gems.move(offset.x - ts, offset.y - ts);app.draw(gems);}app.display();}return 0;}Хм, думаю надо сделать класс для шарика и для сетки. В классе для шарика сделать такие функции как выделение и перемешение, и этот класс опираясь ещё на класс сетки совершал данные действия. Ещё в классе сетки методы сделать для проверки условий. Либо вообще один класс сетки. Я честно говоря для себя редко пишу в ООП, не всегда понимаю его целесообразности. Но если надо то в принципе могу, только не факт что это будет правильно и по всем канонам.
Вот и я тоже подумал, что нужно запилить два класса: один с описанием одного шарика, другой с созданием сетки с помощью этого шарика, а все действия и анимацию я думал прописать в main`e. Остался вопрос как запихать все эти шары в сетку и заставить отображаться в виде 9х9 + рандомные цвета
Вот вам небольшая наброска того как я вижи решение задачи.Создал два класса: сетки и шариков. Сетка состоит из квадратов 30 на30, а шарики представляют и себя структур которая содержит : объект (круг,цвет,размер,и положение на координатной сетке) и маркер(красный,зелёный и синий). По маркеру можно будет отличать шарики в проверке на пересечения. В методе void rulechek() небольшой пример: если два красных шара соприкоснуться они удаляються.
C++123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121class net{public:vector<RectangleShape> netcell;void create(vector<Balls> ballArrey){for (int i = 0; i < 81; i++){RectangleShape cell;cell.setOutlineThickness(1);cell.setOutlineColor(Color::Black);cell.setFillColor(Color::Transparent);cell.setSize(Vector2f(30, 30));netcell.push_back(cell);}pos.x = 0; pos.y = 0;for (int i = 0; i < netcell.size(); i++){pos.x = x;pos.y = y;x += 31;ii++;if (ii > 9){x = 0;y += 31;ii = 0;}netcell[i].setPosition(pos);}for (int i = 0; i < ballArrey.size(); i++)ballArrey[i].ball.setPosition(Vector2f(netcell[i].getPosition().x+1, netcell[i].getPosition().y+1));}void drow(RenderWindow & win){for (int i = 0; i < netcell.size(); i++)win.draw(netcell[i]);}private:int x = 0, y = 0, ii = 0;Vector2f pos;};class Ball{public:struct Balls{ CircleShape ball; enum { Red, Green, Blue }color; };vector<Balls> ballArrey;void create(){Balls ball;for (int i = 0; i < 25; i++){CircleShape redball;redball.setFillColor(Color::Red);redball.setRadius(15);ball.ball = redball;ball.color = ball.Red;ballArrey.push_back(ball);}for (int i = 0; i < 25; i++){CircleShape greenball;greenball.setFillColor(Color::Red);greenball.setRadius(15);ball.ball = greenball;ball.color = ball.Green;ballArrey.push_back(ball);}for (int i = 0; i < 25; i++){CircleShape blueball;blueball.setFillColor(Color::Red);blueball.setRadius(15);ball.ball = blueball;ball.color = ball.Blue;ballArrey.push_back(ball);}for (int i = 0; i < ballArrey.size(); i++){if (ballArrey[i].color == 0)Red.push_back(ballArrey[i]);if (ballArrey[i].color == 1)Green.push_back(ballArrey[i]);if (ballArrey[i].color == 2)Blue.push_back(ballArrey[i]);}}void update(){rulechek();}void drow(RenderWindow & win){for (int i = 0; i < ballArrey.size(); i++)win.draw(ballArrey[i].ball);}private:vector<Balls> Red;vector<Balls> Green;vector<Balls> Blue;void rulechek(){for (int i = 0; i < ballArrey.size(); i++)for (int ii = 0; ii < Red.size(); ii++){if (Red[ii].ball.getGlobalBounds().intersects(ballArrey[i].ball.getLocalBounds()));if (ballArrey[i].color == 1){// ballArrey.erase(ballArrey.begin() + i);// Red.erase(Red.begin() + ii);}}}void control(){}};Спасибо большое за ответ. Ваше наброски интересные и основную идею я понял, но пару вопросов в понимании остались (ибо я тугой). Первый вопрос: разве типы для вектора не ограничиваются int, float и unsignet int?(Сразу скажу что с векторами я плохо знаком и в Visual Studio компилятор выдает ошибку “идентификатор “RectangleShape” не определен” ) Вроде больше вопросов нет. Я набросал два своих класса, но проблема возникла с рандомом он красит все шары в один цвет, а должен в разные. И я пытался и через enum и как только не пытался все равно не выходит сделать их всех разными. А вопрос с сеткой я решил с помощью матрицы, но не уверен что смогу потом с помощью мыши с объектами взаимодействовать
C++123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128#include <SFML/Graphics.hpp>#include <cstdlib>using namespace sf;class Bubble {private:Sprite *sprite;Texture *texture;Color color;public:Bubble(Color _color){setColor(_color);}Bubble(){setColor(GetRandomColor());}void setColor(Color _color){color = _color;texture = new Texture;texture->loadFromFile("images/gray.png");sprite = new Sprite(*texture);sprite->setColor(color);}Sprite* getSprite(){return sprite;}Color getColor(){return color;}static Color GetRandomColor(){const sf::Color colorArray[5] = { sf::Color::Cyan, sf::Color::Blue, sf::Color::Green, sf::Color::Red, sf::Color::Yellow };srand(time(NULL));return(colorArray[rand() % 5]);}};class GridBubbles{private:Bubble matrixBubbles[10][10];const int N = 9;public:GridBubbles(){initMatrix();}Bubble getBubble(int i, int j){return matrixBubbles[i][j];}private:void initMatrix(){for (int i = 0; i < N; i++){for (int j = 0; j < N; j++){matrixBubbles[i][j].setColor(Bubble::GetRandomColor());}}}};int main(){Bubble bubble;GridBubbles grid;srand(time(0));RenderWindow app(VideoMode(800, 600), "Bubbles");app.setFramerateLimit(60);//все для фона ыыыTexture t1;t1.loadFromFile("images/background.png");Sprite background(t1);//базовый цикл для отрисовки и всей фигни (это от бибилиотеки )while (app.isOpen()){sf::Event event;while (app.pollEvent(event)){if (event.type == sf::Event::Closed ||(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape))app.close();}app.clear();app.draw(background);for (int i = 0; i < 9; i++){for (int j = 0; j < 9; j++){Sprite *sprite = grid.getBubble(i, j).getSprite();sprite->setPosition(i * BallSize, j * BallSize);Color color = grid.getBubble(i, j).getColor();sprite->setColor(color);app.draw(*sprite);}}app.display();}}Вложения:
You must be logged in to view attached files.std:: vector<> принемает любую переменную. sf::RectangleShape базовый класс SFML, если он не определен значит у вас проблемы с подключением библиотек.
C++12345Color getColore(){vector<Color> color = { Color::Cyan, sf::Color::Blue, sf::Color::Green, sf::Color::Red, sf::Color::Yellow };return color[0 + rand() % 4];} -
АвторСообщения
Для ответа в этой теме необходимо авторизоваться.