2017-07-24 39 views
1

嗯,您好,使用spritekit为2D移动平台添加轻松入门

我正在使用spritekit为iOS制作2D平台游戏。我有移动的平台,让我的角色与平台一起移动。

我不能只是使用skactions来移动我的平台,因为角色不会随平台一起移动。

问题:
我该如何添加一个轻松进出功能,以获得平台?模拟:SKactionTimeMode.easeInEaseOut

目前的解决方案:
我没有在我面前的代码,但对于左/右移动平台,这是一个很值得我在做什么。这将在平台update()方法中运行。

If platform.position.x < xPositionIWantNodeToStopGoingLeft { 
    velAmount = -velAmount 
} 
else if platform.position.x > xPositionIWantNodeToStopGoingRight { 
    velAmount = -velAmount 
} 
platform.physicsBody?.velocity = SKVector(dx: velAmount, dy: velAmount 
platform.position.y = staticYPosition 

只是为了澄清,这很好。如果有更好的方法来做到这一点,我全部都是耳朵。但是,这会产生锯齿状的停止并转变感觉。我想要这种舒适的感觉,让平台感觉更自然。

感谢您的帮助!

回答

2

数量缓中出功能

如果我们考虑平台作为一个单元从一侧移动到另一侧的时间(可能是10秒,或17帧,这没关系,我们现在单位工作)。

我们对距离做了同样的处理。平台必须在一个单位时间内移动一个单位距离。

对于此回答时间是t和位置是写作为时间的函数f(t)是在时间t平台位置。

对于简单的线性运动,那么功能只是f(t)=t。所以在时间t=0移动的距离是0,在时间0.5(中途)距离是0.5(中途),等等。

所以让我们把它变成更实用的东西。

请原谅我的swift我从来没有使用过它(我相信你可以纠正任何语法错误)。

// First normalise the distance and time (make them one unit long) 
// get the distance 
let distance = Double(xPositionStopGoingLeft - xPositionStopGoingRight); 

// use that and the velocity to get the time to travel 
let timeToTravel = distance/Double(velAmountX); 

// first we have a frame ticker 
gameTick += 1; // that ticks for every frame 

// We can assume that the platform is always moving back and forth 

// Now is the unit time where at now = 2 the platform has move there and back 
// at 3 it has move across again and at 4 back again. 
let now = Double(gameTick)/timeToTravel; // normalize time. 

// get the remainder of 2 as from 0-1 is moving forward and 1-2 is back 
let phase = now % 2.0; 

// We also need the unit time for the function f(t)=t 
let t = abs(phase - 1); 
if phase >= 1 { t = 1 - t } // reverse for return 

// implement the function f(t) = t where f(t) is dist 
let dist = t 

// and convert back to pixel distance 
platform.position.x = Int(dist * distance + Double(xPositionStopGoingLeft)); 

这就是线性平台。为了让运动改变一切,我们需要做的是改变功能f(t)=?,在其行let dist = t

对于出便于上面有是在最方便的应用f(t) = t * t/((t * t) + (1 - t) * (1 - t))

曾经有一个方便的功能是一些t*t哪些是权力,t的权力2或t^2。在迅速其pow(t,2)所以重写如上代码

let dist = pow(t,2)/(pow(t,2) + pow((1-t),2); 

这给出了在开始和结束作为行进的距离和时间的好的易于恒定在中点01​​速度必须更大,以赶上缓慢的开始和结束。 (注意,得到上述函数的导数可以让你在每一个时间点都能测出速度f'(t) = speed(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,但是对于我们需要的最大速度将会这样做)

let maxSpeed = Double(velAmountX + 3)/Double(velAmountX); // 3 pixels per frame faster 

和函数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并且在中途点速度将是一半。为了让所有工作在开始和结束时都更加轻松,将会更快地进入和赶出。 (和作品反向也一样)

为了帮助可能的可视化表示

enter image description here

图像显示平台的来回运动一段时间。距离约为60像素,时间可以是1分钟。所以在1分钟左右就会有一个右边的2分钟,依此类推。

然后,我们通过仅查看运动的一个部分来规范运动和时间。

enter image description here

该图表示从左至右侧移动,距离为1,时间是1。刚刚被缩放以适合单元箱(1由1盒)。

红线代表线性运动f(t)=t(恒速)。在任何时候,你都可以在移动的路线上移动,并且可以找到行驶的距离。

绿线代表缓和功能f(t)=t*t/(t*t+(1-t)*(1-t)),它的工作原理是一样的。在任何时间点扫描找到绿线并向下移动以获得距离。函数f(t)为你做。

随着最高速度,dist 0.5处的线条陡度发生变化,陡峭的坡度代表更快的行程。

+0

谢谢对于深奥的答案...我只是把它扔在那里,这是我的头肯定哈哈。我会花一些时间来研究这一点,以了解发生了什么... – Discoveringmypath

+0

@Discoveringmypath我添加了一个可以帮助您了解解决方案的视觉表示。 – Blindman67

+0

这个答案很棒。 – Fluidity

1

对于物理,玩摩擦和线性阻尼的身体。您甚至可以使用SKAction滑块来减少或增加摩擦力。

,你可以这样做:

physicsBody.friction = (10 - physicsBody.velocity.dx) > 0 ? (10 - physicsBody.velocity.dx)/10 : 0 

基本上它使摩擦时velocity.dx是< 10,你可能要到10调整自己的喜好

+0

我更新了我的问题,我忘记了一行代码并更新了其他2行代码。基本上每次更新,我应用速度,以便它是一个恒定的速度。我喜欢线性阻尼的想法,我可以看到,作为一种减慢速度的好方法,我接近停止点。我绝对忽略了,作为一种选择... – Discoveringmypath

+0

好奇这种情况下摩擦会有帮助吗?因为摩擦更多的是与其他节点接触......而不是减慢平台的速度...... – Discoveringmypath

+0

如果你的身体漂浮在空气中,那么使用linearDamping,如果你的平台在彼此之上,使用摩擦 – Knight0fDragon