Hackernoon logo

Серия «Кодирование для геймеров»: жертва Адского клинка Сенуа [Part 2] | Хакер полдень

Аватар профиля автора

@надя-ПримакНадя Примак

Инженер-программист и инди-разработчик игр. Креативный Технолог.

В моем последнем Кодирование для геймеров пост, о котором мы говорили тиражирование метра голода в The Long Dark, Сегодняшний пост о репликации функции из Адский клинок: жертва Сенуа, Адский клинок — одно из самых душераздирающих путешествий в душевнобольных, которое я когда-либо видел в видеоиграх. Если вы не играли, я настоятельно рекомендую проверить это. Вам даже не нужно беспокоиться о зависимости, потому что у игры есть конкретное начало, середина и конец. Одним из уникальных аспектов Hellblade является мини-игра-головоломка, которая включает в себя поиск в природе фигуры, которая соответствует форме, вырезанной в различных рунах мира.

(Код вставки) https://www.youtube.com/watch?v=-ACZVGP05iE (/ код вставки)

Я решил воссоздать простую версию этой мини-головоломки с Javascript в Glitch. Вы можете посмотреть на это сразу Вот или сначала попробуй сам. В этом уроке мы будем использовать HTML5 Canvas и ванильный Javascript. Мы загрузим фоновое изображение некоторых деревьев, и пользователь будет контролировать треугольную форму поверх него и попытаться найти, где такая же форма может быть найдена среди деревьев.

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

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

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

теги.

<img id="trees" class="hidden" src="https://cdn.glitch.com/eb083ff0-5e3b-41d0-be19-711a1dcd89f5%2FDSC0063-1024x680.jpg?v=1589402686658"/>
canvas width="800" height="600" style="border:1px solid #d3d3d3;" id="canvas">canvas>
<script>Our Javascript will go here, or in a .js file if you prefer script> 
Затем, чтобы сделать ваше изображение скрытым, вы захотите добавить его в свой

теги.

<style>
.hidden {
  display: none;
}
style>

Не беспокойтесь, даже если изображение скрыто, наше волшебное полотно все равно сможет получить доступ к данным, чтобы отобразить их во всей красе. Чудесно! Теперь наш HTML-файл установлен, и мы можем сосредоточиться на Javascript. Первым шагом является идентификация нашего холста и получение контекста, что позволяет нам запускать функции, чтобы фактически изменить то, что отображается.

let img;
let canvas;

window.onload = function() {
  canvas = document.getElementById("canvas");
  context = canvas.getContext("2d");
  img = document.getElementById("trees");
  context.drawImage(img, 0, 0);
};
Я объявляю переменные изображения, холста и контекста сверху, потому что нам потребуется доступ к ним по всему коду. Иметь

window.onload

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

Затем мы получаем наше изображение и рисуем его на холсте

context.drawImage

, Эта функция берет наше изображение, а затем координаты x и y (которые начинаются с 0 в верхнем левом углу, поэтому в этом случае наше изображение займет весь холст). Если бы наш контекст был в трехмерном пространстве вместо 2d, мы также добавили бы третье значение для нашего индекса z, плоскость перспективы.

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

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

function getPosition(el) {
  var xPosition = 0;
  var yPosition = 0;
 
  while (el) {
    xPosition += (el.offsetLeft - el.scrollLeft + el.clientLeft);
    yPosition += (el.offsetTop - el.scrollTop + el.clientTop);
    el = el.offsetParent;
  }
  return {
    x: xPosition,
    y: yPosition
  };
} 
Эта функция принимает элемент canvas и возвращает координаты x и y холста относительно окна браузера. Мы будем вызывать эту функцию внутри

window.onload

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

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

getPosition

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

let context;
let mouseX = 0;
let mouseY = 0;
let canvasPos;
let img;
let canvas;

window.onload = function() {
  canvas = document.getElementById("canvas");
  canvasPos = getPosition(canvas); // getting our canvas position 
  context = canvas.getContext("2d");
  img = document.getElementById("trees");
  context.drawImage(img, 0, 0);
  canvas.addEventListener("mousemove", setMousePosition, false);
//the line above is listening for when the user moves their mouse, and will call the function "setMousePosition" 
};
Хорошо, теперь у нас есть прослушиватель событий, но этот код не будет работать, потому что функция

setMousePosition

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

window.onload

,

function setMousePosition(e) {
  mouseX = e.clientX - canvasPos.x;
  mouseY = e.clientY - canvasPos.y;
}

Приведенный выше код получит нам текущие координаты мыши пользователя на холсте. Мы передаем e, которое обозначает элемент, который передается в функцию, в данном случае наш элемент canvas. Вычитание происходит для учета смещения положения холста в окне браузера, как упоминалось ранее. Теперь мы можем нарисовать нашу форму!

function setMousePosition(e) { 
  mouseX = e.clientX - canvasPos.x;
  mouseY = e.clientY - canvasPos.y;

  context.beginPath(); // tell canvas you want to begin drawing lines
 
  context.moveTo(mouseX, mouseY); // move where the cursor starts the line 
  context.lineTo(mouseX - 25, mouseY + 125); // draw first line
  context.lineTo(mouseX + 25, mouseY + 125); // draw second line
  
  context.fillStyle = "#FF6A6A"; //set the color
  context.fill(); //fill shape with color
}

Как вы, вероятно, можете сказать из моих комментариев к приведенному выше коду, есть несколько шагов для рисования фигуры. Сначала мы должны сообщить холсту, что хотим нарисовать линии с помощью context.beginPath, а затем нам нужно переместить наш курсор. Поскольку мы хотим, чтобы наш треугольник следовал за мышью, мы перемещаем курсор в те же координаты.

Я хочу, чтобы мой треугольник был немного вытянут, поэтому, когда я определяю конечные координаты моей первой линии, я хочу, чтобы они были чуть чуть левее (-25) и дальше вниз (+125). Чтобы держать мою мышь по центру к вершине моего треугольника, я установил координаты другой линии на ту же величину, но в другом направлении по координате х (+25). Последняя строка возвращается к нашим исходным координатам, поэтому вам не нужно никакого дополнительного кода, чтобы завершить форму треугольника.

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

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

function setMousePosition(e) {
  mouseX = e.clientX - canvasPos.x;
  mouseY = e.clientY - canvasPos.y;

// add the lines below
 
  context.clearRect(0, 0, canvas.width, canvas.height); //clearing canvas
  context.drawImage(img, 10, 10); //drawing our image again since that got cleared out
 
  context.beginPath();
 
    context.moveTo(mouseX, mouseY);
    context.lineTo(mouseX - 25, mouseY + 125);
    context.lineTo(mouseX + 25, mouseY + 125);
  
  context.fillStyle = "#FF6A6A";
  context.fill();
  
}

Функция clearRect принимает четыре значения, координаты x и y, которые определяют верхний левый угол прямоугольника, а также высоту и ширину. Если бы мы предоставили что-то меньшее, чем высота и ширина холста, очистилась бы только часть нашего холста, но мы хотим очистить все это. Конечно, это также очищает наше изображение, поэтому нам нужно снова нарисовать его на холсте. Это все должно произойти перед мы нарисуем наш треугольник, или он будет покрыт нашим изображением.

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

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

setMousePosition

функция.

if(mouseX > 625 && mouseX < 630) {
    if(mouseY > 10 && mouseY < 20) {
      context.fillStyle = #a117f2";
      context.fill();
    }
  }

Здесь мы проверяем наши координаты mouseX и mouseY, чтобы увидеть, совпадают ли они с координатами, где мы знаем, что наша форма находится на изображении. Вы можете заметить, что в координатах x и y есть диапазон в 5 пикселей, потому что на самом деле довольно сложно настроить мышь на 1 или 2 конкретных пикселя.

Я взял на себя смелость выяснить координаты изображения в нашем уроке, но если вы хотите сделать это с другим изображением или другой формой, вам нужно будет добавить несколько операторов console.log в mouseX и mouseY, чтобы вы могли оценить где форма должна изменить цвета.

Я меняю цвет на простой белый, хотя вы, очевидно, можете поменять его на любой другой цвет. Проверьте мою версию на Glitch Вот,

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

Комментарии

Теги

Баннер Noonification

Подпишитесь, чтобы получать ежедневные обзоры лучших технических историй!



Источник: Серия «Кодирование для геймеров»: жертва Адского клинка Сенуа [Part 2] | Хакер полдень


Обратная ссылка при копировании статьи: Серия «Кодирование для геймеров»: жертва Адского клинка Сенуа [Part 2] | Хакер полдень

Leave a comment