Мышь контролируется движением первого лица JS
Я пытаюсь реализовать движение первого лица с помощью мыши.
У меня есть работа с клавиатурой, но у меня возникают трудности с ее использованием с помощью мыши, поскольку перемещение на определенную сторону не так ясно (например, перемещение влево может включать перемещение вверх или вниз).
Я хочу использовать matrix3d
для получения измененных значений позиции.
EDIT # 2 Вот jsfiddle.
EDIT Я вставил новый код, который мне удалось решить:
$(document).on('mousemove', function (e) {
var MOVE = 10; // how much to move
var XTURN = 1; // how much to rotate
var YTURN = 1; // how much to rotate
var transformer, origMat, translationMatrix, result;
transformer = document.getElementById("transformer");
if ($.browser.webkit)
origMat = new WebKitCSSMatrix(window.getComputedStyle(transformer).webkitTransform);
//turn left
if (e.pageX < xPrev) {
if (XTURN < 0) {
XTURN *= -1;
}
xPrev = e.pageX;
//turn right
} else {
if (XTURN > 0) {
XTURN *= -1;
}
xPrev = e.pageX;
}
//look up
if (e.pageY < yPrev) {
if (YTURN < 0) {
YTURN *= -1;
}
yPrev = e.pageY;
//look down
} else {
if (YTURN > 0) {
YTURN *= -1;
}
yPrev = e.pageY;
}
translationMatrix = new WebKitCSSMatrix("matrix3d(" + cos(XTURN).toFixed(10) + ",0," + sin(XTURN).toFixed(10) + ",0,0,"+ cos(-YTURN).toFixed(10) +","+ sin(YTURN).toFixed(10) +",0, " + sin(-XTURN).toFixed(10) + ","+ sin(-YTURN).toFixed(10) +"," + cos(XTURN).toFixed(10) + ",0,0,0,0,1)");
transformer.style.webkitTransform = translationMatrix.multiply(origMat).toString();
});
Как вы можете видеть (Извините за матрицу с одной строкой), я указываю изменения поворотов X и Y при одном и том же изменении матрицы, а затем фиксируя это, теперь проблема связана с cos(XTURN).toFixed(10)
, которая может быть связана к поворотам X и Y, поэтому вы можете видеть, что это работает, но не идеально.
Почитал бы любые советы/идеи.
P.S Я не хочу использовать API-указатель указателей, хотя это здорово, так как я хочу, чтобы он поддерживал максимальное количество браузеров.
Ответы
Ответ 1
Чистый JavaScript в основном лучше, чем библиотеки (если только это не означает "Code less do more" ),
так как вы можете понять, что действительно делает ваш код.
Это мой весь код JavaScript:
var velocity = 0.5;
document.onmousemove = function(e) {
var angleX = e.pageY * velocity * Math.PI / 180;
var angleY = e.pageX * velocity * Math.PI / 180;
document.getElementById('transformer').style.webkitTransform = 'matrix3d(' + Math.cos(-angleY) + ',0,' + Math.sin(-angleY) + ',0,' + (Math.sin(angleX)*Math.sin(-angleY)) + ',' + Math.cos(angleX) + ',' + (-Math.sin(angleX)*Math.cos(-angleY)) + ',0,' + (-Math.cos(angleX)*Math.sin(-angleY)) + ',' + Math.sin(angleX) + ',' + (Math.cos(angleX)*Math.cos(-angleY)) + ',0,0,0,0,1)';
};
И это скрипка.
Это работает!
(Я даже сделал пример этого с помощью API-указателей с указателем: fiddle (нажмите квадрат для начала)
Пояснение:
Во-первых, переменная скорости, чтобы легко установить скорость вращения.
Затем выполняется событие mousemove
, в котором установлены два параметра поворота.
Последняя строка состоит в преобразовании из преобразований rotateX
и rotateY
в matrix3d
по запросу.
fooobar.com/questions/72560/...
rotateX(angleX)
равна следующей матрице:
1 0 0 0
0 cos(angleX) -sin(angleX) 0
0 sin(angleX) cos(angleX) 0
0 0 0 1
rotateY(angleY)
равна следующей матрице:
cos(angleY) 0 sin(angleY) 0
0 1 0 0
-sin(angleY) 0 cos(angleY) 0
0 0 0 1
И чтобы использовать их вместе, вам нужно умножить две матрицы.
Поэтому я написал небольшой инструмент JavaScript, чтобы дать мне расчет, который мне нужно сделать, чтобы получить результат этого умножения.
Результат:
cos(angleY) sin(angleX)*sin(angleY) cos(angleX)*sin(angleY) 0
0 cos(angleX) -sin(angleX) 0
-sin(angleY) sin(angleX)*cos(angleY) cos(angleX)*cos(angleY) 0
0 0 0 1
И это способ преобразования rotateX
и rotateY
в matrix3d
.
Надеюсь, это поможет:)
Ответ 2
Мне не совсем понятно, какова ваша цель на высоком уровне. Похоже, вы пытаетесь реализовать подобную Counterstrike игру в JS и CSS. Это потрясающе! Для остальной части этого ответа я собираюсь предположить, что вы пытаетесь сделать что-то подобное.
Реально, вы должны использовать API блокировки указателей. В противном случае вы не сможете обойтись, только перемещая мышь влево. Вы попадете в край окна браузера и перестанете поворачиваться. Поддержка браузера невелика, но это, безусловно, лучший опыт для геймера!
Чтобы преобразовать ваш мир в CSS-преобразования, вам нужно сделать сложную серию преобразований для генерации матрицы для каждой стороны каждого объекта, видимого в игровом мире. Это связано с тем, что перспектива браузера всегда смотрит прямо вдоль оси Z. Поэтому, чтобы оживить "вокруг" глаз зрителя, вы должны перевести и повернуть их вокруг. После некоторого разговора я пришел к выводу, что выполнение всех преобразований в CSS является чрезмерно медленным (и сложным!). Но никогда не бойтесь, там другой путь! WebGL или Canvas для спасения!
Взгляните на игру Исаака Сукина Nemesis. Это отличный пример, и он написал учебник, чтобы придумать что-то подобное! Библиотека, основанная на ней, Three.js, очень широко используется и имеет очень понятный API. Это занимает почти всю сложную часть, и позволяет вам просто создавать 3D-мир!
Удачи в игре!
Ответ 3
Использование кватернионов действительно проще. Я нашел реализацию в Google закрывающей библиотеке, поэтому я сделал пример (также проверьте jsFiddle):
goog.require('goog.vec.Quaternion');
var velocity = 0.5;
var lastX = null;
var lastY = null;
var angleX = 0;
var angleY = 0;
$(document).on('mousemove', function (e) {
if (lastX == null) lastX = e.pageX;
if (lastY == null) lastY = e.pageY;
angleX += (e.pageX - lastX) * velocity * Math.PI / 180;
angleY += (e.pageY - lastY) * velocity * Math.PI / 180;
lastX = e.pageX;
lastY = e.pageY;
var quat = goog.vec.Quaternion.concat(
goog.vec.Quaternion.fromAngleAxis(angleX, [0, 1, 0], []),
goog.vec.Quaternion.fromAngleAxis(-angleY, [1, 0, 0], []), []);
var matrix = goog.vec.Quaternion.toRotationMatrix4(quat, []);
$("#transformer").css({
webkitTransform: "matrix3d(" + matrix.join(",") + ")"
});
});
Ответ 4
Вот моя конструкция на эту тему, если она кому-нибудь поможет в моей нынешней программе для 3d-моделирования, в ней не хватает только масштаба...: P https://twitter.com/necasjanz Также это мой первый пост о stackoverflow, ожидающий изучения и помогите тоже так весело :).
var objMatrix = [];
var MDN = MDN || {};
MDN.matrixArrayToCssMatrix = function (array) {
return "matrix3d(" + array.join(',') + ")";
}
var angX=Rx,angY=Ry,
MCpx=Math.cos(angX * Math.PI / 180),
MSpx=Math.sin(angX * Math.PI / 180),
MSnx=Math.sin(-angX * Math.PI / 180),
MCpy=Math.cos(angY * Math.PI / 180),
MSpy=Math.sin(angY * Math.PI / 180),
MSny=Math.sin(-angY * Math.PI / 180);
if (matrix==true) {
a1= MCpy,
a2 = MSpx*MSpy,
a3= MCpx*MSpy,
a6 = MCpx,
a7 = MSnx,
a9 = MSny,
a10 = MSpx*MCpy,
a11 = MCpx*MCpy;
}
objMatrix = [
a1, a2, a3, a4,
a5, a6, a7, a8,
a9, a10, a11, a12,
a13, a14, a15, a16
];
return objMatrix;
}
// put this code in to a loop like setInterval or animeframe
matrix(objMatrix); // float matrix
var matrixToCSS = MDN.matrixArrayToCssMatrix( matrix(objMatrix) ); // translate raw matrix to css startdart
obj.style.transform = matrixToCSS; // object to transform