-- Animation Stress Profile -- Tests animation system with many concurrent animations local FlexLove = require("FlexLove") local profile = { animationCount = 100, maxAnimations = 1000, minAnimations = 10, root = nil, animations = {}, elements = {}, easingFunctions = { "linear", "easeInQuad", "easeOutQuad", "easeInOutQuad", "easeInCubic", "easeOutCubic", "easeInOutCubic", }, } function profile.init() FlexLove.init({ width = love.graphics.getWidth(), height = love.graphics.getHeight(), }) profile.buildLayout() end function profile.buildLayout() profile.root = FlexLove.new({ width = "100%", height = "100%", backgroundColor = FlexLove.Color.new(0.05, 0.05, 0.1, 1), positioning = "flex", flexDirection = "vertical", overflowY = "scroll", padding = { horizontal = 20, vertical = 20 }, gap = 10, }) -- Create animated elements container local animationContainer = FlexLove.new({ width = "100%", positioning = "flex", flexDirection = "horizontal", flexWrap = "wrap", gap = 10, marginBottom = 20, }) profile.animations = {} profile.elements = {} for i = 1, profile.animationCount do local hue = (i / profile.animationCount) * 360 local baseColor = FlexLove.Color.new( 0.3 + 0.5 * math.sin(hue * math.pi / 180), 0.3 + 0.5 * math.sin((hue + 120) * math.pi / 180), 0.3 + 0.5 * math.sin((hue + 240) * math.pi / 180), 1 ) -- Choose random easing function local easingFunc = profile.easingFunctions[math.random(#profile.easingFunctions)] local box = FlexLove.new({ width = 60, height = 60, backgroundColor = baseColor, borderRadius = 8, margin = { horizontal = 5, vertical = 5 }, }) -- Store base values for animation box._baseY = box.y box._baseOpacity = 1 box._baseBorderRadius = 8 box._baseColor = baseColor -- Create animations manually since elements may not support automatic animation local animDuration = 1 + math.random() * 2 -- 1-3 seconds -- Y position animation local yAnim = FlexLove.Animation.new({ duration = animDuration, start = { offset = 0 }, final = { offset = 20 + math.random() * 40 }, easing = easingFunc, }):yoyo(true):repeatCount(0) -- 0 = infinite loop -- Opacity animation local opacityAnim = FlexLove.Animation.new({ duration = animDuration * 0.8, start = { opacity = 1 }, final = { opacity = 0.3 }, easing = easingFunc, }):yoyo(true):repeatCount(0) -- Border radius animation local radiusAnim = FlexLove.Animation.new({ duration = animDuration * 1.2, start = { borderRadius = 8 }, final = { borderRadius = 30 }, easing = easingFunc, }):yoyo(true):repeatCount(0) -- Store animations with element reference table.insert(profile.animations, { element = box, animation = yAnim, property = "y" }) table.insert(profile.animations, { element = box, animation = opacityAnim, property = "opacity" }) table.insert(profile.animations, { element = box, animation = radiusAnim, property = "borderRadius" }) table.insert(profile.elements, box) animationContainer:addChild(box) end profile.root:addChild(animationContainer) -- Info panel local infoPanel = FlexLove.new({ width = "100%", padding = { horizontal = 15, vertical = 15 }, backgroundColor = FlexLove.Color.new(0.1, 0.1, 0.2, 0.9), borderRadius = 8, positioning = "flex", flexDirection = "vertical", gap = 5, }) infoPanel:addChild(FlexLove.new({ text = string.format("Animated Elements: %d (Press +/- to adjust)", profile.animationCount), fontSize = 18, textColor = FlexLove.Color.new(1, 1, 1, 1), })) infoPanel:addChild(FlexLove.new({ text = string.format("Active Animations: %d", #profile.animations), fontSize = 14, textColor = FlexLove.Color.new(0.8, 0.8, 0.8, 1), })) infoPanel:addChild(FlexLove.new({ text = "Animating: position, opacity, borderRadius", fontSize = 14, textColor = FlexLove.Color.new(0.8, 0.8, 0.8, 1), })) infoPanel:addChild(FlexLove.new({ text = string.format("Easing Functions: %d variations", #profile.easingFunctions), fontSize = 14, textColor = FlexLove.Color.new(0.8, 0.8, 0.8, 1), })) profile.root:addChild(infoPanel) end function profile.update(dt) -- Update all animations and apply to elements for _, animData in ipairs(profile.animations) do animData.animation:update(dt) local values = animData.animation:interpolate() if animData.property == "y" and values.offset then animData.element.y = (animData.element._baseY or animData.element.y) + values.offset elseif animData.property == "opacity" and values.opacity then animData.element.opacity = values.opacity elseif animData.property == "borderRadius" and values.borderRadius then animData.element.borderRadius = values.borderRadius end end end function profile.draw() if profile.root then profile.root:draw() end -- Overlay info love.graphics.setColor(1, 1, 1, 1) love.graphics.print("Animation Stress Test", 10, love.graphics.getHeight() - 100) love.graphics.print( string.format("Animations: %d | Range: %d-%d", #profile.animations, profile.minAnimations * 3, profile.maxAnimations * 3 ), 10, love.graphics.getHeight() - 80 ) love.graphics.print("Press + to add 10 animated elements", 10, love.graphics.getHeight() - 60) love.graphics.print("Press - to remove 10 animated elements", 10, love.graphics.getHeight() - 45) end function profile.keypressed(key, profiler) if key == "=" or key == "+" then -- Create snapshot before changing animation count if profiler then local label = string.format("%d animations", profile.animationCount) profiler:createSnapshot(label, { animationCount = profile.animationCount, activeAnimations = #profile.animations }) end profile.animationCount = math.min(profile.maxAnimations, profile.animationCount + 10) profile.buildLayout() elseif key == "-" or key == "_" then -- Create snapshot before changing animation count if profiler then local label = string.format("%d animations", profile.animationCount) profiler:createSnapshot(label, { animationCount = profile.animationCount, activeAnimations = #profile.animations }) end profile.animationCount = math.max(profile.minAnimations, profile.animationCount - 10) profile.buildLayout() end end function profile.resize(w, h) FlexLove.resize(w, h) profile.buildLayout() end function profile.reset() profile.animationCount = 100 profile.buildLayout() end function profile.cleanup() profile.animations = {} profile.elements = {} profile.root = nil end return profile