close

Collision Detection 碰撞檢測


Collision events 碰撞事件


Physics engine collision events are exposed through the standard Corona event-listener model, with three new event types. For general collision detection, you should listen for an event named "collision". The "collision" event includes phases for "began" and "ended", which signify the moments of initial contact and broken contact. These phases exist for both normal two-body collisions and body-sensor collisions. If you do not implement a "collision" listener, this event will not fire.
物理引擎,碰撞事件暴露通過標準Corona事件偵聽器模型,有三個新的事件類型。對於一般的碰撞檢測,你應該聽的事件名為“碰撞”。在“碰撞“事件,包括階段為“開始“和“結束“,這意味著對初次接觸的瞬間和破碎接觸。這些階段存在正常兩體碰撞和身體碰撞傳感器。如果你沒有實施“碰撞“監聽,這一事件不會觸發。


In addition to "collision" events, two other event types are optionally available whenever two bodies (not sensors) collide. Previously, these were also phases of the "collision" event type, but they have now been separated into unique event types, since they have more specialized uses.
除了“碰撞”事件,另外兩個事件類型可供用戶選擇每當兩個機構(不傳感器)發生碰撞。以前,這些也是階段的“碰撞”事件的類型,但是他們現在已經分成獨特的事件類型,因為他們有更多的專門用途。


"preCollision": an event type that fires right before the objects start to interact. Depending on your game logic, you may wish to detect this event and conditionally override the collision.
“preCollision”:一個正確的觸發事件類型的對象開始之前進行交互。根據你的遊戲邏輯,你不妨檢測此事件,並有條件地覆蓋碰撞。


For example, in a platform game, you may wish to construct “one-sided” platforms that the character can jump vertically through, but only in one direction. You might do this by comparing the character and platform position to see if the character is below the platform, and then using a short timer to make "isSensor" body property temporarily true for the character object so that it passes through the platform. If you do not implement a "preCollision" listener, this event will not fire.
例如,在一個平台上的遊戲,你不妨構建“一邊倒”的平台,垂直跳躍的字符可以通過,但只能在一個方向。你可以這樣做比較的性質和平台的位置,看看下面的字符是平台,然後用很短的計時器,以使“isSensor”身體暫時真實屬性的Character對象,使其穿過平台。如果你不實行“preCollision”聽眾,這一事件不會觸發。


"postCollision": an event type that fires right after the objects have interacted. This is the only event in which the collision force is reported. See the “Collision forces” section below for more on this topic. If you do not implement a "postCollision" listener, this event will not fire.
“postCollision”:一個事件之後觸發類型的對象有互動。這是唯一的事件,其中碰撞力的報導。參見“碰撞力”一節獲得更多關於這個主題。如果你不實行“postCollision”聽眾,這一事件不會觸發。


Note that the “preCollision” events are quite noisy, and may report many times per contact. Therefore, you should only listen for these events if you need pre-collision warnings, and we also recommend that you use local listeners within the objects of interest, rather than listening globally to all "preCollision" events in the world.
請注意,“preCollision”事件是相當嘈雜,可能會報告很多次,每次接觸。因此,你應該只偵聽這些事件,如果您需要預碰撞警告,我們還建議您使用本地聽眾的興趣範圍內的對象,而不是聽全球所有“preCollision”事件在世界上。


Collisions are reported between pairs of objects, and they can be detected either globally, using a Runtime listener, or locally within an object, using a table listener. See the "CollisionDetection" sample code for working examples of global and local collision listeners.
之間的碰撞是對報告的對象,他們可以在全球任何檢測,使用運行時監聽器,或在本地內的對象,使用一個表的傾聽者。參見“CollisionDetection”示例代碼示例工作全局和局部衝突的聽眾。


Global collision listeners全域碰撞監聽

When detected as a Runtime event, each collision event includes event.object1 and event.object2, which contain the table IDs of the two Corona display objects involved.
當作為運行時檢測到的事件,每次碰撞事件包括event.object1和event.object2,其中包含了兩個表IDCorona顯示對象參與。


Because Corona display objects behave like Lua tables, you may freely add any arbitrary data to these tables, such as names, category designators, point values, or even stored functions, and then retrieve this data at collision time. This is similar to the userData attribute in Box2D, but it is essentially unlimited, since you can assign as many custom attributes as you like.
由於Corona顯示對象的Lua的表像,你可以自由添加任意的數據到這些表,如名稱,類別代號,點值,甚至存儲功能,然後檢索這些數據在碰撞時間。這是類似於在Box2D用戶數據屬性,但它本質上是無限的,因為你可以指定多個自定義屬性,你喜歡。


For example, you may wish to store object names in an easily-accessible string format:
例如,您可能希望在一個存儲對象的名稱易於獲取字符串的格式:
-----------------------
local crate1 = display.newImage( "crate.png", 100, 200 )
physics.addBody( crate1, { density = 1.0, friction = 0.3, bounce = 0.2 } )
crate1.myName = "first crate"
 
local crate2 = display.newImage( "crate.png", 100, 120 )
physics.addBody( crate2, { density = 1.0, friction = 0.3, bounce = 0.2 } )
crate2.myName = "second crate"
 
local function onCollision( event )
        if ( event.phase == "began" ) then
 
                print( "began: " .. event.object1.myName .. " & " .. event.object2.myName )
 
        elseif ( event.phase == "ended" ) then
 
                print( "ended: " .. event.object1.myName .. " & " .. event.object2.myName )
 
        end
end
 
Runtime:addEventListener( "collision", onCollision )
--------------------------
Local collision listeners 本地碰撞監聽

When detected with a table listener within an object, each collision event includes event.other, which contains the table ID of the other Corona display object involved in the collision. Again, you may wish to store each object’s name in string format and retrieve it during the collision event:
當檢測到一個表在一個監聽對象,每次碰撞事件包括event.other,其中包含了表中的ID其他Corona顯示對象參與了碰撞。同樣,你可能想存儲每個對象的名稱,字符串格式和檢索它在碰撞事件:
-------------------
local crate1 = display.newImage( "crate.png" )
physics.addBody( crate1, { density=3.0, friction=0.5, bounce=0.3 } )
crate1.myName = "first crate"
 
local crate2 = display.newImage( "crate.png" )
physics.addBody( crate2, { density=3.0, friction=0.5, bounce=0.3 } )
crate2.myName = "second crate"
 
local function onLocalCollision( self, event )
        if ( event.phase == "began" ) then
 
                print( self.myName .. ": collision began with " .. event.other.myName )
 
        elseif ( event.phase == "ended" ) then
 
                print( self.myName .. ": collision ended with " .. event.other.myName )
 
        end
end
 
crate1.collision = onLocalCollision
crate1:addEventListener( "collision", crate1 )
        
crate2.collision = onLocalCollision
crate2:addEventListener( "collision", crate2 )
-------------------
See the "CollisionDetection" sample code for examples of both of these methods. (Run the project using Corona Terminal to see the output of the collisions.)
參見“CollisionDetection“示例代碼例子,這兩種方法。 (運行該項目利用 Corona 終端看到輸出的衝突。)


Collisions with multi-element bodies碰撞的多元素機構

Collision events involving a multi-element body (see "Complex Body Construction") also return the specific body part involved in the collision. This allows for more finely-tuned game logic: for example, you may decide that colliding with the nose of a rocket does more damage than colliding with its tailfins.
碰撞事件涉及多元素機構(見“複合體的建構“)也返回特定的身體部分參與了碰撞。這樣就可以更精細調校的遊戲邏輯:例如,你可以決定撞到火箭的前端比碰撞尾翼 造成的損害還多。


Body elements are identified by a numerical index, where the first element added to the body is given the number 1, the second one is number 2, the third is number 3, and so on.
Body元素是確定一個數字索引,其中第一個元素添加到身體給出數字 1,第二個是數字 2,第三個是3號,依此類推。


For global collision events, two additional integer values are now returned:
對於全球碰撞事件,另外兩個現已返回整數值:
---------------
event.element1
event.element2
---------------


These numerical properties are equal to the index of the elements in object1 and object2 that were involved in the collision. For example, object1 might a rocket with three body elements: nose, body and tail. If the collision is with its tail, the value of event.element1 would be 3; if the collision is with its body, the value of event.element1 would be 2. Again, this number is simply determined by the order in which you declared the elements of the body during its construction.
這些數值性質等同於指數中元素的object1和object2的參與了碰撞。例如,object1可能一火箭三體要素:鼻子,身體和尾巴。如果碰撞是它的尾巴,其價值 event.element1將是3,如果碰撞是與它的身體,其價值 event.element1是2。同樣,這個數字僅僅是確定的順序在其中聲明的元素在其體內的建設。


When collisions involve single-element bodies, both of the above values will always be 1.
當衝突涉及的單元素機構,無論上述值將始終為 1。


Similarly, local collision events (table listeners) now have additional fields:
同樣,本地的碰撞事件(表監聽)現在有額外的字段:

----------------
event.selfElement
event.otherElement
------------------
As above, these values will be 1 in the case of single-element bodies, and in multi-element bodies will range from 1 to the total number of elements in the body, numbered by the order in which the elements were added to the body.
如上所述,這些值將有1例在單元素的體,多元素機構將範圍從 1到總數的元素在體內,編號的順序被添加元素對身體。


Collision forces碰撞力

Once a collision has occurred, you can obtain the direct force of the collision, along with the sideways force between the two objects, which is effectively a frictional force. For example, you may have game objects that should be destroyed only if a collision is sufficiently forceful.
一旦發生碰撞,你可以直接獲得的碰撞力,側向力隨兩個物體之間,這實際上是一個摩擦力。例如,您可能有遊戲對象應該只被銷毀,如果有足夠的有力碰撞。


The direct force of the collision is reported within the "postCollision" event as event.force, and the frictional force is available as event.friction.
直接碰撞力報導在“postCollision“事件為 event.force和摩擦力可作為 event.friction。


-----------------
local function onPostCollision( event )
        if ( event.force > 1.0 ) then
                print( "Collision force: " .. event.force .. " Friction: " .. event.friction )
        end
end
 
Runtime:addEventListener( "postCollision", onPostCollision )
------------------


In the example above, very small forces are screened out. Also, a global listener is used here to simplify the example.
在上面的例子,非常小的力量篩選出。另外,一個全球性的監聽器是用在這裡是簡化的例子。


Since the postCollision event stream from the physics engine can be quite noisy (it registers a series of increasingly tiny forces as objects "settle"), you will probably want to choose your own threshold for ignoring some of it. See the "CollisionDetection" sample project for an example of how to do this (run the project using Corona Terminal to see the output of the collisions.)
由於 postCollision事件流的物理引擎可以很吵鬧(它註冊了一系列微小的力量越來越為對象,“定居“),你可能想選擇自己的門檻,無視它的一些。參見“CollisionDetection“示例項目為例,如何做到這一點(運行該項目利用Corona碼頭看到輸出的衝突。)


(Technical note: Box2D is actually reporting collision impulses, which are forces multiplied by the elapsed time of each world step, but since this time interval is always the same, this distinction can be ignored for the purposes of game logic.)
(技術說明:Box2D的報告實際上是碰撞的衝動,這是部隊所用的時間乘以每個世界同步,但由於這個時間間隔是一樣的,這種區別可以忽略而言的遊戲邏輯。)


Collision categories, masking, and groups碰撞類別,掩蔽和組

By default, all bodies collide with all other bodies, but you may want to fine-tune this behavior. For example, in the classic arcade game Asteroids, none of the asteroids collide with other asteroids, but all of them should collide with the player and with the enemy spaceships. There are two ways to accomplish this.
默認情況下,所有機構和所有其他機構的碰撞,但您可能要微調此行為。例如,在經典的街機遊戲小行星外,並無其他小行星與小行星碰撞,但他們都應該與球員發生碰撞,並與敵人的太空船。有兩種方法可以做到這一點。


First, you can assign categoryBits and maskBits to your objects via a "collision filter" definition, which is an optional table assigned during body construction. An object will only collide with other objects if their categoryBits are among its assigned maskBits. Normally, an object will only have one category bit assigned, but may have one or more mask bits depending on what other things it should collide with.
首先,你可以指定categoryBits和maskBits到你的對象通過“碰撞過濾器“的定義,這是一個可選的期間分配表體建設。對象將只與其他物體相撞,如果他們是在其指定的categoryBits maskBits。通常,一個對象只能有一個類別位分配,但可以有一個或多個掩碼位取決於什麼其他的事情就應該碰撞。


(Update: see the helpful collision filter worksheet and discussion posted here.)
(更新:請參閱表濾波器的有益碰撞與討論張貼在這裡。)


In the example below, the red balloon has a maskBits value of 3, so it would collide with any objects in category bits 2 and 1, which in this case would include other red balloons (category bit 2) or the wall objects (category bit 1). Meanwhile, it will pass through any blue balloons (category bit 4), since bit 4 is not included in its maskBits value.
在下面的例子中,紅色的氣球有maskBits值為 3,所以它與任何物體相撞類別2和1位,在這種情況下,將包括其他的紅氣球(類第2位),或在牆上的對象(類別位1)。同時,將通過任何藍色氣球(類別第4位),因為位4,不包含在其maskBits值。
--------------------------
borderCollisionFilter = { categoryBits = 1, maskBits = 6 } 
-- border collides with (4 & 2) only
 
borderBody = { friction=0.4, bounce=0.8, bodyType="static", filter=borderCollisionFilter }
 
local borderTop = display.newRect( 0, 0, 320, 1 )
physics.addBody( borderTop, borderBody )
 
local borderBottom = display.newRect( 0, 479, 320, 1 )
physics.addBody( borderBottom, borderBody )
 
local borderLeft = display.newRect( 0, 1, 1, 480 )
physics.addBody( borderLeft, borderBody )
 
local borderRight = display.newRect( 319, 1, 1, 480 )
physics.addBody( borderRight, borderBody )
 
local redCollisionFilter = { categoryBits = 2, maskBits = 3 } 
-- red collides with (2 & 1) only
 
local blueCollisionFilter = { categoryBits = 4, maskBits = 5 } 
-- blue collides with (4 & 1) only
 
local redBody = { density=0.2, friction=0, bounce=0.95, radius=43.0, filter=redCollisionFilter }
local blueBody = { density=0.2, friction=0, bounce=0.95, radius=43.0, filter=blueCollisionFilter }
 
redBalloon = display.newImage( "red_balloon.png" )
physics.addBody( redBalloon, redBody )
 
blueBalloon = display.newImage( "blue_balloon.png" )
physics.addBody( blueBalloon, blueBody )
--------------------------------------------------------


Note that categoryBits and maskBits are binary values that are currently assigned using decimal numbers. This is convenient for lower bits like 1, 2, 4 and 8, but not so convenient for higher bits -- since there are 16 possible categoryBits, the highest bit value is 32768. Therefore, future versions of this API may use a different bit assignment syntax, such as binary or hexadecimal values.
請注意,categoryBits和maskBits是二進制值是當前分配使用十進制數字。這是非常方便的低位元,如1,2,4和8,但不是很方便更高位 -因為有16種可能categoryBits,最高位的值是32768。因此,未來版本的該 API可能會使用不同的位分配語法,如二進制或十六進制值。


The second method is to assign a groupIndex to each object, via the same filter definition shown above. This value can be a positive or negative integer, and is a simpler way of specifying collision rules: objects with the same positive groupIndex value will always collide with each other, and objects with the same negative groupIndex value will never collide with each other.
第二種方法是分配一個 groupIndex每個對象,通過相同的過濾器定義上面。這個值可以是正或負的整數,是一個簡單的方式指定碰撞規則:對象與同樣積極的groupIndex值將始終相互碰撞,和對象具有相同的負 groupIndex值不會互相碰撞。
--------------------------
local greenCollisionFilter = { groupIndex = -2 }
--------------------------
If both groupIndex and collisionBits/maskBits are assigned to an object, the groupIndex has higher precedence.
如果同時 groupIndex和collisionBits/ maskBits被分配到一個對象,groupIndex 具有較高的優先 。


See the "CollisionFilter" sample code for an example of collision filtering.
參見“CollisionFilter“示例代碼示例碰撞過濾。


Collision event propagation rules碰撞事件傳播規律


Collision events in Corona now have a propagation model similar to touch events. You can use this to further optimize your game performance by limiting the number of events that are created.
碰撞事件的Corona現在有一個傳播模式類似觸摸事件。你可以用它來進一步優化你的遊戲的性能限制數量的事件所創建的。


By default, a collision between two objects will fire a local event for the first object, then a local event for the second object, then a global event in the Runtime object (assuming all have active listeners enabled). However, you may only be interested in some of this information. For example, in a game with one player character and lots of enemies, you may only be interested in what the player has collided with.
默認情況下,兩個物體之間的碰撞將觸發本地事件的第一個對象,然後是本地事件的第二個對象,然後是全球性事件中的運行時對象(假設所有監聽有積極的啟用)。但是,您可能只在一些有興趣的這些信息。例如,在一場比賽中與一名球員性格和大量的敵人,你可能只關心什麼球員相撞。


As of Alpha 3, any collision event handler that returns true will stop further propagation of that collision event, even if there are further listeners that would otherwise have received it. This allows you to further limit the number of events that are created and passed to the Lua side. While individual events are not very expensive, large numbers of them can affect overall performance, so limiting event propagation is a good practice.
作為 Alpha 3,任何碰撞事件處理程序返回true會停止進一步的傳播,碰撞事件,即使有進一步的監聽,否則已收到。這使您可以進一步限制數量的事件是創建並傳遞到 Lua 的一面。雖然個別事件不是很昂貴,大量可以影響他們的整體表現,因此限制了事件的傳播是一個很好的做法。

arrow
arrow
    全站熱搜

    createps 發表在 痞客邦 留言(1) 人氣()