旋转的无限/重复世界的数学/计算

Nei*_*ard 9 math cocos2d-iphone game-physics cclayer

如何制作处理旋转的无限/重复世界,就像在这个游戏中一样:

http://bloodfromastone.co.uk/retaliation.html

我通过这样的层次结构编码了我的旋转移动世界:

场景
  - mainLayer(CCLayer)
     - rotationLayer(CCNode)
        - positionLayer(CCNode)

rotationLayer和positionLayer具有相同的大小(现在为4000x4000像素).

我通过旋转rotationLayer来旋转整个世界,并通过移动positionLayer来移动整个世界,这样玩家总是在设备屏幕上保持居中,这是移动和旋转的世界.

现在我想做到这样,如果玩家到达世界的界限(世界被移动,以便世界界限进入与设备屏幕界限接触),那么世界被"包裹"到相反的界限这样世界就是无限的.如果世界不旋转那很容易,但现在它确实如此,我不知道如何做到这一点.我在数学和数学思考方面都很傻,所以我需要一些帮助.

现在我认为我不需要任何与cocos2d-iphone相关的帮助.我需要的是一些方法来计算我的球员是否超出了世界范围,然后以某种方式计算我必须给世界包裹世界的新位置.

我想我必须计算一个圆形的半径,这个圆形将成为我在广场世界中的代工,无论方形世界处于什么角度,都将确保可见的矩形(屏幕)始终位于世界广场.然后我需要一种方法来计算可见的矩形边界是否在边界圆之外,如果是这样的话,我需要一种方法来计算边界圆中的新相对位置以移动世界.所以说明我添加了5张图片.

可见矩形在旋转的方形世界内的边界内部:
可视矩形很好地在旋转的方形世界内的边界内圈

可见矩形的顶部在旋转的方形世界中击中边界圆:
在此输入图像描述

旋转的方形世界移动到相反的垂直位置,以便可见矩形的底部现在在旋转的世界内击中边界:
在此输入图像描述

可见矩形顶部的另一个示例是在旋转的方形世界内点击边界以说明不同的场景:
在此输入图像描述

再次旋转的方形世界移动到相反的垂直位置,以便可见矩形的底部现在在旋转的世界内击中边界:
并再次旋转方形世界移动到相反的垂直位置,以便可见矩形的底部现在击中旋转世界内的边界

在非旋转的情况下移动positionLayer是我弄清楚的数学,正如我所说,只要世界没有旋转,我就可以解决这个问题,但事实确实如此.移动/定位的world/CCNode(positionLayer)位于旋转的world/CCNode(rotationLayer)内.旋转的rotationLayer的锚点始终位于屏幕的中心,但是当移动的positionLayer位于旋转的rotationLayer内时,它会围绕rotationLayer的锚点旋转.然后我迷失了...当我将positionLayer向下移动以使其顶部边框击中屏幕顶部时我需要将该positionLayer包装为JohnPS描述但不是那么简单,我需要将其包裹在基于矢量的矢量中关于rotationLayer CCNode的旋转.这个我不知道该怎么做.

谢谢
Søren

vls*_*lsd 7

就像约翰所说,最简单的事情就是建立一个圆环世界.想象一下,你的船是甜甜圈表面上的一个点,它只能在表面上移动.假设您位于两个圆圈(图片中的红色和紫色)​​相交的点:

圆环上的圆圈.

如果你按照这些圈子进行操作,你最终会在你开始的地方.另外,请注意,无论你如何在表面上移动,你都无法达到"边缘".环面的表面没有这样的东西,这就是为什么它用作无限的2D世界是有用的.它有用的另一个原因是方程非常简单.您可以通过两个角度指定环面上的位置:从紫色圆圈上的"原点"行进的角度,找到红色圆圈以及您在红色圆圈上行进的角度,以找到您感兴趣的点.角度包裹在360度.让我们把两个角度thetaphi.他们是世界上你的船的坐标,你改变什么,当你改变的速度,等你基本上把它们作为你的xy,除了你必须确保始终使用模当你改变它们(你的世界将只有360每个方向的度数,然后将环绕).

现在假设您的船位于坐标(theta_ship,phi_ship)并且有方向gamma_ship.你想绘制一个方形窗口,船的中心和长度/宽度等于整个世界的某个百分比n(假设你只希望一次看到世界的四分之一,那么你就设置n = sqrt(1/4) = 1/2并拥有窗口的长度和宽度设置为n*2*pi = pi).要做到这一点,你需要一个函数,它取一个在屏幕坐标(xy)中表示的点,并吐出世界坐标(thetaphi)中的一个点.例如,如果你问它世界的哪个部分对应(0,0)它应该返回船的坐标(theta_ship,phi_ship).如果船的取向是零(xy将与对齐thetaphi),那么一些协调(x_0,y_0)会对应(theta_ship+k*x_0, phi_ship+k*y_0),在这里k是涉及到如何在世界许多地方可以在屏幕上和边界看到一些比例因子xy.旋转gamma_ship引入了一点触发,详见下面的函数.有关数量的确切定义,请参见图片.!蓝色是屏幕坐标系,红色是世界坐标系和配置变量(描述船在世界上的位置).以世界坐标表示的对象是绿色.

坐标转换函数可能如下所示:

# takes a screen coordinate and returns a world coordinate
function screen2world(x,y)
    # this is the angle between the (x,y) vector and the center of the screen           
    alpha = atan2(x,y); 
    radius = sqrt(x^2 + y^2); # and the distance to the center of the screen

    # this takes into account the rotation of the ship with respect to the torus coords
    beta = alpha - pi/2 + gamma_ship;

    # find the coordinates
    theta = theta_ship + n*radius*cos(beta)/(2*pi);
    phi = phi_ship + n*radius*sin(beta)/(2*pi));

    # return the answer, making sure it is between 0 and 2pi
    return (theta%(2*pi),phi%(2*pi))
Run Code Online (Sandbox Code Playgroud)

我认为,这就是它.数学只是一些相对简单的触发器,你应该做一点绘画来说服自己这是正确的.或者,您可以通过使用旋转矩阵及其更大的兄弟,刚体变换(特殊欧几里得群SE(2))以更自动化的方式获得相同的答案.对于后者,我建议阅读免费在线的Murray,Li,Sastry的前几章.

如果你想做相反的事情(从世界坐标到屏幕坐标),你必须或多或少做同样的事情,但相反:

beta = atan2(phi-phi_ship, theta-theta_ship);
radius = 2*pi*(theta-theta_ship)/(n*cos(beta));
alpha = beta + pi/2 - gamma_ship;
x = radius*cos(alpha);
y = radius*sin(alpha);
Run Code Online (Sandbox Code Playgroud)