【问题标题】:Rotating a Rectangle around a Grid To Calculate Players View围绕网格旋转矩形以计算玩家视图
【发布时间】:2012-02-28 12:43:59
【问题描述】:

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

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

我已经尝试了很多方法来实现这种与 Bi-Polar 坐标和 Trig 的混淆,但我无法解决计算应在屏幕上绘制敌人的位置的问题。

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

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

【问题讨论】:

    标签: math rotation trigonometry game-development cartesian


    【解决方案1】:

    如果您要使用类似 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);
    }
    

    这些图表可视化了我在这里使用的变量所代表的含义:

    一旦在 [-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 的比率应该相等屏幕宽度和高度的比例。)

    【讨论】:

    • 这真是一个令人难以置信的答案,我自己当然不会得出这样的结论,所以非常感谢。我现在就开始实现它
    • 我已经设法从中获得了 X,但我也在努力获得 Y
    • @Joel,我添加了一些关于计算 Y 坐标的信息。
    猜你喜欢
    • 1970-01-01
    • 2018-08-24
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    • 2023-04-04
    • 2021-11-07
    • 2015-03-29
    相关资源
    最近更新 更多