Игровое программное приложение «2048». Игровое программное приложение
Скачать 1.3 Mb.
|
Министерство образования Республики Беларусь Учреждение образования БЕЛОРУССКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ИНФОРМАТИКИ И РАДИОЭЛЕКТРОНИКИ Факультет компьютерных систем и сетей Кафедра программного обеспечения информационных технологий Дисциплина: Языки программирования (ЯП) ПОЯСНИТЕЛЬНАЯ ЗАПИСКА к курсовому проекту на тему Игровое программное приложение «2048» БГУИР КП 1–40 01 01 171 ПЗ Выполнил студент гр. 051002 Сусленкова К.В. Проверил: Шостак Е.В. Минск 2021 Учреждение образования «Белорусский государственный университет информатики и радиоэлектроники» Факультет компьютерных систем и сетей УТВЕРЖДАЮ Заведующий кафедрой ПОИТ __________________________ (подпись) Лапицкая Н.В. 2021г. ЗАДАНИЕ по курсовому проектированию Студенту Сусленковой Ксении Вадимовне____________________________ 1. Тема работы Игровое программное приложение «2048» _____________ _________________________________________________________________ 2. Срок сдачи законченной работы 29.11.2021г._________________________ 3. Исходные данные к работе Среда разработки CodeBlocks. Язык программирования C++. Сторонняя графическая библиотека SFML. ____________________________________________________________________________________________________________________________________ 4. Содержание расчетно-пояснительной записки (перечень вопросов, которые подлежат разработке) Введение__________________________________________________________ 1 Анализ литературных источников___________________________________ 2 Постановка задачи________________________________________________ 3 Разработка программного средства_________________________________ 4 Тестирование и проверка работоспособности программного средства____ 5 Руководство по установке и использованию программного средства______ Заключение _______________________________________________________ Список использованных источников___________________________________ _Приложения ______________________________________________________ 5. Перечень графического материала (с точным обозначением обязательных чертежей и графиков) Схема алгоритма в формате А1___________________________ 6. Консультант по курсовой работе Шостак Е.В._________________________ 7.Дата выдачи задания 07.09.2021г.___________________________________ 8. Календарный график работы над проектом на весь период проектирования (с обозначением сроков выполнения и процентом от общего объема работы): Раздел 1. Введение к 15.09.2021г. – 10 % готовности работы;_____________ Раздел 2 к 15.10.2021г. – 30% готовности работы_______________________ Раздел 3 к 15.11.2021г. – 60% готовности работы_______________________ Раздел 4 к 20.11.2021г. – 80% готовности работы_______________________ Раздел 5.Заключение. Приложения к 25.11.2021г. – 90% готовности работы; оформление пояснительной записки и графического материала к 29.11.2021г.– 100% готовности работы._________________________________________ Защита курсового проекта с 13.12.2021г. по 22.12.2021г._________________ РУКОВОДИТЕЛЬ ____________________Шостак Е.В. (подпись) Задание принял к исполнению _____________Cусленкова К.В. 07.09.2021г. (дата и подпись студента) СОДЕРЖАНИЕСОДЕРЖАНИЕ 4 1АНАЛИТИЧЕСКИЙ ОБЗОР ЛИТЕРАТУРЫ 6 1.1 История 6 1.2Анализ прототипов 6 1.3Постановка задачи 8 2МОДЕЛИРОВАНИЕ ПРЕДМЕТНОЙ ОБЛАСТИ 9 2.1 Теоретические сведения по теме 9 2.2 Обоснование выбора языка программирования 9 3ПРОЕКТИРОВАНИЕ ПРОГРАММНОГО СРЕДСТВА 11 3.1 Разработка архитектуры программного средства 11 3.2 Разработка графического интерфейса 11 3.3 Разработка основного игрового цикла 11 4КОНСТРУИРОВАНИЕ ПРОГРАММНОГО СРЕДСТВА 15 4.1 Структура модулей программы 15 4.2 Описание модуля Main 15 5 ТЕСТИРОВАНИЕ И ПРОВЕРКА РАБОТОСПОСОБНОСТИ ПРОГРАММНОГО СРЕДСТВА 16 5.1 Тестирование работоспособности игрового процесса 16 6 РУКОВОДСТВО ПО УСТАНОВКЕ И ИСПОЛЬЗОВАНИЮ ПРОГРАММНОГО СРЕДСТВА 17 Заключение 19 Список использованной литературы 20 Приложение А 21 ПРИЛОЖЕНИЕ B 22 Формат А1 33 ВВЕДЕНИЕ Невозможно представить современный мир без гаджетов, установленных на них приложений, которые улучшают качество жизни и упрощают наше существование, и, конечно, игр. Существует множество разнообразных игр. Одни помогают расслабиться и отвлечься, другие – устремить всю силу мысли на обдумывание стратегии или шагов для решения ряда задач. Данная пояснительная записка содержит следующие основные разделы: 1. Аналитический обзор литературы; 2. Моделирование предметной области; 3. Проектирование программного средства; 4. Констуирование программного средства; 5. Тестирование программного средства и проверка работоспособности программного средства; 6. Руководство по установке и использованию программного средства; АНАЛИТИЧЕСКИЙ ОБЗОР ЛИТЕРАТУРЫ История Развивающие игры – игры, в процессе которых происходит развитие или усовершенствование различных навыков. Понятие развивающих игр связано, в основном, с детским периодом жизни человека, однако может затрагивать и остальные этапы жизни человека. Дети, играющие в развивающие игры, тренируют собственные мышление, изобретательность, воображение, креативность. Стоит заметить, что с развитием технологий, сложно представить человека, в смартфоне у которого не нашлось бы хотя бы одной игры. Одной из действительно увлекательных игр, которые при этом прекрасно подходят не только для того, чтобы скоротать время в очереди или общественном транспорте, но и сделать это с пользой для себя является игра «2048». Она отлично развивает логическое мышление, навыки стратегического планирования и пространственное воображение. Это не совсем сравнимо, но и как множество других открытий и изобретений в области компьютерного ПО, 2048 была разработана не с целью создания успешного коммерческого проекта. Её автор, молодой итальянский программист и веб-разработчик Габриэле Чирулли, решил с пользой провести выходные и попробовать свои силы в написании программ на JavaScript. За основу он взял идею нескольких других цифровых головоломок (в частности Threes и 1024). К концу выходных, а именно 9 марта 2014 г. Г. Чирулли посредством Твиттера поделился ссылкой на своё творение, которое загрузил на Github, с друзьями. Дальше произошло то, что могло произойти только в информационную эпоху – меньше, чем за неделю в 2048 сыграло больше 4 млн. людей. 19-летний разработчик был поражён успехом игры, но зарабатывать на ней деньги не собирался. В интервью он честно говорил, что идея приложения не была оригинальной, он сделал лишь модификацию. Несмотря на это, 2048 по популярности значительно опережала аналогичные игры, вышедшие раньше, а после того, как появилась возможность скачать версии для Android и iOS, спустя 2 месяца после первого релиза, о ней, без преувеличений, заговорил весь мир. Не последнюю роль здесь, конечно же, сыграл тот факт, что приложение распространялось бесплатно. Даже такие издания как «Times», «Wall Street Journal» и «Business Insider» вышли с положительными отзывами о данной компьютерной игре. Анализ прототипов В первую очередь стоит упомянуть прототип, с которого всё началось. Игра «Threes!» была создана небольшой командой независимых разработчиков, и первоначальный выход состоялся на платформе iOS 6 февраля 2014 года. Она стала одной из первых игр которая обзавелась скользящей и числовой механикой. «Threes!» была широко признана как игра вызывающая привыкание и её успех, привел к появлению ряда дополнительных игр что, в конечном итоге, привело к портированию игры на Android, Xbox One, Windows Phone, а также появлению браузерной версии. Вскоре после выхода «Threes!» сторонние недобросовестные разработчики стали выпускать игры-клоны, включая браузерную версию. По состоянию на апрель 2014 года, в App Store выходило в среднем по 15 клонов в день. Рис. 1.1 – Игра «Trees!», 2014 Одним из наиболее популярных прототипов является онлайн-игра «2048». Именно по примеру данного прототипа была осуществлена разработка программного средства. Рис. 1.2 – Онлайн-игра «2048» Постановка задачи Для удобного взаимодействия пользователя с проектируемым программным средством должен быть создан наиболее простой и понятный пользовательский интерфейс. Также программное средство должно иметь достаточный функционал для обеспечения удобной работы. В проектируемом программном средстве должны быть реализованы следующие функции: анимация движения плиток; загрузка рекорда из файла; удобство пользованием клавиатуры для осуществления игрового процесса; обработка соединения плиток одинакового номинала В качестве языка программирования выбран язык C++, графическая библиотека SFML и среда разработки – Code::Blocks, так как C++ позволяет создавать программы с высоким уровнем абстракции без больших потерь в производительности, а выбранная среда разработки с подключенными возможностями библиотеки позволяет освоить принципы графической реализации игровых программ. МОДЕЛИРОВАНИЕ ПРЕДМЕТНОЙ ОБЛАСТИТеоретические сведения по теме Думать на несколько шагов вперёд, грамотно распределять игровые плитки на игровом поле, все время оставлять свободное пространство для следующего хода – всё это является условием для успешного завершения игры «2048». Рис. 2.1 – Расположение плиток «2048» Сетка состоит из пространства 4 на 4, где плитка может скользить по одному из четырех направлений, и периодически на игровом поле будет в случайном месте свободного пространства будет появляться новая плитка. Для того, чтобы плитки сложились в одну, они должны быть одного и того же значения, после этого они примут общую сумму. Эта система служит механизмом подсчета баллов за игру, которые начисляются при подсчёте комбинаций плиток. В игре «2048» должны достичь величины плитки 2048, хотя после достижения игрок может продолжать бороться за высокие баллы это при условии того, что на площадке осталось свободное место. Задание движения плиток в ту или иную сторону для дальнейшего совмещения в одну при соответствующих данных осуществляется за счет передачи кода нажатой клавиши далее в программу. Таким образом, анимация состоит в перерисовке тайлов, в которые заключены данные каждой плитки. Анимация происходит при нажатии клавиш (управление направления объединения плиток). В то же время анимация объединения одинаковых плиток в одну с образованием новой может не происходить, в зависимости от обстановки на поле игры. Обоснование выбора языка программирования В качестве языка программирования выбран язык C++ и среда разработки – Code::Blocks. C++ позволяет создавать программы с высоким уровнем абстракции без больших потерь в производительности. Также язык представляет множество библиотек для удобной работы с компьютерной графикой. Множество игровых движков, фреймворков для игр и библиотек написано на C++ (OpenGl, DirectX и т.д.). Для данного курсового проекта язык C++ предоставляет для удобной работы с двумерной графикой библиотеку SFML. SFML содержит ряд модулей для простого программирования игр и мультимедиа приложений. SFML является более предпочтительным вариантом, так как в таких библиотеках, как OpenGl в частности, упор делается на возможность управления процессом рендеринга 2D и 3D графики. Поскольку при написании двумерной игры необходима высокая скорость перерисовки кадров, библиотека OpenGl будет только замедлять работу, тогда как SFML предоставляет простой интерфейс для производительной работы со звуком и графикой. Использование данной среды разработки дает множество возможностей в создании оконных приложений Windows. С помощью данной среды можно разработать качественное оконное приложение, обеспечить удобные средства для ввода, редактирования, сохранения и отображения данных. ПРОЕКТИРОВАНИЕ ПРОГРАММНОГО СРЕДСТВАРазработка архитектуры программного средства За инициализацию всех начальных параметров игры и главный игровой цикл отвечает класс Game. Также в этом классе происходит выгрузка из текстового файла рекорда игры за весь период ее существования, что позволяет все зависимости от игрока знать лучший результат и стремится к его превышению. Также в классе Game осуществляется реализация логики игры и определение направления смещения плиток в зависимости от нажатой клавиши во время игры. Вся игра происходит до закрытия игрового окна. Все текстуры для анимации загружаются в соответствующие переменные. Класс Tile проводит инициализацию плиток на игровом поле для проведения дальнейшей анимации. Разработка графического интерфейса Интерфейс программного средства создавался при помощи сторонней графической библиотеки SFML. Так как в SFML нет привычных компонентов интерфейса (кнопки, текстовые поля, переключатели) как объектов они создавались при помощи объекта существующего в SFML класса RectangleShape, представляющего собой прямоугольник, и, отслеживая события Event::KeyPressed и Event::Closed, меняли состояние плиток, игрового окна в программе. Разработка основного игрового цикла Игровой цикл продолжается до тех пор, пока логическая переменная isPlaying, являющаяся переменной класса Game, находится в состоянии true. Внутри цикла программа просматривает, какое действие ей нужно совершить: сместить в нужном направлении все плитки, если при сбрасывании две плитки одного номинала «налетают» одна на другую, то происходит превращаются в одну, номинал которой равен сумме соединившихся плиток. Если программа должна добавить новую плитку, то перед этим она проверит, чтобы анимация передвижения плиток и их объединения была завершена. Когда проверка действий пользователя закончится, программа проверит, нужно ли ей создавать новую фигуру, или же продолжать опускать старую. Также программа проверяет условия окончания игры, такие как отсутствие свободных клеток без возможности сдвига в любом из направлений или проверка на достижение числа 2048. В случае, если условие окончания игры соблюдено, программа меняет состояние переменной isPlaying на false и переходит к проверке условия цикла. Так как gameGoing = false, новой итерации не случается и таким образом игра заканчивается, выдавая пользователю экран окончания игры или экран победителя в зависимости от причины окончания. На рисунках 3.1–3.3 изображены различные события, которые происходят внутри программы. Все схемы в данном разделе изображены согласно ГОСТ 19.701-90. Рис. 3.1 – Осуществление функции сдвига внутри программы Рис. 3.2 – Функция игрового процесса и обработки нажатия клавиш Рис. 3.3 – Схема осуществления анимации КОНСТРУИРОВАНИЕ ПРОГРАММНОГО СРЕДСТВАСтруктура модулей программы Программа состоит основного файла реализации main.cpp, в нем находятся все элементы, требуемые для осуществления игрового процесса. Описание модуля Main В этом модуле запускается процесс игры. Таблица 4.7 – Открытые методы модуля Main
5 ТЕСТИРОВАНИЕ И ПРОВЕРКА РАБОТОСПОСОБНОСТИ ПРОГРАММНОГО СРЕДСТВАВ таблице 5.1 представлены результаты тестирования программного средства. Тестирование работоспособности игрового процесса Таблица 5.1 – Тестирование работоспособности игрового процесса
6 РУКОВОДСТВО ПО УСТАНОВКЕ И ИСПОЛЬЗОВАНИЮ ПРОГРАММНОГО СРЕДСТВАДля корректной работы программы необходимо распаковать архив в удобную пользователю папку, затем нажать ПКМ на исполняемый .exe файл, и выбрать «Создать ярлык», после чего этот ярлык поместить в удобное для вас место. При запуске программы можно увидеть игровое поле (рис. 6.1). Рис. 6.1 – Игровое поле При нажатии любой из клавиш управления плитками начнется игра (рис. 6.2). Рис. 6.2 – Игровой процесс Конец игрового процесса выглядит следующим образом (Рис. 6.3) и после нажатия клавиши «Space» игровой процесс начнется заново. Рис. 6.3 – Конец игрового процесса Заключение В ходе данной работы было создано программное средство Игра «2048», которое предоставляет пользователю приятное времяпрепровождение. В ходе работы я получила опыт работы со сторонними графическими библиотеками, в частности SFML. SFML не имеет встроенных компонентов, таких как кнопки, текстовые поля, переключатели и т.д., соответственно все эти компоненты прописывались вручную, для чего потребовалось разобраться в официальной документации на английском языке. В соответствии с полученным результатом работы программы можно сделать вывод, что разработанная программа работает верно, а требования технического задания выполнены в полном объеме. Список использованной литературы [1] Гук, М. Процессоры Pentium II, Pentium Pro и просто Pentium / М. Гук. – СПб. : Питер Ком, 1999. – 288 с. [2] Кузелин, М. О. Современные семейства ПЛИС фирмы Xilinx : справ. пособие / М. О. Кузелин, Д. А. Кнышев, В. Ю. Зотов. – М. : Горячая линия-Телеком, 2004. – 440 с. [3] Технические средства диагностирования : справочник / В.В. Клюев [и др.]. – М. : Машиностроение, 1989. – 672 с. [4] Embedded Microcontrollers : Databook / Intel Corporation. – Santa Clara, Ca, 1994. [5] Newland, D.E. Mechanical Vibration Analysis and Computation / D.E. Newland – New York: Dover Publications, – 2006 – 608 p. [6] MSDN – Microsoft. – Режим доступа: https://docs.microsoft.com/en-us/welcome-to-docs [7] ISO/IEC 14882:2011 Приложение А Рисунок A1 – Схема алгоритма программы ПРИЛОЖЕНИЕ B Main.cpp #include #include #include #include #include #define WINDOW_SIZE 400.0f #define WINDOW_MARGIN 100.0f #define FIELD_SIZE 4 #define START_COUNT 2 #define TILE_PADDING 5 #define ABS(x) ((x<0)?(-(x)):(x)) #define WIN_VALUE 2048 #define ANIM_TIME 200.0f const float TILE_SIZE = WINDOW_SIZE / FIELD_SIZE; using namespace std; using namespace sf; Vector2i operator!(const Vector2i &v) { return Vector2i(ABS(v.y), ABS(v.x)); } Vector2i operator*(const Vector2i &v) { return Vector2i((v.x<0)?0:v.x, (v.y<0)?0:v.y); } class Tile { public: Vector2i pos, prevPos; int value; bool animMove; Tile() : pos(0,0), prevPos(0,0), value(0), animMove(false) {} }; class Game { public: Tile field[FIELD_SIZE][FIELD_SIZE]; int score, best_score; FILE* f; bool isPlaying, win, change; Game(): score(0), isPlaying(true), win(false), change(false), elementsCount(START_COUNT) { f = fopen("best_score.txt", "r"); fscanf(f, "%d", &best_score); fclose(f); for(int i = 0; i < FIELD_SIZE; ++i) //заполнение всех ячеек игрового поля 0 for(int j = 0; j < FIELD_SIZE; ++j) { field[i][j].pos.y=i; field[i][j].pos.x=j; field[i][j].prevPos.y=i; field[i][j].prevPos.x=j; field[i][j].value=0; } static int row, col; for(int i = 0; i < START_COUNT; ++i) //заполнение двух ячеек, выбранных случайным образом, двойками { do { row = rand() % FIELD_SIZE; col = rand() % FIELD_SIZE; } while(field[row][col].value!=0); field[row][col].value=2; } } void move(Vector2i dir) { //shift static Vector2i a, b, ppd; ppd = !dir; change = false; for (int i = 0; i< FIELD_SIZE; ++i) for (int j = 0; j < FIELD_SIZE; ++j) { field[i][j].prevPos = field[i][j].pos; field[i][j].animMove = true; } shift(dir); //add similar tiles together for (int i = 0; i < FIELD_SIZE; ++i) { a = i * ppd + (*dir) * (FIELD_SIZE-1); for (int j = 0; j< FIELD_SIZE-1; ++j) { b = a - dir; if (field[a.y][a.x].value != 0 && field[a.y][a.x].value == field[b.y][b.x].value) { field[a.y][a.x].value *= 2; field[b.y][b.x].value = 0; field[a.y][a.x].prevPos = field[b.y][b.x].prevPos; field[a.y][a.x].animMove = false; if (field[a.y][a.x].value == WIN_VALUE) { isPlaying = false; win = true; } score = score + field[a.y][a.x].value; change = true; --elementsCount; ++j; a -= dir; } a -= dir; } } //shift again shift(dir); for (int i = 0; i< FIELD_SIZE; ++i) for (int j = 0; j < FIELD_SIZE; ++j) { field[i][j].pos.y = i; field[i][j].pos.x = j; } //spawn new tiles and check if the game is over static int row, col; if (change) { do { row = rand() % FIELD_SIZE; col = rand() % FIELD_SIZE; } while(field[row][col].value!=0); field[row][col].value= (rand()% 100 < 90)?2:4; field[row][col].animMove = false; ++elementsCount; if(elementsCount >= FIELD_SIZE*FIELD_SIZE) { bool isMoveAvailable = false; for (int i = 0; i < FIELD_SIZE; ++i) { for (int j = 0; j < FIELD_SIZE; ++j) if((i-1>=0 && field[i][j].value == field[i-1][j].value) || (i+1 (j-1>=0 && field[i][j].value == field[i][j-1].value) || (j+1 { isMoveAvailable = true; break; } if (!isMoveAvailable) break; } if (!isMoveAvailable) { isPlaying = false; win = false; } } } } private: int elementsCount; void shift(Vector2i dir) { static Vector2i a, b, ppd; ppd = !dir; for(int i = 0; i< FIELD_SIZE; ++i) { a = i * ppd + (*dir) * (FIELD_SIZE-1); for(int j = 0; j< FIELD_SIZE; ++j) { if (field[a.y][a.x].value == 0) { b = a - dir; for(int k = j+1; k< FIELD_SIZE; ++k) { if (field[b.y][b.x].value != 0) { field[a.y][a.x].value=field[b.y][b.x].value; field[b.y][b.x].value=0; field[a.y][a.x].prevPos=field[b.y][b.x].pos; field[a.y][a.x].animMove=field[b.y][b.x].animMove; change=true; break; } b -= dir; } } a -= dir; } } } }; string intToString( int num) { static stringstream toStringConverter; static string tempString; toStringConverter.clear(); toStringConverter< toStringConverter>>tempString; return tempString; } int log2(int n) { int a=0; while(n!=1) { n /=2; ++a; } return a; } int main() { srand(time(0)); RenderWindow window(sf::VideoMode (WINDOW_SIZE, WINDOW_SIZE+WINDOW_MARGIN), "2048"); Game game; RectangleShape tile; Font font; font.loadFromFile("arial.ttf"); Text text; text.setFont(font); text.setStyle(Text::Bold); text.setCharacterSize(20); Color colors[11] = { Color(250,231,224), Color(249,225,206), Color(249,179,124), Color(246,149,96), Color(243,125,95), Color(254,92,65), Color(245,208,119), Color(249,208,103), Color(249,202,88), Color(239,196,65), Color(244,198,42) }; Vector2i up(0,-1), down(0,1), left(-1,0), right(1,0); float animCoef = 0; bool animating = false; Tile t; while (window.isOpen()) { game.change = false; Event event; while(window.pollEvent(event)) { if(event.type == Event::Closed) { window.close(); } else if(game.isPlaying && !animating && event.type == Event::KeyPressed) { switch(event.key.code) { case Keyboard::Up: game.move(up); break; case Keyboard::W: game.move(up); break; case Keyboard::Down: game.move(down); break; case Keyboard::S: game.move(down); break; case Keyboard::Left: game.move(left); break; case Keyboard::A: game.move(left); break; case Keyboard::Right: game.move(right); break; case Keyboard::D: game.move(right); break; } } else if (event.type == Event::KeyPressed && !game.isPlaying) { if(event.key.code == Keyboard::Space) { game = Game(); animating = false; animCoef = 0; } } } if (game.change) { animating = true; animCoef = ANIM_TIME; } if (animating) { animCoef -=1.5; if (animCoef <=0) animating = false; } window.clear(Color(250,248,239)); tile.setOrigin(0,0); tile.setSize(Vector2f(WINDOW_SIZE, WINDOW_SIZE)); tile.setPosition(0, WINDOW_MARGIN); tile.setFillColor(Color(166,148,130)); window.draw(tile); tile.setSize(Vector2f(TILE_SIZE - TILE_PADDING*2, TILE_SIZE - TILE_PADDING*2)); tile.setFillColor(Color(191,177,161)); for(int i = 0; i < FIELD_SIZE; ++i) for(int j = 0; j < FIELD_SIZE; ++j) { tile.setPosition(j * TILE_SIZE + TILE_PADDING, i * TILE_SIZE + TILE_PADDING + WINDOW_MARGIN); window.draw(tile); } for(int i = 0; i < FIELD_SIZE; ++i) for(int j = 0; j < FIELD_SIZE; ++j) { t = game.field[i][j]; if(t.value!=0) { if (!animating) { tile.setFillColor(colors[log2(t.value)-1]); tile.setSize(Vector2f(TILE_SIZE - TILE_PADDING*2, TILE_SIZE - TILE_PADDING*2)); tile.setOrigin(tile.getSize() / 2.0f); tile.setPosition(j * TILE_SIZE + TILE_SIZE /2.0f, i * TILE_SIZE + TILE_SIZE /2.0f + WINDOW_MARGIN); } else if(t.animMove) { tile.setFillColor(colors[log2(t.value)-1]); tile.setSize(Vector2f(TILE_SIZE - TILE_PADDING*2, TILE_SIZE - TILE_PADDING*2)); tile.setOrigin(tile.getSize() / 2.0f); tile.setPosition(((t.pos.x - t.prevPos.x) * (ANIM_TIME - animCoef) / ANIM_TIME + t.prevPos.x) * TILE_SIZE + TILE_SIZE / 2.0f, ((t.pos.y - t.prevPos.y) * (ANIM_TIME - animCoef) / ANIM_TIME + t.prevPos.y) * TILE_SIZE + TILE_SIZE / 2.0f + WINDOW_MARGIN); } else { tile.setFillColor(colors[log2(t.value)-2]); tile.setSize(Vector2f(TILE_SIZE - TILE_PADDING*2, TILE_SIZE - TILE_PADDING*2)); tile.setOrigin(tile.getSize() / 2.0f); tile.setPosition(((t.pos.x - t.prevPos.x) * (ANIM_TIME - animCoef) / ANIM_TIME + t.prevPos.x) * TILE_SIZE + TILE_SIZE / 2.0f, ((t.pos.y - t.prevPos.y) * (ANIM_TIME - animCoef) / ANIM_TIME + t.prevPos.y) * TILE_SIZE + TILE_SIZE / 2.0f + WINDOW_MARGIN); window.draw(tile); tile.setFillColor(colors[log2(t.value)-1]); tile.setSize(Vector2f((TILE_SIZE - TILE_PADDING*2) * (1.0f - animCoef / ANIM_TIME / 2.0f), (TILE_SIZE - TILE_PADDING*2)* (1.0f - animCoef / ANIM_TIME / 2.0f))); tile.setOrigin(tile.getSize() / 2.0f); tile.setPosition(j * TILE_SIZE + TILE_SIZE /2.0f, i * TILE_SIZE + TILE_SIZE /2.0f + WINDOW_MARGIN); } window.draw(tile); if (t.value<=4) text.setFillColor(Color(121,112,100)); else text.setFillColor(Color::White); text.setPosition(tile.getPosition()); text.setString(intToString(t.value)); text.setOrigin(text.getLocalBounds().width / 2.0f + text.getLocalBounds().width / 4.0f, text.getLocalBounds().height / 2.0f + text.getLocalBounds().height/ 2.0f); window.draw(text); } } text.setString("Your score:\n"+intToString(game.score)); text.setOrigin(0,0); text.setPosition(10,20); text.setFillColor(Color(121,112,100)); window.draw(text); if (game.score>game.best_score) game.best_score=game.score; text.setString("Best score:\n" + intToString(game.best_score)); text.setOrigin(0,0); text.setPosition(250,20); text.setFillColor(Color(121,112,100)); window.draw(text); if (game.win) { tile.setOrigin(0,0); tile.setSize(Vector2f(WINDOW_SIZE, WINDOW_SIZE)); tile.setPosition(0, WINDOW_MARGIN); tile.setFillColor(Color(255,255,0,100)); window.draw(tile); text.setFillColor(Color::White); text.setString("You win!"); text.setOrigin(text.getLocalBounds().width / 2.0f + text.getLocalBounds().width / 12.0f, text.getLocalBounds().height / 2.0f + text.getLocalBounds().height/ 2.0f); text.setPosition(WINDOW_SIZE / 2.0f, WINDOW_SIZE / 2 + WINDOW_MARGIN); window.draw(text); game.f = fopen("best_score.txt", "w"); fprintf(game.f, "%d", game.best_score); fclose(game.f); } else if(!game.isPlaying) { tile.setOrigin(0,0); tile.setSize(Vector2f(WINDOW_SIZE, WINDOW_SIZE)); tile.setPosition(0, WINDOW_MARGIN); tile.setFillColor(Color(255,255,255,100)); window.draw(tile); text.setFillColor(Color(121, 112, 100)); text.setString("Game over!"); text.setOrigin(text.getLocalBounds().width / 2.0f + text.getLocalBounds().width / 12.0f, text.getLocalBounds().height / 2.0f + text.getLocalBounds().height / 2.0f); text.setPosition(WINDOW_SIZE / 2.0f, WINDOW_SIZE / 2 + WINDOW_MARGIN); window.draw(text); game.f = fopen("best_score.txt", "w"); fprintf(game.f, "%d", game.best_score); fclose(game.f); } window.display(); } return 0; }
|