简体   繁体   English

如何使物体指向鼠标

[英]How to make an object point at mouse

I have a simple sword image (drawn pointing up) that is in an 'open world' game setting, so the player can move around the world to all coordinates. 我在“开放世界”游戏环境中有一个简单的剑图像(朝上绘制),因此玩家可以在世界各地移动到所有坐标。 I would like the sword to point at the mouse. 我想把剑对准鼠标。

My issue (I think) is that the world coordinates and webpage coordinates do not match up. 我的问题(我认为)是世界坐标和网页坐标不匹配。 For example, the player could be at location (6000, 6000), while the mouse coordinates would only be between 0 and 1600 (or whatever the width of the screen is). 例如,播放器可能在位置(6000,6000),而鼠标坐标只能在0到1600之间(或屏幕的宽度如何)。 On top of that, the webpage won't always exist in the same place. 最重要的是,网页不会总是存在于同一位置。

Thoughts so far: 思念至今:

So I need to calculate the position of the mouse relative to the canvas, or vice versa. 因此,我需要计算鼠标相对于画布的位置,反之亦然。

Formula I was using. 我正在使用的公式。 This worked in an older project of mine for XNA: 这在XNA的一个旧项目中起作用:

var xdir = mouse.x - swordcenter.x;
var ydir = mouse.y - swordcenter.y;

var theta = (Math.atan2( ydir, xdir ) - Math.PI/2.0) * (180.0/Math.PI);

I feel like the solution should be simpler than what I'm thinking, but no formula has been working so far. 我觉得解决方案应该比我想的要简单,但是到目前为止,还没有公式能起作用。 Any ideas? 有任何想法吗?

So the question I suppose is why isn't this working? 所以我想的问题是为什么这不起作用? And my best guess is because of the difference in coordinates. 我最好的猜测是因为坐标不同。 I can't figure out how to factor it in. 我不知道该如何考虑。

Edit: I have figured out how to factor it in. With the following code, the mouse position is put in to game coordinates. 编辑:我已经弄清楚了如何将其分解。使用以下代码,鼠标位置将放入游戏坐标。 So if the mouse hovers over the player, then the mouse pos and player pos are equal. 因此,如果鼠标悬停在播放器上方,则鼠标pos和播放器pos相等。 However, the image still spins rapidly with the mouse movement. 但是,图像仍会随着鼠标移动而快速旋转。

document.addEventListener('mousemove', function(e){ 

    mouse.x = e.clientX || e.pageX; 
    mouse.y = e.clientY || e.pageY; 

    var view = document.getElementById('viewport');
    var rect = view.getBoundingClientRect();

    mouse.x -=  rect.left;
    mouse.y -=  rect.top;

    var camX = clamp(x - canvas.width/2, -1000, 1000 - canvas.width);
    var camY = clamp(y - canvas.height/2, -1000, 1000 - canvas.height);

    mouse.x += camX;
    mouse.y += camY;

}, false);

Edit 2: Here is how I get the angle: 编辑2: 这是我如何获得角度:

var getAngle = function() {

    var xdir = mouse.x - x;//where x and y are the sword center
    var ydir = mouse.y - y;

    var theta = Math.atan2( ydir, xdir  ) * (180.0/Math.PI);     

    return theta;
}

Edit 3: Here is how I draw the image: 编辑3: 这是我绘制图像的方式:

var draw = function(ctx) {

    ctx.fillRect(x-15, y-15, 30, 30);//background player rect

    ctx.save();
    ctx.translate(x, y);//x and y is the center of the sword/player     
    ctx.rotate(getAngle());     

    //this correctly draws the sword on top of the player rect, except for rotation
    ctx.drawImage(stanceTexture, -stanceTexture.width/2, -stanceTexture.height/2);

    ctx.restore();
};

You don't need trigonometry for that. 您不需要三角函数。 Basic vector calculus is enough: 基本的矢量演算就足够了:

const sword_length = 10;

var sword_x_start = 0; 
var sword_y_start = 0;

var mouse_x = ...;  // current mouse position
var mouse_y = ...;

var dx = (mouse_x - sword_x_start); 
var dy = (mouse_y - sword_y_start);

// sword to mouse distance 
var length = Math.sqrt( dx*dx + dy*dy );

// unit vector, see: http://en.wikipedia.org/wiki/Unit_vector 
// in sword to mouse direction: 
var unit_v_x = dx / length;
var unit_v_y = dy / length;

// and now coordinates of the sword pointing to mouse:
var sword_x_end = sword_x_start + unit_v_x * sword_length ;
var sword_y_end = sword_y_start + unit_v_y * sword_length ;

After all the additional math done to compute the correct "in-game" mouse location, it turns out that my canvas context wanted radians as well. 在完成所有其他数学运算以计算正确的“游戏中”鼠标位置之后,事实证明,我的画布上下文也需要弧度 Much confuse. 太混乱了。 Every other post I found regarding this turns the value back into degrees ( WRONG ) so I hope this helps someone else out. 我发现的其他与此相关的帖子都会将值重新转换为度数( WRONG ),所以我希望这对其他人有所帮助。 So here is the complete answer, 所以这是完整的答案,

document.addEventListener('mousemove', function(e){ 

    mouse.x = e.clientX || e.pageX; 
    mouse.y = e.clientY || e.pageY; 

    var view = document.getElementById('viewport');
    var rect = view.getBoundingClientRect();

    mouse.x -=  rect.left;
    mouse.y -=  rect.top;

    var camX = clamp(x - canvas.width/2, world.minX, world.maxX - canvas.width);
    var camY = clamp(y - canvas.height/2, world.minY, world.maxX - canvas.height);

    mouse.x += camX;
    mouse.y += camY;

}, false);


var getAngle = function() {

    var xdir = mouse.x - x;//where x and y are the sword center
    var ydir = mouse.y - y;

    //Note: I only subtract Math.PI/2 to flip the image 180 degrees.
    //      The value to subtract will depend on the original angle of your image
    var theta = Math.atan2( ydir, xdir  ) - Math.PI/2.0;     

    return theta;
}

var draw = function(ctx) {

    ctx.fillRect(x-15, y-15, 30, 30);//background player rect

    ctx.save();
    ctx.translate(x, y);//x and y is the center of the sword/player     
    ctx.rotate(getAngle());     

    //this correctly draws the sword on top of the player rect, except for rotation
    ctx.drawImage(stanceTexture, -stanceTexture.width/2, -stanceTexture.height/2);

    ctx.restore();
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM