Уважаемые пользователи Голос!
Сайт доступен в режиме «чтение» до сентября 2020 года. Операции с токенами Golos, Cyber можно проводить, используя альтернативные клиенты или через эксплорер Cyberway. Подробности здесь: https://golos.io/@goloscore/operacii-s-tokenami-golos-cyber-1594822432061
С уважением, команда “Голос”
GOLOS
RU
EN
UA
rassen
7 лет назад

Стать программистом. Практика JavaScript для новичков. Занятие 11.

Доброго времени суток, друзья!

В нашем прошлом занятии мы с вами написали функциональность для правильного расположения нашего питомца внутри его «Домика». При разработке этой функциональности мы познакомились с такими свойствами выборки html-элемента, как offsetWidth и offsetHeight, а внутри метода getPosition() закрепили на практике приём множественного присвоения переменных.

Настало время двигаться дальше.

Стать программистом. Практика JavaScript для новичков. Занятие 11.

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

  1. Питомец должен уметь появляться в разных участках своего домика.
  2. Питомец, должен уметь двигаться внутри своего домика. Он должен уметь это делать во всех направлениях (вниз, вверх, влево, вправо) и при этом не должен выходить за пределы.
  3. Питомец должен уметь играть.
  4. Питомец должен уметь спать.
  5. Питомец должен уметь выполнять все доступные ему действия в произвольном порядке, для эмулирования интеллекта.
  6. Питомец должен уметь прекращать выполнение текущего действия и прекращать выполнения всех действий одновременно.

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

Если проанализировать изображение вверху, то получается, что для чтобы муравей двигался вверх/вниз нам следует уменьшать/увеличивать стилевое свойство top, а для того чтобы муравей двигался влево/вправо нам следует уменьшать/увеличивать свойство left.


Внимание! Перед тем как приступить к созданию непосредственно самой функциональности, нам требуется кое-что исправить в стилях. Я заметил, что допустил ошибку в изначальном значении некоторых стилевых свойств html-элемента нашего питомца. При загрузке нашего index.html они выглядят так:

Стрелочками я показал на свойства, которые заданы неверно. Давайте зайдем в наш styles.css (который лежит в папке styles) и скорректируем их значения. Благо это не слишком сложно:

Скорректируйте свой styles.css так же, как на скриншоте.


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

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

Далее, мы создали сам метод startWalk(), который должен приводить нашего муравья в движение. И вот тут давайте разберёмся. Сам метод получился немаленьким (в последствии мы будем его оптимизировать) и достаточно примитивным. Начали мы с того, что добавили нашему методу параметр direction (направление) (Подчеркнут синей линией). Этот параметр должен будет передаваться нашему методу при вызове и будет он строкового типа String. Кроме этого он будет иметь четыре возможных значения: «left (влево)», «right (вправо)», «up (вверх)» и «down (вниз)».

Далее мы создали две переменных (зеленые стрелки) self и timeForWalk. Первая сохранила в себе контекст на нашего питомца. Вторая – это промежуток времени, через который будет меняется нужное нам свойство для движения нашего муравья.

После этого у нас начинается четыре однотипных блока (оранжевые рамки) с условными операторами if(…) {…}, где мы сравниваем текущее значение нашего параметра direction. Каждое значение запускает интервал, ссылка на который сразу же записывается в наше свойство walkInterval. А далее все просто, в зависимости от направления мы оперируем либо со стилевым свойством left (два первых блока), либо со стилевым свойство top (два последних блока). В каждом таком интервале мы сначала создаем переменную (в зависимости от параметра direction эти переменная либо currentLeft либо currentTop). В эту переменную мы сначала записываем текущее значение стиля left или top. Обратите внимание что для это мы используем встроенный метод JavaScript’a – parseInt() (подчеркнут серой линией). Что такое встроенные методы в JavaScript мы знаем из прошлого курса. Зачем нам нужен этот метод? Дело в том, что значение стилей left и top, когда мы достаем их с помощью строки self.selector.style.left хранит в себе не цифру, а строку, которая может выглядеть как «100px» (вместо 100, конечно будет цифра отражающее текущее положение муравья). Но для наших расчетов нам требуется оперировать именно цифрой. Метод parseInt() преобразует это строковое значение в цифру. Давайте покажем его работу в консоли для наглядности:

То есть благодаря такой записи parseInt(self.selector.style.left) мы можем быть уверены что там окажется цифра. Далее на всякий случай мы с помощью условного оператора OR (ИЛИ) мы страхуемся. И если вдруг, по какой-либо наша запись parseInt(self.selector.style.left) или аналогичная ей parseInt(self.selector.style.top) не вернет никакого значения, то в переменную currentLeft либо currentTop вернется ноль. После этого, мы увеличиваем или уменьшаем (в зависимости от направления) одну из этих переменных на единицу и присваиваем новое полученное значение стилевому свойству left или top. Давайте посмотрим, как работает наш метод, и как он меняет стилевое свойство left или top в зависимости от направления.

Когда мы вызываем метод startWalk('right') мы видим что интервал начинает увеличивать стилевой свойство left.

Соответственно, если мы вызовем метод startWalk('left') - интервал будет уменьшать left.

Собственно со свойством top при вызове нашего метода startWalk('down')

либо startWalk('up') будет происходит то же самое.

И наконец, для того чтобы остановить наше движение мы создали метод stopWalk().

Как видите в нем все просто, мы используем уже знакомый нам метод clearInterval() которому передаем наше свойство walkInterval как параметр. В следствие чего, интервал движения будет прерываться. Давайте проверим:

Как видим, всё работает. На текущий момент наш код в функции-родителе (Pet) должен выглядеть следующим образом.

var Pet = function(x, y) {
    this.selector = document.getElementById('pet');
    this.x = x || 0;
    this.y = y || 0;
    this.walkInterval = null;
}

Pet.prototype =  {
    /* Задаем начальную позицию питомца в домике */
    setPosition: function() {
        var x = this.x;
        var y = this.y;
        var petWidth = this.selector.offsetWidth;
        var petHeight = this.selector.offsetHeight;
        var bottomEnd = Booth.getHeight() - petHeight;
        var rightEnd = Booth.getWidth() - petWidth;
        /* проверрим на верхнюю и левую границы домика */
        if( x < 0 ) {
            this.x = x = 0;
        }
        if( y < 0 ) {
            this.y = y = 0;
        }
        /* проверрим на правую и нижнюю границы домика */
        if( x > rightEnd) {
            this.x = x = rightEnd;
        }
        if( y > bottomEnd) {
            this.y = y = bottomEnd;
        }

        this.selector.style.top = y + 'px';
        this.selector.style.left = x + 'px';
    },
    /* передвижение питомца */
    startWalk: function(direction) {
        var self = this;
        var timeForWalk = 50;

        if(direction == 'left') {
            this.walkInterval = setInterval(function() {
                var currentLeft = parseInt(self.selector.style.left) || 0;

                self.selector.style.left = (currentLeft - 1) + 'px';
            }, timeForWalk);
        }

        if(direction == 'right') {
            this.walkInterval = setInterval(function() {
                var currentLeft = parseInt(self.selector.style.left) || 0;

                self.selector.style.left = (currentLeft + 1) + 'px';
            }, timeForWalk);
        }

        if(direction == 'up') {
            this.walkInterval = setInterval(function() {
                var currentTop = parseInt(self.selector.style.top) || 0;

                self.selector.style.top = (currentTop - 1) + 'px';
            }, timeForWalk);
        }

        if(direction == 'down') {
            this.walkInterval = setInterval(function() {
                var currentTop = parseInt(self.selector.style.top) || 0;

                self.selector.style.top = (currentTop + 1) + 'px';
            }, timeForWalk);
        }


    },
    /* остановка питомца */
    stopWalk: function() {
        var self = this;

        clearInterval(self.walkInterval);
    }
}

/* Создаем муравья, используя функцию-родитель */

var ant = new Pet(0, 0);

Итак мы создали метод который заставляет нашего муравья двигаться. Однако в нем есть два слабых момента.

  1. Обратите внимание на код, по сути в нем присутствует очень много строчек одного вида. Как мы знаем, из прошлых занятий, дублирования кода лучше не допускать. Поэтому нам придется каким-то способом оптимизировать его.
  2. Это границы нашего «Домика». Сейчас наш метод startWalk() их попросту не учитывает. И это приведёт к тому, что если не остановить движения муравья вовремя, то рано или поздно он пересечет допустимы границы «Домика», а после этого вообще уедет за пределы видимой области окна браузера. Примерно вот так:

Решением этих двух моментов мы и будет заниматься в следующем занятии.

А на сегодня всё. Продолжение следует…

Ссылки на предыдущие занятия:

Практика JavaScript для новичков. Занятие 1,
Практика JavaScript для новичков. Занятие 2,
Практика JavaScript для новичков. Занятие 3,
Практика JavaScript для новичков. Занятие 4,
Практика JavaScript для новичков. Занятие 5,
Практика JavaScript для новичков. Занятие 6,
Практика JavaScript для новичков. Занятие 7,
Практика JavaScript для новичков. Занятие 8,
Практика JavaScript для новичков. Занятие 9,
Практика JavaScript для новичков. Занятие 10

Ссылки на предыдущий курс:

Урок 1 - Окружение.,
Урок 2 - Некоторые особенности синтаксиса.,
Урок 3 - Переменные.,
Урок 4 - Типы переменных, как основа для их взаимодействия.,
Урок 5 - Операции с переменными одного типа.,
Урок 6 - Операции с переменными одного типа. Часть II.,
Урок 7 - Взаимодействие переменных с разными типами.,
Урок 8 - Взаимодействие переменных разного типа. часть II.,
Урок 9 - Взаимодействие переменных разного типа. Часть III.,
Урок 10 - Другие возможные взаимодействия между переменными.,
Урок 11 - Другие возможные взаимодействия между переменными. Часть II.,
Урок 12 - Другие возможные взаимодействия между переменными. Операторы присваивания.,
Урок 13 - Другие возможные взаимодействия между переменными. Операторы сравнения.,
Урок 14 - Сложные переменные. Array и Object.,
Урок 15 - Условные операторы.,
Урок 16 - Циклы.,
Урок 17 - Циклы. Часть II.,
Урок 18 - Функции.,
Урок 19 - Функции. Часть II.,
Урок 20 - Профилирование. Функции, часть III.,
Урок 21 - Функции, Часть IV. Аргументы.,
Урок 22 - Objects (Объекты).,
Урок 23 - Встроенные функции и объекты.,
Урок 24 - Встроенные функции и Объекты, Часть II. Глобальные функции и переменные.,
Урок 25 - Встроенные функции и Объекты, Часть III. Document Object Model.,
Урок 26 - Встроенные функции и Объекты, Часть III. Document Object Model.
Урок 27 - Встроенные объекты. Объект Style, Events, Часть II.
Урок 28 - Встроенная переменная this. Глобальная и локальная области видимости.
Урок 29 - Объектно-ориентированное Программирование. Введение.
Урок 30 - Объектно-ориентированное Программирование. Часть II. Полиморфизм.
Урок 31 - OОП. Наследование, Часть I. Оператор new.
Урок 32 - ООП. Наследование, Часть II. PROTOTYPE.
Урок 33 - ООП. Часть II. Полиморфизм.
Урок 34 - ООП. Часть III. Инкапсуляция.

0
53.424 GOLOS
На Golos с December 2016
Комментарии (1)
Сортировать по:
Сначала старые