【Defold】EasingアニメーションをSequenceを繋いで書ける様にする「deftween」

2019/07/10Defold, DEVELOP

UnityのアセットDoTweenの様な記述でEasingアニメーションをSequence風に書ける様にしてみます。

そもそもDefold Engineって何?という方はこちら

Defold標準のイージングアニメーションの書き方

	local pos = go.get_position()
	go.animate(".", "position.x", go.PLAYBACK_LOOP_PINGPONG, pos.x + 100,go.EASING_INOUTSINE, math.random(4, 6))

これをシーケンス繋ぎで、書ける様にしてみます。Assetsビューにdeftweenフォルダを作成しフォルダを右クリック->[New…]->[Lua Module]を選択します。ファイル名はdef_tween_sequenceとします。

luaモジュールの実装

def_tween_sequence.luaに記述します。

local M = {}
local empty_func = function()
end
function M.new()
    local this = {
        paused = true,
        index = 0,
        animations = {},
        group = 0,
        completed = function()
        end
    }
    function animate(animator)
        if animator.paused then
            return
        end
        animator.index = animator.index + 1
        local animation = animator.animations[animator.index]
        animator.group = animation.group
        local callback = function()
            if animator.paused == false then
                animator.paused = true
                animator.completed()
            end
        end
        if animator.index + 1 <= #animator.animations then
            callback = function()
                animation.turns = animation.turns - 1
                if animation.turns <= 0 then
                    local func = empty_func
                    func()
                    animate(animator)
                end
            end
        end
        local animations = animation.animations
        for i, animation in ipairs(animations) do
            go.animate(
                animation.url,
                animation.property,
                animation.playback,
                animation.to,
                animation.easing,
                animation.duration,
                animation.delay,
                function()
                    animation.on_completed()
                    callback()
                end
            )
        end
    end
    function regist(url, property, playback, to, easing, duration, delay, group)
        local func = {
            url = url,
            property = property,
            playback = playback or go.PLAYBACK_ONCE_FORWARD,
            to = to,
            easing = easing or go.EASING_LINEAR,
            duration = duration or 0,
            delay = delay or 0,
            group = group,
            on_completed = empty_func
        }
        function get_animation(animations, i, l)
            if i > #animations then
                return nil
            elseif animations[i].group == l then
                return animations[i]
            end
            return get_animation(animations, i + 1, l)
        end
        local animation = get_animation(this.animations, 1, this.group)
        if animation == nil then
            animation = {
                animations = {
                    func
                },
                group = this.group,
                turns = 1
            }
            table.insert(this.animations, animation)
        else
            table.insert(animation.animations, func)
            animation.turns = #animation.animations
        end
    end
    this.append = function(url, property, playback, to, easing, duration, delay)
        this.group = this.group + 1
        regist(url, property, playback, to, easing, duration, delay, this.group)
        return this
    end
    this.join = function(url, property, playback, to, easing, duration, delay)
        this.group = this.group
        regist(url, property, playback, to, easing, duration, delay, this.group)
        return this
    end
    this.play = function()
        this.paused = false
        animate(this)
    end
    this.on_completed = function(callback)
        this.completed = callback
    end
    this.stop = function(url, property)
        go.cancel_animations(url, property)
    end
    this.clear = function(url)
        this.stop(url, "position")
        this.paused = true
        this.index = 0
        this.animations = {}
        this.group = 0
        this.completed = function()
        end
    end
    return this
end
return M

使い方

	local def_tween_sequence = require("main.deftween.def_tween_sequence")
	local seq = def_tween_sequence.new()
	-- Tweenの追加
	local pos = go.get_position()
	seq.append(".", "position.x", nil, pos.x + 100, go.EASING_INOUTSINE, 2)
	seq.append(".", "position.y", nil, pos.y - 100, go.EASING_INOUTCUBIC, 2)
	seq.join(".", "position.x", go.PLAYBACK_LOOP_PINGPONG, pos.x + 200, go.EASING_INOUTSINE, 1)
	-- 再生完了通知
	seq.on_completed(
		function()
			print("complete!")
		end
	)
	
	-- 再生
	seq.play()

requireでモジュールを取り込んでいます。モジュールのパスは、Assets以下からのファイルパスを記述します。

Posted by kazupon