Перейти к содержимому

some blog name

  • записей
    15
  • комментарий
    41
  • просмотров
    17 257

Робот с геосканером. Часть #2 [сканирование]

Doob

666 просмотров

Робот может двигаться, пора добавить функцию сканирования породы и калибровки компаса.

(Пока тестировал, обнаружил баг работы с зачарованными инструментами, пришлось немного переделать функцию step() - теперь после неудачного свинга, робот дополнительно проверяет наличие блока. Можно будет оставить, даже когда разрабы это исправят)

 

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

На расстоянии x8 z8 y1 от геосканера, максимальная плотность бедрока равна -0.317, внесем в фильтр -0.31. Для руды 3.683, но это ванильная руда, в модах бывает и больше. Минимальная плотность обсидиана 49.312, значит, eсли он не нужен, установим для полезных блоков максимальную плотность 40.

C минимальной плотностью не все так гладко. Свинцовая руда из индастриала имеет плотность 2.5 это как у деревянных предметов, разброс с учетом шума от 1.3 до 2.7, это пересекается с камнем, у которого 0.8 - 2.2.

Вот таблица некоторых блоков с минимальной и максимальной плотностью:

Руда      2.312 - 3.683
Стекло   -0.388 - 0.983
Камень    0.812 - 2.183
Грязь    -0.188 - 1.183
Сундук    1.312 - 2.683
Обсидиан 49.312 - 50.683

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

Исходя из этих данных, полезные блоки будут отмечаться с минимальной плотностью 2.3 и максимальной 40

 

Теперь опишем функцию сканирования. Заглянем в подсказку.

Чтобы получить сырые данные, зададим координаты и размеры квадрата, относительно сканера.

geolyzer.scan(позиция_х, позиция_z, позиция_y, ширина, длина, высота)

 

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

Преобразовываем данные в координаты, попутно анализируя плотность условным оператором и устанавливаем метки.

При обнаружении бедрока устанавливаем соответсвующий флаг во внешней для всех функций переменной.

Получаем функцию scan(), выглядеть она будет примерно так:

local function scan(xx, zz) -- сканирование квадрата x8 относительно робота
  local raw, index = geolyzer.scan(xx, zz, -1, 8, 8, 1), 1 -- получить сырые данные, установить индекс в начало таблицы
  for z = zz, zz+7 do -- развертка данных по z
    for x = xx, xx+7 do -- развертка данных по х
      if raw[index] >= 2.3 and raw[index] <= 40 then -- если обнаружен блок с плотностью от 2.3 до 40
        table.insert(WORLD.x, X+x) --| записать метку в список
        table.insert(WORLD.y, Y-1) --| с коррекцией локальных
        table.insert(WORLD.z, Z+z) --| координат геосканера
      elseif raw[index] < -0.31 then -- если обнаружен блок с отрицательной плотностью
        border = true -- сделать отметку
      end
      index = index + 1 -- переход к следующему индексу сырых даннх
    end
  end
end

 

Раз уже взялись за геосканер, напишем и компас.

Чтобы определить стороны света, надо сломать блок перед носом, просканировать его, затем установить обратно и, если есть разница - выдать результат. Для большей надежности добавим вращение вокруг своей оси, т. к. блока перед носом может и не быть или быть, но не тот.

Координаты блоков задаем в таблице, сбрасываем текущее направление, определяем заново, вот и вся функция. Назовем ее compass()

local function compass() -- определение сторон света
  local sides = {{-1,0}, {0,-1}, {1,0}, [0]={0,1}} -- привязка значений сторон света к смежным блокам
  D = nil -- обнуление текущего направления
  while not D do -- пока направление не найдено
    for n = 0, 3 do -- перебор сторон света
      robot.swing(3) -- разрушение блока
      if geolyzer.scan(sides[n][1], sides[n][2], 0, 1, 1, 1)[1] == 0 and robot.place(3) then -- тестовое сканирование и установка блока
        if geolyzer.scan(sides[n][1], sides[n][2], 0, 1, 1, 1)[1] > 0 then -- если обнаружена разница в сканах
          D = n -- установить новое направление
          break -- выйти из цикла
        end
      end
    end
    turn() -- задействовать простой поворот
  end
end

 

Самые важные функции готовы, можно приступить к тестированию.

 

 

 

  • Нравится 5


0 комментариев


Рекомендуемые комментарии

Нет комментариев для отображения

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

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...