物理 (Physics)
物理身體 (Physics Body)
Corona SDK 中預設的物理身體是方形,他的長寬取決於當下的顯示物件大小,有些時候,方形的物理身體無法滿足我們,像是形狀接近三角形的飛機會需要一個三角形的物理身體,更不用說其它更複雜的圖形了,在 Corona SDK 之中支援了不少物理身體形態,當然你也可以在本模板使用它們,它們分為:
圓形身體 (Circular Body)
透過 radius
半徑畫出圓形的物理身體。
enemy:setBody({radius = enemy.width/2*0.6})
方形身體 (Rectangular Body)
預設物理身體的進階版,你可以改變身體大小與位移。
enemy:setBody({
box = {
halfWidth = enemy.width/5,
halfHeight = enemy.height/5,
x = 0,
y = enemy.height * 0.3,
angle = 45,
}
})
突多邊形身體 (Polygon Body)
直接帶入突多邊形的點,注意點的順序要是順時針而且不能用這個方法帶入凹多邊形。這邊用了一個迴圈去根據螢幕大小調整突多邊形大小。
local pentagonShape = { 0,-37, 37,-10, 23,34, -23,34, -37,-10 }
for i = 1, #pentagonShape do
pentagonShape[i] = pentagonShape[i] * gameConfig.scaleFactor * 0.6
end
enemy:setBody({
shape = pentagonShape
})
邊線身體 (Edge Shape (Chain) Body)
邊線身體是一個沒有被填滿的邊線,你可以透過 connectFirstAndLastChainVertex
決定第一個點是不是要和最後一個點相連。
local chainPoints = { -120,-140, -100,-90, -80,-60, -40,-20, 0,0, 40,0, 70,-10, 110,-20, 140,-20, 180,-10 }
for i = 1, #chainPoints do
chainPoints[i] = chainPoints[i] * gameConfig.scaleFactor * 0.6
end
enemy:setBody({
chain = chainPoints,
connectFirstAndLastChainVertex = true
})
Outline Body
直接透過 graphics.newOutline
方法產生可以當作邊界參數的點。由於預設的邊線中心點不同,我們需要一個 for 迴圈去調整它。graphics.newOutline
的第一個參數決定邊線的完整程度,數字越小越完整,越影響效能,反之邊線較不完整,效能較佳。
local outline = graphics.newOutline(50, Sprite["expansion-4"].getSheet(), Sprite["expansion-4"].getFrameIndex("Ships/22"))
for i = 1, #outline do
if i % 2 == 1 then
outline[i] = outline[i] - enemy.width/2
else
outline[i] = outline[i] - enemy.height/2
end
end
enemy:setBody({
chain = outline,
connectFirstAndLastChainVertex = true
})
注意當你要重新調整物理身體大小時,必須要重啟該物件的物理引擎,以下例子將敵人的大小增加至兩倍,並重新調整其物理身體大小。
local Enemy = require("Enemy")
local Sprite = require("Sprite")
local gameConfig = require("gameConfig")
local MyEnemy = {}
MyEnemy.new = function()
local enemy = Enemy.new()
local sprite = Sprite["expansion-4"].new("Ships/22")
enemy:insert(sprite)
--Circular Body
--enemy:setBody({radius = enemy.width/2*0.6})
--Rectangular Body
--[[
enemy:setBody({
box = {
halfWidth = enemy.width/5,
halfHeight = enemy.height/5,
x = 0,
y = enemy.height * 0.3,
angle = 45,
}
})
--]]
--
--Polygon Body:
--The coordinates must be defined in clockwise order, and the resulting shape must be convex at all angle points.
--[[
local pentagonShape = { 0,-37, 37,-10, 23,34, -23,34, -37,-10 }
for i = 1, #pentagonShape do
pentagonShape[i] = pentagonShape[i] * gameConfig.scaleFactor * 0.6
end
enemy:setBody({
shape = pentagonShape
})
--]]
--Edge Shape (Chain) Body: Edge shapes are not restricted to convex angles like polygonal bodies.
--[[
local chainPoints = { -120,-140, -100,-90, -80,-60, -40,-20, 0,0, 40,0, 70,-10, 110,-20, 140,-20, 180,-10 }
for i = 1, #chainPoints do
chainPoints[i] = chainPoints[i] * gameConfig.scaleFactor * 0.6
end
enemy:setBody({
chain = chainPoints,
connectFirstAndLastChainVertex = true
})
--]]
--Outline Body
--[[
local outline = graphics.newOutline(50, Sprite["expansion-4"].getSheet(), Sprite["expansion-4"].getFrameIndex("Ships/22"))
for i = 1, #outline do
if i % 2 == 1 then
outline[i] = outline[i] - enemy.width/2
else
outline[i] = outline[i] - enemy.height/2
end
end
enemy:setBody({
chain = outline,
connectFirstAndLastChainVertex = true
})
--]]
enemy:enablePhysics()
--[[
enemy:addTimer(2000, function ()
enemy:scaleWithChangedBody()
end)
--]]
function enemy:scaleWithChangedBody()
transition.to(self, {
xScale = 2,
yScale = 2,
onComplete = function()
enemy:setBody({
box = {
halfWidth = enemy.width,
halfHeight = enemy.height,
x = 0,
y = 0,
angle = 0,
}
})
local vx, vy = enemy:getLinearVelocity()
enemy:reInitPhysics()
enemy:setLinearVelocity(vx, vy)
end
})
end
return enemy
end
return MyEnemy