Урок №14. Создание игры «Змейка» на C++/Qt5

  Дмитрий Бушуев  | 

  |

  Обновл. 20 Июл 2021  | 

 66083

 ǀ   10 

Сегодня мы создадим аналог популярной игры «Змейка» на С++/Qt5.

Игра «Змейка»

Игра «Змейка» — это старая классическая видеоигра. Впервые она была создана в конце 70-х годов для использования на игровых автоматах, а затем в 1979 году её перенесли и на ПК. В этой игре игрок управляет тонким существом, похожим на змею, которое перемещается по игровому полю без остановки. Цель состоит в том, чтобы съесть как можно больше яблок, появляющихся в процессе игры. Каждый раз, когда змея съедает яблоко, она становится длиннее, что усложняет дальнейший процесс игры. Змея при этом должна избегать столкновений со стенами и собственным телом.

Разработка игры «Змейка»


Размер каждой отдельной «части» тела змеи составляет 10 пикселей. Управляется она с клавиатуры при помощи стрелочек: , , , . Изначально тело змеи состоит из трех «частей». Если игра завершилась, то в центре игрового поля отображается сообщение "Game Over".

Заголовочный файл — Snake.h:

Константы B_WIDTH и B_HEIGHT определяют размеры (ширину и высоту) игрового поля. DOT_SIZE — это размеры яблока и «частей» тела змеи. Константа ALL_DOTS определяет максимальное количество возможных точек на доске (900 = (300*300)/(10*10)). Константа RAND_POS используется для вычисления случайной позиции яблока, а константа DELAY определяет скорость игры:

Следующие два массива содержат координаты (x;y) всех «частей» тела змеи:

В файле snake.cpp содержится логика нашей игры.

Файл реализации — snake.cpp:

При помощи метода loadImages() мы загружаем изображения, которые будут использоваться в игре. Класс QImage используется для хранения данных PNG-изображений:

В методе initGame() мы создаем змею, случайным образом определяем позицию на игровом поле, где будет располагаться яблоко, и запускаем таймер:

Если голова сталкивается с яблоком, то мы увеличиваем количество «частей» тела змеи. Затем вызываем метод locateApple(), который случайным образом позиционирует новое яблоко:

В методе move() у нас находится ключевой алгоритм игры. Чтобы понять его, посмотрите, как движется змея. Мы контролируем только голову змеи. При этом мы можем изменить её направление движения с помощью стрелочек. Остальные «части» тела змеи по цепочке перемещаются друг за другом. Вторая «часть» движется туда, где была первая, третья — туда, где была вторая и т.д.:

Перемещаем «части» тела змеи друг за другом:

Голова перемещается в любом из 4 направлений. Например, перемещаем голову змеи влево:

В методе checkCollision() мы определяем, столкнулась ли змея со стеной или со своим телом. Если змея ударится головой о какую-нибудь «часть» своего тела, то игра окончена:

Игра заканчивается, если змея сталкивается с любой частью доски, например, с нижней:

Метод timerEvent() формирует игровой цикл. При условии, что игра еще не закончена, мы выполняем обнаружение столкновений змеи с препятствиями и выполняем её дальнейшее перемещение. Функция repaint() вызывает перерисовку окна:

Например, если пользователь нажимает стрелочку , то мы устанавливаем значение true для переменной leftDirection. Эта переменная используется в функции move() для изменения координат змеи. Стоит отметить, что когда змея направляется вправо, мы не можем сразу же повернуть налево (т.е. сразу развернуться на 180 градусов):

Основной файл программы — main.cpp:

Результат выполнения программы:


  GitHub / Урок №14. Создание игры «Змейка» на C++/Qt5 — Исходный код

Заключение

Вот такой вот несложный, но интересный урок. На следующем уроке мы попробуем создать еще одну популярную игру — «Арканоид».


Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (43 оценок, среднее: 4,95 из 5)
Загрузка...

Комментариев: 10

  1. Finchi:

    Мое решение на Qt6 в среде MS VS 2022 Enterprise Edition, некоторые моменты реализовал совершенно по-другому, возможно будет кому-то полезным:

    Snake.h

    Snake.cpp

    main.cpp

     

  2. Александр:

    Спасибо. Ваши уроки проясняют многое в плюсах). Я сейчас осваиваю С++ в контексте Unreal Engine. Игра "Змейка" у меня готова, но есть один баг движения: Например, когда змейка движется влево, если нажать вверх и затем сразу вправо, то змейка не успевает поменять направление вверх и сразу уходит вправо, тем самым врезаясь в саму себя. Не подскажете, как убрать сей баг? Как запретить уходить вправо, пока все элементы змейки не сместились вверх?

    Моя змейка:

    https://gitlab.com/atrushilev/snakegame/-/tree/master/Source/SnakeGame

    Буду признателен за любую помощь или совет:)

    1. Павел:

      Баг возникает из-за того, что игра перерисовывается по timerEvent раз в 140мс, в то время как keyPressEvent принимает нажатие клавиш неограниченное количество раз. Значит прописанное в нем условие запрета на обратное движение снимается нажатием перед этим другой клавиши.

      Можно в keyPressEvent нажатую клавишу просто сохранять в int переменную, а всю обработку перенести в timerEvent — выше вызова метода move.

  3. Сергей:

    Это все чушь , создайте в каталоге папку images
    поместите в нее файлы изображений , в проекте создайте ресурс с префиксом, например snake , добавьте к нему картинки
    внесите следующие исправление в loadImages()

    и все закрутится 🙂

  4. Даниил:

    Увеличил изображение с 10px до 24px, в итоге когда змея попадает на яблоко, оно не пропадает и змея не становится больше.

  5. noname:

    Можете подробнее расписать про gameOver функцию?

    1. Фото аватара Дмитрий Бушуев:

      А какие конкретно места в функции gameOver() у вас вызывают вопросы? 🙂

  6. noname:

    Пробую добавить плюшки в игру.
    Например кнопку старт в начале игры. В конструктор прописал

    Но ругается на виртуальную таблицу методов. В чем может быть дело?

  7. KaligayevX3:

    Извините, пишу второй раз, потому что отчаялся, уже 5 часов пытаюсь сделать так, чтобы картинка прогрузилась, ничего не помогает.

    Насколько я понял, это часть кода, из-за которой моя змейка невидимая

    1. Фото аватара Дмитрий Бушуев:

      Да, проблема в том, что у Qt не получается подгрузить данные файлы. Решить её можно несколькими способами:

      Способ 1:
      Пропишите полные пути к файлам-картинкам, Например:

      Не забудьте при этом проверить, чтобы у вас была создана папка C:\Snake и в ней лежали эти 3 файла.

      Способ 2:
      Закройте Qt Creator. Найдите у себя в скачанных исходниках файл My_QtApplication.pro.user. Удалите данный файл. После этого снова откройте проект в Qt Creator и запустите его.

      Способ 3: Перекачайте исходники с сайта. Там эта ошибка уже исправлена.

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *