math - 围绕网格旋转矩形来计算玩家 View

标签 math rotation trigonometry game-development cartesian

我有一个可以在 2D 笛卡尔网格周围旋转和移动的玩家,我需要计算在屏幕上绘制敌人的位置。

玩家应该有一个特定的视点,即玩家所面对的方向前面的屏幕大小。 (有点落后)

我尝试了很多方法来使用双极坐标和三角函数来实现这种困惑,但我无法解决计算敌人应该在屏幕上绘制的位置的问题。

这个问题最好以图表的形式表示,绿色是视点,它是一个可以旋转和围绕网格移动的矩形,点代表玩家和敌人。

Blue is player, Red is Enemy Green represents viewpoint

所以我需要计算出屏幕上敌人相对于玩家旋转和位置的位置。

最佳答案

如果您想要类似《毁灭战士》的视角,您应该将查看区域想象为平行四边形,而不是矩形。想象一下,在你的角色后面有一个摄像师,有自己的位置和角度。

The camera frustum

敌人的屏幕位置与摄像机和敌人之间的角度有关。

//indicates where on the screen an enemy should be drawn.
//-1 represents the leftmost part of the screen, 
//and 1 is the rightmost.
//Anything larger or smaller is off the edge of the screen and should not be drawn.
float calculateXPosition(camera, enemy){
    //the camera man can see anything 30 degrees to the left or right of its line of sight. 
    //This number is arbitrary; adjust to your own tastes.
    frustumWidth = 60;

    //the angle between the enemy and the camera, in relation to the x axis.
    angle = atan2(enemy.y - camera.y, enemy.x - camera.x);

    //the angle of the enemy, in relation to the camera's line of sight. If the enemy is on-camera, this should be less than frustumWidth/2.
    objectiveAngle = camera.angle - angle;

    //scale down from [-frustumWidth/2, frustumWidth/2] to [-1, 1]
    return objectiveAngle / (frustrumWidth / 2);
}

这些图表直观地展示了我在这里使用的变量所代表的含义:

depiction of <code>angle</code>

enter image description here

一旦您获得了 [-1, 1] 范围内的“X 位置”,就可以很容易地将其转换为像素坐标。例如,如果您的屏幕宽度为 500 像素,您可以执行类似 ((calculateXPosition(camera,敌人) + 1)/2) * 500;

编辑:

您可以执行类似的操作,根据点的高度和距相机的距离来查找该点的 y 坐标。 (我不确定你应该如何定义敌人和摄像机的高度 - 任何数字都可以,只要它们与笛卡尔网格的 x 和 y 尺寸设置的比例相匹配即可。)

side view - camera looking at enemy

//this gives you a number between -1 and 1, just as calculateXPosition does.
//-1 is the bottom of the screen, 1 is the top.
float getYPosition(pointHeight, cameraHeight, distanceFromCamera){
    frustrumWidth = 60;
    relativeHeight = pointHeight - cameraHeight;
    angle = atan2(relativeHeight, distanceFromCamera);
    return angle / (frustrumWidth / 2);
}

enter image description here

您可以调用该方法两次来确定敌人顶部和底部的 y 位置:

distanceFromCamera = sqrt((enemy.x - camera.x)^2 + (enemy.y - camera.y)^2);
topBoundary = convertToPixels(getYPosition(enemy.height, camera.height, distanceFromCamera));
bottomBoundary = convertToPixels(getYPosition(0, camera.height, distanceFromCamera));

这应该为您提供足够的信息来正确缩放和定位敌人的 Sprite 。

(旁白:两种方法中的截头宽度不需要相同 - 事实上,如果您要绘制的屏幕是矩形,它们应该不同。x 截头和 y 截头的比率应该相等与屏幕的宽度和高度的比例。)

关于math - 围绕网格旋转矩形来计算玩家 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9482141/

相关文章:

java - JSyn:两个 channel 上的正弦波

php - 为自动增量图像的文件系统结构创建算法

安卓大图旋转

c# - 倾斜模型根据加速度统一

ios - 使用 CADisplayLink 的 UIImageView 旋转动画 - 跟踪旋转

c++ - 旋转算法演示

c - 另一个快速三角函数

python - 手动排序 4 个数字

Python 三角函数返回复数?

math - 确定物体跟随者的轨迹 - 追踪曲线