almost there with complex
45
README.md
@ -1,15 +1,21 @@
|
||||
# light_world.lua
|
||||
|
||||
This is the light modeling done by Priorblue [here](https://bitbucket.org/PriorBlue/love2d-light-and-shadow-engine),
|
||||
only it has been largely refactored and edited to allow for scaling and proper translation.
|
||||
A library for Love2d to create a dynamic lighting system, supporting:
|
||||
- Shadows for any shape
|
||||
- Normal maps for 3d like reflections
|
||||
- Glow maps
|
||||
- Postshader effects
|
||||
- Animations with normal maps
|
||||
|
||||
*Supports love 11.2(master branch), 0.10.1(commit 414b9b74c0eb95bfb8b5e26a11caf2b32beccca0)
|
||||
All of this is base of a previous version made by [PriorBlue](https://bitbucket.org/PriorBlue/love2d-light-and-shadow-engine),
|
||||
|
||||
## Installation
|
||||
|
||||
Copy and rename the lib folder into your project.
|
||||
|
||||
## How to use
|
||||
For more information please check out the [wiki](https://github.com/tanema/light_world.lua/wiki) and see the examples directory to see how it is fully used.
|
||||
This project can be run with love to see the demonstrations in action.
|
||||
|
||||
```lua
|
||||
local LightWorld = require "lib" --the path to where light_world is (in this repo "lib")
|
||||
@ -17,7 +23,7 @@ local LightWorld = require "lib" --the path to where light_world is (in this rep
|
||||
--create light world
|
||||
function love.load()
|
||||
lightWorld = LightWorld({
|
||||
ambient = {55/255,55/255,55/255}, --the general ambient light in the environment
|
||||
ambient = {0.21,0.21,0.21}, --the general ambient light in the environment
|
||||
})
|
||||
end
|
||||
|
||||
@ -37,35 +43,6 @@ function love.draw()
|
||||
end
|
||||
```
|
||||
|
||||
For more information please check out the [wiki](https://github.com/tanema/light_world.lua/wiki) and see the examples directory to see how it is fully used. This project can be run with love to see the demonstrations in action.
|
||||
|
||||
### Gamera & HUMP
|
||||
There are example in the example directory how to use both of these with the library.
|
||||
|
||||
## Features ##
|
||||
* **[Preview (Video)](https://www.youtube.com/watch?v=6V5Dtsa6Nd4)**
|
||||
* polygon shadow calculation [Preview](http://onepixelahead.de/love2d_polyshadow.png)
|
||||
* circle shadow calculation
|
||||
* image shadow calculation [Preview](http://onepixelahead.de/love2d_polyshadow18.png)
|
||||
* shadow blur
|
||||
* light color, range, smooth and glow [Preview](http://onepixelahead.de/love2d_polyshadow2.png)
|
||||
* ambient light
|
||||
* self shadowing on images with normal maps [Preview](http://onepixelahead.de/love2d_polyshadow_pixelshadow.png)
|
||||
* dynamic glow effect on images and circle/poly objects [Preview](http://onepixelahead.de/love2d_polyshadow_glow.png) [Preview](http://onepixelahead.de/love2d_polyshadow15.gif)
|
||||
* generate flat or gradient normal maps [Preview](http://onepixelahead.de/love2d_polyshadow7.png)
|
||||
* convert height maps to normal maps [Preview](http://onepixelahead.de/love2d_polyshadow8.png)
|
||||
* generate a normal map directly from the image (usually gives poor results)
|
||||
* shadow color and alpha (glass) [Preview](http://onepixelahead.de/love2d_polyshadow9.png)
|
||||
* directional light [Preview](http://onepixelahead.de/love2d_polyshadow12.png)
|
||||
* refractions (moveable) [Preview](http://onepixelahead.de/love2d_polyshadow13.gif)
|
||||
* chromatic aberration [Preview](http://onepixelahead.de/love2d_polyshadow16.gif)
|
||||
* postshader with many included postshaders, plus easy to extend
|
||||
* animations in tandem with normal maps thanks to [anim8](https://github.com/kikito/anim8)
|
||||
|
||||
## License
|
||||
|
||||
A License has been included in this project
|
||||
|
||||
## Contributors
|
||||
- Jon @xiejiangzhi
|
||||
- Brandon Blanker Lim-it @flamendless
|
||||
@ -73,3 +50,5 @@ A License has been included in this project
|
||||
- Gustavo Kishima @gukiboy
|
||||
- Rose L. Liverman @TangentFoxy
|
||||
- Kyle McLamb @Alloyed
|
||||
- @Buckle2000
|
||||
- Benoit Giannangeli @giann
|
||||
|
10
conf.lua
@ -1,9 +1,9 @@
|
||||
function love.conf(t)
|
||||
t.identity = nil -- The name of the save directory (string)
|
||||
t.version = "11.2" -- The LÖVE version this game was made for (string)
|
||||
t.version = "11.3" -- The LÖVE version this game was made for (string)
|
||||
t.console = true -- Attach a console (boolean, Windows only)
|
||||
|
||||
t.window.title = "Untitled" -- The window title (string)
|
||||
t.window.title = "Light & Shadow" -- The window title (string)
|
||||
t.window.icon = nil -- Filepath to an image to use as the window's icon (string)
|
||||
t.window.width = 800 -- The window width (number)
|
||||
t.window.height = 600 -- The window height (number)
|
||||
@ -19,15 +19,15 @@ function love.conf(t)
|
||||
t.window.highdpi = false -- Enable high-dpi mode for the window on a Retina display (boolean). Added in 0.9.1
|
||||
t.window.srgb = false -- Enable sRGB gamma correction when drawing to the screen (boolean). Added in 0.9.1
|
||||
|
||||
t.modules.audio = true -- Enable the audio module (boolean)
|
||||
t.modules.audio = false -- Enable the audio module (boolean)
|
||||
t.modules.event = true -- Enable the event module (boolean)
|
||||
t.modules.graphics = true -- Enable the graphics module (boolean)
|
||||
t.modules.image = true -- Enable the image module (boolean)
|
||||
t.modules.joystick = true -- Enable the joystick module (boolean)
|
||||
t.modules.joystick = false -- Enable the joystick module (boolean)
|
||||
t.modules.keyboard = true -- Enable the keyboard module (boolean)
|
||||
t.modules.math = true -- Enable the math module (boolean)
|
||||
t.modules.mouse = true -- Enable the mouse module (boolean)
|
||||
t.modules.physics = true -- Enable the physics module (boolean)
|
||||
t.modules.physics = false -- Enable the physics module (boolean)
|
||||
t.modules.sound = true -- Enable the sound module (boolean)
|
||||
t.modules.system = true -- Enable the system module (boolean)
|
||||
t.modules.timer = true -- Enable the timer module (boolean)
|
||||
|
@ -3,8 +3,8 @@ local x, y, z, scale = 20, -55, 1, 3.5
|
||||
|
||||
local function load()
|
||||
-- load images
|
||||
image = love.graphics.newImage("examples/gfx/scott_pilgrim.png")
|
||||
image_normal = love.graphics.newImage("examples/gfx/scott_pilgrim_NRM.png")
|
||||
image = love.graphics.newImage("examples/img/animation/scott_pilgrim.png")
|
||||
image_normal = love.graphics.newImage("examples/img/animation/scott_pilgrim_NRM.png")
|
||||
-- create light world
|
||||
lightWorld = LightWorld({ambient = {0.49, 0.49, 0.49}})
|
||||
-- create light
|
||||
|
@ -1,172 +1,43 @@
|
||||
local gamera = require "examples/vendor/gamera"
|
||||
local LightWorld = require "lib"
|
||||
|
||||
function initScene()
|
||||
-- physic world
|
||||
physicWorld = love.physics.newWorld(0, 9.81 * 64, true)
|
||||
wall1 = {}
|
||||
wall1.body = love.physics.newBody(physicWorld, 400, 605, "static")
|
||||
wall1.shape = love.physics.newRectangleShape(0, 0, 800, 10)
|
||||
wall1.fixture = love.physics.newFixture(wall1.body, wall1.shape)
|
||||
|
||||
wall2 = {}
|
||||
wall2.body = love.physics.newBody(physicWorld, -5, 300, "static")
|
||||
wall2.shape = love.physics.newRectangleShape(0, 0, 10, 600)
|
||||
wall2.fixture = love.physics.newFixture(wall2.body, wall2.shape)
|
||||
|
||||
wall3 = {}
|
||||
wall3.body = love.physics.newBody(physicWorld, 805, 300, "static")
|
||||
wall3.shape = love.physics.newRectangleShape(0, 0, 10, 600)
|
||||
wall3.fixture = love.physics.newFixture(wall3.body, wall3.shape)
|
||||
|
||||
wall4 = {}
|
||||
wall4.body = love.physics.newBody(physicWorld, 400, -5, "static")
|
||||
wall4.shape = love.physics.newRectangleShape(0, 0, 800, 10)
|
||||
wall4.fixture = love.physics.newFixture(wall4.body, wall4.shape)
|
||||
|
||||
phyCnt = 0
|
||||
phyLight = {}
|
||||
end
|
||||
local objects = {}
|
||||
local obj = require "examples.lib.object"
|
||||
local keyboard = require "examples.lib.keyboard"
|
||||
local cam, font, quadScreen, imgFloor, imgLight
|
||||
local lightRange = 300
|
||||
local lightDirection = 0.0
|
||||
local colorAberration = 0.0
|
||||
local lightWorld, mouseLight
|
||||
|
||||
local function load()
|
||||
math.randomseed(love.timer.getTime())
|
||||
cam = gamera.new(0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
love.graphics.setBackgroundColor(0, 0, 0)
|
||||
love.graphics.setDefaultFilter("nearest", "nearest")
|
||||
|
||||
-- load image font
|
||||
font = love.graphics.newImageFont("examples/gfx/font.png", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\"")
|
||||
font = love.graphics.newImageFont("examples/img/complex/font.png", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\"")
|
||||
love.graphics.setFont(font)
|
||||
|
||||
-- set background
|
||||
quadScreen = love.graphics.newQuad(0, 0, love.graphics.getWidth() + 32, love.graphics.getHeight() + 24, 32, 24)
|
||||
imgFloor = love.graphics.newImage("examples/gfx/floor.png")
|
||||
imgFloor = love.graphics.newImage("examples/img/complex/floor.png")
|
||||
imgFloor:setWrap("repeat", "repeat")
|
||||
|
||||
-- load image examples
|
||||
circle = love.graphics.newImage("examples/gfx/circle.png")
|
||||
circle_normal = love.graphics.newImage("examples/gfx/circle_normal.png")
|
||||
cone = love.graphics.newImage("examples/gfx/cone.png")
|
||||
cone_large = love.graphics.newImage("examples/gfx/cone_large.png")
|
||||
cone_large_normal = love.graphics.newImage("examples/gfx/cone_large_normal.png")
|
||||
cone_normal = love.graphics.newImage("examples/gfx/cone_normal.png")
|
||||
chest = love.graphics.newImage("examples/gfx/chest.png")
|
||||
chest_normal = love.graphics.newImage("examples/gfx/chest_normal.png")
|
||||
machine = love.graphics.newImage("examples/gfx/machine.png")
|
||||
machine_normal = love.graphics.newImage("examples/gfx/machine_normal.png")
|
||||
machine_glow = love.graphics.newImage("examples/gfx/machine_glow.png")
|
||||
machine2 = love.graphics.newImage("examples/gfx/machine2.png")
|
||||
machine2_normal = love.graphics.newImage("examples/gfx/machine2_normal.png")
|
||||
machine2_glow = love.graphics.newImage("examples/gfx/machine2_glow.png")
|
||||
blopp = love.graphics.newImage("examples/gfx/blopp.png")
|
||||
tile = love.graphics.newImage("examples/gfx/tile.png")
|
||||
tile_normal = love.graphics.newImage("examples/gfx/tile_normal.png")
|
||||
tile_glow = love.graphics.newImage("examples/gfx/tile_glow.png")
|
||||
refraction_normal = love.graphics.newImage("examples/gfx/refraction_normal.png")
|
||||
water = love.graphics.newImage("examples/gfx/water.png")
|
||||
led = love.graphics.newImage("examples/gfx/led.png")
|
||||
led2 = love.graphics.newImage("examples/gfx/led2.png")
|
||||
led3 = love.graphics.newImage("examples/gfx/led3.png")
|
||||
led_normal = love.graphics.newImage("examples/gfx/led_normal.png")
|
||||
led_glow = love.graphics.newImage("examples/gfx/led_glow.png")
|
||||
led_glow2 = love.graphics.newImage("examples/gfx/led_glow2.png")
|
||||
led_glow3 = love.graphics.newImage("examples/gfx/led_glow3.png")
|
||||
ape = love.graphics.newImage("examples/gfx/ape.png")
|
||||
ape_normal = love.graphics.newImage("examples/gfx/ape_normal.png")
|
||||
ape_glow = love.graphics.newImage("examples/gfx/ape_glow.png")
|
||||
imgLight = love.graphics.newImage("examples/gfx/light.png")
|
||||
|
||||
-- materials
|
||||
material = {}
|
||||
|
||||
local files = love.filesystem.getDirectoryItems("examples/gfx/sphere")
|
||||
for i, file in ipairs(files) do
|
||||
material[i] = love.graphics.newImage("examples/gfx/sphere/" .. file)
|
||||
end
|
||||
|
||||
-- light world
|
||||
lightRange = 400
|
||||
lightSmooth = 1.0
|
||||
|
||||
lightWorld = LightWorld({
|
||||
ambient = {15,15,15},
|
||||
refractionStrength = 16.0,
|
||||
reflectionVisibility = 0.75,
|
||||
shadowBlur = 2.0
|
||||
})
|
||||
|
||||
imgLight = love.graphics.newImage("examples/img/complex/light.png")
|
||||
lightWorld = LightWorld({ambient = {15,15,15}, refractionStrength = 16.0, reflectionVisibility = 0.75, shadowBlur = 2.0})
|
||||
mouseLight = lightWorld:newLight(0, 0, 1, 191/ 255, 0.5, lightRange)
|
||||
mouseLight:setGlowStrength(0.3)
|
||||
mouseLight:setSmooth(lightSmooth)
|
||||
mouseLight.z = 63
|
||||
lightDirection = 0.0
|
||||
colorAberration = 0.0
|
||||
|
||||
-- init physic world
|
||||
initScene()
|
||||
|
||||
helpOn = false
|
||||
physicOn = false
|
||||
lightOn = true
|
||||
gravityOn = 1
|
||||
shadowBlur = 2.0
|
||||
bloomOn = 0.0
|
||||
textureOn = true
|
||||
normalOn = false
|
||||
glowBlur = 1.0
|
||||
effectOn = 0.0
|
||||
|
||||
offsetX = 0.0
|
||||
offsetY = 0.0
|
||||
scale = 1.0
|
||||
offsetOldX = 0.0
|
||||
offsetOldY = 0.0
|
||||
offsetChanged = false
|
||||
|
||||
tileX = 0
|
||||
tileY = 0
|
||||
end
|
||||
|
||||
local function update(dt)
|
||||
love.window.setTitle("Light vs. Shadow Engine (FPS:" .. love.timer.getFPS() .. ")")
|
||||
|
||||
mx, my = (love.mouse.getX() - offsetX)/scale, (love.mouse.getY() - offsetY)/scale
|
||||
|
||||
mouseLight:setPosition(mx, my, 1 + (math.sin(lightDirection)+1.0))
|
||||
|
||||
local x, y, scale = keyboard.update(dt)
|
||||
cam:setScale(scale)
|
||||
cam:setPosition(x, y)
|
||||
local mx, my = cam:toScreen(love.mouse.getX(),love.mouse.getY())
|
||||
lightWorld:setTranslation(offsetX,offsetY, scale)
|
||||
lightDirection = lightDirection + dt
|
||||
mouseLight:setPosition(mx, my, 1 + (math.sin(lightDirection)+1.0))
|
||||
for i, o in ipairs(objects) do o:update(dt) end
|
||||
colorAberration = math.max(0.0, colorAberration - dt * 10.0)
|
||||
|
||||
if love.keyboard.isDown("up") then
|
||||
offsetY = offsetY + dt * 200
|
||||
elseif love.keyboard.isDown("down") then
|
||||
offsetY = offsetY - dt * 200
|
||||
end
|
||||
|
||||
if love.keyboard.isDown("left") then
|
||||
offsetX = offsetX + dt * 200
|
||||
elseif love.keyboard.isDown("right") then
|
||||
offsetX = offsetX - dt * 200
|
||||
end
|
||||
|
||||
if love.keyboard.isDown("-") then
|
||||
scale = scale - 0.01
|
||||
elseif love.keyboard.isDown("=") then
|
||||
scale = scale + 0.01
|
||||
end
|
||||
|
||||
for i = 1, lightWorld:getLightCount() do
|
||||
lightWorld:getLight(i):setDirection(lightDirection)
|
||||
end
|
||||
|
||||
tileX = tileX + dt * 32.0
|
||||
tileY = tileY + dt * 8.0
|
||||
for i = 1, phyCnt do
|
||||
if phyLight[i]:getType() == "refraction" then
|
||||
phyLight[i]:setNormalTileOffset(tileX, tileY)
|
||||
end
|
||||
end
|
||||
|
||||
-- draw shader
|
||||
if colorAberration > 0.0 then
|
||||
-- vert / horz blur
|
||||
lightWorld.post_shader:addEffect("blur", 2.0, 2.0)
|
||||
lightWorld.post_shader:addEffect("chromatic_aberration",
|
||||
{math.sin(lightDirection * 10.0) * colorAberration, math.cos(lightDirection * 10.0) * colorAberration},
|
||||
@ -176,401 +47,76 @@ local function update(dt)
|
||||
lightWorld.post_shader:removeEffect("blur")
|
||||
lightWorld.post_shader:removeEffect("chromatic_aberration")
|
||||
end
|
||||
|
||||
if bloomOn > 0.0 then
|
||||
-- blur, strength
|
||||
lightWorld.post_shader:addEffect("bloom", 2.0, bloomOn)
|
||||
else
|
||||
lightWorld.post_shader:removeEffect("bloom")
|
||||
end
|
||||
lightWorld:update(dt)
|
||||
end
|
||||
|
||||
local function draw()
|
||||
-- set shader buffer
|
||||
lightWorld:setTranslation(offsetX,offsetY, scale)
|
||||
love.graphics.push()
|
||||
love.graphics.translate(offsetX, offsetY)
|
||||
love.graphics.scale(scale)
|
||||
cam:draw(function(l,t,w,h)
|
||||
lightWorld:draw(function(l, t, w, h, s)
|
||||
love.graphics.setBlendMode("alpha")
|
||||
if normalOn then
|
||||
love.graphics.setColor(0.5, 0.5, 1)
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
else
|
||||
love.graphics.setColor(1, 1, 1)
|
||||
if textureOn then
|
||||
love.graphics.draw(imgFloor, quadScreen, 0,0)
|
||||
else
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, phyCnt do
|
||||
if phyLight[i]:getType() == "refraction" then
|
||||
if not normalOn then
|
||||
love.graphics.setBlendMode("alpha")
|
||||
love.graphics.setColor(1, 1, 1, 191/255)
|
||||
love.graphics.draw(water, phyLight[i].x - phyLight[i].ox, phyLight[i].y - phyLight[i].oy)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
love.graphics.setBlendMode("alpha")
|
||||
for i = 1, phyCnt do
|
||||
if phyLight[i]:getType() == "polygon" then
|
||||
math.randomseed(i)
|
||||
love.graphics.setColor(math.random(), math.random(), math.random())
|
||||
love.graphics.polygon("fill", phyLight[i]:getPoints())
|
||||
elseif phyLight[i]:getType() == "circle" then
|
||||
math.randomseed(i)
|
||||
love.graphics.setColor(math.random(), math.random(), math.random())
|
||||
local cx, cy = phyLight[i]:getPosition()
|
||||
love.graphics.circle("fill", cx, cy, phyLight[i]:getRadius())
|
||||
elseif phyLight[i]:getType() == "image" then
|
||||
if normalOn and phyLight[i].normal then
|
||||
love.graphics.setColor(1, 1, 1)
|
||||
love.graphics.draw(phyLight[i].normal, phyLight[i].x - phyLight[i].nx, phyLight[i].y - phyLight[i].ny)
|
||||
elseif not phyLight[i].material then
|
||||
math.randomseed(i)
|
||||
love.graphics.setColor(
|
||||
math.random(127, 255) / 255, math.random(127, 255)/ 255, math.random(127, 255) / 255
|
||||
)
|
||||
love.graphics.draw(phyLight[i].img, phyLight[i].x - phyLight[i].ix, phyLight[i].y - phyLight[i].iy)
|
||||
end
|
||||
end
|
||||
end
|
||||
for i, ob in ipairs(objects) do ob:draw() end
|
||||
end)
|
||||
love.graphics.pop()
|
||||
|
||||
local mx, my = cam:toScreen(love.mouse.getX(),love.mouse.getY())
|
||||
love.graphics.draw(imgLight, mx - 5, (my - 5) - (16.0 + (math.sin(lightDirection) + 1.0) * 64.0))
|
||||
|
||||
-- draw help
|
||||
if helpOn then
|
||||
end)
|
||||
love.graphics.setBlendMode("alpha")
|
||||
love.graphics.setColor(0, 0, 0, 191)
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), 44)
|
||||
love.graphics.rectangle("fill", 0, love.graphics.getHeight() - 68, 240, 68)
|
||||
love.graphics.rectangle("fill", love.graphics.getWidth() - 244, love.graphics.getHeight() - 84, 244, 84)
|
||||
love.graphics.setColor(0, 1, 0)
|
||||
love.graphics.print("F1: Help (on)", 4 + 152 * 0, 4)
|
||||
if shadowBlur >= 1.0 then
|
||||
love.graphics.setColor(0, 1, 0)
|
||||
love.graphics.print("F5: Shadowblur (" .. shadowBlur .. ")", 4 + 152 * 4, 4)
|
||||
else
|
||||
love.graphics.setColor(1, 0, 0)
|
||||
love.graphics.print("F5: Shadowblur (off)", 4 + 152 * 4, 4)
|
||||
end
|
||||
if bloomOn > 0.0 then
|
||||
love.graphics.setColor(0, 1, 0)
|
||||
love.graphics.print("F6: Bloom (" .. (bloomOn * 4) .. ")", 4 + 152 * 0, 4 + 20 * 1)
|
||||
else
|
||||
love.graphics.setColor(1, 0, 0)
|
||||
love.graphics.print("F6: Bloom (off)", 4 + 152 * 0, 4 + 20 * 1)
|
||||
end
|
||||
if textureOn then
|
||||
love.graphics.setColor(0, 1, 0)
|
||||
love.graphics.print("F7: Texture (on)", 4 + 152 * 1, 4 + 20 * 1)
|
||||
else
|
||||
love.graphics.setColor(1, 0, 0)
|
||||
love.graphics.print("F7: Texture (off)", 4 + 152 * 1, 4 + 20 * 1)
|
||||
end
|
||||
if normalOn then
|
||||
love.graphics.setColor(0, 1, 0)
|
||||
love.graphics.print("F8: Normal (on)", 4 + 152 * 2, 4 + 20 * 1)
|
||||
else
|
||||
love.graphics.setColor(1, 0, 0)
|
||||
love.graphics.print("F8: Normal (off)", 4 + 152 * 2, 4 + 20 * 1)
|
||||
end
|
||||
if glowBlur >= 1.0 then
|
||||
love.graphics.setColor(0, 1, 0)
|
||||
love.graphics.print("F9: Glow Blur (" .. glowBlur .. ")", 4 + 152 * 3, 4 + 20 * 1)
|
||||
else
|
||||
love.graphics.setColor(1, 0, 0)
|
||||
love.graphics.print("F9: Glow Blur (off)", 4 + 152 * 3, 4 + 20 * 1)
|
||||
end
|
||||
if effectOn >= 1.0 then
|
||||
love.graphics.setColor(0, 1, 0)
|
||||
love.graphics.print("F10: Effects (" .. effectOn .. ")", 4 + 152 * 4, 4 + 20 * 1)
|
||||
else
|
||||
love.graphics.setColor(1, 0, 0)
|
||||
love.graphics.print("F10: Effects (off)", 4 + 152 * 4, 4 + 20 * 1)
|
||||
end
|
||||
love.graphics.setColor(1, 0, 1)
|
||||
love.graphics.print("F11: Clear obj.", 4 + 152 * 4, 4 + 20 * 2)
|
||||
love.graphics.print("F12: Clear lights", 4 + 152 * 4, 4 + 20 * 3)
|
||||
love.graphics.setColor(0, 0.5, 1)
|
||||
love.graphics.print("WASD Keys: Move objects", 4, love.graphics.getHeight() - 20 * 3)
|
||||
love.graphics.print("c: chromatic abberation", 4, love.graphics.getHeight() - 20 * 6)
|
||||
love.graphics.print("F1-F9: Shaders", 4, love.graphics.getHeight() - 20 * 5)
|
||||
love.graphics.print("F10: Clear Bodies", 4, love.graphics.getHeight() - 20 * 4)
|
||||
love.graphics.print("F11: Clear Lights", 4, love.graphics.getHeight() - 20 * 3)
|
||||
love.graphics.print("Arrow Keys: Move map", 4, love.graphics.getHeight() - 20 * 2)
|
||||
love.graphics.print("0-9 Keys: Add object", 4, love.graphics.getHeight() - 20 * 1)
|
||||
love.graphics.setColor(1, 0.5, 0)
|
||||
love.graphics.print("M.left: Add cube", love.graphics.getWidth() - 240, love.graphics.getHeight() - 20 * 4)
|
||||
love.graphics.print("M.middle: Add light", love.graphics.getWidth() - 240, love.graphics.getHeight() - 20 * 3)
|
||||
love.graphics.print("M.right: Add circle", love.graphics.getWidth() - 240, love.graphics.getHeight() - 20 * 2)
|
||||
love.graphics.print("M.scroll: Change smooth", love.graphics.getWidth() - 240, love.graphics.getHeight() - 20 * 1)
|
||||
love.graphics.setColor(1, 0.5, 0)
|
||||
else
|
||||
love.graphics.setColor(1, 1, 1, 191/255)
|
||||
love.graphics.print("F1: Help", 4, 4)
|
||||
end
|
||||
love.graphics.print("M.left: Add cube", love.graphics.getWidth() - 180, love.graphics.getHeight() - 20 * 3)
|
||||
love.graphics.print("M.middle: Add light", love.graphics.getWidth() - 180, love.graphics.getHeight() - 20 * 2)
|
||||
love.graphics.print("M.right: Add circle", love.graphics.getWidth() - 180, love.graphics.getHeight() - 20 * 1)
|
||||
end
|
||||
|
||||
local function mousepressed(x, y, c)
|
||||
if c == "m" then
|
||||
-- add light
|
||||
local r = lightWorld:getLightCount() % 3
|
||||
local light
|
||||
|
||||
if r == 0 then
|
||||
light = lightWorld:newLight(x, y, 31/ 255, 0.5, 63/ 255, lightRange)
|
||||
elseif r == 1 then
|
||||
light = lightWorld:newLight(x, y, 0.5, 63/255, 31/255, lightRange)
|
||||
else
|
||||
light = lightWorld:newLight(x, y, 31/255, 63/255, 127/255, lightRange)
|
||||
end
|
||||
light:setSmooth(lightSmooth)
|
||||
if c == 3 then
|
||||
local light = lightWorld:newLight(x, y, math.random(), math.random(), math.random(), lightRange)
|
||||
light:setGlowStrength(0.3)
|
||||
elseif c == "l" then
|
||||
-- add rectangle
|
||||
math.randomseed(love.timer.getTime())
|
||||
phyCnt = phyCnt + 1
|
||||
local w, h = math.random(32, 64), math.random(32, 64)
|
||||
phyLight[phyCnt] = lightWorld:newPolygon(
|
||||
x, y,
|
||||
x+w, y,
|
||||
x+w, y+h,
|
||||
x, y+h
|
||||
)
|
||||
elseif c == "r" then
|
||||
-- add circle
|
||||
math.randomseed(love.timer.getTime())
|
||||
cRadius = math.random(8, 32)
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newCircle(x, y, cRadius)
|
||||
elseif c == "wu" then
|
||||
if lightSmooth < 4.0 then
|
||||
lightSmooth = lightSmooth * 1.1
|
||||
mouseLight:setSmooth(lightSmooth)
|
||||
end
|
||||
elseif c == "wd" then
|
||||
if lightSmooth > 0.5 then
|
||||
lightSmooth = lightSmooth / 1.1
|
||||
mouseLight:setSmooth(lightSmooth)
|
||||
if love.keyboard.isDown("rshift") or love.keyboard.isDown("lshift") then
|
||||
light:setAngle(math.random(1, 5) * 0.1 * math.pi)
|
||||
light:setDirection(math.random(1, 5) * 0.1 * math.pi)
|
||||
end
|
||||
elseif c == 1 then table.insert(objects, obj.Rect:new(lightWorld, x, y, math.random(32, 64), math.random(32, 64)))
|
||||
elseif c == 2 then table.insert(objects, obj.Circle:new(lightWorld, x, y, math.random(8, 32)))
|
||||
end
|
||||
end
|
||||
|
||||
local function keypressed(k, u)
|
||||
-- debug options
|
||||
if k == "f1" then
|
||||
helpOn = not helpOn
|
||||
elseif k == "f5" then
|
||||
shadowBlur = math.max(1, shadowBlur * 2.0)
|
||||
if shadowBlur > 8.0 then
|
||||
shadowBlur = 0.0
|
||||
end
|
||||
lightWorld:setShadowBlur(shadowBlur)
|
||||
elseif k == "f6" or k == "b" then
|
||||
bloomOn = math.max(0.25, bloomOn * 2.0)
|
||||
if bloomOn > 1.0 then
|
||||
bloomOn = 0.0
|
||||
end
|
||||
elseif k == "f7" then
|
||||
textureOn = not textureOn
|
||||
elseif k == "f8" then
|
||||
normalOn = not normalOn
|
||||
elseif k == "f9" then
|
||||
glowBlur = glowBlur + 1.0
|
||||
if glowBlur > 8.0 then
|
||||
glowBlur = 0.0
|
||||
end
|
||||
lightWorld:setGlowStrength(glowBlur)
|
||||
local mx, my = cam:toScreen(love.mouse.getX(),love.mouse.getY())
|
||||
if k == "f1" then lightWorld.post_shader:toggleEffect("four_colors", {0.05, 0.21, 0.05}, {0.18, 0.38, 0.18}, {0.54, 0.67, 0.05}, {0.60, 0.73, 0.05})
|
||||
elseif k == "f2" then lightWorld.post_shader:toggleEffect("scanlines")
|
||||
elseif k == "f3" then lightWorld.post_shader:toggleEffect("bloom", 2.0, 0.25)
|
||||
elseif k == "f4" then lightWorld.post_shader:toggleEffect("black_and_white")
|
||||
elseif k == "f5" then lightWorld.post_shader:toggleEffect("curvature")
|
||||
elseif k == "f6" then lightWorld.post_shader:toggleEffect("edges")
|
||||
elseif k == "f7" then lightWorld.post_shader:toggleEffect("pip")
|
||||
elseif k == "f8" then lightWorld.post_shader:toggleEffect("pixellate")
|
||||
elseif k == "f9" then lightWorld.post_shader:toggleEffect("waterpaint")
|
||||
elseif k == "f10" then
|
||||
effectOn = effectOn + 1.0
|
||||
if effectOn > 4.0 then
|
||||
effectOn = 0.0
|
||||
end
|
||||
|
||||
if effectOn == 1.0 then
|
||||
lightWorld.post_shader:addEffect("four_colors", {15, 56, 15}, {48, 98, 48}, {139, 172, 15}, {155, 188, 15})
|
||||
--lightWorld.post_shader:addEffect("4colors", {108, 108, 78}, {142, 139, 87}, {195, 196, 165}, {227, 230, 201})
|
||||
else
|
||||
lightWorld.post_shader:removeEffect("four_colors")
|
||||
end
|
||||
|
||||
if effectOn == 2.0 then
|
||||
lightWorld.post_shader:addEffect("monochrome")
|
||||
else
|
||||
lightWorld.post_shader:removeEffect("monochrome")
|
||||
end
|
||||
|
||||
if effectOn == 3.0 then
|
||||
lightWorld.post_shader:addEffect("scanlines")
|
||||
else
|
||||
lightWorld.post_shader:removeEffect("scanlines")
|
||||
end
|
||||
|
||||
if effectOn == 4.0 then
|
||||
lightWorld.post_shader:addEffect("tilt_shift", 4.0)
|
||||
else
|
||||
lightWorld.post_shader:removeEffect("tilt_shift")
|
||||
end
|
||||
|
||||
elseif k == "f11" then
|
||||
physicWorld:destroy()
|
||||
lightWorld:clearBodies()
|
||||
initScene()
|
||||
elseif k == "f12" then
|
||||
objects = {}
|
||||
elseif k == "f11" then
|
||||
lightWorld:clearLights()
|
||||
mouseLight = lightWorld:newLight(0, 0, 1, 191/255, 0.5, lightRange)
|
||||
mouseLight:setGlowStrength(0.3)
|
||||
mouseLight:setSmooth(lightSmooth)
|
||||
elseif k == "1" then
|
||||
-- add image
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newImage(circle, mx, my)
|
||||
phyLight[phyCnt]:setNormalMap(circle_normal)
|
||||
phyLight[phyCnt]:setShadowType("circle", 16)
|
||||
elseif k == "2" then
|
||||
local r = lightWorld:getBodyCount() % 2
|
||||
if r == 0 then
|
||||
-- add image
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newImage(cone, mx, my, 24, 12, 12, 16)
|
||||
phyLight[phyCnt]:setNormalMap(cone_normal)
|
||||
phyLight[phyCnt]:setShadowType("circle", 12)
|
||||
elseif r == 1 then
|
||||
-- add image
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newImage(chest, mx, my, 32, 24, 16, 0)
|
||||
phyLight[phyCnt]:setNormalMap(chest_normal)
|
||||
end
|
||||
elseif k == "3" then
|
||||
-- add image
|
||||
local r = lightWorld:getBodyCount() % #material
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newImage(ape, mx, my, 160, 128, 80, 64)
|
||||
phyLight[phyCnt]:setNormalMap(ape_normal)
|
||||
if r == 3 then
|
||||
phyLight[phyCnt]:setGlowMap(ape_glow)
|
||||
end
|
||||
phyLight[phyCnt]:setMaterial(material[r + 1])
|
||||
phyLight[phyCnt]:setShadowType("image", 0, -16, 0.0)
|
||||
elseif k == "4" then
|
||||
-- add glow image
|
||||
local r = lightWorld:getBodyCount() % 5
|
||||
if r == 0 then
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newImage(machine, mx, my, 32, 24, 16, 0)
|
||||
phyLight[phyCnt]:setNormalMap(machine_normal)
|
||||
phyLight[phyCnt]:setGlowMap(machine_glow)
|
||||
elseif r == 1 then
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newImage(machine2, mx, my, 24, 12, 12, -4)
|
||||
phyLight[phyCnt]:setNormalMap(machine2_normal)
|
||||
phyLight[phyCnt]:setGlowMap(machine2_glow)
|
||||
elseif r == 2 then
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newImage(led, mx, my, 32, 6, 16, -8)
|
||||
phyLight[phyCnt]:setNormalMap(led_normal)
|
||||
phyLight[phyCnt]:setGlowMap(led_glow)
|
||||
elseif r == 3 then
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newImage(led2, mx, my, 32, 6, 16, -8)
|
||||
phyLight[phyCnt]:setNormalMap(led_normal)
|
||||
phyLight[phyCnt]:setGlowMap(led_glow2)
|
||||
elseif r == 4 then
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newImage(led3, mx, my, 32, 6, 16, -8)
|
||||
phyLight[phyCnt]:setNormalMap(led_normal)
|
||||
phyLight[phyCnt]:setGlowMap(led_glow3)
|
||||
end
|
||||
elseif k == "5" then
|
||||
-- add image
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newImage(cone_large, mx, my, 24, 128, 12, 64)
|
||||
phyLight[phyCnt]:setNormalMap(cone_large_normal)
|
||||
phyLight[phyCnt]:setShadowType("image", 0, -6, 0.0)
|
||||
elseif k == "6" then
|
||||
-- add image
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newImage(blopp, mx, my, 42, 16, 21, 0)
|
||||
phyLight[phyCnt]:generateNormalMapGradient("gradient", "gradient")
|
||||
phyLight[phyCnt]:setAlpha(0.5)
|
||||
elseif k == "7" then
|
||||
-- add image
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newImage(tile, mx, my)
|
||||
phyLight[phyCnt]:setHeightMap(tile_normal, 2.0)
|
||||
phyLight[phyCnt]:setGlowMap(tile_glow)
|
||||
phyLight[phyCnt]:setShadow(false)
|
||||
phyLight[phyCnt].reflective = false
|
||||
elseif k == "8" then
|
||||
-- add rectangle
|
||||
phyCnt = phyCnt + 1
|
||||
local w, h = math.random(32, 64), math.random(32, 64)
|
||||
phyLight[phyCnt] = lightWorld:newPolygon(
|
||||
mx, my,
|
||||
mx+w, my,
|
||||
mx+w, my+h,
|
||||
mx, my+h
|
||||
)
|
||||
phyLight[phyCnt]:setAlpha(0.5)
|
||||
phyLight[phyCnt]:setGlowStrength(1.0)
|
||||
math.randomseed(phyCnt)
|
||||
phyLight[phyCnt]:setGlowColor(math.random(), math.random(), math.random())
|
||||
math.randomseed(phyCnt)
|
||||
phyLight[phyCnt]:setColor(math.random(), math.random(), math.random())
|
||||
elseif k == "9" then
|
||||
-- add circle
|
||||
math.randomseed(love.timer.getTime())
|
||||
cRadius = math.random(8, 32)
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newCircle(mx, my, cRadius)
|
||||
phyLight[phyCnt]:setAlpha(0.5)
|
||||
phyLight[phyCnt]:setGlowStrength(1.0)
|
||||
math.randomseed(phyCnt)
|
||||
phyLight[phyCnt]:setGlowColor(math.random(), math.random(), math.random())
|
||||
math.randomseed(phyCnt)
|
||||
phyLight[phyCnt]:setColor(math.random(), math.random(), math.random())
|
||||
elseif k == "0" then
|
||||
phyCnt = phyCnt + 1
|
||||
phyLight[phyCnt] = lightWorld:newRefraction(refraction_normal, mx, my)
|
||||
phyLight[phyCnt]:setReflection(true)
|
||||
elseif k == "k" then
|
||||
-- add light
|
||||
local r = lightWorld:getLightCount() % 3
|
||||
local light
|
||||
|
||||
if r == 0 then
|
||||
light = lightWorld:newLight(mx, my, 31/255, 127 / 255, 63 / 255, lightRange)
|
||||
elseif r == 1 then
|
||||
light = lightWorld:newLight(mx, my, 127 / 255, 63 / 255, 31 / 255, lightRange)
|
||||
else
|
||||
light = lightWorld:newLight(mx, my, 31 / 255, 63 / 255, 127 / 255, lightRange)
|
||||
end
|
||||
light:setSmooth(lightSmooth)
|
||||
light:setGlowStrength(0.3)
|
||||
elseif k == "l" then
|
||||
-- add light
|
||||
local r = lightWorld:getLightCount() % 3
|
||||
local light
|
||||
|
||||
if r == 0 then
|
||||
light = lightWorld:newLight(mx, my, 31/255, 127/255, 63/255, lightRange)
|
||||
elseif r == 1 then
|
||||
light = lightWorld:newLight(mx, my, 127/255, 63/255, 31/255, lightRange)
|
||||
else
|
||||
light = lightWorld:newLight(mx, my, 31, 63, 127, lightRange)
|
||||
end
|
||||
light:setSmooth(lightSmooth)
|
||||
light:setGlowStrength(0.3)
|
||||
math.randomseed(love.timer.getTime())
|
||||
light:setAngle(math.random(1, 5) * 0.1 * math.pi)
|
||||
elseif k == "c" then
|
||||
if colorAberration == 0.0 then
|
||||
colorAberration = 3.0
|
||||
end
|
||||
elseif k == "1" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/ape", mx, my, "image"))
|
||||
elseif k == "2" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/chest", mx, my))
|
||||
elseif k == "3" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/cone", mx, my, "circle"))
|
||||
elseif k == "4" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/cube", mx, my))
|
||||
elseif k == "5" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/cylinder", mx, my, "circle"))
|
||||
elseif k == "6" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/screen1", mx, my))
|
||||
elseif k == "7" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/screen2", mx, my))
|
||||
elseif k == "8" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/screen3", mx, my))
|
||||
elseif k == "9" then table.insert(objects, obj.ImageObject:new(lightWorld, "examples/img/complex/tile", mx, my))
|
||||
elseif k == "0" then table.insert(objects, obj.Refraction:new(lightWorld, "examples/img/complex/water", mx, my))
|
||||
elseif k == "c" then colorAberration = 3.0
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
local List = require('examples.lib.list')
|
||||
local LightWorld = require('lib')
|
||||
local examples = {
|
||||
["Animation Example"] = "animation.lua",
|
||||
["Complex Example"] = "complex.lua",
|
||||
["Gamera Example"] = "gamera.lua",
|
||||
["Hump Example"] = "hump.lua",
|
||||
["Normal Map Example"] = "normalMap.lua",
|
||||
["Only Postshader Example"] = "postshaders.lua",
|
||||
["Simple Example"] = "simple.lua",
|
||||
["STI Example"] = "simple_tiled_impl.lua",
|
||||
{"Simple", "simple.lua"},
|
||||
{"Gamera", "gamera.lua"},
|
||||
{"Hump", "hump.lua"},
|
||||
{"Normal Map", "normalMap.lua"},
|
||||
{"Animation", "animation.lua"},
|
||||
{"STI Example", "simple_tiled_impl.lua"},
|
||||
{"Only Postshader Example", "postshaders.lua"},
|
||||
{"Complex Example", "complex.lua"},
|
||||
}
|
||||
local list, smallfont, bigfont, bigball, lightWorld, lightMouse
|
||||
|
||||
@ -34,12 +34,9 @@ local function load()
|
||||
smallfont = love.graphics.newFont(12)
|
||||
bigfont = love.graphics.newFont(24)
|
||||
list.font = smallfont
|
||||
bigball = love.graphics.newImage("examples/gfx/love-big-ball.png")
|
||||
local n = 0
|
||||
for c, v in pairs(examples) do
|
||||
n = n + 1
|
||||
local title = string.format("%04d", n) .. " " .. c .. " (" .. v .. ")"
|
||||
list:add(title, v, function() start(v) end)
|
||||
bigball = love.graphics.newImage("examples/img/love-big-ball.png")
|
||||
for n, v in ipairs(examples) do
|
||||
list:add(string.format("%04d", n).." "..v[1].." ("..v[2]..")", function() start(v[2]) end)
|
||||
end
|
||||
love.window.setTitle("LOVE Example Browser")
|
||||
lightWorld = LightWorld({ambient = {0.49, 0.49, 0.49}})
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 194 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 990 B After Width: | Height: | Size: 990 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 193 B After Width: | Height: | Size: 193 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 981 B After Width: | Height: | Size: 981 B |
Before Width: | Height: | Size: 967 B After Width: | Height: | Size: 967 B |
Before Width: | Height: | Size: 1019 B After Width: | Height: | Size: 1019 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 981 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
examples/img/complex/screen3/normal.png
Normal file
After Width: | Height: | Size: 981 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1018 B After Width: | Height: | Size: 1018 B |
Before Width: | Height: | Size: 1012 B After Width: | Height: | Size: 1012 B |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 116 KiB |
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 127 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
BIN
examples/img/simple/machine.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
examples/img/simple/machine_glow.png
Normal file
After Width: | Height: | Size: 990 B |
BIN
examples/img/simple/machine_normal.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
@ -10,10 +10,10 @@ function List:new(x, y, w, h)
|
||||
return o
|
||||
end
|
||||
|
||||
function List:add(item, file, cb)
|
||||
function List:add(label, cb)
|
||||
local x, y = self.x+2, self.y+((self.h+1)*(#self.items-1)+1)
|
||||
local w, h = self.w-3, self.h
|
||||
table.insert(self.items, {item = item, file = file, cb = cb, x = x, y = y, w = w, h = h, hover = false})
|
||||
table.insert(self.items, {label = label, cb = cb, x = x, y = y, w = w, h = h, hover = false})
|
||||
end
|
||||
|
||||
function List:update(dt)
|
||||
@ -36,7 +36,7 @@ function List:draw()
|
||||
love.graphics.setColor(0, 0, 0, item.hover and 0.49 or 0.24)
|
||||
love.graphics.rectangle("fill", item.x+1, item.y+1, item.w-3, item.h)
|
||||
love.graphics.setColor(1, 1, 1, item.hover and 1 or 0.49)
|
||||
love.graphics.print(item.item, item.x+10, item.y+6)
|
||||
love.graphics.print(item.label, item.x+10, item.y+6)
|
||||
end
|
||||
end
|
||||
|
||||
|
120
examples/lib/object.lua
Normal file
@ -0,0 +1,120 @@
|
||||
local inspect = require 'examples.vendor.inspect'
|
||||
local ImageObject, Rect, Circle, Refraction = {}, {}, {}, {}
|
||||
ImageObject.__index = ImageObject
|
||||
Rect.__index = Rect
|
||||
Circle.__index = Circle
|
||||
Refraction.__index = Refraction
|
||||
local imageCache = {}
|
||||
|
||||
local function loadImg(path)
|
||||
if imageCache[path] == nil and love.filesystem.getInfo(path) ~= nil then
|
||||
imageCache[path] = love.graphics.newImage(path)
|
||||
end
|
||||
return imageCache[path]
|
||||
end
|
||||
|
||||
local function loadMaterials(path)
|
||||
if imageCache[path] == nil and love.filesystem.getInfo(path) ~= nil then
|
||||
imageCache[path] = {}
|
||||
local files = love.filesystem.getDirectoryItems(path)
|
||||
for i, file in ipairs(files) do
|
||||
imageCache[path][i] = loadImg(path .."/" .. file)
|
||||
end
|
||||
end
|
||||
return imageCache[path]
|
||||
end
|
||||
|
||||
function ImageObject:new(lightWorld, path, x, y, shadowType)
|
||||
o = {x = x, y = y, shadowType = shadowType}
|
||||
setmetatable(o, self)
|
||||
o.base = loadImg(path .. "/base.png")
|
||||
o.normal = loadImg(path .. "/normal.png")
|
||||
o.glow = loadImg(path .. "/glow.png")
|
||||
o.materials = loadMaterials(path .. "/materials")
|
||||
o.body = lightWorld:newImage(o.base, x, y)
|
||||
o.x, o.y = o.x - o.base:getWidth() * 0.5, o.y - o.base:getHeight() * 0.5
|
||||
if o.normal ~= nil then o.body:setNormalMap(o.normal) end
|
||||
if o.glow ~= nil then o.body:setGlowMap(o.glow) end
|
||||
if shadowType ~= nil then
|
||||
o.body:setShadowType(shadowType)
|
||||
end
|
||||
if o.materials ~= nil and #o.materials > 0 then
|
||||
o.body:setMaterial(o.materials[math.random(1, #o.materials-1)])
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
function ImageObject:update(dt) end
|
||||
|
||||
function ImageObject:draw()
|
||||
love.graphics.setColor(1, 1, 1)
|
||||
love.graphics.draw(self.base, self.x, self.y)
|
||||
end
|
||||
|
||||
function Rect:new(lightWorld, x, y, w, h)
|
||||
local w, h = math.random(32, 64), math.random(32, 64)
|
||||
local r, g, b = math.random(), math.random(), math.random()
|
||||
o = {x = x, y = y, w = w, h = h, r = r, g = g, b = b}
|
||||
setmetatable(o, self)
|
||||
o.body = lightWorld:newRectangle(x, y, w, h)
|
||||
o.x, o.y = o.x - o.w * 0.5, o.y - o.h * 0.5
|
||||
o.body:setGlowStrength(1.0)
|
||||
o.body:setGlowColor(math.random(), math.random(), math.random())
|
||||
o.body:setColor(r, g, b)
|
||||
return o
|
||||
end
|
||||
|
||||
function Rect:update(dt) end
|
||||
|
||||
function Rect:draw()
|
||||
love.graphics.setColor(self.r, self.g, self.b)
|
||||
love.graphics.rectangle("fill", self.x, self.y, self.w, self.h)
|
||||
end
|
||||
|
||||
function Circle:new(lightWorld, x, y, rad)
|
||||
local r, g, b = math.random(), math.random(), math.random()
|
||||
o = {x = x, y = y, rad = rad, r = r, g = g, b = b}
|
||||
setmetatable(o, self)
|
||||
o.body = lightWorld:newCircle(x, y, rad)
|
||||
o.body:setGlowStrength(1.0)
|
||||
o.body:setGlowColor(math.random(), math.random(), math.random())
|
||||
o.body:setColor(r, g, b)
|
||||
return o
|
||||
end
|
||||
|
||||
function Circle:update(dt) end
|
||||
|
||||
function Circle:draw()
|
||||
love.graphics.setColor(self.r, self.g, self.b)
|
||||
love.graphics.circle("fill", self.x, self.y, self.rad)
|
||||
end
|
||||
|
||||
function Refraction:new(lightWorld, path, x, y)
|
||||
o = {x = x, y = y, tx = 0, ty = 0}
|
||||
setmetatable(o, self)
|
||||
o.base = loadImg(path .. "/base.png")
|
||||
o.normal = loadImg(path .. "/normal.png")
|
||||
o.body = lightWorld:newRefraction(o.normal, x, y)
|
||||
o.x, o.y = o.x - o.base:getWidth() * 0.5, o.y - o.base:getHeight() * 0.5
|
||||
o.body:setReflection(true)
|
||||
return o
|
||||
end
|
||||
|
||||
function Refraction:update(dt)
|
||||
self.tx = self.tx + dt * 32.0
|
||||
self.ty = self.ty + dt * 8.0
|
||||
self.body:setNormalTileOffset(self.tx, self.ty)
|
||||
end
|
||||
|
||||
function Refraction:draw()
|
||||
love.graphics.setBlendMode("alpha")
|
||||
love.graphics.setColor(1, 1, 1, 0.74)
|
||||
love.graphics.draw(self.base, self.x, self.y)
|
||||
end
|
||||
|
||||
return {
|
||||
ImageObject = ImageObject,
|
||||
Rect = Rect,
|
||||
Circle = Circle,
|
||||
Refraction = Refraction,
|
||||
}
|
@ -5,8 +5,8 @@ local lightWorld, lightMouse
|
||||
|
||||
local function load()
|
||||
-- load images
|
||||
image = love.graphics.newImage("examples/gfx/rock.png")
|
||||
image_normal = love.graphics.newImage("examples/gfx/rock_n.png")
|
||||
image = love.graphics.newImage("examples/img/normalMap/rock.png")
|
||||
image_normal = love.graphics.newImage("examples/img/normalMap/normal.png")
|
||||
-- create light world
|
||||
lightWorld = LightWorld({ambient = {0.21,0.21,0.21}})
|
||||
-- create light
|
||||
|
@ -6,7 +6,7 @@ local img
|
||||
local function load()
|
||||
post_shader = PostShader()
|
||||
render_buffer = love.graphics.newCanvas(love.graphics.getWidth(), love.graphics.getHeight())
|
||||
img = love.graphics.newImage("examples/gfx/kingscard.jpeg")
|
||||
img = love.graphics.newImage("examples/img/postshaders/kingscard.jpeg")
|
||||
end
|
||||
|
||||
local function keypressed(k)
|
||||
|
@ -12,9 +12,9 @@ local box_locations = {
|
||||
}
|
||||
|
||||
local function load()
|
||||
image = love.graphics.newImage("examples/gfx/machine.png")
|
||||
normal = love.graphics.newImage("examples/gfx/machine_normal.png")
|
||||
glow = love.graphics.newImage("examples/gfx/machine_glow.png")
|
||||
image = love.graphics.newImage("examples/img/simple/machine.png")
|
||||
normal = love.graphics.newImage("examples/img/simple/machine_normal.png")
|
||||
glow = love.graphics.newImage("examples/img/simple/machine_glow.png")
|
||||
-- create light world
|
||||
lightWorld = LightWorld({ambient = {0.21,0.21,0.21}})
|
||||
-- create light
|
||||
|
@ -5,8 +5,8 @@ local lightWorld, map, image_normal, lightMouse
|
||||
local function load()
|
||||
-- create light world
|
||||
lightWorld = LightWorld({ambient = {0.49, 0.49, 0.49}})
|
||||
map = sti.new("examples/gfx/map.lua")
|
||||
image_normal = love.graphics.newImage("examples/gfx/border_NRM.png")
|
||||
map = sti.new("examples/img/sti/map.lua")
|
||||
image_normal = love.graphics.newImage("examples/img/sti/border_NRM.png")
|
||||
-- create light
|
||||
lightMouse = lightWorld:newLight(0, 0, 1, 0.49, 0.24, 300)
|
||||
lightMouse:setGlowStrength(0.3)
|
||||
|
330
examples/vendor/inspect.lua
vendored
Normal file
@ -0,0 +1,330 @@
|
||||
local inspect ={
|
||||
_VERSION = 'inspect.lua 3.1.0',
|
||||
_URL = 'http://github.com/kikito/inspect.lua',
|
||||
_DESCRIPTION = 'human-readable representations of tables',
|
||||
_LICENSE = [[
|
||||
MIT LICENSE
|
||||
Copyright (c) 2013 Enrique García Cota
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
}
|
||||
|
||||
local tostring = tostring
|
||||
|
||||
inspect.KEY = setmetatable({}, {__tostring = function() return 'inspect.KEY' end})
|
||||
inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end})
|
||||
|
||||
local function rawpairs(t)
|
||||
return next, t, nil
|
||||
end
|
||||
|
||||
-- Apostrophizes the string if it has quotes, but not aphostrophes
|
||||
-- Otherwise, it returns a regular quoted string
|
||||
local function smartQuote(str)
|
||||
if str:match('"') and not str:match("'") then
|
||||
return "'" .. str .. "'"
|
||||
end
|
||||
return '"' .. str:gsub('"', '\\"') .. '"'
|
||||
end
|
||||
|
||||
-- \a => '\\a', \0 => nil
|
||||
local shortControlCharEscapes = {
|
||||
["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n",
|
||||
["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v", ["\127"] = "\\127",
|
||||
}
|
||||
local longControlCharEscapes = {["\127"]="\127"} -- \a => nil, \0 => \000, 31 => \031
|
||||
for i=0, 31 do
|
||||
local ch = string.char(i)
|
||||
if not shortControlCharEscapes[ch] then
|
||||
shortControlCharEscapes[ch] = "\\"..i
|
||||
longControlCharEscapes[ch] = string.format("\\%03d", i)
|
||||
end
|
||||
end
|
||||
--longControlCharEscapes["\127"]="\\127"
|
||||
|
||||
local function escape(str)
|
||||
return (str:gsub("\\", "\\\\")
|
||||
:gsub("(%c)%f[0-9]", longControlCharEscapes)
|
||||
:gsub("%c", shortControlCharEscapes))
|
||||
end
|
||||
|
||||
local function isIdentifier(str)
|
||||
return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" )
|
||||
end
|
||||
|
||||
local function isSequenceKey(k, sequenceLength)
|
||||
return type(k) == 'number'
|
||||
and 1 <= k
|
||||
and k <= sequenceLength
|
||||
and math.floor(k) == k
|
||||
end
|
||||
|
||||
local defaultTypeOrders = {
|
||||
['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4,
|
||||
['function'] = 5, ['userdata'] = 6, ['thread'] = 7
|
||||
}
|
||||
|
||||
local function sortKeys(a, b)
|
||||
local ta, tb = type(a), type(b)
|
||||
|
||||
-- strings and numbers are sorted numerically/alphabetically
|
||||
if ta == tb and (ta == 'string' or ta == 'number') then return a < b end
|
||||
|
||||
local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb]
|
||||
-- Two default types are compared according to the defaultTypeOrders table
|
||||
if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb]
|
||||
elseif dta then return true -- default types before custom ones
|
||||
elseif dtb then return false -- custom types after default ones
|
||||
end
|
||||
|
||||
-- custom types are sorted out alphabetically
|
||||
return ta < tb
|
||||
end
|
||||
|
||||
-- For implementation reasons, the behavior of rawlen & # is "undefined" when
|
||||
-- tables aren't pure sequences. So we implement our own # operator.
|
||||
local function getSequenceLength(t)
|
||||
local len = 1
|
||||
local v = rawget(t,len)
|
||||
while v ~= nil do
|
||||
len = len + 1
|
||||
v = rawget(t,len)
|
||||
end
|
||||
return len - 1
|
||||
end
|
||||
|
||||
local function getNonSequentialKeys(t)
|
||||
local keys, keysLength = {}, 0
|
||||
local sequenceLength = getSequenceLength(t)
|
||||
for k,_ in rawpairs(t) do
|
||||
if not isSequenceKey(k, sequenceLength) then
|
||||
keysLength = keysLength + 1
|
||||
keys[keysLength] = k
|
||||
end
|
||||
end
|
||||
table.sort(keys, sortKeys)
|
||||
return keys, keysLength, sequenceLength
|
||||
end
|
||||
|
||||
local function countTableAppearances(t, tableAppearances)
|
||||
tableAppearances = tableAppearances or {}
|
||||
|
||||
if type(t) == 'table' then
|
||||
if not tableAppearances[t] then
|
||||
tableAppearances[t] = 1
|
||||
for k,v in rawpairs(t) do
|
||||
countTableAppearances(k, tableAppearances)
|
||||
countTableAppearances(v, tableAppearances)
|
||||
end
|
||||
countTableAppearances(getmetatable(t), tableAppearances)
|
||||
else
|
||||
tableAppearances[t] = tableAppearances[t] + 1
|
||||
end
|
||||
end
|
||||
|
||||
return tableAppearances
|
||||
end
|
||||
|
||||
local copySequence = function(s)
|
||||
local copy, len = {}, #s
|
||||
for i=1, len do copy[i] = s[i] end
|
||||
return copy, len
|
||||
end
|
||||
|
||||
local function makePath(path, ...)
|
||||
local keys = {...}
|
||||
local newPath, len = copySequence(path)
|
||||
for i=1, #keys do
|
||||
newPath[len + i] = keys[i]
|
||||
end
|
||||
return newPath
|
||||
end
|
||||
|
||||
local function processRecursive(process, item, path, visited)
|
||||
if item == nil then return nil end
|
||||
if visited[item] then return visited[item] end
|
||||
|
||||
local processed = process(item, path)
|
||||
if type(processed) == 'table' then
|
||||
local processedCopy = {}
|
||||
visited[item] = processedCopy
|
||||
local processedKey
|
||||
|
||||
for k,v in rawpairs(processed) do
|
||||
processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)
|
||||
if processedKey ~= nil then
|
||||
processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)
|
||||
end
|
||||
end
|
||||
|
||||
local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
|
||||
if type(mt) ~= 'table' then mt = nil end -- ignore not nil/table __metatable field
|
||||
setmetatable(processedCopy, mt)
|
||||
processed = processedCopy
|
||||
end
|
||||
return processed
|
||||
end
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
local Inspector = {}
|
||||
local Inspector_mt = {__index = Inspector}
|
||||
|
||||
function Inspector:puts(...)
|
||||
local args = {...}
|
||||
local buffer = self.buffer
|
||||
local len = #buffer
|
||||
for i=1, #args do
|
||||
len = len + 1
|
||||
buffer[len] = args[i]
|
||||
end
|
||||
end
|
||||
|
||||
function Inspector:down(f)
|
||||
self.level = self.level + 1
|
||||
f()
|
||||
self.level = self.level - 1
|
||||
end
|
||||
|
||||
function Inspector:tabify()
|
||||
self:puts(self.newline, string.rep(self.indent, self.level))
|
||||
end
|
||||
|
||||
function Inspector:alreadyVisited(v)
|
||||
return self.ids[v] ~= nil
|
||||
end
|
||||
|
||||
function Inspector:getId(v)
|
||||
local id = self.ids[v]
|
||||
if not id then
|
||||
local tv = type(v)
|
||||
id = (self.maxIds[tv] or 0) + 1
|
||||
self.maxIds[tv] = id
|
||||
self.ids[v] = id
|
||||
end
|
||||
return tostring(id)
|
||||
end
|
||||
|
||||
function Inspector:putKey(k)
|
||||
if isIdentifier(k) then return self:puts(k) end
|
||||
self:puts("[")
|
||||
self:putValue(k)
|
||||
self:puts("]")
|
||||
end
|
||||
|
||||
function Inspector:putTable(t)
|
||||
if t == inspect.KEY or t == inspect.METATABLE then
|
||||
self:puts(tostring(t))
|
||||
elseif self:alreadyVisited(t) then
|
||||
self:puts('<table ', self:getId(t), '>')
|
||||
elseif self.level >= self.depth then
|
||||
self:puts('{...}')
|
||||
else
|
||||
if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end
|
||||
|
||||
local nonSequentialKeys, nonSequentialKeysLength, sequenceLength = getNonSequentialKeys(t)
|
||||
local mt = getmetatable(t)
|
||||
|
||||
self:puts('{')
|
||||
self:down(function()
|
||||
local count = 0
|
||||
for i=1, sequenceLength do
|
||||
if count > 0 then self:puts(',') end
|
||||
self:puts(' ')
|
||||
self:putValue(t[i])
|
||||
count = count + 1
|
||||
end
|
||||
|
||||
for i=1, nonSequentialKeysLength do
|
||||
local k = nonSequentialKeys[i]
|
||||
if count > 0 then self:puts(',') end
|
||||
self:tabify()
|
||||
self:putKey(k)
|
||||
self:puts(' = ')
|
||||
self:putValue(t[k])
|
||||
count = count + 1
|
||||
end
|
||||
|
||||
if type(mt) == 'table' then
|
||||
if count > 0 then self:puts(',') end
|
||||
self:tabify()
|
||||
self:puts('<metatable> = ')
|
||||
self:putValue(mt)
|
||||
end
|
||||
end)
|
||||
|
||||
if nonSequentialKeysLength > 0 or type(mt) == 'table' then -- result is multi-lined. Justify closing }
|
||||
self:tabify()
|
||||
elseif sequenceLength > 0 then -- array tables have one extra space before closing }
|
||||
self:puts(' ')
|
||||
end
|
||||
|
||||
self:puts('}')
|
||||
end
|
||||
end
|
||||
|
||||
function Inspector:putValue(v)
|
||||
local tv = type(v)
|
||||
|
||||
if tv == 'string' then
|
||||
self:puts(smartQuote(escape(v)))
|
||||
elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or
|
||||
tv == 'cdata' or tv == 'ctype' then
|
||||
self:puts(tostring(v))
|
||||
elseif tv == 'table' then
|
||||
self:putTable(v)
|
||||
else
|
||||
self:puts('<', tv, ' ', self:getId(v), '>')
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function inspect.inspect(root, options)
|
||||
options = options or {}
|
||||
|
||||
local depth = options.depth or math.huge
|
||||
local newline = options.newline or '\n'
|
||||
local indent = options.indent or ' '
|
||||
local process = options.process
|
||||
|
||||
if process then
|
||||
root = processRecursive(process, root, {}, {})
|
||||
end
|
||||
|
||||
local inspector = setmetatable({
|
||||
depth = depth,
|
||||
level = 0,
|
||||
buffer = {},
|
||||
ids = {},
|
||||
maxIds = {},
|
||||
newline = newline,
|
||||
indent = indent,
|
||||
tableAppearances = countTableAppearances(root)
|
||||
}, Inspector_mt)
|
||||
|
||||
inspector:putValue(root)
|
||||
|
||||
return table.concat(inspector.buffer)
|
||||
end
|
||||
|
||||
setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })
|
||||
|
||||
return inspect
|
@ -60,6 +60,7 @@ local function new(id, type, ...)
|
||||
local ox = args[5] or width * 0.5
|
||||
local oy = args[6] or height * 0.5
|
||||
|
||||
obj.type = "polygon"
|
||||
obj:setPoints(
|
||||
x - ox, y - oy,
|
||||
x - ox + width, y - oy,
|
||||
|