2012-05-13 61 views
5

在我的應用程序中,我有一個有腳的角色,我想讓它在我的應用程序中看起來就像站在另一個CCSprite頂部,因爲它在屏幕上移動(動畫)。一切都工作正常除了有一個小的定位問題,我無法弄清楚! 讓我再解釋一下這個問題,當角色位於CCSprite頂部時,看起來好像角色以非常快的間隔向上/向下移動約10個點。當CCSprite在屏幕上顯示動畫時,CCSprite定位問題在其他CCSprite之上?

有沒有人知道爲什麼會發生這種情況?

謝謝!

FINAL EDIT:我只想再次感謝你幫助我完成所有這些。首先,由於帖子太長,我刪除了所有其他修改,如果您需要參考舊版編輯,只需查看我的編輯歷史記錄即可!所以經過大約一個小時的測試,我已經縮小到一個你剛纔提到的問題,if語句檢查角色和地板是否碰撞是不是在遊戲中被調用每次迭代當他們SHOULD(只要他們看UI)循環。

我cocosGameLoop日誌之外,之前所有的碰撞檢測代碼,但在比賽還有loop.f

我也注意到在我NSLogs的模式,你可以看到如下:

2012-05-27 17:00:54.791 App[2769:707] cocosGameLoop 
2012-05-27 17:00:54.811 App[2769:707] cocosGameLoop 
2012-05-27 17:00:54.825 App[2769:707] cocosGameLoop 
2012-05-27 17:00:54.841 App[2769:707] cocosGameLoop 
2012-05-27 17:00:54.858 App[2769:707] cocosGameLoop 
2012-05-27 17:00:54.874 App[2769:707] cocosGameLoop 
2012-05-27 17:00:54.891 App[2769:707] cocosGameLoop 
2012-05-27 17:00:54.908 App[2769:707] cocosGameLoop 
2012-05-27 17:00:54.924 App[2769:707] cocosGameLoop 
2012-05-27 17:00:54.928 App[2769:707] collisiontwo 
2012-05-27 17:00:54.929 App[2769:707] two 
2012-05-27 17:00:54.941 App[2769:707] cocosGameLoop 
2012-05-27 17:00:54.944 App[2769:707] collisiontwo 
2012-05-27 17:00:54.945 App[2769:707] two 
2012-05-27 17:00:54.958 App[2769:707] cocosGameLoop 
2012-05-27 17:00:54.974 App[2769:707] cocosGameLoop 
2012-05-27 17:00:54.991 App[2769:707] cocosGameLoop 
2012-05-27 17:00:55.008 App[2769:707] cocosGameLoop 
2012-05-27 17:00:55.025 App[2769:707] cocosGameLoop 
2012-05-27 17:00:55.043 App[2769:707] cocosGameLoop 
2012-05-27 17:00:55.058 App[2769:707] cocosGameLoop 
2012-05-27 17:00:55.076 App[2769:707] cocosGameLoop 
2012-05-27 17:00:55.078 App[2769:707] collisiontwo 
2012-05-27 17:00:55.078 App[2769:707] two 
2012-05-27 17:00:55.091 App[2769:707] cocosGameLoop 
2012-05-27 17:00:55.094 App[2769:707] collisiontwo 

我也注意到當我NSLog字符Y座標是它停留在幾個interations的相同點(即使它應該是碰撞,所以它將與上面的NSLog中的一堆cocosGameLoop調用重合),然後當它實際上會發生碰撞(以編程方式),它會從Y座標上移約14個點。所以存在大約14個點的抖動。

所以底線是,我怎樣才能讓碰撞代碼被稱爲每次迭代並且不會抖動大約14個點?我不想更改定位點,因爲這會攪亂我的動畫定位等等。無論如何,你推薦什麼?另外請記住,我只使用Box2D進行碰撞檢測,因此我必須將所有內容保存在Cocos2D代碼中。

最後,我認爲我的應用程序中存在舍入點錯誤,因爲重力,但即使當我將值改變爲重力等整數時,它也沒有修復閃爍,因此它是100%問題我上面提到。

無論如何,這是問題的核心,我認爲你可以看到我無法做到的事情!讓我知道你的想法:)

非常感謝!

+0

對不起,你放在這裏的coe讓我覺得沒有語境。你可以把整個語句不是其他的如果。 – Coder404

+0

我增加了一些代碼來提供更多的上下文。同樣在大的註釋掉線之下,它會從另一個開始,因爲我有其他的if語句用於碰撞檢測,但在這個問題中不相關。 –

+0

您應該可以將Box2d添加到您的標籤(用於增加流量)和 – Coder404

回答

3

看起來很奇怪的第一件事是您在Some other tag collision checking before評論之後檢查標籤。這會更有意義:

else if ((spriteA.tag == 1 && spriteB.tag == 5) || (spriteB.tag == 1 && spriteA.tag == 5)) 
... 
else if ((spriteA.tag == 6 && spriteB.tag == 1) || (spriteB.tag == 6 && spriteA.tag == 1)) 
... 

即,假設您正在測試的碰撞接觸可以按任一順序給出兩個物體 - 例如,對於兩個物體碰撞,比如說角色和地面,接觸聽者可以將身體A和腳作爲身體B,將腳作爲身體A並將腳作爲身體B接地。上面的聲明可以保證無論順序如何,都可以執行相同的條件塊。執行路徑是否可能在兩個else if塊之間振盪,並因此在進入錯誤塊時設置錯誤的位置?好吧,假設那些條件都是正確的(我也不明白,因爲我不知道標籤所指的是什麼物體,接收者是如何設置的等等),那麼振盪必須由物理模擬引起。使用Box2D在Cocos2d中設置CCSprite的位置時會發生什麼?設置精靈的位置是否也會改變物理體的位置,還是兩者是分開的(精靈通常在物理體的位置渲染)?自從我使用Cocos2d以來,這已經有一段時間了,從早期開始它就發生了很大的變化,所以我不確定這一點,而不打開最新版本並查看。如果改變CCSprite的位置也會改變物理體的位置,那麼這是一件壞事 - 所有的運動都應該由物理模擬來控制(所以如果你想移動一個物理體,你應該是施加一個力量或衝動,而不是直接設置位置)。在物理模擬的下一步運行時,改變物理體外的位置可能會導致振盪或不正確的脈衝應用於物體。如果你想改變精靈的位置而不擾亂物理模擬,那麼考慮從物理模擬中刪除與精靈相關的物理體,直到你想要直接設置位置的所有時間,然後再重新添加它如果你想讓它在物理學下運作。這可能意味着刪除物理主體並在以後重新創建它,如果沒有乾淨的方法將其從物理世界中添加/刪除。

另一種解決方案是在要移動的身體之間創建一個關節。距離連接或焊接接頭將是最合適的。這會導致它們相互連接,所以當你移動它時另一個也會移動,保持兩個物體之間的距離相同。在這種情況下,它們都將在物理模擬下進行。

實際上,剛纔我想到你可能會改變角色和CCSprite的物理實體的位置。在這種情況下,不僅是因爲物理模擬無法控制,而且你的位置計算也可能導致兩個物體輕微重疊,所以當物理模擬接下來運行時,它會對這兩個物體施加很大的力強制它們分開,但是你將位置改回到重疊的位置,這樣下一次更新會再次產生一個強大的力量。

如果你改變CCSprite的位置實際上並沒有改變物理體的位置,並且你基本上只是將玩家的渲染位置設置在與物理體所在的位置不同的位置世界,那麼你需要考慮物理學界正在發生什麼。它是否在滾動,從世界中掉落,在其他物體或其他物體之間擺動?如果不瞭解更多關於遊戲的信息,我很難判斷它會發生什麼。但是它發生的事情可能會影響你的位置計算。考慮從物理世界中移除物理對象,如果你想在精靈周圍移動而不需要物理模擬。在處理物理實體時進行某種調試繪製是非常有用的,所以您可以看到每個實體的確切形狀和位置以及與之交互的內容,而不管您自己的任何精靈或其他藝術作品。不確定Cocos2D/Box2D組合是否提供了這種開箱即用的功能,但如果不是這樣,那麼可以考慮使用它來開啓/關閉它。

一個更需要考慮的事情有兩種說法:

if (spriteA.position.x - spriteA.boundingBox.size.height*.5 <= spriteB.position.x + spriteB.boundingBox.size.height*.5) 

if (spriteB.position.x - spriteB.boundingBox.size.height*.5 <= spriteA.position.x + spriteA.boundingBox.size.height*.5) 

你有沒有試圖消除這兩個語句,讓你設置一個新的位置每一幀,而不是等待對於在幾幀內建立的位置有些錯誤?如果你正在移動一個物體,並且你希望另一個物體如同牢固地連接一樣移動,那麼你會想要每一幀更新位置。這可能是因爲你只能通過這種有條件的說法,即每30幀中有10幀,所以假設30幀/秒,這會產生一個非常明顯的干擾運動,而不是你想要的平滑運動。

希望上面提到的東西解決了您的問題,或者至少讓您更好地瞭解從哪裏開始尋找。提供了更多的信息在你的問題 - 或許是應對一些我所提到的假設/未知的 - 應該幫助我們得到你的問題:)

編輯1

感謝您填寫我們的底與額外的細節 - 使事情更清晰。現在你所做的事情總是有意義的,因爲我知道你只是在用Box2D進行碰撞檢測。

我想說,要解決您的問題,在您的for循環中查看聯繫人,您發現已建立聯繫的地方,您應該設置一個標誌,而不是在此處更改角色的位置例如BOOL characterOnPlatform - 檢測到聯繫時將其設置爲YES。除了for循環之外(不一定採用相同的方法 - 它可以是任何稱爲每幀的地方,並且最有意義的地方),您將檢查該標誌,並且如果characterOnPlatfom == YES,則將該字符的位置設置爲位置計算您目前正在聯繫偵聽器for循環中執行操作。即不要在接觸監聽器for循環中做任何事情,除了改變某些你會在其他地方引用的狀態。

這種改變會讓你的角色與平臺完全一致。如果你仍然希望角色能夠跳出平臺,那麼如果玩家進行跳躍等輸入,則需要將該標誌設置回NO,否則他們所需的移動將被我們強制將其強制置於某個位置在平臺上。

EDIT 2

這不是真的有可能,看看到底是怎麼回事你的新代碼。例如,您的resetgravity方法中發生了什麼?你如何將hasCollided設置爲NO(即,如何檢測角色不再在平臺上)?你的角色仍然在上下運動,或者你提到的與之前不同的閃爍?

假設你仍然得到上下運動,我仍然認爲這可能是由於你發佈的代碼沒有被調用每一幀,或者它與其他一些定位代碼(例如,無論你移動角色以響應玩家的輸入,你在哪裏施加重力等)。

請確保在平臺上保留角色的代碼沒有將位置設置得太高,並導致角色被檢測爲不在平臺上,因爲這樣您最終會陷入惡性循環:

  • 字符與平臺相撞
  • 字符位置被設置爲正上方平臺
  • 字符不再與平臺相撞,所以定位代碼不能運行重新定位他在平臺上
  • 性格屬於向下應有對重力的影響(或者無論你模擬這一點)
  • 字符與平臺
  • 碰撞...

如果是這樣的話,那麼你就需要改善時,字符不是碰撞檢測與平臺,或偏移您的定位代碼,以便角色保持與平臺稍微交叉(不是如果這看起來很糟糕的視覺,你可能想稍微偏離Box2D的形狀,使物理主體與平臺稍微相交但角色的腳似乎恰好在平臺上。

編輯3

這聽起來像你已經排除了很多的東西,可能會造成抖動!我問另一位遊戲開發者,他建議說,你的問題可能是由世界空間轉換爲屏幕空間造成的。因此,您可以嘗試註銷角色的世界位置,以及渲染它的屏幕位置(這可能意味着在Cocos2D中更改此轉換完成的代碼)。至少看看註銷的值可能有助於縮小抖動/振盪的一些值。您還可以查找可能引入的任何舍入點錯誤,例如將浮點精度截斷爲整數。如果你的抖動看起來像是隻有+或 - 1像素的區域,那麼它可能很值得關注世界位置和屏幕位置。記錄這些值比每幀停止調試器要容易得多。

+0

查看我的edit1以上! –

+0

在我的回答中提供了額外的詳細信息以迴應您的額外細節:) –

+0

另外我想補充一點,當角色在平臺上時,它仍然能夠在它上面移動時左右移動。它應該仍然能夠移動和下降,只要它想基於用戶輸入。 –