Ios 使用spritekit for 2d platformer为移动平台添加轻松进出功能

Ios 使用spritekit for 2d platformer为移动平台添加轻松进出功能,ios,swift,sprite-kit,2d,game-physics,Ios,Swift,Sprite Kit,2d,Game Physics,那么你好, 我正在用spritekit为iOS制作一个2d平台。我有移动平台,允许我的角色随平台移动 我不能只用skactions来移动我的平台,因为角色不会随平台移动 问题: 我将如何添加一个Easy in and out功能,以便拥有这些平台???模拟:SKactionTimeMode.easeInEaseOut 当前解决方案: 我面前没有代码,但对于左/右移动平台,这就是我正在做的。这将在platforms update()方法中运行 If platform.position.xxposi

那么你好,

我正在用spritekit为iOS制作一个2d平台。我有移动平台,允许我的角色随平台移动

我不能只用skactions来移动我的平台,因为角色不会随平台移动

问题:
我将如何添加一个Easy in and out功能,以便拥有这些平台???模拟:SKactionTimeMode.easeInEaseOut

当前解决方案:
我面前没有代码,但对于左/右移动平台,这就是我正在做的。这将在platforms update()方法中运行

If platform.position.xxpositioniwantnodetostoppingright{
velAmount=-velAmount
}
platform.physicsBody?.velocity=SKVector(dx:velAmount,dy:velAmount
platform.position.y=静态位置
澄清一下,这很好用。如果有更好的方法,我洗耳恭听。但这会产生一种锯齿状的停转感觉。我想要那种进出自如的感觉,让平台感觉更自然


感谢您的帮助!!!

对于physic,您可以利用身体的摩擦力和线性阻尼。您甚至可以使用SKAction跑步垫块来减少或增加摩擦力

你可以这样做:

physicsBody.friction = (10 - physicsBody.velocity.dx) > 0 ? (10 - physicsBody.velocity.dx) / 10 : 0
基本上,当velocity.dx小于10时,它会产生摩擦力,您可能需要根据自己的喜好调整10 如果我们考虑平台从一个方向移到另一个单元的时间(可能是10秒,或者17帧,这没关系,我们现在在单位中工作)。 我们对距离也这么做。平台必须在一个单位的时间内移动一个单位的距离

对于这个回答,时间是
t
,位置是时间的函数,写为
f(t)
是时间
t
的平台位置

对于简单的线性运动,则函数为
f(t)=t
。因此,在
t=0时,移动的距离为0,在时间0.5(一半)时,移动的距离为0.5(一半),依此类推

所以,让我们把它变成更实际的东西

请原谅我的swift,我以前从未使用过它(我相信你可以纠正我弄错的任何语法)

这就是线性平台。要改变运动,我们需要做的就是改变函数
f(t)=?
,在上面的行中
let dist=t

为了方便使用,有一个方便的功能可用于大多数ease应用程序
f(t)=t*t/((t*t)+(1-t)*(1-t))

有一些
t*t
是幂,
t
等于2或t^2的幂。在swift中,它的
pow(t,2)
因此将上述内容重写为代码

let dist = pow(t,2) / (pow(t,2) + pow((1-t),2);
这使得开始和结束时非常容易,因为行驶的距离和时间是恒定的。中间点的速度
t=0.5
必须更大才能赶上缓慢的开始和结束。(旁注,获得上述函数的导数可以让你在时间的每个点上锻炼速度
f'(t)=速度(t)=2(-(t-1)t)^(2-1)/(t^2+(1-t)^2^2

这个函数非常好,时间0.5的速度是2,与功率相同(对于线性行程,它应该是1)。这个函数的一个方便的特性是,中间点的速度总是与功率相同。如果你想让它在中点移动得非常快,比如说快4倍,那么你可以使用4的功率

设dist=pow(t,4)/(pow(t,4)+pow((1-t),4)

如果你只想让它加速一点点,比如说中心速度的1.2倍,那么功率是1.2

let dist = pow(t,1.2) / (pow(t,1.2) + pow((1-t),1.2);   
因此,现在我们可以引入另一个术语,
maxSpeed
,它是标准化的maxSpeed(旁注更准确地说,它是t=0.5时的速度,因为它可能比1慢,但出于我们的需要,max speed可以)

函数
f(t)=t^m/(t^m+(1-t)^m)
其中m是
maxSpeed

和作为代码

设dist=pow(t,maxSpeed)/(pow(t,maxSpeed)+pow((1-t),maxSpeed)

把这些放在一起

// the next 3 lines can be constats
let distance = Double(xPositionStopGoingLeft - xPositionStopGoingRight);
let timeToTravel = distance / Double(velAmountX);  
let maxSpeed = Double(velAmountX + 3) / Double(velAmountX);

gameTick += 1; // that ticks for every frame

let now = Double(gameTick) / timeToTravel; // normalize time.    
let phase = now % 2.0;
let t = abs(phase - 1);
if phase >= 1 { t = 1 - t } // reverse for return 

// the next line is the ease function
let dist = pow(t, maxSpeed) / (pow(t, maxSpeed) + pow((1-t) ,maxSpeed);

// position the platform
platform.position.x = Int(dist * distance + Double(xPositionStopGoingLeft));
现在,您可以在任何时间点计算平台的位置。如果您想降低整个游戏的速度,并以半点的速度步进帧,它仍然可以工作。如果您加快游戏速度
gameTick+=2
它仍然可以工作

此外,最大速度可以低于线性速度。如果您希望平台在中心处的速度为正常速度的一半
t=0.5
则设置
maxSpeed=0.5
,而在中间点,速度将为正常速度的一半。为了保持一切正常工作,开始和结束时的轻松程度将更快,即冲入和冲出。(也适用于反转)

也许是为了帮助视觉表现

图中显示了平台在一段时间内的来回移动。距离约为60像素,时间可能为1分钟。因此,在1分钟时,右侧为1分钟,左侧为2分钟,依此类推

然后,我们通过只观察运动的一部分,使运动和时间正常化

该图形表示从左到右的移动,距离为1,时间为1。它刚刚被缩放以适合单位框(1乘1框)

红线表示直线运动
f(t)=t
(恒定速度)。在任何时间点,你移动穿过直线,向下移动,你可以找到移动的距离

绿线表示ease函数
f(t)=t*t/(t*t+(1-t)*(1-t))
,其工作原理相同。在任何时间点,扫描以找到绿线并向下移动以获得距离。函数f(t)为您实现这一点


使用maxSpeed,距离0.5处直线的陡度会发生变化,陡度越大表示行驶速度越快。

我更新了我的问题,忘记了一行代码,并更新了另外两行代码。基本上每次更新,我都应用速度,使其成为恒定速度。我喜欢
let dist = pow(t,1.2) / (pow(t,1.2) + pow((1-t),1.2);   
let maxSpeed = Double(velAmountX + 3) / Double(velAmountX); // 3 pixels per frame faster
// the next 3 lines can be constats
let distance = Double(xPositionStopGoingLeft - xPositionStopGoingRight);
let timeToTravel = distance / Double(velAmountX);  
let maxSpeed = Double(velAmountX + 3) / Double(velAmountX);

gameTick += 1; // that ticks for every frame

let now = Double(gameTick) / timeToTravel; // normalize time.    
let phase = now % 2.0;
let t = abs(phase - 1);
if phase >= 1 { t = 1 - t } // reverse for return 

// the next line is the ease function
let dist = pow(t, maxSpeed) / (pow(t, maxSpeed) + pow((1-t) ,maxSpeed);

// position the platform
platform.position.x = Int(dist * distance + Double(xPositionStopGoingLeft));