Русский
Русский
English
Статистика
Реклама

Engine

Перевод Пишем простой шахматный движок на Go

17.12.2020 20:07:58 | Автор: admin
Всем, кто сейчас смотрит нашумевший сериал Ход королевы (The Queen's Gambit), посвящается. Еще больше шахматных терминов в нашем новом переводе.

В данной статье мы постараемся разобраться, как работают шахматные движки путем портирования шахматного движка sunfish на Go. Sunfish примечателен своей простотой и небольшим размером, но при этом он все-таки способен сыграть достойную шахматную партию. Go в свою очередь известен как простой и хорошо читаемый язык программирования, поэтому я надеюсь, что вместе они составят отличную пару.

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

  • Каким образом представить шахматную доску (клетки, фигуры, допустимые ходы)?
  • Как оценивать доску (кто выиграет с большей вероятностью)?
  • Как выполнять поиск оптимального хода?

Фрагменты кода в этом посте упрощены и содержат только самые важные части. Вы можете найти полный код движка по ссылке github.com/zserge/carnatus (carnatus латинское название морского окуня, вид Sebastes carnatus).

Клетки и фигуры


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

Обычно доска представляет собой набор клеток. Мы добавим отступы вокруг стандартной доски 8x8, чтобы недопустимые ходы фигур попадали в эту область. Это позволит нам избежать проверки границ и значительно упростит код.

Мы будем использовать линейный массив. Самое большое расстояние, на которое может переместиться шахматная фигура, это ход коня на 2 клетки. Конечно, другие скользящие фигуры могут перемещаться на большие расстояния, но такие ходы будут последовательно оцениваться по мере преодоления каждой клетки, а значит границы доски будут обнаружены раньше, чем фигура сможет выйти за них.

Таким образом, нам необходим отступ по краям доски в две клетки. Мы могли бы создать доску 12x12, но так как мы представляем ее в виде линейного массива, нам нужна доска 12x10, потому что крайний правый квадрат отступа в предыдущей строке может использоваться в качестве крайнего левого квадрата отступа в следующей строке ( = отступ):

................................................................

В нашем обозначении a1 выглядела бы как 910+1=91, а a8 как 210+1"=21.

Каждая ячейка в массиве доски представляла бы шахматную фигуру, пустую клетку или зону отступа. Мы могли бы использовать числовые константы для этих значений, но, чтобы упростить отладку, используем символы, понятные человеку. Прописными и строчными буквами будут обозначаться фигуры, пробелом зоны отступа, а точками пустые клетки:

          |          | RNBQKBNR | PPPPPPPP | ........ | ........ | ........ | <- выглядит как настоящая шахматная доска ........ | ........ | ........ | pppppppp | rnbkqbnr |          |          |

Расшифровка сокращений
R rook ладья
N knight конь
B bishop слон
Q queen ферзь
K king король

Наконец мы можем начать писать код:

type Piece bytefunc (p Piece) Value() int { ... }func (p Piece) Ours() bool { ... }func (p Piece) Flip() Piece { ... }type Board [120]piecefunc (b Board) Flip() Board { ... }type Square intfunc (s Square) Flip() Square { ... }

Фигуры имеют определенную ценность. Эти значения нужны, чтобы оценивать позиции на доске и понимать, кто выигрывает. Обычно пешка = 100, конь = 280, слон = 320, ладья = 479, ферзь = 929, а король имеет настолько высокую ценность, что она превосходит 8 ферзей (пешки, превратившиеся в ферзей) в совокупности с парами коней, слонов и ладей. Если мы обладаем всем этим богатством, но теряем короля, подсчет все равно покажет, что мы проиграем.

Каждый тип имеет метод переворота (Flip() method), который возвращает то же самое значение после переворота доски перед ходом противника. У фигур он меняет регистр символа фигуры. У клеток он возвращает 119 клеток (считая с другого конца доски). Что касается доски, он копирует все фигуры с клеток в обратном порядке, меняя их регистр.

Генератор ходов


Итак, у нас уже есть кирпичики для движка, и теперь мы можем подумать об игровых позициях. Позиция это доска с фигурами и дополнительные состояния в игре, такие как квадрат прохода, блуждающий квадрат и возможности рокировки. Если бы мы хотели упростить игру, мы бы могли повторно использовать тип доски (Board type), но мы создадим отдельный тип позиции (Position type), отвечающий за ходы и оценку доски.

Что такое ход? Это комбинация двух клеток клетка, на которой фигура находилась до совершения хода, и клетка, куда переместились фигура. Позиция это шахматная доска со счетом, правилами рокировки для каждого игрока и квадратами прохода / блуждающими квадратами. Оба типа также имеют метод переворота (Flip() method) для ходов соперника.

type Move struct {  from Square  to   Square}func (m Move) Flip() Move { ... }type Position struct {  board Board   // текущая доска  score int     // очки по доске  чем их больше, тем лучше  wc    [2]bool // возможности рокировки для белых  bc    [2]bool // возможности рокировки для черных  ep    Square  // битое поле, где пешка может быть взята на проходе  kp    Square  // поле во время рокировки, где король может быть взят}func (p Position) Flip() Position { ... }

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

Чтобы сгенерировать все допустимые ходы, нам нужно:

  • составить список всех одношаговых ходов в каждом направлении для каждой фигуры;
  • выполнить то же самое для всех клеток, игнорируя не белые фигуры;
  • обозначить ход в каждом возможном направлении для каждой белой фигуры;
  • если длина хода фигуры не ограничена (ладья, слон, ферзь), продолжайте двигать ее, пока на пути не встретится препятствие: фигура соперника или отступ за краем доски.

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

Чтобы сделать арифметику направлений более читаемой, мы будем использовать константы направления N/E/S/W:

const N, E, S, W = -10, 1, 10, -1var directions = map[Piece][]Square{  'P': {N, N + N, N + W, N + E},  'N': {N + N + E, E + N + E, E + S + E, S + S + E, S + S + W, W + S + W, W + N + W, N + N + W},  'B': {N + E, S + E, S + W, N + W},  'R': {N, E, S, W},  'Q': {N, E, S, W, N + E, S + E, S + W, N + W},  'K': {N, E, S, W, N + E, S + E, S + W, N + W},}func (pos Position) Moves() (moves []Move) {  for index, p := range pos.board {    if !p.ours() {      continue    }    i := Square(index)    for _, d := range directions[p] {      for j := i + d; ; j = j + d {        q := pos.board[j]        if q == ' ' || (q != '.' && q.ours()) {          break        }        if p == 'P' {          if (d == N || d == N+N) && q != '.' {            break          }          if d == N+N && (i < A1+N || pos.board[i+N] != '.') {            break          }        }        moves = append(moves, Move{from: i, to: j})        if p == 'P' || p == 'N' || p == 'K' || (q != ' ' && q != '.' && !q.ours()) {          break        }      }    }  }  return moves}

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

func (pos Position) Move(m Move) (np Position) {  np = pos  np.board[m.to] = pos.board[m.from]  np.board[m.from] = '.'  return np.Flip()}

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

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

Но как понять, что мы проигрываем?

Оценка доски


За каждую позицию на доске начисляются очки. Изначально счет равняется нулю, так как оба игрока начинают в равных условиях. После выполнения хода счет меняется в зависимости от того, какие фигуры были взяты и как фигуры поменяли положение на доске.

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

Гораздо более точный и удивительно простой подход это таблицы соотношения фигур и клеток (PST Piece-Square Tables). Для каждой фигуры создается таблица такого же размера, как шахматная доска, где для каждой клетки назначается соответствующая ценность. Эти значения являются эмпирическими, поэтому я просто взял их из движка Sunfish.

На самом деле, более продвинутые шахматные движки обновляют PST-таблицы во время игры, потому что ценность фигур меняется (т. е. пешки становятся более ценными к концу игры). Но у нас будет простой движок.

Чтобы оценить позицию после хода, нам нужно:

  • определить рейтинг текущей позиции,
  • вычесть ценность передвигаемой фигуры,
  • прибавить новую ценность фигуры в соответствии с таблицей PTS,
  • прибавить ценность захваченной фигуры, если такие имеются.

Дополнительно нам нужно отрегулировать в PST-таблице ценность ладьи во время рокировки и ценность пешки во время превращения или взятия на проходе. Но в здесь мы не будем это рассматривать:

var pst = map[Piece][120]int{  'P': { ... },  'N': { ... },  'B': { ... },  'R': { ... },  'Q': { ... },  'K': { .... },}func (pos Position) value(m Move) int {  i, j := m.from, m.to  p, q := Piece(pos.board[i]), Piece(pos.board[j])  // Настроить значение передвигаемой фигуры в PST-таблице  score := pst[p][j] - pst[p][i]  if q != '.' && q != ' ' && !q.ours() {    // Настроить значение захваченной фигуры в PST-таблице    score += pst[q.Flip()][j.Flip()]  }  return score}

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

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

Алгоритм поиска


Наиболее распространенный алгоритм поиска в шахматных движках попроще поиск в глубину, который начинается с корня и спускается до заданного предела глубины, повторяя все возможные ходы перед возвратом. Для каждого хода вычисляется ценность позиции с использованием алгоритма минимакс (minimax) c альфа-бета отсечением (alpha-beta pruning).

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

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

Альфа-бета отсечение (alpha-beta pruning) используется для ускорения алгоритма минимакс путем удаления узлов, которые не стоит рассматривать. В основе альфа-бета отсечения лежит следующая логика: представьте, что вы играете в шахматы и обнаруживаете очень хороший ход А. Вы продолжаете смотреть на доску и находите еще более удачный ход B. Но затем вы анализируете ситуацию глубже и понимаете, что в случае выбора хода B противник объявит вам шах и мат через несколько ходов. Теперь вы отбросите ход B и не будете тратить время на анализ других возможных комбинаций после хода B.

Как минимакс, так и альфа-бета отсечение важны для понимания принципа работы шахматного движка. Движок Sunfish использует усовершенствованный алгоритм поиска MDF(f), который также является вариантом алгоритма минимакс, совмещенного с отсечением.

В нашем движке мы будем постепенно увеличивать глубину поиска и вызывать алгоритм MDF(f) для поиска нижних и верхних границ оптимального результата. Алгоритм MDF (f) будет использовать итерации альфа-бета отсечения с кэшем транспозиции.

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

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

Что дальше?


Если вам интересны простые шахматные движки, настоятельно рекомендую сыграть с Sunfish. Кстати, основой для Sunfish послужил движок Micromax, к нему прилагается замечательная документация от автора, которую определенно стоит прочитать.



Что касается нашего движка в Go, я добавил небольшую реализацию протокола UCI, чтобы его можно было использовать с пользовательским интерфейсом PyChess. Скорее всего, в нем еще куча ошибок и большой потенциал для улучшений, но это был интересный путь: от идеи о разработке шахматного движка до готовой, работающей компьютерной шахматной программы.

Да, он слабенький, но он играет настоящие шахматные партии!

Надеюсь, вам понравилась эта статья. Вы можете подписаться на меня в Github, Twitter или подписаться через rss.
Подробнее..

Твоя первая игра на Godot Engine

02.12.2020 18:09:40 | Автор: admin

1. Предисловие

Здравствуй, в данной статье я хочу в максимально сжатой форме познакомить тебя с основами создания простых 2d платформеров на движке Godot. Иногда мы будем останавливаться на некоторых важных моментах, а иногда пропускать ненужную тебе на начальном уровне информацию.

2.Стартуем!

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

Создание проекта.Создание проекта.

В выплывшем окошке введи название проекта и выбери его расположение в файловой системе. В пункте отрисовщик выбираем OpenGL ES 3.0, у нас нет нужды использовать более старую версию opengl, т.к ее обычно применяют при создании браузерных игр.

3.Знакомство с интерфейсом

2D сцена в Godot Engine.2D сцена в Godot Engine.

Итак, мы создали твой первый проект! Отличное начало, на сегодня хватит. Ладно, а если серьезно, то изучать интерфейс программы, особенно на первых парах, очень важно. Перед тобой открылась интересная картина с пустой 3d сценой, но она нам сегодня не понадобится, поэтому переходим в вкладку 2d. Кнопка находится сверху посередине. Стало немного проще, не правда ли? Ну, а теперь перейдем к самому интерфейсу программы (его кстати можно настроить под себя, перетащив какие-то элементы левой кнопкой мыши, но пока лучше оставит все как есть).

4.Работа с файлами через Godot

Не очень удобно каждый раз лазить в проводник, чтобы достать какие-то файлы, согласен? Для этого в Godot существует отдельное окошко, оно находится в левом нижнем углу редактора.

Проводник в Godot Engine.Проводник в Godot Engine.

Пока что там пусто, но это потому, что мы еще ничего не добавили. Так давай сделаем это! Ссылку на архив я прикрепил в конце поста, скачивай его и наслаждайся халявными спрайтами для игры (сразу говорю, они не мои). Если конечно у тебя заготовлена своя графика, то милости прошу.Итак, выделяем все нужные нам файлы и переносим их в окошечко. Вжух и они скопировались в движок! Но на этом магия не заканчивается! Здесь можно делать все то, что ты делаешь в обычном проводнике! Одним словом, полная свобода действий.

Но давай пока оставим эту часть экрана в покое и перейдем к более серьезным вещам.

5.Работа со сценами

Создание новых сцен.Создание новых сцен.

Посмотри в верхний левый угол редактора. Здесь есть вкладка, которая называется Сцена. Давай добавим твою первую сцену! Делается это просто, тебе нужно либо нажать на плюсик, либо ввести сочетание клавиш ctrl + A. Перед тобой выплыло меню, в поиске которого нужно ввести заветное слово Node. Мы давай это будет наша основная сцена, назовем ее World, но название в принципе неважно. Чтобы переименовать сцену нужно лишь дважды щелкнуть на нее левой кнопкой мыши. Теперь давай добавим на сцену игрока!

Многие просто добавляют объект Sprite, но это большая ошибка! Так делать нельзя! Запомни это раз и навсегда! Мы с тобой, как продвинутые пользователи добавим не Sprite, а KinematicBody2D.

Теперь древо твоего проекта выглядит так:

Добавляем игрока.Добавляем игрока.

Как ты наверное успел заметить, напротив нашего KinematicBode2D висит какой-то желты значок. Что он тут забыл? Дело в том, что наш объект пока что не имеет форму, вот Godot и ругается. Но прежде чем добавить форму нашему игроку, давай добавим его спрайт( И не забудь заменить название KinrmaticBode2D на Player ). Для этого нажми один раз правой кнопкой мыши на нашего Player и сочетанием клавиш ctrl + A добавь объект Sprite. Потом опять нажми на Игрока и добавь объект CollisionShape2D. У тебя должна быть примерно такая картина:

Добавляем в спрайт и границы игрока.Добавляем в спрайт и границы игрока.

Если все так, едем дальше. Теперь зададим картинку спрайта нашего персонажа. Выбираем объект Sprite, а потом перетаскиваем из моего архива картинку Player.png( или твою картинку) в раздел Texture. Если картинка импортировалась с сжатым качеством, просто нажми на нее, и в Godot в верхнем левом углу перейди в вкладку Импорт, там в разделе Flags убери галочку с пункта Filter и нажми Переимпортировать. Если не помогло, то просто перезапусти Godot.

Итак, мы добавили спрайт игрока, но выглядит это немного странно.

Добавляем текстуру спрайта игрока.Добавляем текстуру спрайта игрока.

Что же делать? Без паники, все поправимо в пару кликов. В левой части панели Инспектор выбираем параметр Hframes, и подгоняем его по размерам ( у меня это 25). Ну что, поменялась картинка?

Устанавливаем границы спрайта.Устанавливаем границы спрайта.

Супер, едем дальше! Ты еще не забыл про CollisionShape2D? Выделяй его и в пункте Shape выбирай Новый RectangleShape2D. Теперь изменяй его под размер персонажа. У меня получилось так:

CollisionShape2d.CollisionShape2d.

6.Отдельные сцены в Godot

Это все конечно классно,но хорошим тоном в Godot является создание отдельных сцен для объектов. Поэтому нам нужно сделать так, чтобы объект Player был отдельной сценой. Но не создавать же нам все заново? Нет, для этого в движке предусмотрена отдельная функция.Нажмите на Player правой кнопкой мыши и выберете Сохранить ветку,как ветку.

Создание сцены из ветки.Создание сцены из ветки.

Теперь Player это отдельная сцена, отлично!Чтобы перейти на сцену игрока достаточно нажать на иконку:

Перейдем на сцену игрока и приступим к очень интересному занятию программированию.

7. Скрипт игрока, GDscript

Для того чтобы добавить скрипт какому-либо объекту нежно просто выбрать этот объект и нажать на иконку свитка:

Создать скрипт.Создать скрипт.

После этого выплывет такая табличка:

Скрипт для игрока.Скрипт для игрока.

Нажимаем Создать и у нас открывается встроенный редактор кода в Godot.Теперь начинается более сложная часть туториала, поэтому слушай внимательнее.Пока что наш персонаж просто стоит на сцене и ничего не делает, это слишком скучно. Ну так давай сделаем управление персонажем!Что нам для этого понадобится? Нам нужен скрипт, который будет обрабатывать нажатия клавиш с клавиатуры, двигать персонажа, проигрывать анимацию. Но давай пойдем по порядку и начнем с самого простого управления.

Простое управление.Простое управление.

Пишем вот такой код, не волнуйся сейчас все объясню. Первая строчка объявляет Godot, что мы используем объект KinematicBody2D. Ее создал сам движок. На 3 и 4 строчке мы задаем две константы, отвечающие за ускорение и максимальную скорость. Они нужны для плавного перемещения персонажа по сцене. На 6 строчке объявляем переменную для вектора перемещения. После этого на 8 строчке создаем функцию physicsprocess, это системная функция движка. Она нужна, чтобы привязать к персонажу физику. В нашем случае - это физика перемещения и сила гравитации. 9 строчка отвечает за управление по оси X. Метод Input помогает нам считывать те самые кнопки для управления (стрелка влево и стрелка вправо). После на 11 строчке мы проверяем была ли нажата какая-то кнопка. Потом мы перемещаемся влево или вправо.

Как ты заметил, мы прибавляем к координате игрока произведение направления по координате на ускорение и на какую-то delta. Вопрос, что такое delta? Delta показывает сколько времени (в секундах, тип float) прошло с момента отрисовки прошлого кадра.Зачем это сделано? Если мы не будем привязывать передвижение игрока ко времени, то оно автоматически привязывается к частоте процессора. На крутых компьютерах или телефонах разница незаметна, но запустив приложение на старом пк или телефоне, ты все поймешь. Поэтому всегда привязывай передвижение к delta!

Потом в строке 13 мы используем какой-то clamp. Опять неразбериха! Все просто, clamp, как можно догадаться из названия, сжимает значение переменной. Сделано это для оптимизации и плавности движения.Ну и в последней строке мы просто запускаем передвижение нашего игрока. Не так уж все и сложно!

8. Первый запуск.

Вот сделали мы все это с тобой, а где результат? Ну так давай поскорее запустим с тобой первую демку! Все очень просто, нажми клавишу F5, после этого выплывет окно, которое скажет тебе, что основания сцена не выбрана. В нашем случае основная сцена World.tscn. Выбираем ее и снова жмем F5. Должно появиться что-то такое:

Окно демки.Окно демки.

В верхнем левом углу можно заметить маленькую часть нашего персонажа. Давай приведем все в порядок. Для этого сначала закрое окошко демки и перейдем в настройки проекта. Чтобы это сделать, в левой верхней части нажми на Проект, а в выплывшем окне нажми Настройки проекта. Здесь переходим в вкладку Window и ставим разрешение на 320x180. Почему такое маленькое? Все просто, мы с тобой задали разрешение экрана в самой сцене, для платформера такие размеры идеальны. А для экрана самой демки нужно задать нормальное разрешение. Это можно сделать в пунктах Test Width и Test Height. Я задам его в формате 1280x720. Спустимся пониже и в пункте Mode ставим 2d, а в Aspect ставим keep. Для красоты предлагаю обратно перейти на сцену и передвинуть персонажа в середину экрана. Делается это легко, просто зажми персонажа левой кнопкой мыши и начни перетаскивать. Теперь все приготовления закончены,можно запускать демку.

Красота, правда? Попробуй передвигать персонажа стрелками на клавиатур. Получилось? Да, но персонаж будто скользит по экрану и не может остановиться. Не волнуйся, скоро мы это исправим. Однако сейчас наш персонаж как бы висит в воздухе, это ней есть хорошо. Давай сделаем землю для нашего игрока!

9.Tilemaps

Что такое Tilemap? Тайлы это плитки, вместе образующие сетку тайлов. Чаще всего они принимают форму квадратов. Как же их добавить в наш платформер? Очень просто, для начала выбери объект World(нашу основную сцену), нажми клавиши ctrl + A и выбери TileMap.

Теперь в этом окошке выбири Tile Set и нажми Новый TileSet.Снова нажми на TileSet, должно получиться ка-то так:

Добавляем анимацию.Добавляем анимацию.

Давай добавим спрайт для нашего tilemap, для этого нажми на плюс снизу и выбери tile.png.

Следующий шаг будет довольно сложным, поэтому слушай внимательно.Итак, в вкладке Регион полостью выделяем нашу картинку, в вкалдке snap options ставим step по x и y на 16. Такие же действия повторяем в вкладках столкновение, перекрытие, навигация, битовая маска. А последней мы остановимся поподробней.

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

Задаем границы тайла.Задаем границы тайла.

Отлично, сохраняем все и переходим обратно на сцену. Еще рах кликаем на Tilemap и в раздеел Cell меняем size на 16x16.Теперь можно делать уровень!

Создаем простой уровень.Создаем простой уровень.

Вот как у меня получилось. Супер, но на нашего игрока до сих пор не действует гравитация, давай это исправим. Для этого перейдем в скрипт player и введем там такой код.

Константы для прыжка и гравитации.Константы для прыжка и гравитации.

Здесь к существующим переменным мы добавляем friction, gravity, jumpforce, airresistance. Названия говорят сами за себя, поэтому объяснять за что они отвечают я не буду.

Реализация прыжка и гравитации.Реализация прыжка и гравитации.

Следом идет сама сила гравитации. Мы прибавляем к motion.y силу тяжести, умноженную на delta. Это действие заставляет нашего игрока падать вниз, если под ним ничего нет. После этого скрипт обрабатывает нажатия на кнопки, характерные для прыжка (стрелочка вверх). И заставляет игрока падать вниз, когда он уже прыгнул.

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

Как выглядит при запуске.Как выглядит при запуске.

10.Анимации

Простые анимации в Godot сделать очень легко. Для этого перейдем на сцену player и добавим туда AnimationPlayer. Жмем на кнопку анимация, далее жмем новый и вводим название анимации. Сделаю анимацию для бега и назову ее Run.Чтобы добавить новый кадр для анимации нужно перейти в sprite.

Добавляем кадры в анимацию.Добавляем кадры в анимацию.

Напротив пункта frame есть клчик,если нажать на него, то кадр из спрайта добавиться в анимацию. Постепенно увеличиваем frame от 0 до 8 и ключиком добавляем кадр в анимацию. Вот как в итоге это должно выглядеть:

Создаем анимацию из кадров.Создаем анимацию из кадров.

Тоже самое повторяем для других анимаций, просто меняя номер кадра. В итоге у тебя будет несколько анимаций для прыжка, ходьбы, и анимация idle. Теперь все это нужно добавить в код.Переходим в код player и вносим некоторые изменения:

Добавляем переменные для анимации.Добавляем переменные для анимации.

Добавляем две переменные sprite и player. Но ты заметил, они какие-то странные. Почему в начале стоит слово onready, что за странное значение этой переменной? Сейчас все объясню. Переменные типа onready нужны для взаимодействий с другими объектами на сцене. В данном случае мы подключаем их для воспроизведения анимации и получения спрайта игрока.

Анимация при ходьбе.Анимация при ходьбе.

На 16-ой строчке мы проигрываем анимацию ходьбы. Однако здесь еще появилась какая-то странная 22 строчка, что она делает? Она зеркально отражает анимацию игрока в зависимости от того, куда он идет. А на 24 строке мы говорим, что если игрок стоит, то проигрывать нужно анимацию idle.

Анимация прыжка.Анимация прыжка.

На 22 строчке мы проигрываем анимацию прыжка, если игрок не на земле. Вот собственно и все изменения в коде.

Заключение

Если ты все правильно делал, то у тебя должен получиться простой платформер. Что делать дальше? Да все что угодно! Улучшай свои навыки в использовании движка, создавай свои собственные игры изучай новые фишки. А этом я вынужден с тобой проститься, надеюсь ты хорошо провел время и научился чему-то новому.

Вот все материалы для этого туториала:

Подробнее..

Rocket Lab титановый гном в космосе и мягкая посадка

23.11.2020 02:14:32 | Автор: admin
В пятницу в 15:20:01 по новозеландскому времени с частного космодрома Rocket Lab на полуострове Махия, расположенном на восточном побережье Северного острова Новой Зеландии, стартовала РН Electron в рамках миссии с символичным названием Вернуть отправителю, так как это был первый раз, когда ракета Electron взлетела с парашютами и вспомогательными системами на борту, и первая попытка выполнить полную серию маневров контролируемого спуска.



Первая ступень Electron на своем пути к Земле успешно совершила следующие запланированные маневры:
  • Примерно через 2.5 минуты после старта на высоте около 80 км первая и вторая ступени Electron разделятся в соответствии со стандартной процедурой полета. Вторая ступень Electron продолжает движение к орбите, где разгонный блок разведет спутники на свои орбиты.
  • Теперь, когда двигатели на первой ступени Electron выключены, система управления реакцией развернет ступень на 180 градусов, чтобы направить ее под идеальным углом для входа, чтобы она могла выдержать невероятную температуру и давление воздуха во время его спуска на Землю, известные как The wall.
  • После замедления до скорости <2 Махов тормозной парашют будет развернут для увеличения сопротивления и стабилизации первой ступени при спуске.
  • На последних километрах спуска будет развернут основной парашют, чтобы еще больше замедлить ступень и обеспечить контролируемое приводнение.
  • Судно Rocket Lab встретится со ступенью после приводнения и заберет ее для транспортировки обратно в производственный комплекс Rocket Lab для проверки.


Rocket Lab стала всего лишь второй частной компанией, вернувшей на Землю ракету-носитель орбитального класса в целости и сохранности. Ступень из углеродного композита приводнилась в нескольких сотнях миль от стартовой площадки Rocket Lab в Новой Зеландии.



Спасательная бригада, дислоцировашаяся в Тихом океане, оперативно прибыла к месту посадки, чтобы не дать ступени затонуть, затем погрузили ее на судно и отправиться обратно на Ново-Зеландскую фабрику для проверки состояния первой ступени.

Успешное приводнение первой ступени Electron приблизило калифорнийскую Rocket Lab (компания имеет офис в Калифорнии) к повторному использованию ракетных ускорителей, что, по словам компании, позволит запускать миссии с большей частотой и потенциально сократить расходы. Изначальные планы подразумевают 100 пусков год, при этом молодая компания в этот непростой год уже совершила 6 запусков.

Разработанная для вывода на орбиту небольших спутников, ракета Электрон частной разработки совершила 16 пусков, включая миссию в четверг. В конце прошлого года Rocket Lab оснастила ускорители Electron приборами для изучения тепловых, аэродинамических и структурных нагрузок, с которыми ступень сталкивается при входе в атмосферу.



Почему гном? Геймеры могут узнать в фигурке гнома Чомпски из игры Half-Life 2: Episode 2, где имеется задание перетащить гнома через все уровни игры и в конце посадить на ракету, чтобы запустить в космос. Этот же маленький друг полетит на самом деле.

Созданный при поддержке удостоенной множества наград дизайн-студии Weta Workshop, уникальный космический компонент изготовлен аддитивно из титана и напечатан в форме игрового символа Half-Life Гнома Чомпски, пишет Rocket Lab в пресс-релизе для миссии в четверг. Миссия служит данью уважения инновациям и творчеству геймеров во всем мире, а также направлена на тестирование и верификацию новой технологии 3D-печати, которая может быть использована для компонентов будущих космических кораблей. 150-миллиметровый гном останется прикрепленным к разгонному блоку Electron'а и сойдет с орбиты вместе с ней, когда ступень сгорит при входе в атмосферу Земли.
Создатель игры Half-Life Гейб Ньюэлл из Valve пожертвует по 1 доллару отделению педиатрической интенсивной терапии Оакленда за каждого зрителя на прямой трансляции запуска.

Запись трансляции запуска миссии Return to sender.

В то время как первая ступень спускалась с парашютом в Тихий океан, вторая ступень Электрона вывела 30 полезных нагрузок и ступень на предварительную переходную орбиту. В течение часа после запуска третья ступень, называемая kick stage зажглась, чтобы вывести небольшие полезные нагрузки на круговую орбиту высотой 310 миль (500 километров).

Два космических аппарата для запуска на Electron были построены Millennium Space Systems, дочерней компанией Boeing, для миссии под названием DragRacer для испытания устройства, вызывающего сопротивление, которое могло бы помочь небольшим спутникам на низкой околоземной орбите быстрее сойти с нее. Это устройство называется лентой терминатора (Terminator Tape). Лента, разработанная компанией Tethers Unlimited, имеет ширину всего 5-7 см, но ее можно разматывать на десятки метров.


Этот Terminator не имеет отношения к Terminator Tape.

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


Оба спутника миссии DragRacer в представлении художника.

Первый спутник Новой Зеландии также вышел на орбиту благодаря ракете Electron. Спроектированный и построенный в Оклендском университете, CubeSat получил название Te Waka miorangi o Aotearoa, что в переводе с английского означает новозеландский спутниковый аппарат (Официально аппарат известен как APSS-1).

Другие полезные нагрузки, запущенные в рамках миссии Rocket Lab в четверг вечером, включают два CubeSat размером с чемодан для французского стартапа UnseenLabs. Спутники Bro-2 и Bro-3, созданные датским производителем малых спутников GomSpace, являются вторыми и третьими спутниками, запущенными UnseenLabs.

Французская компания планирует запустить группировку из 20-25 спутников в течение следующих пяти лет для наблюдения за морскими водами. UnseenLabs заявляет, что ее флот наноспутников сможет обнаруживать и идентифицировать корабли по всему миру, предоставлять услуги слежения для морских операторов и помогать силам безопасности следить за пиратами и контрабандистами.


Представленная инфографика показывает все этапы миссии. Источник: Rocket Lab.

Rocket Lab намеревается в конечном итоге использовать вертолет для захвата ступеней ракет, спускающихся на парашютах, чтобы избегать попадания морской воды. Но Бек сказал перед запуском, что Rocket Lab сначала попытается извлечь ускорители Electron из моря и затем тщательно исследует возвращенный экземпляр, чтобы внести необъодимые изменения в дизайн.

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

Источник
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru