2017-07-24 36 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