- 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 = {
|
||||||
|
target = Vec3 {},
|
||||||
__Camera = {
|
|
||||||
pivotPosition = Vec3 {},
|
|
||||||
position = Vec3 {},
|
position = Vec3 {},
|
||||||
velocity = Vec3 {},
|
lerp_speed = 5.0
|
||||||
fixed = false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 = {
|
__Entity = {
|
||||||
id = nil,
|
id = nil,
|
||||||
sprite = __AnimatedSprite,
|
sprite = __AnimatedSprite,
|
||||||
position = Vec3 {},
|
position = Vec3 {}, -- world position
|
||||||
velocity = Vec3 {},
|
velocity = Vec3 {},
|
||||||
rotation = 0, -- clockwise radians
|
rotation = 0, -- clockwise radians
|
||||||
friction = 0.98,
|
friction = 0.98,
|
||||||
speed = 3, -- m/s
|
speed = 3, -- m/s
|
||||||
rotation_speed = 1, --rad/sec
|
|
||||||
state = "walk"
|
state = "walk"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,8 +29,14 @@ end
|
|||||||
|
|
||||||
function __Entity:processMovement()
|
function __Entity:processMovement()
|
||||||
self.position = self.position + self.velocity
|
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
|
end
|
||||||
|
|
||||||
function __Entity:lookAt(vec)
|
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)]
|
return lookup[get_direction_index(rotation)]
|
||||||
end
|
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 }
|
acc = acc + Vec3 { 0, 1 }
|
||||||
end
|
end
|
||||||
|
|
||||||
self.entity.velocity = self.entity.velocity
|
self.entity.velocity = ((acc:normalize() or Vec3 {})
|
||||||
+ ((acc:normalize() or Vec3 {})
|
* self.entity.speed * dt)
|
||||||
* self.entity.speed
|
|
||||||
* dt)
|
|
||||||
|
|
||||||
|
|
||||||
self.entity:update(dt)
|
self.entity:update(dt)
|
||||||
|
|||||||
108
main.lua
108
main.lua
@ -1,77 +1,105 @@
|
|||||||
require "lib.asset_bundle"
|
require "lib.asset_bundle"
|
||||||
require "lib.player"
|
require "lib.player"
|
||||||
require "lib.math2"
|
require "lib.math2"
|
||||||
|
require "lib.light_source"
|
||||||
|
require "lib.camera"
|
||||||
|
|
||||||
PIXEL_PER_METER = 48
|
PIXELS_PER_METER = 48
|
||||||
|
|
||||||
P = nil
|
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()
|
function love.load()
|
||||||
AssetBundle:load()
|
AssetBundle:load()
|
||||||
love.window.setMode(1080, 720, { resizable = true, msaa = 4 })
|
love.window.setMode(1080, 720, { resizable = true, msaa = 4 })
|
||||||
|
|
||||||
P = Player('fox')
|
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')
|
print('ready')
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.update(dt)
|
function love.update(dt)
|
||||||
P:update(dt)
|
P:update(dt)
|
||||||
|
|
||||||
|
Camera.target = P.entity.position
|
||||||
|
Camera:update(dt)
|
||||||
end
|
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()
|
function love.draw()
|
||||||
love.graphics.clear(1, 1, 1)
|
love.graphics.clear(1, 1, 1)
|
||||||
local spriteCanvas = love.graphics.newCanvas()
|
local spriteCanvas = love.graphics.newCanvas()
|
||||||
|
local width, height = spriteCanvas:getDimensions()
|
||||||
spriteCanvas:setFilter("linear", "linear")
|
spriteCanvas:setFilter("linear", "linear")
|
||||||
|
|
||||||
love.graphics.setCanvas(spriteCanvas)
|
love.graphics.setCanvas(spriteCanvas)
|
||||||
love.graphics.clear(1, 1, 1)
|
love.graphics.clear(1, 1, 1)
|
||||||
|
|
||||||
drawShadow(P.entity, Vec3 { 200, 200 }, 200)
|
love.graphics.push()
|
||||||
drawShadow(P.entity, Vec3 { 300, 200 }, 200)
|
love.graphics.translate(width / 2, height / 2) -- теперь экранный ноль координат будет в центре экрана
|
||||||
drawShadow(P.entity, Vec3 { 400, 200 }, 200)
|
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.setColor(1, 0, 0, 1)
|
||||||
love.graphics.circle("fill", 200, 200, 10)
|
love.graphics.push()
|
||||||
love.graphics.circle("fill", 300, 200, 10)
|
love.graphics.translate(worldToScreen(Lights[1].position).x, worldToScreen(Lights[1].position).y)
|
||||||
love.graphics.circle("fill", 400, 200, 10)
|
love.graphics.circle("fill", 0, 0, 0.1 * PIXELS_PER_METER)
|
||||||
|
love.graphics.pop()
|
||||||
|
love.graphics.pop()
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
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()
|
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.draw(spriteCanvas, 0, 0, 0, scale, scale)
|
||||||
|
|
||||||
|
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
end
|
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