- added world coordinates
- added camera following some target world position
This commit is contained in:
parent
6a8bc1e07c
commit
7aefcd4331
@ -1,25 +0,0 @@
|
||||
extern vec2 light_dir; // направление света, нормализованное
|
||||
extern float flatten; // насколько тень сплющена (0.2 - норм)
|
||||
extern float softness; // степень мягкости по краям
|
||||
|
||||
vec4 effect(vec4 color, Image tex, vec2 tex_coords, vec2 screen_coords)
|
||||
{
|
||||
// Получаем оригинальный цвет спрайта
|
||||
vec4 tex_color = Texel(tex, tex_coords);
|
||||
|
||||
// Преобразуем цвет в "тень"
|
||||
float alpha = tex_color.a;
|
||||
vec3 shadow_color = vec3(0.0); // черная тень
|
||||
|
||||
// Модифицируем UV, чтобы проецировать вниз и вбок
|
||||
vec2 offset = tex_coords;
|
||||
offset.y -= tex_coords.y * flatten; // сплющиваем вниз
|
||||
offset.x += tex_coords.y * flatten * light_dir.x; // сдвигаем в сторону
|
||||
|
||||
vec4 proj = Texel(tex, offset);
|
||||
|
||||
// Мягкость края тени (можно отключить, если не нужно)
|
||||
float edge_fade = smoothstep(0.0, softness, proj.a);
|
||||
|
||||
return vec4(shadow_color, proj.a * edge_fade * 0.6); // альфа настраивается
|
||||
}
|
||||
@ -1,8 +1,13 @@
|
||||
require 'lib.entity'
|
||||
|
||||
__Camera = {
|
||||
pivotPosition = Vec3 {},
|
||||
Camera = {
|
||||
target = Vec3 {},
|
||||
position = Vec3 {},
|
||||
velocity = Vec3 {},
|
||||
fixed = false,
|
||||
lerp_speed = 5.0
|
||||
}
|
||||
|
||||
function Camera:update(dt)
|
||||
if not self.target then return end
|
||||
|
||||
-- Плавное движение камеры к цели
|
||||
local to_target = self.target - self.position
|
||||
self.position = self.position + to_target:scale(dt * self.lerp_speed)
|
||||
end
|
||||
|
||||
@ -4,12 +4,11 @@ require 'lib.vec3'
|
||||
__Entity = {
|
||||
id = nil,
|
||||
sprite = __AnimatedSprite,
|
||||
position = Vec3 {},
|
||||
position = Vec3 {}, -- world position
|
||||
velocity = Vec3 {},
|
||||
rotation = 0, -- clockwise radians
|
||||
friction = 0.98,
|
||||
speed = 3, -- m/s
|
||||
rotation_speed = 1, --rad/sec
|
||||
state = "walk"
|
||||
}
|
||||
|
||||
@ -30,8 +29,14 @@ end
|
||||
|
||||
function __Entity:processMovement()
|
||||
self.position = self.position + self.velocity
|
||||
self.velocity = self.velocity * self.friction
|
||||
self.rotation = self.velocity:direction()
|
||||
|
||||
--self.velocity = self.velocity * self.friction
|
||||
if self.velocity:length() > self.speed then
|
||||
self.velocity = self.velocity:normalize() * self.speed
|
||||
end
|
||||
if (self.velocity:length() ~= 0) then
|
||||
self.rotation = self.velocity:direction()
|
||||
end
|
||||
end
|
||||
|
||||
function __Entity:lookAt(vec)
|
||||
|
||||
14
lib/light_source.lua
Normal file
14
lib/light_source.lua
Normal file
@ -0,0 +1,14 @@
|
||||
__LightSource = {
|
||||
position = Vec3 {},
|
||||
power = 0, -- in meters
|
||||
color = Vec3 {} --r, g, b
|
||||
}
|
||||
|
||||
function LightSource(position, power, color)
|
||||
local l = {
|
||||
position = position,
|
||||
power = power,
|
||||
color = color
|
||||
}
|
||||
return setmetatable(l, { __index = __LightSource })
|
||||
end
|
||||
@ -20,3 +20,8 @@ math.named_direction = function(rotation)
|
||||
|
||||
return lookup[get_direction_index(rotation)]
|
||||
end
|
||||
|
||||
-- Округляет вниз n до самого большого k * step, большего или равного n
|
||||
math.step_floor = function(n, step)
|
||||
return math.floor(n / step) * step
|
||||
end
|
||||
|
||||
@ -25,10 +25,8 @@ function __Player:update(dt)
|
||||
acc = acc + Vec3 { 0, 1 }
|
||||
end
|
||||
|
||||
self.entity.velocity = self.entity.velocity
|
||||
+ ((acc:normalize() or Vec3 {})
|
||||
* self.entity.speed
|
||||
* dt)
|
||||
self.entity.velocity = ((acc:normalize() or Vec3 {})
|
||||
* self.entity.speed * dt)
|
||||
|
||||
|
||||
self.entity:update(dt)
|
||||
|
||||
108
main.lua
108
main.lua
@ -1,77 +1,105 @@
|
||||
require "lib.asset_bundle"
|
||||
require "lib.player"
|
||||
require "lib.math2"
|
||||
require "lib.light_source"
|
||||
require "lib.camera"
|
||||
|
||||
PIXEL_PER_METER = 48
|
||||
PIXELS_PER_METER = 48
|
||||
|
||||
P = nil
|
||||
|
||||
Entities = {}
|
||||
Lights = {
|
||||
LightSource(Vec3 { 1, 1 }, 5),
|
||||
-- LightSource(Vec3 { 300, 200 }, 5),
|
||||
-- LightSource(Vec3 { 400, 200 }, 5)
|
||||
}
|
||||
|
||||
function love.conf(t)
|
||||
t.console = true
|
||||
end
|
||||
|
||||
function love.load()
|
||||
AssetBundle:load()
|
||||
love.window.setMode(1080, 720, { resizable = true, msaa = 4 })
|
||||
|
||||
P = Player('fox')
|
||||
P.entity.position = Vec3 { 200, 200 }
|
||||
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, radius)
|
||||
local shadow_vec = light - entity.position
|
||||
local dist = shadow_vec:length()
|
||||
if dist > radius then return end
|
||||
|
||||
|
||||
love.graphics.setColor(0, 0, 0, math.min(0.5, 1 - (dist / radius)))
|
||||
local tex, quad = entity:spriteFromAngle(shadow_vec:direction())
|
||||
|
||||
love.graphics.draw(tex, quad,
|
||||
worldToScreen(entity.position).x,
|
||||
worldToScreen(entity.position).y - 10,
|
||||
math.step_floor(shadow_vec:direction() - math.pi / 2, math.pi / 4),
|
||||
1, math.sin(20), tex:getHeight() / 2, tex:getHeight())
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
|
||||
function love.draw()
|
||||
love.graphics.clear(1, 1, 1)
|
||||
local spriteCanvas = love.graphics.newCanvas()
|
||||
local width, height = spriteCanvas:getDimensions()
|
||||
spriteCanvas:setFilter("linear", "linear")
|
||||
|
||||
love.graphics.setCanvas(spriteCanvas)
|
||||
love.graphics.clear(1, 1, 1)
|
||||
|
||||
drawShadow(P.entity, Vec3 { 200, 200 }, 200)
|
||||
drawShadow(P.entity, Vec3 { 300, 200 }, 200)
|
||||
drawShadow(P.entity, Vec3 { 400, 200 }, 200)
|
||||
love.graphics.push()
|
||||
love.graphics.translate(width / 2, height / 2) -- теперь экранный ноль координат будет в центре экрана
|
||||
for _, e in pairs(Entities) do
|
||||
for _, l in pairs(Lights) do
|
||||
drawShadow(e, l.position, l.power)
|
||||
end
|
||||
|
||||
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.setColor(1, 0, 0, 1)
|
||||
love.graphics.circle("fill", 200, 200, 10)
|
||||
love.graphics.circle("fill", 300, 200, 10)
|
||||
love.graphics.circle("fill", 400, 200, 10)
|
||||
love.graphics.push()
|
||||
love.graphics.translate(worldToScreen(Lights[1].position).x, worldToScreen(Lights[1].position).y)
|
||||
love.graphics.circle("fill", 0, 0, 0.1 * PIXELS_PER_METER)
|
||||
love.graphics.pop()
|
||||
love.graphics.pop()
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
|
||||
local tex, quad = P.entity:spriteFromAngle(math.pi / 2)
|
||||
love.graphics.draw(tex, quad, P.entity.position.x, P.entity.position.y,
|
||||
0,
|
||||
1, 1, tex:getHeight() / 2, tex:getHeight())
|
||||
|
||||
love.graphics.setCanvas()
|
||||
|
||||
local scale = math.min(love.graphics.getDimensions()) / (15 * PIXEL_PER_METER);
|
||||
local scale = math.min(love.graphics.getDimensions()) / (15 * PIXELS_PER_METER);
|
||||
love.graphics.draw(spriteCanvas, 0, 0, 0, scale, scale)
|
||||
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
function love.conf(t)
|
||||
t.console = true
|
||||
end
|
||||
|
||||
function drawShadow(entity, light, radius)
|
||||
local shadow_vec = light - entity.position
|
||||
local dist = shadow_vec:length()
|
||||
if dist > radius then return end
|
||||
|
||||
love.graphics.setColor(0, 0, 0, math.min(0.5, 1 - (dist / radius)))
|
||||
local tex, quad = P.entity:spriteFromAngle(shadow_vec:direction())
|
||||
love.graphics.draw(tex, quad, P.entity.position.x, P.entity.position.y - 10,
|
||||
shadow_vec:direction() - math.pi / 2,
|
||||
1, math.sin(20), tex:getHeight() / 2, tex:getHeight())
|
||||
|
||||
-- love.graphics.push()
|
||||
-- love.graphics.setColor(0, 0, 0, 0.5)
|
||||
-- love.graphics.translate(entity.position.x, entity.position.y)
|
||||
-- love.graphics.scale(1, 0.342)
|
||||
-- love.graphics.circle("fill", 0, 0, 20)
|
||||
-- love.graphics.pop()
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 1) -- сброс цвета
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user