working on rotation and scaling of light bodies

This commit is contained in:
Tim Anema 2015-01-30 14:35:49 -05:00
parent 691da848de
commit 115d64f51f
3 changed files with 145 additions and 67 deletions

View File

@ -86,12 +86,6 @@ function love.keypressed(k)
if colorAberration == 0.0 then
colorAberration = 3.0
end
elseif k == "f" then
lightWorld:remove(lightMouse)
elseif k == "g" then
lightWorld:remove(circleTest)
elseif k == "d" then
lightWorld:remove(rectangleTest)
end
end
@ -122,6 +116,17 @@ function love.update(dt)
polygonTest:move((dt * 200), 0)
end
if love.keyboard.isDown("f") then
polygonTest:scale(0.005)
elseif love.keyboard.isDown("a") then
polygonTest:scale(-0.005)
end
if love.keyboard.isDown("s") then
polygonTest:rotate(0.05)
elseif love.keyboard.isDown("d") then
polygonTest:rotate(-0.05)
end
if love.keyboard.isDown("-") then
scale = scale - 0.01
elseif love.keyboard.isDown("=") then

View File

@ -28,6 +28,10 @@ local function new(id, type, ...)
obj.tileY = 0
obj.zheight = 1
obj.rotation = 0
obj.scalex = 1
obj.scaley = 1
obj.castsNoShadow = false
obj.visible = true
obj.is_on_screen = true
@ -49,21 +53,19 @@ local function new(id, type, ...)
obj:setShadowType('circle', args[3], args[4], args[5])
elseif obj.type == "rectangle" then
obj.x = args[1] or 0
obj.y = args[2] or 0
local x = args[1] or 0
local y = args[2] or 0
local width = args[3] or 64
local height = args[4] or 64
local ox = args[5] or width * 0.5
local oy = args[6] or height * 0.5
local rectangle_canvas = love.graphics.newCanvas(args[3], args[4])
util.drawto(rectangle_canvas, 0, 0, 1, function()
love.graphics.rectangle('fill', 0, 0, args[3], args[4])
end)
obj.img = love.graphics.newImage(rectangle_canvas:getImageData())
obj.imgWidth = obj.img:getWidth()
obj.imgHeight = obj.img:getHeight()
obj.ix = obj.imgWidth * 0.5
obj.iy = obj.imgHeight * 0.5
obj:generateNormalMapFlat("top")
obj:setShadowType('rectangle', args[3], args[4])
obj:setPoints(
x - ox, y - oy,
x - ox + width, y - oy,
x - ox + width, y - oy + height,
x - ox, y - oy + height
)
elseif obj.type == "polygon" then
obj:setPoints(...)
elseif obj.type == "image" then
@ -106,27 +108,67 @@ local function new(id, type, ...)
obj.oy = obj.height * 0.5
obj.reflection = true
end
obj.old_x, obj.old_y = obj.x, obj.y
obj:commit_changes()
return obj
end
-- refresh
function body:refresh()
if self.shadowType == "rectangle" then
self.data = {
self.x - self.ox, self.y - self.oy,
self.x - self.ox + self.width, self.y - self.oy,
self.x - self.ox + self.width, self.y - self.oy + self.height,
self.x - self.ox, self.y - self.oy + self.height
}
elseif self.shadowType == 'polygon' and (self.old_x ~= self.x or self.old_y ~= self.y) then
local dx, dy = self.x - self.old_x, self.y - self.old_y
if self.shadowType == 'polygon' and self:has_changed() then
local dx, dy, dr, dsx, dsy = self:changes()
if self:position_changed() then
for i = 1, #self.data, 2 do
self.data[i], self.data[i+1] = self.data[i] + dx, self.data[i+1] + dy
end
self.old_x, self.old_y = self.x, self.y
end
if self:rotation_changed() then
local center = vector(self.x, self.y)
for i = 1, #self.data, 2 do
self.data[i], self.data[i+1] = vector(self.data[i], self.data[i+1]):rotateAround(center, dr):unpack()
end
end
if self:scale_changed() then
for i = 1, #self.data, 2 do
self.data[i] = self.x + (self.data[i] - self.x) + ((self.data[i] - self.x) * dsx)
self.data[i+1] = self.y + (self.data[i+1] - self.y) + ((self.data[i+1] - self.y) * dsy)
end
end
self:commit_changes()
end
end
function body:has_changed()
return self:position_changed() or self:rotation_changed() or self:scale_changed()
end
function body:position_changed()
return self.old_x ~= self.x or
self.old_y ~= self.y
end
function body:rotation_changed()
return self.old_rotation ~= self.rotation
end
function body:scale_changed()
return self.old_scalex ~= self.scalex or
self.old_scaley ~= self.scaley
end
function body:changes()
return self.x - self.old_x,
self.y - self.old_y,
self.rotation - self.old_rotation,
self.scalex - self.old_scalex,
self.scaley - self.old_scaley
end
function body:commit_changes()
self.old_x, self.old_y = self.x, self.y
self.old_rotation = self.rotation
self.old_scalex, self.old_scaley = self.scalex, self.scaley
end
function body:newGrid(frameWidth, frameHeight, imageWidth, imageHeight, left, top, border)
@ -162,6 +204,7 @@ function body:pauseAtEnd() self.animation:pauseAtEnd() end
function body:pauseAtStart() self.animation:pauseAtStart() end
function body:update(dt)
self:refresh()
if self.type == "animation" and self.animation then
local frame = self.animation.frames[self.animation.position]
_,_,self.width, self.height = frame:getViewport()
@ -173,12 +216,29 @@ function body:update(dt)
end
end
function body:rotate(angle)
self:setRotation(self.rotation + angle)
end
function body:setRotation(angle)
self.rotation = angle
end
function body:scale(sx, sy)
self.scalex = self.scalex + sx
self.scaley = self.scaley + (sy or sx)
end
function body:setScale(sx, sy)
self.scalex = sx
self.scaley = sy or sx
end
-- set position
function body:setPosition(x, y)
if x ~= self.x or y ~= self.y then
self.x = x
self.y = y
self:refresh()
end
end
@ -190,7 +250,6 @@ function body:move(x, y)
if y then
self.y = self.y + y
end
self:refresh()
end
-- get x position
@ -218,19 +277,11 @@ function body:getImageHeight()
return self.imgHeight
end
-- set dimension
function body:setDimension(width, height)
self.width = width
self.height = height
self:refresh()
end
-- set offset
function body:setOffset(ox, oy)
if ox ~= self.ox or oy ~= self.oy then
self.ox = ox
self.oy = oy
self:refresh()
end
end
@ -453,11 +504,18 @@ function body:setShadowType(type, ...)
self.ox = args[2] or 0
self.oy = args[3] or 0
elseif self.shadowType == "rectangle" then
self.shadowType = "polygon"
self.width = args[1] or 64
self.height = args[2] or 64
self.ox = args[3] or self.width * 0.5
self.oy = args[4] or self.height * 0.5
self:refresh()
self.data = {
self.x - self.ox, self.y - self.oy,
self.x - self.ox + self.width, self.y - self.oy,
self.x - self.ox + self.width, self.y - self.oy + self.height,
self.x - self.ox, self.y - self.oy + self.height
}
elseif self.shadowType == "polygon" then
self.data = args or {0, 0, 0, 0, 0, 0}
elseif self.shadowType == "image" then
@ -507,16 +565,16 @@ function body:inRange(l, t, w, h, s)
end
function body:drawAnimation()
self.animation:draw(self.img, self.x - self.ix, self.y - self.iy)
self.animation:draw(self.img, self.x, self.y, self.rotation, self.scalex, self.scaley, self.ix, self.iy)
end
function body:drawNormal()
if not self.refraction and not self.reflection and self.normalMesh then
love.graphics.setColor(255, 255, 255)
if self.type == 'animation' then
self.animation:draw(self.normal, self.x - self.nx, self.y - self.ny)
self.animation:draw(self.normal, self.x, self.y, self.rotation, self.scalex, self.scaley, self.nx, self.ny)
else
love.graphics.draw(self.normalMesh, self.x - self.nx, self.y - self.ny)
love.graphics.draw(self.normalMesh, self.x, self.y, self.rotation, self.scalex, self.scaley, self.nx, self.ny)
end
end
end
@ -526,8 +584,6 @@ function body:drawGlow()
if self.type == "circle" then
love.graphics.circle("fill", self.x, self.y, self.radius)
elseif self.type == "rectangle" then
love.graphics.rectangle("fill", self.x, self.y, self.width, self.height)
elseif self.type == "polygon" then
love.graphics.polygon("fill", unpack(self.data))
elseif (self.type == "image" or self.type == "animation") and self.img then
@ -541,9 +597,9 @@ function body:drawGlow()
end
if self.type == "animation" then
self.animation:draw(self.img, self.x - self.ix, self.y - self.iy)
self.animation:draw(self.img, self.x, self.y, self.rotation, self.scalex, self.scaley, self.ix, self.iy)
else
love.graphics.draw(self.img, self.x - self.ix, self.y - self.iy)
love.graphics.draw(self.img, self.x, self.y, self.rotation, self.scalex, self.scaley, self.ix, self.iy)
end
love.graphics.setShader()
@ -554,10 +610,10 @@ function body:drawRefraction()
if self.refraction and self.normal then
love.graphics.setColor(255, 255, 255)
if self.tileX == 0.0 and self.tileY == 0.0 then
love.graphics.draw(self.normal, self.x - self.nx, self.y - self.ny)
love.graphics.draw(self.normal, self.x, self.y, self.rotation, self.scalex, self.scaley, self.nx, self.ny)
else
self.normalMesh:setVertices(self.normalVert)
love.graphics.draw(self.normalMesh, self.x - self.nx, self.y - self.ny)
love.graphics.draw(self.normalMesh, self.x, self.y, self.rotation, self.scalex, self.scaley, self.nx, self.ny)
end
end
@ -566,14 +622,12 @@ function body:drawRefraction()
if not self.refractive then
if self.type == "circle" then
love.graphics.circle("fill", self.x, self.y, self.radius)
elseif self.type == "rectangle" then
love.graphics.rectangle("fill", self.x, self.y, self.width, self.height)
elseif self.type == "polygon" then
love.graphics.polygon("fill", unpack(self.data))
elseif self.type == "image" and self.img then
love.graphics.draw(self.img, self.x - self.ix, self.y - self.iy)
love.graphics.draw(self.img, self.x, self.y, self.rotation, self.scalex, self.scaley, self.ix, self.iy)
elseif self.type == 'animation' then
self.animation:draw(self.img, self.x - self.ix, self.y - self.iy)
self.animation:draw(self.img, self.x, self.y, self.rotation, self.scalex, self.scaley, self.ix, self.iy)
end
end
end
@ -582,21 +636,21 @@ function body:drawReflection()
if self.reflection and self.normal then
love.graphics.setColor(255, 0, 0)
self.normalMesh:setVertices(self.normalVert)
love.graphics.draw(self.normalMesh, self.x - self.nx, self.y - self.ny)
love.graphics.draw(self.normalMesh, self.x, self.y, self.rotation, self.scalex, self.scaley, self.nx, self.ny)
end
if self.reflective and self.img then
love.graphics.setColor(0, 255, 0)
if self.type == 'animation' then
self.animation:draw(self.img, self.x - self.ix, self.y - self.iy)
self.animation:draw(self.img, self.x, self.y, self.rotation, self.scalex, self.scaley, self.ix, self.iy)
else
love.graphics.draw(self.img, self.x - self.ix, self.y - self.iy)
love.graphics.draw(self.img, self.x, self.y, self.rotation, self.scalex, self.scaley, self.ix, self.iy)
end
elseif not self.reflection and self.img then
love.graphics.setColor(0, 0, 0)
if self.type == 'animation' then
self.animation:draw(self.img, self.x - self.ix, self.y - self.iy)
self.animation:draw(self.img, self.x, self.y, self.rotation, self.scalex, self.scaley, self.ix, self.iy)
else
love.graphics.draw(self.img, self.x - self.ix, self.y - self.iy)
love.graphics.draw(self.img, self.x, self.y, self.rotation, self.scalex, self.scaley, self.ix, self.iy)
end
end
end
@ -607,9 +661,9 @@ function body:drawMaterial()
love.graphics.setColor(255, 255, 255)
self.materialShader:send("material", self.material)
if self.type == 'animation' then
self.animation:draw(self.normal, self.x - self.nx, self.y - self.ny)
self.animation:draw(self.normal, self.x, self.y, self.rotation, self.scalex, self.scaley, self.nx, self.ny)
else
love.graphics.draw(self.normal, self.x - self.nx, self.y - self.ny)
love.graphics.draw(self.normal, self.x, self.y, self.rotation, self.scalex, self.scaley, self.nx, self.ny)
end
love.graphics.setShader()
end
@ -617,7 +671,7 @@ end
function body:drawStencil()
if not self.refraction and not self.reflection and not self.castsNoShadow then
love.graphics.draw(self.img, self.x - self.ix, self.y - self.iy)
love.graphics.draw(self.img, self.x, self.y, self.rotation, self.scalex, self.scaley, self.ix, self.iy)
end
end
@ -627,7 +681,7 @@ function body:drawShadow(light)
end
love.graphics.setColor(self.red, self.green, self.blue, self.alpha)
if self.shadowType == "rectangle" or self.shadowType == "polygon" then
if self.shadowType == "polygon" then
self:drawPolyShadow(light)
elseif self.shadowType == "circle" then
self:drawCircleShadow(light)
@ -721,7 +775,7 @@ function body:drawImageShadow(light)
{0, shadowStartY, 0, 1, self.red, self.green, self.blue, self.alpha}
})
love.graphics.draw(self.shadowMesh, self.x - self.ox, self.y - self.oy, 0, s, s)
love.graphics.draw(self.shadowMesh, self.x, self.y, self.rotation, self.scalex, self.scaley, self.ox, self.oy)
end
return setmetatable({new = new}, {__call = function(_, ...) return new(...) end})

View File

@ -43,4 +43,23 @@ function vector:dist(b)
return math.sqrt(math.pow(b.x - self.x, 2) + math.pow(b.y-self.y, 2))
end
function vector:unpack()
return self.x, self.y
end
function vector:rotateAround(origin, angle)
local s = math.sin(angle)
local c = math.cos(angle)
-- translate point back to origin
self.x = self.x - origin.x
self.y = self.y - origin.y
-- rotate point
self.x = (self.x * c - self.y * s)
self.y = (self.x * s + self.y * c)
-- translate point back
self.x = self.x + origin.x
self.y = self.y + origin.y
return self
end
return setmetatable({new = new}, {__call = function(_, ...) return new(...) end})