代码之家  ›  专栏  ›  技术社区  ›  Discoveringmypath

使用spritekit for 2d platformer为移动平台增加了进出便利性

  •  1
  • Discoveringmypath  · 技术社区  · 7 年前

    你好,

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

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


    我面前没有代码,但对于左/右移动的平台,这几乎就是我正在做的。这将在platforms 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 回复  |  直到 7 年前
        1
  •  2
  •   Community leo1    4 年前

    Ease in-out功能

    我们对距离也是这样。平台必须在一个单位的时间内移动一个单位距离。

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

    f(t)=t .所以当时 t=0

    请原谅我的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

    为了方便使用,大多数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) = 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 这是归一化的最大速度(请注意,更准确地说,它是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是 最大速度

    作为代码

    设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

    然后,我们通过只观察运动的一个部分来归一化运动和时间。

    enter image description here

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

    绿线表示ease函数 f(t)=t*t/(t*t+(1-t)*(1-t))

        2
  •  1
  •   Knight0fDragon    7 年前

    你可以这样做:

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

    基本上,当速度增加时,它会产生摩擦力。dx为(<);10,你可以根据自己的喜好调整10