2

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

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

我已经尝试了很多方法来使用双极坐标和 Trig 来实现这种混乱,但我无法解决计算应该在屏幕上绘制敌人的位置的问题。

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

蓝色是玩家,红色是敌人 绿色代表观点

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

4

1 回答 1

2

如果你想要一个类似 Doom 的视角,你应该把视域想象成一个平行四边形,而不是一个矩形。想象一下,在你的角色背后是一个有自己的位置和角度的摄影师。

相机截锥体

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

//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);
}

这些图表可视化了我在这里使用的变量代表什么:

<code>角度</code>的描绘

在此处输入图像描述

一旦在 [-1, 1] 范围内有了“X 位置”,就应该很容易将其转换为像素坐标。例如,如果您的屏幕是 500 像素宽,您可以执行类似的操作((calculateXPosition(camera, enemy) + 1) / 2) * 500;

编辑:

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

侧视图-相机看着敌人

//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);
}

在此处输入图像描述

您可以调用该方法两次以确定敌人顶部和底部的 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));

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

(除此之外:两种方法中的 frustrumWidths 不需要相同 - 事实上,如果您要绘制的屏幕是矩形,它们应该是不同的。x frustrum 和 y frustrum 的比率应该等于比率屏幕的宽度和高度。)

于 2012-02-28T13:48:32.423 回答