I have a question
I would like to add a sprite blur effect, when the object is moving. The higher the speed, the bigger the blur. Is it possible to achieve this programmatically ?
Youd have to search and learn about render targets. Although im not the best person to give aid about, for i have tried in the past making something similar but didnt quite achieve it. But i think that for something like that there might be an already existing extension.
Hi @FredZX !
What you want to achieve is most probably a motion blur. I once adapted an implementation of motion blur from shadertoy (Shader - Shadertoy BETA) as a fragment program for a sprite to Defold:
You probably want it rather to be aplied to everything on your screen, so you might render your scene to a render target (a separate, internal buffer/texture) and then perform this motion blur as a postprocessing when drawing this render target to a quad (simplest plane, a geometry to which you assign a texture) and this quad will fill the screen. This is the most common post-processing pipeline in Defold, let us know if this is understandable to you or you need more explanations
You might get to know how to draw to an offset buffer / render target and to quad filling the screen after watchin my video:
or reading official Defold example:
After understading how to make post-processing with this technique - let us know how are you familiar with GLSL and if you can adapt the motion blur example to your needs
I’m not familiar with this technique, but I’m going to try it
I will be experimenting with this, maybe I will come with some solution, but please don’t rely on me, it could be that I will get it done quickly or after ages, as I rarely have time for such experiments, sorry!
But if you will try and get stuck on anything, let us know and we will try to help
Did you find a solution? I made a trail.
--[[
Estela Simple con go.animate() y Delay por Segmento - v21 (Cabeza Animada)
- CORRECCIÓN: La cabeza AHORA TAMBIÉN se mueve con go.animate().
- Al hacer clic:
- La 'cabeza' (este GO) inicia una animación go.animate() hacia el punto de clic (delay 0).
- TODOS los segmentos inician una animación go.animate() hacia el MISMO punto de clic.
- Cada segmento inicia su animación con un DELAY diferente y configurable.
- Usa go.EASING_OUTELASTIC para TODO.
- SIN seguimiento continuo, SIN Lerp manual para segmentos.
Asegúrate de que 'anim_duration' sea suficientemente largo para apreciar el rebote elástico.
]]
-- Propiedades Necesarias --
go.property("numero_segmentos", 10)
go.property("url_fabrica_segmento", msg.url("#trail_factory")) -- Fábrica para los segmentos
go.property("anim_duration", 0.8) -- Duración de la animación de CADA objeto (cabeza y segmentos)
-- ¡Prueba valores ALTOS (0.6+) para ver el rebote!
go.property("segment_delay_step", 0.05) -- Delay ADICIONAL por cada segmento (segundos)
-- INIT: Crear los segmentos
function init(self)
msg.post(".", "acquire_input_focus")
-- Validar propiedades
self.numero_segmentos = math.max(0, self.numero_segmentos)
self.anim_duration = math.max(0.01, self.anim_duration)
self.segment_delay_step = math.max(0.0, self.segment_delay_step)
self.segments_id = {} -- Tabla para guardar los IDs
-- Crear los segmentos iniciales
local initial_pos = go.get_position()
for i = 1, self.numero_segmentos do
local id = factory.create(self.url_fabrica_segmento, initial_pos)
if id then
table.insert(self.segments_id, id)
else
print("ERROR: No se pudo crear segmento", i, "desde", self.url_fabrica_segmento)
end
end
print("Estela Simple v21 lista (Cabeza Animada). Segmentos:", self.numero_segmentos)
print("Anim Duration:", self.anim_duration, "s | Delay Step:", self.segment_delay_step, "s")
print("Haz clic para mover la estela con Easing OUTELASTIC y delay.")
end
-- ON_INPUT: Detectar clic y lanzar TODAS las animaciones (incluida la cabeza)
function on_input(self, action_id, action)
if (action_id == hash("touch") or action_id == hash("click")) and action.pressed then
-- 1. Determinar la posición objetivo final (el clic)
local target_pos = vmath.vector3(action.x, action.y, 0)
local current_head_pos = go.get_position() -- Posición actual antes de animar
target_pos.z = current_head_pos.z
print("Clic -> Animando cabeza y segmentos hacia", target_pos)
-- 2. *** CAMBIO CLAVE: Animar la CABEZA en lugar de moverla instantáneamente ***
-- Cancelar animación previa de la cabeza
go.cancel_animations(".", "position")
-- Animar la cabeza hacia el target con delay 0
go.animate(
".", -- Este GO (la cabeza)
"position",
go.PLAYBACK_ONCE_FORWARD,
target_pos, -- El destino del clic
go.EASING_OUTELASTIC,
self.anim_duration, -- Misma duración que los segmentos
0 -- Sin delay para la cabeza
)
-- Ya NO usamos: go.set_position(target_pos, ".")
-- 3. Iterar sobre TODOS los segmentos y lanzar su animación con su delay
for i, segment_id in ipairs(self.segments_id) do
local segment_exists = pcall(function() return go.exists(segment_id) end)
if segment_exists then
-- Calcular el delay para ESTE segmento
-- (El delay ahora es relativo al inicio de la animación de la cabeza)
local delay = i * self.segment_delay_step -- Ajuste: el primero (i=1) tiene step*1 de delay
-- Si quieres que el primero siga pegado a la cabeza, usa (i-1) * step
-- Cancelar animación de posición anterior para este segmento
go.cancel_animations(segment_id, "position")
-- Iniciar la animación para ESTE segmento hacia el MISMO target_pos
go.animate(
segment_id,
"position",
go.PLAYBACK_ONCE_FORWARD,
target_pos, -- Mismo destino que la cabeza
go.EASING_OUTELASTIC,
self.anim_duration,
delay -- El delay calculado
)
end
end
end
end
-- FINAL: Limpiar los segmentos creados
function final(self)
msg.post(".", "release_input_focus")
for _, segment_id in ipairs(self.segments_id) do
pcall(function()
if go.exists(segment_id) then
go.cancel_animations(segment_id)
go.delete(segment_id)
end
end)
end
self.segments_id = {}
end
-- UPDATE: No necesario
-- function update(self, dt)
-- end
If you’re looking for a trail fx, there’s a great one: