admin管理员组文章数量:1354751
I'm trying to implement a first person movement using the mouse.
I do have it working with keyboard yet I'm having difficulties implementing it using mouse since movement to a specific side isn't that clear (i.e moving left can include moving up or down).
I want to use the matrix3d
in order to receive changed values of the position.
EDIT #2 Here is a jsfiddle.
EDIT I've pasted the new code I've managed to resolve:
$(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();
});
As you can see (Sorry for the one line matrix) I'm stating the changes of the X and Y rotations on the same matrix change and then mitting it, the issue now is with the cos(XTURN).toFixed(10)
which can be related to the X and Y rotations, so you can see it works but not perfect.
Would appreciate any tips/ideas.
P.S I don't want to use the Pointer Lock API, even though it's great, since I want it to support maximal number of browsers.
I'm trying to implement a first person movement using the mouse.
I do have it working with keyboard yet I'm having difficulties implementing it using mouse since movement to a specific side isn't that clear (i.e moving left can include moving up or down).
I want to use the matrix3d
in order to receive changed values of the position.
EDIT #2 Here is a jsfiddle.
EDIT I've pasted the new code I've managed to resolve:
$(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();
});
As you can see (Sorry for the one line matrix) I'm stating the changes of the X and Y rotations on the same matrix change and then mitting it, the issue now is with the cos(XTURN).toFixed(10)
which can be related to the X and Y rotations, so you can see it works but not perfect.
Would appreciate any tips/ideas.
P.S I don't want to use the Pointer Lock API, even though it's great, since I want it to support maximal number of browsers.
Share Improve this question edited Aug 15, 2013 at 14:42 Shahar Galukman asked Aug 15, 2013 at 11:14 Shahar GalukmanShahar Galukman 9023 gold badges16 silver badges35 bronze badges 4- If you have it working, please post what you change in an answer, or delete the question (the answer would be better). – Brigand Commented Aug 15, 2013 at 14:14
- It's not working as it should be therefore it is not resolved so posting an answer to it would be the wrong thing to do. I've posted an edit of what have changed since my first question. – Shahar Galukman Commented Aug 15, 2013 at 14:16
- Oh, sorry, I misunderstood. I thought you said you resolved it. – Brigand Commented Aug 15, 2013 at 14:20
- 1 Did you had a look at quaternions ? I could try to find some of my old code using this technic if you are interrested. Those are really easier to manipulate with less putation. – IcanDivideBy0 Commented Aug 23, 2013 at 12:24
3 Answers
Reset to default 3 +50Pure JavaScript is mostly better than libraries (unless it's a "Code less do more" thing),
since you can understand what your code really does.
This is my entire JavaScript code:
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)';
};
And this is the fiddle.
It works!
(I even made an example of this using the Pointer Lock API: fiddle (click the square to begin)
Explanation:
First, a velocity variable to easily set the rotation speed.
Then, a mousemove
event which has the two rotation variabls set.
The last line is to convert from rotateX
and rotateY
transformations, to matrix3d
as requested.
This Stackoverflow question helped me get to the following solution.
rotateX(angleX)
is equal to the following matrix:
1 0 0 0
0 cos(angleX) -sin(angleX) 0
0 sin(angleX) cos(angleX) 0
0 0 0 1
rotateY(angleY)
is equal to the following matrix:
cos(angleY) 0 sin(angleY) 0
0 1 0 0
-sin(angleY) 0 cos(angleY) 0
0 0 0 1
And to use them both together, you need to multiply the two matrices. So I wrote a small JavaScript tool to give me the calculation I need to do to get the result of this multiplication.
The result:
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
And that's the way to convert rotateX
and rotateY
to matrix3d
.
Hope it helps :)
It's not quite clear to me what your high level goal is. It sounds like you're trying to implement a Counterstrike-like game in JS and CSS. Which is awesome! For the rest of this answer, I'm going to assume that you are trying to do something like that.
Realistically, you must use the Pointer Lock API. Otherwise, you won't be able to turn around by only moving the mouse left. You'll hit the edge of the browser window and stop turning. The browser support isn't great, but it's by far a better experience for the gamer!
In order to render your world with CSS transforms, you need to do a plicated series of transforms to generate the matrix for every side of every object visible in the game world. This is because the browser's perspective is always looking directly along the Z axis. So in order to animate things "around" the viewer's eye, you have to translate and rotate them around. After a bit of poking around, I came to the conclusion that doing all the transforms in CSS is prohibitively slow (and plicated!). But never fear, there's another way! WebGL or Canvas to the rescue!
Take a look at Isaac Sukin's game Nemesis. It's an excellent example, and he's written a tutorial to e up with something similar! The library it's based on, Three.js, is very widely used and has a very understandable API. It takes almost all of the hard part out, and lets you just make a 3D world!
Good luck with the game!
Using quaternions is really easier. I found an implementation in Google closure library so I made an example (also, check the 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(",") + ")"
});
});
本文标签: javascriptMouse controlled first person movement JSStack Overflow
版权声明:本文标题:javascript - Mouse controlled first person movement JS - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1743937644a2564975.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论