使用物理处理多个 objects 的碰撞事件
Handling Collision Events for multiple objects with physics
所以我正在用 Corona(在 lua 中)构建一个游戏,其中有多个 objects 包含 Physic 属性,并且目前正在尝试以我可以的方式存储和操作它们使碰撞处理更容易...
这个想法是 3 个 objects 中没有 2 个发生碰撞。
Objects 是
1/ 一个球(可以出现在屏幕上的许多球)
2/ Table(具有一些物理属性)
和 3/ 口袋(最后只是一些不可见的矩形)
经过 2 周的处理,我得出了这个结论
- 球击中其他球
- 球击中Table
- Table 没有击中口袋(静态 body)
- 口袋不击球(静态body)
- 球击中口袋
代码结构示例
创建 100 个球
balls = {}
local i = 1
function createBalls ()
for i = 1,100,1 do -- create the 100 and hide them?
ball = display.newImage("ball.png")
ball.isVisible = false
ball.id = tostring( "ball " ..i )
balls[#ball+1] = ball
sceneGroup:insert(ball[#ball])
end
end
声明6个口袋(使用id作为碰撞处理的标志)
local Pocket1 = display.newRect( screenWidth * .28, screenHeight * .5, 15, 18) --Left Pocket 60pts
physics.addBody( Pocket1, "kinematic", {isSensor = true})
Pocket1:addEventListener( "collision", Pocket1 ) Pocket1.isVisible = true Pocket1.alpha = 0.5
Pocket1.id ="Left Pocket 60pts"
local Pocket2 = display.newRect( screenWidth * .3945, screenHeight * .556, 15, 18) -- Left Pocket 30pts
physics.addBody( Pocket2, "kinematic", {isSensor = true} )
Pocket2:addEventListener( "collision", Pocket2 ) Pocket2.isVisible = false
Pocket2.id ="Left Pocket 30pts"
local Pocket3 = display.newRect( screenWidth * .512, screenHeight * .490, 15, 18) -- Center Pocket 10 pts
physics.addBody( Pocket3, "kinematic", {isSensor = true} )
Pocket3:addEventListener( "collision", Pocket3 ) Pocket3.isVisible = false
Pocket3.id ="Center Pocket 10pts"
local Pocket4 = display.newRect( screenWidth * .613, screenHeight * .556, 15, 18) -- Right Pocket 30 pts
physics.addBody( Pocket4, "kinematic", {isSensor = true} )
Pocket4:addEventListener( "collision", Pocket4 ) Pocket4.isVisible = false
Pocket4.id ="Right Pocket 30pts"
local Pocket5 = display.newRect( screenWidth * .736, screenHeight * .5, 15, 18) -- Far Right Pocket 60pts
physics.addBody( Pocket5, "kinematic", {isSensor = true} )
Pocket5:addEventListener( "collision", Pocket5 ) Pocket5.isVisible = false
Pocket5.id ="Right Pocket 60pts"
local Pocket6 = display.newRect( screenWidth * .512, screenHeight * .638, 50, 10) -- Kill-z Pocketphysics.addBody( Pocket6, "kinematic", {isSensor = true} )
Pocket6:addEventListener( "collision", Pocket6 ) Pocket6.isVisible = false
Pocket6.id ="Kill Pocket"
我的问题,碰撞检测仅适用于最后加载的球,
(以防有人要求加载程序功能)
--handle loader
function shootBall()
createBalls() --obviously this will now spawn 100 balls
if ballLoaded == true then
r1 = -687.5 r2 = -668
r3 = 595 r4 = 645
ball[k].x = screenWidth * .378 ball[k].y = screenHeight * .638
ball[k]:scale(0.16,0.16)
ball[k].isVisible = true
physics.addBody( ball[k], "dynamic", {radius = 5.5, density=15.0, friction=0.8, bounce=0.0 } )
ball[k]:setLinearVelocity( math.random(r1,r2), math.random(r3,r4))
--and here it will have done nothing productive other than fill the screen with balls
end
a 回滚编辑 这最初是所谓的,但正如您所看到的那样,组织得不好,因为最近的代码是一团糟..
local i = 1
local balls = {}
local function spawnBall()
if i > 0 or i < 100 then
balls[i] = display.newImage("ball.png")
balls[i].id = "ball "..i
balls[i].x = screenWidth * .378
balls[i].y = screenHeight * .638
balls[i]:scale(0.16,0.16)
balls[i].isVisible = true
physics.addBody( balls[i], "dynamic", {radius = 5.5, density=15.0, friction=0.8, bounce=0.0 } )
balls[i]:setLinearVelocity(math.random(-687.5,-668), math.random(595,645))
sceneGroup:insert(balls[i])
print(balls[i].id.. " shot")
i = i + 1
end
end`
function createBalls ()
for k = 1,100,1 do
ball = {} -- we do this every loop cycle!!!
ball[k] = display.newImage("ball.png")
ball[k].isVisible = false
ball[k].id = tostring( "ball " ..i )
ball[#ball+1] = ball[k]
sceneGroup:insert(ball[#ball])
end
end
这里你重新定义全局变量ball 100次。
当你在每个循环中重新创建球时,#ball 将始终为 1。
因此,您创建了一个 table,在索引 k 和 2 处向其添加了各种值,然后再次重新创建它...因此您的全局 table 球完全被搞砸了。
在 shootBall()
中,您使用了未在提供的代码中定义的索引 k
...
逐行检查您的代码并考虑一下。用笔在纸上画一个table...
请阅读 Lua!!!!
中有关局部变量使用的一些内容
这是我的解决方案,它非常全面我要感谢来自 Corona Labs 的 Danny 提供了大部分解决方案,通过函数传递参数在列表中但不是特别优先,但感谢大部分工作。
--on "Press" event
--Function to spawn an object
local function spawn(params)
local ball = display.newImage(params.image)
--Set the objects table to a table passed in by parameters
ball.Table = params.Table
--Automatically set the table index to be inserted into the next available table index
ball.index = #ball.Table + 1
--Give the object a custom name
ball.id = "ball : " .. ball.index
--If the object should have a body create it, else dont.
if params.hasBody then
--Allow physics parameters to be passed by parameters:
ball.x = params.x or contentCenterX
ball.y = params.y or contentCenterY
ball.isVisible = params.isVisible or false
ball.radius = params.radius or nil
ball.density = params.density or 0
ball.friction = params.friction or 0
ball.bounce = params.bounce or 0
ball.isSensor = params.isSensor or false
ball.bodyType = params.bodyType or "dynamic"
physics.addBody(ball, ball.bodyType, {radius = ball.radius, density = ball.density, friction = ball.friction, bounce = ball.bounce, isSensor = ball.isSensor})
ball:setLinearVelocity(params.xVelocity or 0, params.yVelocity or 0)
ball:scale(params.xScale or 1,params.yScale or 1)
end
--The objects group
ball.group = params.group or nil
--If the function call has a parameter named group then insert it into the specified group
ball.group:insert(ball)
--Insert the object into the table at the specified index
ball.Table[ball.index] = ball
return ball
end
local displayGroup = display.newGroup()
--Create a table to hold balls
local ballTable = {}
--Create spawns
local function ballSpawn()
for i=1 ,1,1 do
local spawns = spawn(
{
image = "ball.png",
Table = ballTable,
hasBody = true,
x = screenWidth * .378,
y = screenHeight * .638,
isVisible = true,
bodyType = "dynamic", radius = 5.5, density= 15.0, friction= 0.8, bounce = 0.0,
xVelocity = math.random(-687.5,-678),
yVelocity = math.random(595,645),
xScale = 0.16, yScale = 0.16,
group = sceneGroup,
}
)
end
end
这是代码中比较不典型的部分,我想在球无论是 3、5 还是 25 时进行按键测试,如果 i=5 并且球:3 与测试碰撞发生碰撞口袋我想确保打印出所有碰撞。
local function onPocketsCollision ( event)
local self = event.object2.id
local other = event.object1.id
if event.phase == "began" then
for i = 1, #ballTable,1 do
if (self == ballTable[i].id and other == Pocket1.id) then
print(self .. " hit for " .. Pocket1.id)
ballTable[i]:removeSelf()
score.add(1)
end
if (self == ballTable[i].id and other == Pocket2.id) then
print(self .. " hit for " .. Pocket2.id)
ballTable[i]:removeSelf()
score.add(1)
end
if (self == ballTable[i].id and other == Pocket3.id) then
print(self .. " hit for " .. Pocket3.id)
ballTable[i]:removeSelf()
score.add(1)
end
if (self == ballTable[i].id and other == Pocket4.id) then
print(self .. " hit for " .. Pocket4.id)
ballTable[i]:removeSelf()
score.add(1)
end
if (self == ballTable[i].id and other == Pocket5.id) then
print(self .. " hit for " .. Pocket5.id)
ballTable[i]:removeSelf()
score.add(1)
end
if (self == ballTable[i].id and other == Pocket6.id) then
print(self .. " hit " .. Pocket6.id)
ballTable[i]:removeSelf()
score.add(-1)
end
end
end
end
Runtime:addEventListener( "collision", onPocketsCollision )
太棒了,它工作得很好,只是减少它的情况,所以它看起来不像废话......我以后一定会在共享代码时多加注意, 必须逐行阅读...
所以我正在用 Corona(在 lua 中)构建一个游戏,其中有多个 objects 包含 Physic 属性,并且目前正在尝试以我可以的方式存储和操作它们使碰撞处理更容易... 这个想法是 3 个 objects 中没有 2 个发生碰撞。 Objects 是 1/ 一个球(可以出现在屏幕上的许多球) 2/ Table(具有一些物理属性) 和 3/ 口袋(最后只是一些不可见的矩形)
经过 2 周的处理,我得出了这个结论
- 球击中其他球
- 球击中Table
- Table 没有击中口袋(静态 body)
- 口袋不击球(静态body)
- 球击中口袋
代码结构示例 创建 100 个球
balls = {}
local i = 1
function createBalls ()
for i = 1,100,1 do -- create the 100 and hide them?
ball = display.newImage("ball.png")
ball.isVisible = false
ball.id = tostring( "ball " ..i )
balls[#ball+1] = ball
sceneGroup:insert(ball[#ball])
end
end
声明6个口袋(使用id作为碰撞处理的标志)
local Pocket1 = display.newRect( screenWidth * .28, screenHeight * .5, 15, 18) --Left Pocket 60pts
physics.addBody( Pocket1, "kinematic", {isSensor = true})
Pocket1:addEventListener( "collision", Pocket1 ) Pocket1.isVisible = true Pocket1.alpha = 0.5
Pocket1.id ="Left Pocket 60pts"
local Pocket2 = display.newRect( screenWidth * .3945, screenHeight * .556, 15, 18) -- Left Pocket 30pts
physics.addBody( Pocket2, "kinematic", {isSensor = true} )
Pocket2:addEventListener( "collision", Pocket2 ) Pocket2.isVisible = false
Pocket2.id ="Left Pocket 30pts"
local Pocket3 = display.newRect( screenWidth * .512, screenHeight * .490, 15, 18) -- Center Pocket 10 pts
physics.addBody( Pocket3, "kinematic", {isSensor = true} )
Pocket3:addEventListener( "collision", Pocket3 ) Pocket3.isVisible = false
Pocket3.id ="Center Pocket 10pts"
local Pocket4 = display.newRect( screenWidth * .613, screenHeight * .556, 15, 18) -- Right Pocket 30 pts
physics.addBody( Pocket4, "kinematic", {isSensor = true} )
Pocket4:addEventListener( "collision", Pocket4 ) Pocket4.isVisible = false
Pocket4.id ="Right Pocket 30pts"
local Pocket5 = display.newRect( screenWidth * .736, screenHeight * .5, 15, 18) -- Far Right Pocket 60pts
physics.addBody( Pocket5, "kinematic", {isSensor = true} )
Pocket5:addEventListener( "collision", Pocket5 ) Pocket5.isVisible = false
Pocket5.id ="Right Pocket 60pts"
local Pocket6 = display.newRect( screenWidth * .512, screenHeight * .638, 50, 10) -- Kill-z Pocketphysics.addBody( Pocket6, "kinematic", {isSensor = true} )
Pocket6:addEventListener( "collision", Pocket6 ) Pocket6.isVisible = false
Pocket6.id ="Kill Pocket"
我的问题,碰撞检测仅适用于最后加载的球,
(以防有人要求加载程序功能)
--handle loader
function shootBall()
createBalls() --obviously this will now spawn 100 balls
if ballLoaded == true then
r1 = -687.5 r2 = -668
r3 = 595 r4 = 645
ball[k].x = screenWidth * .378 ball[k].y = screenHeight * .638
ball[k]:scale(0.16,0.16)
ball[k].isVisible = true
physics.addBody( ball[k], "dynamic", {radius = 5.5, density=15.0, friction=0.8, bounce=0.0 } )
ball[k]:setLinearVelocity( math.random(r1,r2), math.random(r3,r4))
--and here it will have done nothing productive other than fill the screen with balls
end
a 回滚编辑 这最初是所谓的,但正如您所看到的那样,组织得不好,因为最近的代码是一团糟..
local i = 1
local balls = {}
local function spawnBall()
if i > 0 or i < 100 then
balls[i] = display.newImage("ball.png")
balls[i].id = "ball "..i
balls[i].x = screenWidth * .378
balls[i].y = screenHeight * .638
balls[i]:scale(0.16,0.16)
balls[i].isVisible = true
physics.addBody( balls[i], "dynamic", {radius = 5.5, density=15.0, friction=0.8, bounce=0.0 } )
balls[i]:setLinearVelocity(math.random(-687.5,-668), math.random(595,645))
sceneGroup:insert(balls[i])
print(balls[i].id.. " shot")
i = i + 1
end
end`
function createBalls ()
for k = 1,100,1 do
ball = {} -- we do this every loop cycle!!!
ball[k] = display.newImage("ball.png")
ball[k].isVisible = false
ball[k].id = tostring( "ball " ..i )
ball[#ball+1] = ball[k]
sceneGroup:insert(ball[#ball])
end
end
这里你重新定义全局变量ball 100次。
当你在每个循环中重新创建球时,#ball 将始终为 1。 因此,您创建了一个 table,在索引 k 和 2 处向其添加了各种值,然后再次重新创建它...因此您的全局 table 球完全被搞砸了。
在 shootBall()
中,您使用了未在提供的代码中定义的索引 k
...
逐行检查您的代码并考虑一下。用笔在纸上画一个table...
请阅读 Lua!!!!
中有关局部变量使用的一些内容这是我的解决方案,它非常全面我要感谢来自 Corona Labs 的 Danny 提供了大部分解决方案,通过函数传递参数在列表中但不是特别优先,但感谢大部分工作。
--on "Press" event
--Function to spawn an object
local function spawn(params)
local ball = display.newImage(params.image)
--Set the objects table to a table passed in by parameters
ball.Table = params.Table
--Automatically set the table index to be inserted into the next available table index
ball.index = #ball.Table + 1
--Give the object a custom name
ball.id = "ball : " .. ball.index
--If the object should have a body create it, else dont.
if params.hasBody then
--Allow physics parameters to be passed by parameters:
ball.x = params.x or contentCenterX
ball.y = params.y or contentCenterY
ball.isVisible = params.isVisible or false
ball.radius = params.radius or nil
ball.density = params.density or 0
ball.friction = params.friction or 0
ball.bounce = params.bounce or 0
ball.isSensor = params.isSensor or false
ball.bodyType = params.bodyType or "dynamic"
physics.addBody(ball, ball.bodyType, {radius = ball.radius, density = ball.density, friction = ball.friction, bounce = ball.bounce, isSensor = ball.isSensor})
ball:setLinearVelocity(params.xVelocity or 0, params.yVelocity or 0)
ball:scale(params.xScale or 1,params.yScale or 1)
end
--The objects group
ball.group = params.group or nil
--If the function call has a parameter named group then insert it into the specified group
ball.group:insert(ball)
--Insert the object into the table at the specified index
ball.Table[ball.index] = ball
return ball
end
local displayGroup = display.newGroup()
--Create a table to hold balls
local ballTable = {}
--Create spawns
local function ballSpawn()
for i=1 ,1,1 do
local spawns = spawn(
{
image = "ball.png",
Table = ballTable,
hasBody = true,
x = screenWidth * .378,
y = screenHeight * .638,
isVisible = true,
bodyType = "dynamic", radius = 5.5, density= 15.0, friction= 0.8, bounce = 0.0,
xVelocity = math.random(-687.5,-678),
yVelocity = math.random(595,645),
xScale = 0.16, yScale = 0.16,
group = sceneGroup,
}
)
end
end
这是代码中比较不典型的部分,我想在球无论是 3、5 还是 25 时进行按键测试,如果 i=5 并且球:3 与测试碰撞发生碰撞口袋我想确保打印出所有碰撞。
local function onPocketsCollision ( event)
local self = event.object2.id
local other = event.object1.id
if event.phase == "began" then
for i = 1, #ballTable,1 do
if (self == ballTable[i].id and other == Pocket1.id) then
print(self .. " hit for " .. Pocket1.id)
ballTable[i]:removeSelf()
score.add(1)
end
if (self == ballTable[i].id and other == Pocket2.id) then
print(self .. " hit for " .. Pocket2.id)
ballTable[i]:removeSelf()
score.add(1)
end
if (self == ballTable[i].id and other == Pocket3.id) then
print(self .. " hit for " .. Pocket3.id)
ballTable[i]:removeSelf()
score.add(1)
end
if (self == ballTable[i].id and other == Pocket4.id) then
print(self .. " hit for " .. Pocket4.id)
ballTable[i]:removeSelf()
score.add(1)
end
if (self == ballTable[i].id and other == Pocket5.id) then
print(self .. " hit for " .. Pocket5.id)
ballTable[i]:removeSelf()
score.add(1)
end
if (self == ballTable[i].id and other == Pocket6.id) then
print(self .. " hit " .. Pocket6.id)
ballTable[i]:removeSelf()
score.add(-1)
end
end
end
end
Runtime:addEventListener( "collision", onPocketsCollision )
太棒了,它工作得很好,只是减少它的情况,所以它看起来不像废话......我以后一定会在共享代码时多加注意, 必须逐行阅读...