Sin, cos и прочая магия или Куда смотрит игрок?
Sin, cos и прочая магия или Куда смотрит игрок?
В очередной раз я выслушиваю жалобы о том, что математика 8-го класса и всех последующих классов никому не нужна. Особое внимание нежелающие учится обращают на тригонометрию – sin, cos, tg (или tan, амер.), ctg (или cot, амер.). Давайте разберемся внимательнее в этом вопросе и поймем, зачем нам нужны эти страшные, на первый взгляд, функции.
Рассмотрим следующий прямоугольный треугольник:
У нас есть три стороны (логично, не правда ли?), два катета и гипотенуза, прямой угол и два острых угла. Теперь посмотрим, что представляют из себя основные тригонометрические функции:
Синус – отношение противолежащего катета к гипотенузе, sin α = a/c. При этом для каждого значения sin α существует только один острый угол α. Это и используют кодеры для определения углов.
Аналогично, cos α = b/c; tg α = a/b; ctg α = b/a. Это, в принципе, несложно найти и в интернете. Теперь к применению на практике. Для примера нам понадобятся функции Entity.getPitch(entity) и Entity.getYaw(entity).
Entity.getPitch(entity) – возвращает угол наклона головы вверх или вниз, в пределах от -90° до 90°.
Entity.getYaw(entity) – возвращает угол поворота головы, причем он может принимать любое значение, результат возвращается тоже в °.
С помощью этих функций выполним следующие строчки кода:
1 2 3 4 | var player = Player.getEntity(); //для удобства var velX = -1 * Math.sin(getYaw(player) / 180 * Math.PI); var velY = Math.sin((getPitch(player) - 180) / 180 * Math.PI); var velZ = Math.cos(getYaw(player) / 180 * Math.PI); |
В принципе, понимать смысл этих вычислений не нужно, разве что понять, что такое getYaw(player) / 180 * Math.PI (это перевод градусов в радианы).
Важно! Функции sin, cos, tan, cot в Javascript принимают в качестве аргумента число в радианах!
Важно понять, какую величину содержат эти переменные. Ответ прост: смещение. Теперь объясню. Для того, чтобы знать, на какой блок смотрит этот игрок, нужно определить линию, вдоль которой он будет находится. И тут на помощь приходит смещение:
На первый взгляд, сложно, но на самом деле все просто. Чтобы определить, на какой блок смотрит игрок, нужно сначала найти вектор, вдоль которого игрок смотрит. На иллюстрации это луч b. Далее нужно, двигаясь по этому вектору, проверять, нет ли тут блока (воздух, ясное дело, не считается). Для этого будем проверять каждые a долей блока (любое число, меньшее или равное 1, в идеале – 1), не появился ли на этих координатах блок. Если появился – блок наш. Координаты блока получить просто – берем, например, x игрока и прибавляем к нему смещение по оси x, наше velX. Аналогично и с остальными координатами. На картинке эти величины обозначены как ax, ay и az, и мы видим, что это проекции отрезков a на оси координат.
Теперь перейдем к коду, вот он целиком:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | function modTick() { var player = Player.getEntity(); //смещение по осям var velX = -1 * Math.sin(getYaw(player) / 180 * Math.PI); var velY = Math.sin((getPitch(player) - 180) / 180 * Math.PI); var velZ = Math.cos(getYaw(player) / 180 * Math.PI); //координаты игрока var px = Player.getX(); var py = Player.getY(); var pz = Player.getZ(); //проверим 40 раз, это будет блоков 30, хотя я не уверен в точном количестве for(var i = 0; i < 40; i++){ var x = Math.round(px + velX*i); var y = Math.round(py + velY*i); var z = Math.round(pz + velZ*i); var block = getTile(x, y, z); if(block != 0){//если не воздух ModPE.showTipMessage("Looking at (" + x + "," + y + "," + z + " ), id: " + block); break;//выйти из цикла, иначе наш вектор пройдет сквозь блок и пойдет дальше } } } |
Фух, вроде все.
Теперь, в качестве бонуса, хочу вам сообщить, что то смещение, которое мы находили, может служить и для бросания чего-либо в ту сторону, куда смотрит игрок. Воспользуйтесь функциями Entity.setVelX/Y/Z(entity, velocity).
Comments