├── README.md ├── LICENCE.md └── splashy ├── init.lua └── tween.lua /README.md: -------------------------------------------------------------------------------- 1 | ![](https://i.imgur.com/9mlZVeT.png) 2 | 3 | __splashy__ is a simple and basic library for LÖVE, that allows the easy implementation of splash screens to any project. 4 | 5 | 6 | # Installation 7 | To install, extract the splashy folder to somewhere in your project (usually a /libs folder) 8 | 9 | Then setup your main.lua like this: 10 | 11 | ```lua 12 | splashy = require 'path/to/splashy/folder' 13 | 14 | function love.draw() 15 | 16 | splashy.draw() 17 | 18 | end 19 | 20 | function love.update(dt) 21 | 22 | splashy.update(dt) 23 | 24 | end 25 | ``` 26 | 27 | Then you'll have a barebones installation complete! 28 | 29 | # Demo 30 | You can see the code demo of the library [here.](https://github.com/VideahGams/splashyDemo) 31 | 32 | # Interface 33 | 34 | ## Splash Creation 35 | 36 | ```lua 37 | splashy.addSplash(image, duration, index, color, scale) 38 | ``` 39 | 40 | * `image` is a drawable (usually an image) to be drawed in a splash. 41 | * `duration` is an optional argument, to set how long the image fade will last. It must be a positive number. (default: 2) 42 | * `index` is an optional argument allowing to set custom splash index number for any reason you would need to do so. 43 | * `color` is an optional argument that will determine the background color of the splash screen 44 | * `scale` is an optional argument that will affect the final size of the splash screen image 45 | 46 | ## On Complete 47 | 48 | ```lua 49 | splashy.onComplete(func) 50 | ``` 51 | 52 | * `func` is a callable function to be ran once all the splash screens are finished. 53 | 54 | There are 2 main ways of using this: 55 | 56 | ```lua 57 | splashy.onComplete(function() print("This is ran one time after all splashes are finished.") end) 58 | ``` 59 | ```lua 60 | splashy.onComplete(printFinishText) 61 | 62 | function printFinishText() 63 | 64 | print("This is ran one time after all splashes are finished.") 65 | 66 | end 67 | ``` 68 | Using this function is useful for switching gamestate. 69 | 70 | ## Splash Skipping 71 | 72 | This function skips the current splash screen onto the next one: 73 | 74 | ```lua 75 | splashy.skipSplash() 76 | ``` 77 | Whilst this one skips all splashes, running the onComplete function: 78 | 79 | ```lua 80 | splashy.skipAll() 81 | ``` 82 | 83 | ## Custom Resolutions 84 | 85 | Use this function to set the screen resolution that will be used in the internal calculations. This is useful if you use a screen scaling library, like [push](https://github.com/Ulydev/push) or [TLfres](https://love2d.org/wiki/TLfres). 86 | 87 | ```lua 88 | splashy.setScreenSize (width, height) 89 | ``` 90 | 91 | # Credits 92 | 93 | [tween.lua](https://github.com/kikito/tween.lua) is used for the tweening/fading. 94 | 95 | Check LICENCE.md for more info. 96 | 97 | # Changelog 98 | 99 | v1.0: 100 | 101 | * First Release. 102 | 103 | # Notes 104 | 105 | This library has/is a learning experience for me, if theres any problems be sure to raise them in the issues. 106 | 107 | Pull requests are welcome :) 108 | 109 | -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | # splashy 2 | 3 | This code is licensed under the [**MIT Open Source License**][MIT]. 4 | 5 | 6 | Copyright (c) 2015 Ruairidh Carmichael - ruairidhcarmichael@live.co.uk 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | 27 | [MIT]: http://www.opensource.org/licenses/mit-license.html 28 | 29 | # tween.lua 30 | 31 | Copyright (c) 2011, Enrique García Cota 32 | All rights reserved. 33 | 34 | Redistribution and use in source and binary forms, with or without modification, 35 | are permitted provided that the following conditions are met: 36 | 37 | 1. Redistributions of source code must retain the above copyright notice, 38 | this list of conditions and the following disclaimer. 39 | 2. Redistributions in binary form must reproduce the above copyright notice, 40 | this list of conditions and the following disclaimer in the documentation 41 | and/or other materials provided with the distribution. 42 | 3. Neither the name of tween.lua nor the names of its contributors 43 | may be used to endorse or promote products derived from this software 44 | without specific prior written permission. 45 | 46 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 47 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 48 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 50 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 51 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 52 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 53 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 54 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 55 | OF THE POSSIBILITY OF SUCH DAMAGE. 56 | 57 | ===================================================================================== 58 | 59 | The easing functions were taken from emmanuelOga's easing functions 60 | (https://github.com/EmmanuelOga/easing). 61 | 62 | Here's its license: 63 | 64 | Tweener authors, 65 | Yuichi Tateno, 66 | Emmanuel Oga 67 | 68 | The MIT License 69 | -------- 70 | Copyright (c) 2010, Emmanuel Oga. 71 | 72 | Permission is hereby granted, free of charge, to any person obtaining a copy 73 | of this software and associated documentation files (the "Software"), to deal 74 | in the Software without restriction, including without limitation the rights 75 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 76 | copies of the Software, and to permit persons to whom the Software is 77 | furnished to do so, subject to the following conditions: 78 | 79 | The above copyright notice and this permission notice shall be included in 80 | all copies or substantial portions of the Software. 81 | 82 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 83 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 84 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 85 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 86 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 87 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 88 | THE SOFTWARE. 89 | 90 | ===================================================================================== 91 | 92 | Emmanuel Oga's functions, in turn, were adapted from Penner's Easing Equations 93 | and http://code.google.com/p/tweener/ (jstweener javascript version) 94 | 95 | Disclaimer for Robert Penner's Easing Equations license: 96 | 97 | TERMS OF USE - EASING EQUATIONS 98 | 99 | Open source under the BSD License. 100 | 101 | Copyright © 2001 Robert Penner 102 | All rights reserved. 103 | 104 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 105 | 106 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 107 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 108 | * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. 109 | 110 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 111 | 112 | 113 | -------------------------------------------------------------------------------- /splashy/init.lua: -------------------------------------------------------------------------------- 1 | -- This code is licensed under the MIT Open Source License. 2 | 3 | -- Copyright (c) 2015 Ruairidh Carmichael - ruairidhcarmichael@live.co.uk 4 | 5 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 6 | -- of this software and associated documentation files (the "Software"), to deal 7 | -- in the Software without restriction, including without limitation the rights 8 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | -- copies of the Software, and to permit persons to whom the Software is 10 | -- furnished to do so, subject to the following conditions: 11 | 12 | -- The above copyright notice and this permission notice shall be included in 13 | -- all copies or substantial portions of the Software. 14 | 15 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | -- THE SOFTWARE. 22 | 23 | local path = ... 24 | local tween = require(path .. '/tween') 25 | 26 | local splashy = {} 27 | splashy.list = {} 28 | splashy.inalpha = 0 29 | splashy.outalpha = 1 30 | splashy.count = 1 31 | splashy.tweenlist = {} 32 | splashy.colorList = {} 33 | splashy.scaleList = {} 34 | splashy.fadestate = "in" 35 | splashy.finished = false 36 | splashy.onCompleteFunction = function () end 37 | splashy.screenWidth = love.graphics.getWidth() 38 | splashy.screenHeight = love.graphics.getHeight() 39 | 40 | --- Sets the expected screen resolution that Splashy will use for rendering. 41 | -- You should set this manually if you use screen scaling libraries like Push or TLfres 42 | function splashy.setScreenSize (width, height) 43 | splashy.screenWidth, splashy.screenHeight = width, height 44 | end 45 | 46 | --- Adds a splash screen to the queue. 47 | -- @param image (drawable) Usually an image to be drawn in the splash screen 48 | -- @param duration (number) Optional. Determines how long the image fade will last. Defaults to 2 49 | -- @param index (number) Optional. Allows you to set a custom index for the splash screen, which will change the order it is rendered 50 | -- @param color (table) Optional. Affects the background color of the splash screen. Defaults to transparent black 51 | -- @param scale (number) Optional. Determines the scale at which the image is drawn 52 | function splashy.addSplash(image, duration, index, color, scale) 53 | 54 | duration = duration or 2 55 | assert(type(duration) == 'number' and duration > 0, "duration must be a positive number.") 56 | 57 | index = index or #splashy.list + 1 58 | assert(type(index) == "number", "index must be a number") 59 | 60 | color = color or {0, 0, 0, 0} 61 | assert(type(color) == "table", "color must be a table") 62 | 63 | scale = scale or 1 64 | assert(type(scale) == "number", "scale must be a number") 65 | 66 | splashy.list[index] = image 67 | 68 | splashy.tweenlist[index] = tween.new(duration, splashy, {inalpha = 1, outalpha = 0}) 69 | 70 | splashy.colorList[index] = color 71 | 72 | splashy.scaleList[index] = scale 73 | end 74 | 75 | --- Skips the current splash screen. 76 | function splashy.skipSplash() 77 | 78 | splashy.fadestate = "in" 79 | 80 | splashy.count = splashy.count + 1 81 | 82 | end 83 | 84 | --- Skips all the splash screens. 85 | function splashy.skipAll() 86 | 87 | splashy.fadestate = "in" 88 | 89 | splashy.count = #splashy.list + 1 90 | 91 | end 92 | 93 | --- Sets a callback function that will execute when all the splash screens have finished. 94 | -- @param func (function) The callback function 95 | function splashy.onComplete(func) 96 | 97 | assert(type(func) == "function", "func must be a function") 98 | 99 | splashy.onCompleteFunction = func 100 | 101 | end 102 | 103 | --- Renders the splash screens. 104 | -- This should be placed in love.draw () 105 | function splashy.draw() 106 | 107 | if splashy.finished == false then 108 | 109 | for i=1, #splashy.list do 110 | 111 | -- If the current splash is the one in the list. 112 | 113 | if splashy.count == i then 114 | 115 | -- Then grab the splash from the list and draw it to the screen. 116 | 117 | local splash = splashy.list[i] 118 | local scale = splashy.scaleList[i] 119 | local centerwidth = splashy.screenWidth / 2 120 | local centerheight = splashy.screenHeight / 2 121 | 122 | local centerimagewidth = (splash:getWidth() * scale) / 2 123 | local centerimageheight = (splash:getHeight() * scale) / 2 124 | 125 | love.graphics.setColor (splashy.colorList[i]) 126 | love.graphics.rectangle ("fill", 0, 0, splashy.screenWidth, splashy.screenHeight) 127 | 128 | if splashy.fadestate == "in" then 129 | 130 | love.graphics.setColor(1, 1, 1, splashy.inalpha) 131 | 132 | elseif splashy.fadestate == "out" then 133 | 134 | love.graphics.setColor(1, 1, 1, splashy.outalpha) 135 | 136 | end 137 | 138 | love.graphics.draw(splash, centerwidth - centerimagewidth, centerheight - centerimageheight, nil, scale, scale) 139 | 140 | end 141 | 142 | end 143 | 144 | love.graphics.setColor(1, 1, 1, 1) 145 | 146 | end 147 | 148 | end 149 | 150 | --- Renders Splashy. 151 | -- This should be placed in love.update (dt) 152 | function splashy.update(dt) 153 | 154 | if splashy.finished == false then 155 | 156 | for i=1, #splashy.tweenlist do 157 | 158 | if splashy.count == i then 159 | 160 | local tweenComplete = splashy.tweenlist[i]:update(dt) 161 | 162 | if tweenComplete then 163 | 164 | if splashy.fadestate == "in" then 165 | 166 | splashy.tweenlist[i]:reset() 167 | 168 | splashy.fadestate = "out" 169 | 170 | elseif splashy.fadestate == "out" then 171 | 172 | splashy.tweenlist[i]:reset() 173 | 174 | splashy.count = splashy.count + 1 175 | 176 | splashy.fadestate = "in" 177 | 178 | end 179 | 180 | end 181 | 182 | end 183 | 184 | end 185 | 186 | if splashy.count >= #splashy.list + 1 then 187 | 188 | assert(type(splashy.onCompleteFunction) == "function", "onComplete needs a valid function.") 189 | 190 | splashy.finished = true 191 | 192 | splashy.onCompleteFunction() 193 | 194 | end 195 | 196 | end 197 | 198 | end 199 | 200 | return splashy 201 | -------------------------------------------------------------------------------- /splashy/tween.lua: -------------------------------------------------------------------------------- 1 | local tween = { 2 | _VERSION = 'tween 2.0.0', 3 | _DESCRIPTION = 'tweening for lua', 4 | _URL = 'https://github.com/kikito/tween.lua', 5 | _LICENSE = [[ 6 | MIT LICENSE 7 | 8 | Copyright (c) 2014 Enrique García Cota, Yuichi Tateno, Emmanuel Oga 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a 11 | copy of this software and associated documentation files (the 12 | "Software"), to deal in the Software without restriction, including 13 | without limitation the rights to use, copy, modify, merge, publish, 14 | distribute, sublicense, and/or sell copies of the Software, and to 15 | permit persons to whom the Software is furnished to do so, subject to 16 | the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included 19 | in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | ]] 29 | } 30 | 31 | -- easing 32 | 33 | -- Adapted from https://github.com/EmmanuelOga/easing. See LICENSE.txt for credits. 34 | -- For all easing functions: 35 | -- t = time == how much time has to pass for the tweening to complete 36 | -- b = begin == starting property value 37 | -- c = change == ending - beginning 38 | -- d = duration == running time. How much time has passed *right now* 39 | 40 | local pow, sin, cos, pi, sqrt, abs, asin = math.pow, math.sin, math.cos, math.pi, math.sqrt, math.abs, math.asin 41 | 42 | -- linear 43 | local function linear(t, b, c, d) return c * t / d + b end 44 | 45 | -- quad 46 | local function inQuad(t, b, c, d) return c * pow(t / d, 2) + b end 47 | local function outQuad(t, b, c, d) 48 | t = t / d 49 | return -c * t * (t - 2) + b 50 | end 51 | local function inOutQuad(t, b, c, d) 52 | t = t / d * 2 53 | if t < 1 then return c / 2 * pow(t, 2) + b end 54 | return -c / 2 * ((t - 1) * (t - 3) - 1) + b 55 | end 56 | local function outInQuad(t, b, c, d) 57 | if t < d / 2 then return outQuad(t * 2, b, c / 2, d) end 58 | return inQuad((t * 2) - d, b + c / 2, c / 2, d) 59 | end 60 | 61 | -- cubic 62 | local function inCubic (t, b, c, d) return c * pow(t / d, 3) + b end 63 | local function outCubic(t, b, c, d) return c * (pow(t / d - 1, 3) + 1) + b end 64 | local function inOutCubic(t, b, c, d) 65 | t = t / d * 2 66 | if t < 1 then return c / 2 * t * t * t + b end 67 | t = t - 2 68 | return c / 2 * (t * t * t + 2) + b 69 | end 70 | local function outInCubic(t, b, c, d) 71 | if t < d / 2 then return outCubic(t * 2, b, c / 2, d) end 72 | return inCubic((t * 2) - d, b + c / 2, c / 2, d) 73 | end 74 | 75 | -- quart 76 | local function inQuart(t, b, c, d) return c * pow(t / d, 4) + b end 77 | local function outQuart(t, b, c, d) return -c * (pow(t / d - 1, 4) - 1) + b end 78 | local function inOutQuart(t, b, c, d) 79 | t = t / d * 2 80 | if t < 1 then return c / 2 * pow(t, 4) + b end 81 | return -c / 2 * (pow(t - 2, 4) - 2) + b 82 | end 83 | local function outInQuart(t, b, c, d) 84 | if t < d / 2 then return outQuart(t * 2, b, c / 2, d) end 85 | return inQuart((t * 2) - d, b + c / 2, c / 2, d) 86 | end 87 | 88 | -- quint 89 | local function inQuint(t, b, c, d) return c * pow(t / d, 5) + b end 90 | local function outQuint(t, b, c, d) return c * (pow(t / d - 1, 5) + 1) + b end 91 | local function inOutQuint(t, b, c, d) 92 | t = t / d * 2 93 | if t < 1 then return c / 2 * pow(t, 5) + b end 94 | return c / 2 * (pow(t - 2, 5) + 2) + b 95 | end 96 | local function outInQuint(t, b, c, d) 97 | if t < d / 2 then return outQuint(t * 2, b, c / 2, d) end 98 | return inQuint((t * 2) - d, b + c / 2, c / 2, d) 99 | end 100 | 101 | -- sine 102 | local function inSine(t, b, c, d) return -c * cos(t / d * (pi / 2)) + c + b end 103 | local function outSine(t, b, c, d) return c * sin(t / d * (pi / 2)) + b end 104 | local function inOutSine(t, b, c, d) return -c / 2 * (cos(pi * t / d) - 1) + b end 105 | local function outInSine(t, b, c, d) 106 | if t < d / 2 then return outSine(t * 2, b, c / 2, d) end 107 | return inSine((t * 2) -d, b + c / 2, c / 2, d) 108 | end 109 | 110 | -- expo 111 | local function inExpo(t, b, c, d) 112 | if t == 0 then return b end 113 | return c * pow(2, 10 * (t / d - 1)) + b - c * 0.001 114 | end 115 | local function outExpo(t, b, c, d) 116 | if t == d then return b + c end 117 | return c * 1.001 * (-pow(2, -10 * t / d) + 1) + b 118 | end 119 | local function inOutExpo(t, b, c, d) 120 | if t == 0 then return b end 121 | if t == d then return b + c end 122 | t = t / d * 2 123 | if t < 1 then return c / 2 * pow(2, 10 * (t - 1)) + b - c * 0.0005 end 124 | return c / 2 * 1.0005 * (-pow(2, -10 * (t - 1)) + 2) + b 125 | end 126 | local function outInExpo(t, b, c, d) 127 | if t < d / 2 then return outExpo(t * 2, b, c / 2, d) end 128 | return inExpo((t * 2) - d, b + c / 2, c / 2, d) 129 | end 130 | 131 | -- circ 132 | local function inCirc(t, b, c, d) return(-c * (sqrt(1 - pow(t / d, 2)) - 1) + b) end 133 | local function outCirc(t, b, c, d) return(c * sqrt(1 - pow(t / d - 1, 2)) + b) end 134 | local function inOutCirc(t, b, c, d) 135 | t = t / d * 2 136 | if t < 1 then return -c / 2 * (sqrt(1 - t * t) - 1) + b end 137 | t = t - 2 138 | return c / 2 * (sqrt(1 - t * t) + 1) + b 139 | end 140 | local function outInCirc(t, b, c, d) 141 | if t < d / 2 then return outCirc(t * 2, b, c / 2, d) end 142 | return inCirc((t * 2) - d, b + c / 2, c / 2, d) 143 | end 144 | 145 | -- elastic 146 | local function calculatePAS(p,a,c,d) 147 | p, a = p or d * 0.3, a or 0 148 | if a < abs(c) then return p, c, p / 4 end -- p, a, s 149 | return p, a, p / (2 * pi) * asin(c/a) -- p,a,s 150 | end 151 | local function inElastic(t, b, c, d, a, p) 152 | local s 153 | if t == 0 then return b end 154 | t = t / d 155 | if t == 1 then return b + c end 156 | p,a,s = calculatePAS(p,a,c,d) 157 | t = t - 1 158 | return -(a * pow(2, 10 * t) * sin((t * d - s) * (2 * pi) / p)) + b 159 | end 160 | local function outElastic(t, b, c, d, a, p) 161 | local s 162 | if t == 0 then return b end 163 | t = t / d 164 | if t == 1 then return b + c end 165 | p,a,s = calculatePAS(p,a,c,d) 166 | return a * pow(2, -10 * t) * sin((t * d - s) * (2 * pi) / p) + c + b 167 | end 168 | local function inOutElastic(t, b, c, d, a, p) 169 | local s 170 | if t == 0 then return b end 171 | t = t / d * 2 172 | if t == 2 then return b + c end 173 | p,a,s = calculatePAS(p,a,c,d) 174 | t = t - 1 175 | if t < 0 then return -0.5 * (a * pow(2, 10 * t) * sin((t * d - s) * (2 * pi) / p)) + b end 176 | return a * pow(2, -10 * t) * sin((t * d - s) * (2 * pi) / p ) * 0.5 + c + b 177 | end 178 | local function outInElastic(t, b, c, d, a, p) 179 | if t < d / 2 then return outElastic(t * 2, b, c / 2, d, a, p) end 180 | return inElastic((t * 2) - d, b + c / 2, c / 2, d, a, p) 181 | end 182 | 183 | -- back 184 | local function inBack(t, b, c, d, s) 185 | s = s or 1.70158 186 | t = t / d 187 | return c * t * t * ((s + 1) * t - s) + b 188 | end 189 | local function outBack(t, b, c, d, s) 190 | s = s or 1.70158 191 | t = t / d - 1 192 | return c * (t * t * ((s + 1) * t + s) + 1) + b 193 | end 194 | local function inOutBack(t, b, c, d, s) 195 | s = (s or 1.70158) * 1.525 196 | t = t / d * 2 197 | if t < 1 then return c / 2 * (t * t * ((s + 1) * t - s)) + b end 198 | t = t - 2 199 | return c / 2 * (t * t * ((s + 1) * t + s) + 2) + b 200 | end 201 | local function outInBack(t, b, c, d, s) 202 | if t < d / 2 then return outBack(t * 2, b, c / 2, d, s) end 203 | return inBack((t * 2) - d, b + c / 2, c / 2, d, s) 204 | end 205 | 206 | -- bounce 207 | local function outBounce(t, b, c, d) 208 | t = t / d 209 | if t < 1 / 2.75 then return c * (7.5625 * t * t) + b end 210 | if t < 2 / 2.75 then 211 | t = t - (1.5 / 2.75) 212 | return c * (7.5625 * t * t + 0.75) + b 213 | elseif t < 2.5 / 2.75 then 214 | t = t - (2.25 / 2.75) 215 | return c * (7.5625 * t * t + 0.9375) + b 216 | end 217 | t = t - (2.625 / 2.75) 218 | return c * (7.5625 * t * t + 0.984375) + b 219 | end 220 | local function inBounce(t, b, c, d) return c - outBounce(d - t, 0, c, d) + b end 221 | local function inOutBounce(t, b, c, d) 222 | if t < d / 2 then return inBounce(t * 2, 0, c, d) * 0.5 + b end 223 | return outBounce(t * 2 - d, 0, c, d) * 0.5 + c * .5 + b 224 | end 225 | local function outInBounce(t, b, c, d) 226 | if t < d / 2 then return outBounce(t * 2, b, c / 2, d) end 227 | return inBounce((t * 2) - d, b + c / 2, c / 2, d) 228 | end 229 | 230 | tween.easing = { 231 | linear = linear, 232 | inQuad = inQuad, outQuad = outQuad, inOutQuad = inOutQuad, outInQuad = outInQuad, 233 | inCubic = inCubic, outCubic = outCubic, inOutCubic = inOutCubic, outInCubic = outInCubic, 234 | inQuart = inQuart, outQuart = outQuart, inOutQuart = inOutQuart, outInQuart = outInQuart, 235 | inQuint = inQuint, outQuint = outQuint, inOutQuint = inOutQuint, outInQuint = outInQuint, 236 | inSine = inSine, outSine = outSine, inOutSine = inOutSine, outInSine = outInSine, 237 | inExpo = inExpo, outExpo = outExpo, inOutExpo = inOutExpo, outInExpo = outInExpo, 238 | inCirc = inCirc, outCirc = outCirc, inOutCirc = inOutCirc, outInCirc = outInCirc, 239 | inElastic = inElastic, outElastic = outElastic, inOutElastic = inOutElastic, outInElastic = outInElastic, 240 | inBack = inBack, outBack = outBack, inOutBack = inOutBack, outInBack = outInBack, 241 | inBounce = inBounce, outBounce = outBounce, inOutBounce = inOutBounce, outInBounce = outInBounce 242 | } 243 | 244 | 245 | 246 | -- private stuff 247 | 248 | local function copyTables(destination, keysTable, valuesTable) 249 | valuesTable = valuesTable or keysTable 250 | local mt = getmetatable(keysTable) 251 | if mt and getmetatable(destination) == nil then 252 | setmetatable(destination, mt) 253 | end 254 | for k,v in pairs(keysTable) do 255 | if type(v) == 'table' then 256 | destination[k] = copyTables({}, v, valuesTable[k]) 257 | else 258 | destination[k] = valuesTable[k] 259 | end 260 | end 261 | return destination 262 | end 263 | 264 | local function checkSubjectAndTargetRecursively(subject, target, path) 265 | path = path or {} 266 | local targetType, newPath 267 | for k,targetValue in pairs(target) do 268 | targetType, newPath = type(targetValue), copyTables({}, path) 269 | table.insert(newPath, tostring(k)) 270 | if targetType == 'number' then 271 | assert(type(subject[k]) == 'number', "Parameter '" .. table.concat(newPath,'/') .. "' is missing from subject or isn't a number") 272 | elseif targetType == 'table' then 273 | checkSubjectAndTargetRecursively(subject[k], targetValue, newPath) 274 | else 275 | assert(targetType == 'number', "Parameter '" .. table.concat(newPath,'/') .. "' must be a number or table of numbers") 276 | end 277 | end 278 | end 279 | 280 | local function checkNewParams(duration, subject, target, easing) 281 | assert(type(duration) == 'number' and duration > 0, "duration must be a positive number. Was " .. tostring(duration)) 282 | local tsubject = type(subject) 283 | assert(tsubject == 'table' or tsubject == 'userdata', "subject must be a table or userdata. Was " .. tostring(subject)) 284 | assert(type(target)== 'table', "target must be a table. Was " .. tostring(target)) 285 | assert(type(easing)=='function', "easing must be a function. Was " .. tostring(easing)) 286 | checkSubjectAndTargetRecursively(subject, target) 287 | end 288 | 289 | local function getEasingFunction(easing) 290 | easing = easing or "linear" 291 | if type(easing) == 'string' then 292 | local name = easing 293 | easing = tween.easing[name] 294 | if type(easing) ~= 'function' then 295 | error("The easing function name '" .. name .. "' is invalid") 296 | end 297 | end 298 | return easing 299 | end 300 | 301 | local function performEasingOnSubject(subject, target, initial, clock, duration, easing) 302 | local t,b,c,d 303 | for k,v in pairs(target) do 304 | if type(v) == 'table' then 305 | performEasingOnSubject(subject[k], v, initial[k], clock, duration, easing) 306 | else 307 | t,b,c,d = clock, initial[k], v - initial[k], duration 308 | subject[k] = easing(t,b,c,d) 309 | end 310 | end 311 | end 312 | 313 | -- Tween methods 314 | 315 | local Tween = {} 316 | local Tween_mt = {__index = Tween} 317 | 318 | function Tween:set(clock) 319 | assert(type(clock) == 'number', "clock must be a positive number or 0") 320 | 321 | self.clock = clock 322 | 323 | if self.clock <= 0 then 324 | 325 | self.clock = 0 326 | copyTables(self.subject, self.initial) 327 | 328 | elseif self.clock >= self.duration then -- the tween has expired 329 | 330 | self.clock = self.duration 331 | copyTables(self.subject, self.target) 332 | 333 | else 334 | 335 | performEasingOnSubject(self.subject, self.target, self.initial, self.clock, self.duration, self.easing) 336 | 337 | end 338 | 339 | return self.clock >= self.duration 340 | end 341 | 342 | function Tween:reset() 343 | return self:set(0) 344 | end 345 | 346 | function Tween:update(dt) 347 | assert(type(dt) == 'number', "dt must be a number") 348 | return self:set(self.clock + dt) 349 | end 350 | 351 | 352 | -- Public interface 353 | 354 | function tween.new(duration, subject, target, easing) 355 | easing = getEasingFunction(easing) 356 | checkNewParams(duration, subject, target, easing) 357 | return setmetatable({ 358 | duration = duration, 359 | subject = subject, 360 | target = target, 361 | easing = easing, 362 | 363 | initial = copyTables({},target,subject), 364 | clock = 0 365 | }, Tween_mt) 366 | end 367 | 368 | return tween 369 | 370 | --------------------------------------------------------------------------------