Как сделать змейку телом

Пишем игру змейка с помощью JavaScript + Canvas

Подготовка

Пожалуй, стоит вообще начать с подготовки к созданию игры и написанию кода. Мы будем использовать простой редактор Sublime Text. Впрочем, это не важно. Все делаем в одном документе, чтобы было быстрее.

Первым делом, напишем сам код для встраивания canvas в документ. Напомню, что canvas поддерживается только в HTML5.

Подготовка завершена, теперь мы можем приступать к созданию самой игры.

Начинаем

Для начала, я хотел бы вам вообще объяснить как будет работать змейка, так будет гораздо понятнее. Наша змейка — это массив. Массив элементов, элементы — это ее части, на которые она делиться. Это всего лишь квадратики, которые имеют координаты X и Y. Как вы знаете, X — горизонталь, Y — вертикаль. В обычном виде мы представляем себе координатную плоскость вот так:

Как сделать змейку телом. Смотреть фото Как сделать змейку телом. Смотреть картинку Как сделать змейку телом. Картинка про Как сделать змейку телом. Фото Как сделать змейку телом

Она абсолютно правильная, в этом нет сомнения, но на мониторе компьютера (в частности, canvas) она выглядит по-другому, вот так:

Как сделать змейку телом. Смотреть фото Как сделать змейку телом. Смотреть картинку Как сделать змейку телом. Картинка про Как сделать змейку телом. Фото Как сделать змейку телом

Это нужно знать, если вы вдруг в первый раз столкнулись с canvas. Я, когда столкнулся с этим, сначала вообще не понял где точка (0,0), благо я быстро разобрался. Надеюсь и у вас проблем не возникло.

Вернемся к элементам змейки, ее частям. Представим, что каждый элемент имеет свои координаты, но одинаковую высоту и одинаковую ширину. Это квадратики, не более. А теперь представим, что мы вот нарисовали змейку, все квадратики, они идут друг за другом, одинаковые такие. И тут мы решили, что нам нужно подвинуть змейку вправо. Как бы вы поступили?

Некоторые люди ответили бы, что нам нужно первый элемент подвинуть вправо, затем второй, затем третий и так далее. Но для меня этот вариант не является правильным, так как в случае, если вдруг змейка огромная, а компьютер слабый, мы можем заметить, что змейка иногда разрывается, что вообще не должно быть. Да и вообще, данный способ требует слишком много команд, когда можно обойтись гораздо меньшим количеством, не потеряв качество. А теперь мой способ: Мы берем последний элемент змейки, и ставим его в начало, изменяя его координаты так, чтобы он был после головы. Теперь этот элемент — голова. Всего-то! И да, эффект движения будет присутствовать, а на компьютере вообще не будет заметно, как мы спрятали хвост, а потом его поставили в начало. именно так мы и будем поступать во время создания движения змейки.

Вот тут точно начинаем

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

И так, вообще, нужно чуть-чуть пояснить зачем нам нужно в функции возвращения случайного числа, умножать и делить на переменную s, которая хранит в себе ни что иное, как ширину, по совместительству и высоту элементов змейки. На самом деле, это нужно, чтобы не было смещений во время движения, так как у нас ширина элемента — 30, то если мы хотим двигать ее без разрывов, то все координаты должны делиться на 30 без остатка. Именно поэтому я делю на число, округляю, а потом умножаю. Таким образом, число возвращается таким, что его можно разделить без остатка на 30.

Вы могли бы возразить, сказав, что ты мог бы просто холсту сделать ширину и высоту, кратную 30. Но на самом деле, это не лучший вариант. Так как я лично привык использовать всю ширину экрана. И в случае, если ширина = 320, то мне пришлось бы аж целых 20 пикселей забирать у пользователя, что могло бы доставить дискомфорт. Именно поэтому в нашей змейки все координаты объектов делятся на 30, чтобы не было никаких неожиданных моментов. Было бы даже правильнее вынести это как отдельную функцию, так как она достаточно часто используется в коде. Но к этому выводу я пришел поздно. (Но возможно это даже не нужно).

Теперь сделаем так, чтобы картинка имела четкое качество отображения. По ходу статьи, я буду дописывать код, в некоторых местах возвращаться к началу, так что при себе имейте полную картину кода.

Если что, то переменные innerWidth и innerHeight хранятся в глобальном пространстве имен.
Поэтому к ним можно обратиться именно так. Правда, я не знаю правильно ли так делать.

Ну что же, теперь начинаем писать код змейки.

Чтобы было движение, нам нужна анимация, мы будем использовать функцию setInterval, вторым параметром которой будет число 60. Можно чуть больше, 75 на пример, но мне нравится 60. Функция всего на всего каждые 60 мс. рисует змейку «заново». Дальнейшее написание кода — это только этот интервал.

Покажу вообще простую отрисовку нашей змейки, пока что без движения.

Чтобы проверить, что наша змейка не сталкивается сама с собой, нам нужно сделать некоторую проверку для каждого элемента, кроме последнего. Мы будем проверять, не равны ли координаты последнего элемента (головы) змейки любым из… То есть проще говоря: не произошло ли столкновение. Эта строчка кода была единой строкой, но вам сделал ее понятной. Напоминаю, что все это добавляется в функцию интервала.

А теперь, вы наверное заметили, что во время того, как мы изменяем координаты, мы вечно что-то «сохраняем», сначала поделив, а потом округлив и умножив на число s. Это все тот же самый способ выравнивания змейки относительно яблока. Движение в данном случае строгое, простое, поэтому и есть змейка яблоко может строго по определенным правилам, которые задан в самом начале интервала. И если бы координаты головы змейки хоть на 1px сместились бы, то яблоко нельзя было бы съесть. И да, это простой вариант, поэтому все так сильно ограничено.

Ну а нам же осталось что сделать? Правильно, удалить из массива хвост (первый элемент), добавить новый элемент в самый конец и отрисовать всю змейку. Сделаем это, добавив в конец интервала вот такие строчки кода.

В добавок к отрисовке змейки, я добавил код, который делает ощущение, что конец экрана — это его начало. И если змейка выходит за границы, то она потом выходит из начала, на погибая.
Вы можете заменить обнуление координат, на пример, на сбрасывание игры, если у вас все очень жестко. Но мне нравится больше так. Ну а теперь, осталось только по нажатию кнопок изменять направление змейки. Делает за считанные секунды. Нужно лишь написать этот код сразу после setInterval. Примерно так:

Тут мы сделали так, что если змейка двигается вправо, то она не может изменить направление налево. Это логично, на самом деле.

Вот и все, друзья. Моя первая статья, написанная новичком для новичков. Надеюсь, все было понятно и кому-то это пригодилось. Змейку можно усовершенствовать, добавив на пример, счетчик очков, рекорды, дополнительные фишки, но это все уже дополнения, которые вы можете сделать сами. На этом все, всем удачи!

Источник

Своя змейка, или пишем первый проект. Часть 0

Предисловие

Привет Хабр! Меня зовут Евгений «Nage», и я начал заниматься программированием около года назад, в свободное от работы время. Просмотрев множество различных туториалов по программированию задаешься вопросом «а что же делать дальше?», ведь в основном все рассказывают про самые основы и дальше как правило не заходят. Вот после продолжительного времени за просмотром разных роликов про одно и тоже я решил что стоит двигаться дальше, и браться за первый проект. И так, сейчас мы разберем как можно написать игру «Змейка» в консоли со своими начальными знаниями.

Глава 1. Итак, с чего начнем?

Для начала нам ничего лишнего не понадобится, только блокнот (или ваш любимый редактор), и компилятор C#, он присутствует по умолчанию в Windows, находится он в С:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe. Можно использовать компилятор последней версии который поставляется с visual studio, он находится Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Roslyn\csc.exe.

«@echo off» отключает отображение команд в консоли. С помощью команды goto получаем бесконечный цикл. Задаем переменную name, а с модификатором /p в переменную записывается значение введенное пользователем в консоль. «echo.» просто оставляет пустую строчку в консоли. Далее вызываем компилятор и передаем ему файл нашего кода, который он скомпилирует.

Глава 2. Первые шаги

Подготовим поле нашей игры, начиная с точки входа в нашу программу. Задаем переменные X и Y, размер и буфер окна консоли, и скроем отображение курсора.

Для вывода на экран нашей «графики» создадим свой тип данных — точка. Он будет содержать координаты и символ, который будет выводится на экран. Также сделаем методы для вывода на экран точки и ее «стирания».

Это интересно!
Оператор => называется лямбда-оператор, он используется в качестве определения анонимных лямбда выражений, и в качестве тела, состоящего из одного выражения, синтаксический сахар, заменяющий оператор return. Приведенный выше метод переопределения оператора (про его назначение чуть ниже) можно переписать так:

Создадим класс стен, границы игрового поля. Напишем 2 метода на создание вертикальных и горизонтальных линий, и в конструкторе вызываем отрисовку всех 4х сторон заданным символом. Список всех точек в стенке нам пригодится позже.

Как вы могли заметить для инициализации типа данных Point используется форма Point p = (x, y, ch); как и у встроенных типов, это становится возможным при переопределении оператора implicit, в котором описывается как задаются переменные.

Вернемся к классу Game и объявим поле walls, а в методе Main инициализируем ее.

Все! Можно скомпилировать код и посмотреть, что наше поле построилось, и самая легкая часть позади.

Глава 3. А что сегодня на завтрак?

Добавим генерацию еды на нашем поле, для этого создадим класс FoodFactory, который и будет заниматься созданием еды внутри границ.

Добавляем инициализацию фабрики и создадим еду на поле

Глава 4. Время главного героя

Перейдем к созданию самой змеи, и для начала определим перечисление направления движения змейки.

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

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

Осталось вывести ее на экран.

Готово! теперь у нас есть все что нужно, поле огороженное стенами, рандомно появляющаяся еда, и змейка. Пришла пора заставить все это взаимодействовать друг с другом.

Глава 5. Л-логика

Заставим нашу змейку двигаться, напишем бесконечный цикл для считывания клавиш нажатых на клавиатуре, и передаем клавишу в метод поворота змеи

Теперь, перед тем как написать метод движения змейки, надо реализовать взаимодействие головы с едой, стенками и хвостом змеи. Для этого надо написать метод, позволяющий сравнивать две точки на совпадение координат. Переопределим оператор равенства и не равенства, их обязательно нужно переопределять в паре.

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

И похожий метод проверяющий не совпадает ли точка с хвостом.

И методом проверки съела ли еду наша змейка, и сразу делаем ее длиннее.

теперь можно написать метод движения, со всеми нужными проверками.

Вот и все! Наша змейка в консоли закончена и можно поиграть.
Как сделать змейку телом. Смотреть фото Как сделать змейку телом. Смотреть картинку Как сделать змейку телом. Картинка про Как сделать змейку телом. Фото Как сделать змейку телом

Заключение

Мы посмотрели как можно реализовать первую простенькую игру с небольшим использованием ООП, научились перегружать операторы, посмотрели на кортежи и лямбда оператор, надеюсь это было полезно!

Это была пилотная статья, и если вам понравилось, я напишу про реализацию змейки на Unity.
Всем удачи!

Источник

Большой разбор: как ИИ играет в змейку

Помни­те, рань­ше была такая игра — змей­ка? Она появи­лась в 70-х, и в неё игра­ли на всём: от ком­пью­те­ров и при­ста­вок до кно­поч­ных теле­фо­нов. Напри­мер, если вы про­пу­сти­ли то вре­мя, это мог­ло выгля­деть вот так:

Как сделать змейку телом. Смотреть фото Как сделать змейку телом. Смотреть картинку Как сделать змейку телом. Картинка про Как сделать змейку телом. Фото Как сделать змейку телом

В нача­ле игры всё про­сто: поле пустое, змей­ка воль­гот­но по нему пол­за­ет и жрёт. Но даль­ше змей­ка посте­пен­но рас­тёт, зани­мая всё боль­шую пло­щадь экра­на, и в какой-то момент пере­дви­гать­ся ста­но­вит­ся супер­слож­но. И вот тогда нуж­на стра­те­гия и ловкость.

Австра­лий­ский про­грам­мист Эван, он же CodeBullet, научил искус­ствен­ный интел­лект играть в эту игру и сде­лал об этом видео:

Если вы зна­е­те англий­ский, про­сто смот­ри­те и полу­чай­те удо­воль­ствие, а если нет — мы при­го­то­ви­ли подроб­ный раз­бор того, что про­ис­хо­дит в ролике.

Начало: 5 разных алгоритмов

В самом нача­ле Эван экс­пе­ри­мен­ти­ро­вал с ней­ро­се­тью, что­бы най­ти луч­ший алго­ритм для игры в змей­ку. В ито­ге у него полу­чи­лось 5 раз­ных алго­рит­мов, каж­до­му из кото­рых он дал своё имя. Они отли­ча­лись сти­лем игры, пове­де­ни­ем в раз­ных ситу­а­ци­ях и результативностью.

Сте­пан. Это одна из пер­вых вер­сий алго­рит­ма, у кото­рой есть одна харак­тер­ная осо­бен­ность: Стё­па любит дви­гать­ся по диагонали.

Как сделать змейку телом. Смотреть фото Как сделать змейку телом. Смотреть картинку Как сделать змейку телом. Картинка про Как сделать змейку телом. Фото Как сделать змейку телом

Несмот­ря на то, что кажет­ся, что змей­ка дела­ет всё пра­виль­но, это самая худ­шая вер­сия ней­рон­ки, кото­рая полу­чи­лась у про­грам­ми­ста. При этом уме­ние Стёп­ки дви­гать­ся по диа­го­на­ли — уни­каль­но, оно силь­но при­го­дит­ся в будущем.

Лена. Она умнее Стё­пы, дви­га­ет­ся более пред­ска­зу­е­мо, а ещё у неё класс­но полу­ча­ет­ся избе­гать столк­но­ве­ния с собой. Это важ­ное уме­ние для змей­ки, пото­му что если голо­ва упрёт­ся в хвост или в тело — игра закончится.

Миша. Быст­рая, эффек­тив­ная змей­ка почти без еди­но­го лиш­не­го дви­же­ния. Миша почти иде­а­лен, но это­го недостаточно.

Как сделать змейку телом. Смотреть фото Как сделать змейку телом. Смотреть картинку Как сделать змейку телом. Картинка про Как сделать змейку телом. Фото Как сделать змейку телом

Коля. Уме­ет соби­рать мно­го кусоч­ков, но когда ста­но­вит­ся совсем длин­ным, то раз­мер начи­на­ет ему мешать.

Как сделать змейку телом. Смотреть фото Как сделать змейку телом. Смотреть картинку Как сделать змейку телом. Картинка про Как сделать змейку телом. Фото Как сделать змейку телом

Сёма. Чем­пи­он сре­ди этих вер­сий, пото­му что толь­ко он смог набрать 136 очков — боль­ше, чем осталь­ные кандидаты.

Как сделать змейку телом. Смотреть фото Как сделать змейку телом. Смотреть картинку Как сделать змейку телом. Картинка про Как сделать змейку телом. Фото Как сделать змейку телом

Собираем в одно целое

Мож­но было оста­но­вить­ся на Сёме, но Эван решил пой­ти даль­ше и поду­мал: «А что если объ­еди­нить эти змей­ки в одну, что­бы вме­сте они рабо­та­ли мак­си­маль­но эффективно?»

Для это­го про­грам­мист сде­лал одну боль­шую ней­ро­сеть, в кото­рую поме­стил 5 зме­ек по тако­му алгоритму:

Смысл в том, что­бы исполь­зо­вать силь­ные сто­ро­ны каж­дой змей­ки для наи­боль­ше­го эффекта.

Добавляем цвета

Что­бы сто­рон­не­му наблю­да­те­лю было понят­но, что про­ис­хо­дит на экране и о чём имен­но «дума­ет» ней­рон­ка, Эван при­ду­мал рас­кра­ши­вать змей­ку в раз­ные цвета:

Теперь мы тоже можем пони­мать, какие реше­ния при­ни­ма­ет искус­ствен­ный интел­лект в каж­дой ситу­а­ции. Самое инте­рес­ное, что ино­гда мы даже можем понять, какая из зме­ек сей­час взя­ла управ­ле­ние на себя.

Появил­ся синий цвет: это озна­ча­ет, что змей­ка видит еду и дума­ет, как бы подо­брать­ся к ней поближе.

Запу­стим сно­ва и про­ве­рим, полу­чит­ся ли побить этот рекорд:

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

Что дальше

Даль­ше как обыч­но — новые боль­шие раз­бо­ры, объ­яс­не­ние того, как рабо­та­ют ней­ро­се­ти и как это при­ме­нить на прак­ти­ке. Лайк, под­пис­ка, все дела.

Источник

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

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