161 lines
4.4 KiB
Lua
161 lines
4.4 KiB
Lua
require "lib.asset_bundle"
|
|
require "lib.player"
|
|
require "lib.math2"
|
|
require "lib.light_source"
|
|
require "lib.camera"
|
|
|
|
PIXELS_PER_METER = 48
|
|
|
|
P = nil
|
|
|
|
Entities = {}
|
|
Lights = nil
|
|
|
|
function love.conf(t)
|
|
t.console = true
|
|
end
|
|
|
|
function love.load()
|
|
AssetBundle:load()
|
|
love.window.setMode(1080, 720, { resizable = true, msaa = 4, vsync = true })
|
|
|
|
Lights = { LightSource(Vec3 { 1, 1 }, 3, Vec3 { 0.5, 0.2, 1.0 }),
|
|
LightSource(Vec3 { 4, 1 }, 10, Vec3 { 0.3, 0.7, 1.0 }, nil, AssetBundle.files.masks.noise),
|
|
LightSource(Vec3 { 7, 1 }, 3, Vec3 { 0.8, 0.3, 1.0 }), }
|
|
|
|
P = Player('fox')
|
|
P.entity.position = Vec3 { 7, 7 }
|
|
Entities.player = P.entity
|
|
|
|
Camera.position = Vec3 { 0, 0 }
|
|
|
|
print('ready')
|
|
end
|
|
|
|
function love.update(dt)
|
|
P:update(dt)
|
|
|
|
Camera.target = P.entity.position
|
|
Camera:update(dt)
|
|
end
|
|
|
|
-- Преобразует вектор мировых координат (в метрах) в вектор экранных координат (в пикселях)
|
|
local function worldToScreen(worldPos)
|
|
return (worldPos - Camera.position) * PIXELS_PER_METER
|
|
end
|
|
|
|
|
|
local function drawShadow(entity, light)
|
|
local shadow_vec = light.position - entity.position
|
|
local dist = shadow_vec:length()
|
|
if dist > light.power then return end
|
|
|
|
|
|
love.graphics.setColor(0, 0, 0, math.min(0.5, 1 - (dist / light.power)))
|
|
local tex, quad = entity:spriteFromAngle(shadow_vec:direction())
|
|
|
|
love.graphics.draw(tex, quad,
|
|
worldToScreen(entity.position).x,
|
|
worldToScreen(entity.position).y - 10,
|
|
shadow_vec:direction() - math.pi / 2,
|
|
1, math.sin(20), tex:getHeight() / 2, tex:getHeight())
|
|
|
|
love.graphics.setColor(1, 1, 1, 1)
|
|
end
|
|
|
|
local function drawLight(light)
|
|
local shader = light.shader
|
|
|
|
local pos = worldToScreen(light.position)
|
|
shader:send("color", { light.color.x, light.color.y, light.color.z })
|
|
shader:send("time", love.timer.getTime() + light.seed)
|
|
|
|
local scale = light.power * PIXELS_PER_METER / 64
|
|
love.graphics.setShader(shader)
|
|
love.graphics.setColor(1, 1, 1, 1)
|
|
love.graphics.draw(light.mask,
|
|
pos.x - light.power * PIXELS_PER_METER,
|
|
pos.y - light.power * PIXELS_PER_METER,
|
|
0,
|
|
scale,
|
|
scale)
|
|
love.graphics.setShader()
|
|
end
|
|
|
|
|
|
local function applyBlur(input, output, radius)
|
|
local blurShader = AssetBundle.files.shaders.blur
|
|
|
|
-- Горизонтальный проход
|
|
blurShader:send("direction", { 1.0, 0.0 })
|
|
blurShader:send("radius", radius)
|
|
|
|
output:renderTo(function()
|
|
love.graphics.setShader(blurShader)
|
|
love.graphics.draw(input)
|
|
love.graphics.setShader()
|
|
end)
|
|
|
|
-- Вертикальный проход
|
|
input:renderTo(function()
|
|
love.graphics.setShader(blurShader)
|
|
blurShader:send("direction", { 0.0, 1.0 })
|
|
love.graphics.draw(output)
|
|
love.graphics.setShader()
|
|
end)
|
|
end
|
|
|
|
function love.draw()
|
|
local width, height = love.graphics.getDimensions()
|
|
love.graphics.clear(0.1, 0.1, 0.1, 1.0)
|
|
|
|
local spriteCanvas = love.graphics.newCanvas()
|
|
local shadowCanvas = love.graphics.newCanvas()
|
|
local lightCanvas = love.graphics.newCanvas()
|
|
|
|
love.graphics.clear(0.1, 0.1, 0.1, 1.0)
|
|
|
|
love.graphics.push()
|
|
love.graphics.translate(width / 2, height / 2) -- теперь экранный ноль координат будет в центре экрана
|
|
for _, e in pairs(Entities) do
|
|
for _, l in pairs(Lights) do
|
|
love.graphics.setCanvas(shadowCanvas)
|
|
drawShadow(e, l)
|
|
end
|
|
|
|
love.graphics.setCanvas(spriteCanvas)
|
|
local tex, quad = e:spriteFromAngle(math.pi / 2)
|
|
love.graphics.draw(tex, quad,
|
|
worldToScreen(e.position).x,
|
|
worldToScreen(e.position).y,
|
|
0,
|
|
1, 1, tex:getHeight() / 2, tex:getHeight())
|
|
end
|
|
|
|
|
|
love.graphics.setCanvas(lightCanvas)
|
|
love.graphics.clear(0, 0, 0, 1)
|
|
|
|
for _, light in ipairs(Lights) do
|
|
drawLight(light)
|
|
end
|
|
|
|
love.graphics.setCanvas()
|
|
|
|
|
|
|
|
love.graphics.pop()
|
|
love.graphics.setColor(1, 1, 1, 1)
|
|
love.graphics.setCanvas()
|
|
|
|
applyBlur(shadowCanvas, love.graphics.newCanvas(), 10.0) -- тени мягче
|
|
love.graphics.draw(shadowCanvas)
|
|
love.graphics.draw(spriteCanvas)
|
|
|
|
love.graphics.setBlendMode("add", "premultiplied")
|
|
love.graphics.draw(lightCanvas)
|
|
love.graphics.setBlendMode("alpha")
|
|
|
|
love.graphics.setColor(1, 1, 1, 1)
|
|
end
|