class 'M3Item'

-- CONSTANTS
M3Item.MOVE_TIME       = 0.1
M3Item.KILL_TIME       = 0.2
M3Item.SHAKE_LOCK_TIME = 0.5
M3Item.BOUNCE_TIME     = 0.3
M3Item.BOUNCE_DY       = -10
M3Item.SELECTED_SCALE  = 1.2

-- STATIC VARIABLES
M3Item.uniqueNameId = 0
-------------------------------------------------------------------------------

function M3Item:__init(id, name, pTimer)
    M3Item.uniqueNameId = M3Item.uniqueNameId + 1
    
    self.anchor = nil
    self.sprite = nil
    self.shine  = nil
    self.ice    = nil
    self.ice2   = nil
    self.crashSprite = nil
    self.charge_particle = nil

    self.name        = name
    self.uniqueId    = M3Item.uniqueNameId
    self.id          = id
    self.pTimer      = pTimer
    self.fallHeight  = 0
    self.crashHeight = 0
    
    self.anchorEffector = nil
    self.spriteEffector = nil
    self.shineEffector  = nil
    
    self.bAnimating    = false  -- флаг, отвечающий за анимированое состояние (появление, ищезновение, отскок, тряску замка)
    self.bMoving       = false  -- флаг, отвечающий за состояние перемещения к другой ячейке
    self.bFalling      = false  -- вспомагательный флаг, отвечающий за состояние падения (введен для того, чтобы отловить коней падения и проиграть эффект тряски)
    
    self.bFocused      = false
    self.bSelected     = false
    
    self.bCombinable = true
    self.bChargeable = true
    self.bShufflable = true
    self.bExplodable = true
    self.bPassable   = false
    
    self.bLocked     = false
    self.bCharged    = false
    self.bKilled     = false
    
    self:_createAnchor()
    self:_createSptire()
    self:_createShineSptire()
end
-------------------------------------------------------------------------------

function M3Item:destroy()
    if self.spriteAction then
        self.spriteAction:kill()
        self.spriteAction = nil
    end
    
    if self.shineAction then
        self.shineAction:kill()
        self.shineAction = nil
    end
    
    self:destroyLock()
    
    if self.crashSprite then
        if current_scene:getPlayField() then
            self.crashSprite:setRespondable(true)
        end
        
        self.crashSprite:destroy()  --TODO: проверить, возможно ли объект уже удален ранее на текущем Update
        self.crashSprite = nil
    end
    
    do
        if current_scene:getPlayField() then
            self.shine:setRespondable(true)
        end
        
        self.shine:destroy()    --TODO: проверить, возможно ли объект уже удален ранее на текущем Update
        self.shine = nil
    end
    
    do
        if current_scene:getPlayField() then
            self.sprite:setRespondable(true)
        end
        
        self.sprite:destroy()
        self.sprite = nil
    end
    
    if self.anchor then
        self.anchor:destroy()
        self.anchor = nil
    end
    
    self.pTimer = nil
end
-------------------------------------------------------------------------------

function M3Item:destroyLock()
    if self.iceAnim then
        self.iceAnim:setRespondable(true)
        self.iceAnim:destroy()
        self.iceAnim = nil
    end
    
    if self.ice then       
        self.ice:setRespondable(true)
        self.ice:destroy()
        self.ice = nil
    end
    
    if self.ice2 then       
        self.ice2:setRespondable(true)
        self.ice2:destroy()
        self.ice2 = nil
    end
end
-------------------------------------------------------------------------------

function M3Item:getAnchor()
    return self.anchor
end
-------------------------------------------------------------------------------

function M3Item:getSprite()
    return self.sprite
end
-------------------------------------------------------------------------------

function M3Item:getUniqueId()
    return self.uniqueId
end
-------------------------------------------------------------------------------

function M3Item:getFallHeight()
    return self.fallHeight
end
-------------------------------------------------------------------------------

function M3Item:getCrashHeight()
    return self.crashHeight
end
-------------------------------------------------------------------------------

function M3Item:setPos(x, y)
    self.anchor:setXY(x, y)
end
-------------------------------------------------------------------------------

function M3Item:setCrashHeight(crashHeight)
    self.crashHeight = crashHeight
end
-------------------------------------------------------------------------------

function M3Item:setFocused(bFocused)
    if self.bFocused ~= bFocused then
        self.bFocused = bFocused
        
        if bFocused then
            self:addAnchorZ(6)
        else
            self:addAnchorZ(-6)
        end
        
        if self.bSelected then
        else
            if self.spriteAction then
                self.spriteAction:kill()
                self.spriteAction = nil
            end
            
            if self.spriteEffector then
                self.spriteEffector:destroy()
                self.spriteEffector = nil
            end
            
            local time = 0.2
            
            self.spriteEffector = CreateAnimationEffector()
            self.spriteEffector:setDestroysOnEnd(false)
            self.spriteEffector:attachTo(self.sprite)
            
            self.spriteEffector:setKey(_TRACK_X, 0, self.sprite:getX())
            self.spriteEffector:setKey(_TRACK_Y, 0, self.sprite:getY())
            self.spriteEffector:setKey(_TRACK_S, 0, self.sprite:getScale().x)
            
            self.spriteEffector:setKey(_TRACK_X, time, 0)
            
            if bFocused then
                local height = self.sprite:getHeight()
                local dy     = -height*(M3Item.SELECTED_SCALE - 1) / 2
                
                self.spriteEffector:setKey(_TRACK_Y, time, dy)
                self.spriteEffector:setKey(_TRACK_S, time, M3Item.SELECTED_SCALE)
            else
                
                self.spriteEffector:setKey(_TRACK_Y, time, 0)
                self.spriteEffector:setKey(_TRACK_S, time, 1)
            end
            
            self.spriteEffector:play()
            
            self.spriteAction = self.pTimer:add(function()
                                                    self.spriteAction = nil
                                                    
                                                    if self.spriteEffector then
                                                        self.spriteEffector:destroy()
                                                        self.spriteEffector = nil
                                                    end
                                                    
                                                    if bFocused and bSelected then
                                                        self.spriteEffector = self:_createRotateEffector()
                                                    end
                                                end,
                                                time)
        end
    end
end
-------------------------------------------------------------------------------

function M3Item:setSelected(bSelected)
    if self.bSelected ~= bSelected then
        self.bSelected = bSelected
        
        if bSelected then
            self:addAnchorZ(3)
            self:_shineOn(2, true)
            
            if not self.spriteEffector then
                self.spriteEffector = self:_createRotateEffector()
            end
        else
            local time = 0.2
            
            self:addAnchorZ(-3)
            self:_shineOff(time)
            
            if self.spriteAction then
                self.spriteAction:kill()
                self.spriteAction = nil
            end
            
            if self.spriteEffector then
                self.spriteEffector:destroy()
                self.spriteEffector = nil
            end
            
            self.spriteEffector = CreateAnimationEffector()
            self.spriteEffector:setDestroysOnEnd(false)
            self.spriteEffector:attachTo(self.sprite)
            
            self.spriteEffector:setKey(_TRACK_X, 0,    self.sprite:getX())
            self.spriteEffector:setKey(_TRACK_Y, 0,    self.sprite:getY())
            self.spriteEffector:setKey(_TRACK_S, 0,    self.sprite:getScale().x)
                
            if self.bFocused then
                local height = self.sprite:getHeight()
                local dy     = -height*(M3Item.SELECTED_SCALE - 1) / 2
                
                self.spriteEffector:setKey(_TRACK_X, time, 0)
                self.spriteEffector:setKey(_TRACK_Y, time, dy)
                self.spriteEffector:setKey(_TRACK_S, time, M3Item.SELECTED_SCALE)
            else
                self.spriteEffector:setKey(_TRACK_X, time, 0)
                self.spriteEffector:setKey(_TRACK_Y, time, 0)
                self.spriteEffector:setKey(_TRACK_S, time, 1)
            end
            
            self.spriteEffector:play()
            
            self.spriteAction = self.pTimer:add(function()
                                                    self.spriteAction = nil
                                                    
                                                    if self.spriteEffector then
                                                        self.spriteEffector:destroy()
                                                        self.spriteEffector = nil
                                                    end
                                                end,
                                                time)
        end
    end
end
-------------------------------------------------------------------------------

function M3Item:addAnchorZ(deltaOrder)
    local currOrder = self.anchor:getOrder()
    self.anchor:setOrder(currOrder + deltaOrder)
end
-------------------------------------------------------------------------------

function M3Item:lock()
    if not self.bLocked then
        self:_createLock()
        self.bLocked = true
    end
end
-------------------------------------------------------------------------------

function M3Item:unlock(type, bFatality)
    if self.bLocked then
        self:_createUnlockAnimation(type)        
     
        local time = self.iceAnim:getFramesCount()
        self.iceAnim:play()
        
        self.ice:setOpacity(0)
        self.ice2:ChangeOpacity(1, 0, time * 0.3)
        
        self.bAnimating = true
        self.bLocked    = false
        self.pTimer:add(function()
                            self:destroyLock()
                            self.bAnimating = false
                            
                            if bFatality then
                                self:kill()
                            end
                        end,
                        time)
    end
end
-------------------------------------------------------------------------------

function M3Item:charge()
    assert(not self.bLocked)
    
    self.bCharged = true  
    self.charge_particle  = CreateParticleEntity()
    self.charge_particle:setParticle('Data/ParticleSystems/M3ChargedItem.psi', 'Data/Textures/Common/particle_10.png')
    self.charge_particle:attachTo(self.anchor)
    self.charge_particle:setOrder(3)
    self.charge_particle:setParticlesScale(0.55)
    self.charge_particle:setXY(0, 0)
    self.charge_particle:setRespondable(false)
    self.charge_particle:setGenerateAreaSize(46, 46)
    self.charge_particle:fire()
end
-------------------------------------------------------------------------------

function M3Item:appear()
    assert(not self.bAnimating)
    
    local time = M3Item.MOVE_TIME * 0.99
    self.sprite:ChangeOpacity(0, 1, time)
    
    self.bAnimating = true
    self.pTimer:add(function()
                        self.bAnimating = false
                    end,
                    time)
end
-------------------------------------------------------------------------------

function M3Item:kill()
    assert(not self.bLocked)
    
    if self.anchorEffector then
        self.anchorEffector:destroy()
    end
    
    local time = M3Item.KILL_TIME
    local targetScale = 0.1
    
    self.anchorEffector = CreateAnimationEffector()
    self.anchorEffector:setDestroysOnEnd(false)
    self.anchorEffector:attachTo(self.anchor)
    self.anchorEffector:setKey(_TRACK_S, 0,    self.sprite:getScale().x)
    self.anchorEffector:setKey(_TRACK_O, 0,    self.sprite:getOpacity())
    self.anchorEffector:setKey(_TRACK_S, time, targetScale)
    self.anchorEffector:setKey(_TRACK_O, time, 0)
    self.anchorEffector:play()
    
    self.bAnimating = true
    self.bKilled    = true

    self.pTimer:add(function()
                        if self.anchorEffector then
                            self.anchorEffector:destroy()
                            self.anchorEffector = nil
                        end
                        
                        self.bAnimating = false
                    end,
                    time)
end
-------------------------------------------------------------------------------

function M3Item:crash()
    assert(not self.bLocked)
    
    self:setFocused(false)
    
    if self.anchorEffector then
        self.anchorEffector:destroy()
        self.anchorEffector = nil
    end
    
    self:_createCrashAnim()
    self.sprite:setVisible(false)
    self.shine:setVisible(false)
    
    
    local time = self.crashSprite:getFramesCount()
    self.crashSprite:play()
    
    self.bFalling   = false
    self.bAnimating = true
    self.bKilled    = true
    
    self.pTimer:add(function()
                        self.bAnimating = false
                    end,
                    time)
end
-------------------------------------------------------------------------------

function M3Item:explode(angle)
    assert(not self.bLocked)
    assert(not self.bAnimating)
    
    self:addAnchorZ(7)
    
    if self.anchorEffector then
        self.anchorEffector:destroy()
    end
    
    self.anchorEffector = CreateAnimationEffector()
    self.anchorEffector:attachTo(self.anchor)
    self.anchorEffector:setDestroysOnEnd(false)
    
    local time = 1.5
    
    do
        local iterations = 20
        local dt = time/iterations
        local dAngle = M_PI / iterations
        local gravity = 50 / iterations
        local power = 7
        local pos = Vector2f(self.anchor:getX(),
                           self.anchor:getY())
                                
        local velocity = Vector2f(power * math.cos(angle),
                                power * math.sin(angle))
        
        for i=0, iterations do
            local percent = math.sin(i*dAngle)
            local t = time * i/iterations
            
            pos = pos + velocity
            velocity.y = velocity.y + gravity
            
            self.anchorEffector:setKey(_TRACK_X, t, pos.x)
            self.anchorEffector:setKey(_TRACK_Y, t, pos.y)
        end
    end
    
    self.anchorEffector:setKey(_TRACK_O, 0,          1)
    self.anchorEffector:setKey(_TRACK_O, time * 0.5, 1)
    self.anchorEffector:setKey(_TRACK_O, time,       0)
    self.anchorEffector:play()
    
    self.bAnimating = true
    self.bKilled    = true
    
    self.pTimer:add(function()
                        if self.anchorEffector then
                            self.anchorEffector:destroy()
                            self.anchorEffector = nil
                        end
                        
                        self.bAnimating = false
                    end,
                    time)
end
-------------------------------------------------------------------------------

function M3Item:moveHome(time)
    time = time or M3Item.MOVE_TIME
    
    if self.anchorEffector then
        self.anchorEffector:destroy()
    end
    
    self.anchorEffector = self.anchor:MoveTo(0, 0, time)
    self.anchorEffector:setDestroysOnEnd(false)
    
    self.bMoving = true
    self.pTimer:add(function()
                        if self.anchorEffector then
                            self.anchorEffector:destroy()
                            self.anchorEffector = nil
                        end
                        
                        self.anchor:setXY(0, 0)
                        self.bMoving = false
                    end,
                    time)
end
-------------------------------------------------------------------------------

function M3Item:flyHome(rect, time)
    if self.anchorEffector then
        self.anchorEffector:Destroy()
    end
    
    if self.anchorEffector then
        self.anchorEffector:Destroy()
    end
    
    do
        local maxScale = 1.2
        
        self.anchorEffector = CreateAnimationEffector()
        self.anchorEffector:SetDestroysOnEnd(false)
        self.anchorEffector:AttachTo(self.anchor)
        self.anchorEffector:SetKey(_TRACK_S, 0,        self.anchor:GetScale())
        self.anchorEffector:SetKey(_TRACK_S, time / 2, maxScale)
        self.anchorEffector:SetKey(_TRACK_S, time / 2, 1)
        self.anchorEffector:Play()
    end
    
    self.anchorEffector = CreateAnimationEffector()
    self.anchorEffector:SetDestroysOnEnd(false)
    self.anchorEffector:AttachTo(self.anchor)
    
    
    do
        local startPos  = Vector(self.anchor:GetX(), self.anchor:GetY())
        local finishPos = Vector(0, 0)
        local dot1      = Vector(rect.x + math.random() * rect.w, rect.y + math.random() * rect.h)
        local dot2      = Vector(rect.x + math.random() * rect.w, rect.y + math.random() * rect.h)
        
        MakePositionKeysBySpline(self.anchorEffector,
                                 startPos, dot1, finishPos, dot2,
                                 20,
                                 time, 0)
    end
    
    self.anchorEffector:Play()
    
    self.bMoving = true
    self.pTimer:Add(function()
                        if self.anchorEffector then
                            self.anchorEffector:Destroy()
                            self.anchorEffector = nil
                        end
                        
                        self.anchor:SetXY(0, 0)
                        self.bMoving = false
                    end,
                    time)
end
-------------------------------------------------------------------------------

function M3Item:fall(fallHeight)
    local time = (fallHeight) and M3Item.MOVE_TIME * fallHeight or M3Item.MOVE_TIME
    
    self:moveHome(time)
    
    self.fallHeight = self.fallHeight + 1
    self.bFalling   = true
end
-------------------------------------------------------------------------------

function M3Item:bounce()
    --assert(not self.bAnimating)
    
    if self.anchorEffector then
        self.anchorEffector:Destroy()
    end
    
    self.anchorEffector = CreateAnimationEffector()
    self.anchorEffector:setDestroysOnEnd(false)
    self.anchorEffector:attachTo(self.anchor)
    
    do
        local iterations = 20
        local dAngle     = M_PI / iterations
        
        for i=0, iterations do
            local percent      = math.sin(i*dAngle)
            local currTime     = M3Item.BOUNCE_TIME * i/iterations
            
            self.anchorEffector:setKey(_TRACK_Y, currTime, M3Item.BOUNCE_DY * percent)
        end
    end
    
    self.anchorEffector:play()
    
    self.fallHeight = 0
    self.bFalling   = false
    self.bAnimating = true
    
    self.pTimer:add(function()
                        if self.anchorEffector then
                            self.anchorEffector:destroy()
                            self.anchorEffector = nil
                        end
                        
                        -- TODO: kostil
                        if self.anchor then
                            self.anchor:setXY(0, 0)
                        end
                        self.bAnimating = false
                    end,
                    M3Item.BOUNCE_TIME)
end
-------------------------------------------------------------------------------

function M3Item:shakeLock()
    assert(not self.bAnimating)
    
    local time = M3Item.SHAKE_LOCK_TIME
    local effector = CreateAnimationEffector()
    effector:setDestroysOnEnd(true)
    effector:attachTo(self.ice)
    
    do
        local iterations = 10
        local dAngle     = M_PI / iterations
        local maxAmplituda = 2
        
        for i=0, iterations do
            local currTime  = time * i/iterations
            local amplituda = maxAmplituda * math.sin(i*dAngle)
            local angle     = math.random() * M_TWO_PI
            
            local x = amplituda * math.cos(angle)
            local y = amplituda * math.sin(angle)
            
            effector:setKey(_TRACK_X, currTime, x)
            effector:setKey(_TRACK_Y, currTime, y)
        end
    end
    effector:play()
    
    self.bAnimating = true
    self.pTimer:add(function()
                        self.bAnimating = false
                    end,
                    time)
end
-------------------------------------------------------------------------------

function M3Item:isAnimated()
    return self.bAnimating
end
-------------------------------------------------------------------------------

function M3Item:isMoving()
    return self.bMoving
end
-------------------------------------------------------------------------------

function M3Item:isKilled()
    return self.bKilled
end
-------------------------------------------------------------------------------

function M3Item:isFalling()
    return self.bFalling
end
-------------------------------------------------------------------------------

function M3Item:isLocked()
    return self.bLocked
end
-------------------------------------------------------------------------------

function M3Item:isCharged()
    return self.bCharged
end
-------------------------------------------------------------------------------

function M3Item:isCombinable()
    return self.bCombinable
end
-------------------------------------------------------------------------------

function M3Item:isChargeable()
    return self.bChargeable
end
-------------------------------------------------------------------------------

function M3Item:isShufflable()
    return self.bShufflable
end
-------------------------------------------------------------------------------

function M3Item:isExplodable()
    return self.bExplodable
end
-------------------------------------------------------------------------------

function M3Item:isPassable()
    return self.bPassable
end
-------------------------------------------------------------------------------

function M3Item:isCalm()
    return not self:isAnimated() and
           not self:isMoving()   and
           not self:isKilled()   and
           not self:isFalling()
end
-------------------------------------------------------------------------------

function M3Item:isFocused()
    return self.bFocused
end
-------------------------------------------------------------------------------

function M3Item:canCrash()
    return self.crashHeight > 0 and self.fallHeight >= self.crashHeight
end
-------------------------------------------------------------------------------


-------------------------------------------------------------------------------
-- PRIVATE
-------------------------------------------------------------------------------

function M3Item:_createRotateEffector()
    local time       = 2
    local radius     = 2
    local iterations = 20
        
    local effector = CreateAnimationEffector()
    effector:setDestroysOnEnd(false)
    effector:attachTo(self.sprite)
    effector:setMode(_ANIM_FWD + _ANIM_LOOP)
    
    do
        local startAngle = -M_PI_OVER_2
        local dAngle     = M_TWO_PI / iterations
        local center     = Vector2f(self.sprite:getX(), self.sprite:getY() + radius)
        
        for i=0, iterations do
            local currTime = time * i/iterations
            
            local angle = startAngle + dAngle*i
            local dx    = radius * math.cos(angle)
            local dy    = radius * math.sin(angle)
            
            effector:setKey(_TRACK_X, currTime, center.x + dx)
            effector:setKey(_TRACK_Y, currTime, center.y + dy)
        end
    end
    
    effector:play()
    
    return effector
end
-------------------------------------------------------------------------------

function M3Item:_shineOn(time, cyclic)
    local maxOpacity = 0.5
    
    if self.shineAction then
        self.shineAction:kill()
        self.shineAction = nil
    end
    
    if self.shineEffector then
        self.shineEffector:destroy()
    end
    
    self.shineEffector = CreateAnimationEffector()
    self.shineEffector:setDestroysOnEnd(false)
    self.shineEffector:attachTo(self.shine)
    
    if cyclic then
        self.shineEffector:setMode(_ANIM_FWD + _ANIM_LOOP)
    end
    
    self.shineEffector:setKey(_TRACK_O, 0,        0)
    self.shineEffector:setKey(_TRACK_O, time / 2, maxOpacity)
    self.shineEffector:setKey(_TRACK_O, time,     0)
    self.shineEffector:play()
    
    if not cyclic then
        self.shineAction = self.pTimer:add( function()
                                                self.shineAction = nil
                                                
                                                self.shineEffector:destroy()
                                                self.shineEffector = nil
                                                
                                                self.shine:setOpacity(0)
                                            end,
                                            time)
    end
end
-------------------------------------------------------------------------------

function M3Item:_shineOff(time)
    if self.shineAction then
        self.shineAction:kill()
        self.shineAction = nil
    end
    
    if self.shineEffector then
        self.shineEffector:destroy()
    end
    
    self.shineEffector = CreateAnimationEffector()
    self.shineEffector:setDestroysOnEnd(false)
    self.shineEffector:attachTo(self.shine)
    
    self.shineEffector:setKey(_TRACK_O, 0,    self.shine:getOpacity())
    self.shineEffector:setKey(_TRACK_O, time, 0)
    self.shineEffector:play()
    
    self.shineAction = self.pTimer:add( function()
                                            self.shineAction = nil
                                            
                                            self.shineEffector:destroy()
                                            self.shineEffector = nil
                                            
                                            self.shine:setOpacity(0)
                                        end,
                                        time)
end
-------------------------------------------------------------------------------

function M3Item:_createAnchor()
    local objectName = 'itemAnchor'..tostring(self.id)..'_'..tostring(self.uniqueId)
    
    self.anchor = CreateSpriteEntity('')
    self.anchor:setName(objectName)
end
-------------------------------------------------------------------------------

function M3Item:_createSptire()
    local texture    = M3Game.TEXTURE_PATH..'Items/'..self.name..'.png'
	local objectName = 'item'..tostring(self.id)..'_'..tostring(self.uniqueId)
	local anim       = CreateSpriteEntity(texture)

    anim:setName(objectName)
    anim:setOrder(4)
    anim:setXY(0, 0)
    anim:attachTo(self.anchor)
	anim:setRespondable(false)

	self.sprite = anim	
end
-------------------------------------------------------------------------------

function M3Item:_createShineSptire()
    local texture    = M3Game.TEXTURE_PATH..'Items/'..self.name..'.png'
	local objectName = 'itemShine'..tostring(self.id)..'_'..tostring(self.uniqueId)
    local anim       = CreateSpriteEntity(texture)

    anim:setName(objectName)
    anim:setOrder(1)
    anim:setXY(0, 0)
    anim:attachTo(self.sprite)
    anim:setOpacity(0)
    anim:setRespondable(false)

    self.shine = anim 
end
-------------------------------------------------------------------------------

function M3Item:_createLock()
    do
        local objectName = 'lock'..tostring(self.id)..'_'..tostring(self.uniqueId)
        local texture    = M3Game.TEXTURE_PATH..'ice_above.png'
        local anim       = CreateSpriteEntity(texture)

        anim:setName(objectName)
        anim:setOrder(2)
        anim:setXY(0, 0)
        anim:attachTo(self.sprite)
        anim:setOpacity(0)
        anim:setRespondable(false)

        self.ice = anim 
    end
    
    do
        local objectName = 'lockUnder'..tostring(self.id)..'_'..tostring(self.uniqueId)
        local texture    = M3Game.TEXTURE_PATH..'ice_under.png'
        local anim       = CreateSpriteEntity(texture)

        anim:setName(objectName)
        anim:setOrder(2)
        anim:setXY(0, 0)
        anim:attachTo(self.sprite)
        anim:setOpacity(0)
        anim:setRespondable(false)

        self.ice2 = anim 
    end
end
-------------------------------------------------------------------------------

function M3Item:_createCrashAnim()
    local info = {}
    
    if self.name == 'item6' then
        info.w      = 72
        info.h      = 72
        info.frames = 18
        info.fps    = 24
    elseif self.name == 'item3' then
        info.w      = 72
        info.h      = 72
        info.frames = 23
        info.fps    = 24
    elseif self.name == 'item8' then
        info.w      = 72
        info.h      = 72
        info.frames = 24
        info.fps    = 24
    elseif self.name == 'item10' then
        info.w      = 72
        info.h      = 72
        info.frames = 21
        info.fps    = 24
    else
        assert(false)
    end
    
    
    local objectName = 'crashAnim'..tostring(self.id)..'_'..tostring(self.uniqueId)
    local texture = M3Game.TEXTURE_PATH..'Anims/'..self.name..'CrashAnim.png'

    local anim       = CreateSpriteEntity(texture)
    anim:setAnimationSize(info.w, info.h)
    anim:setFramesCount(info.frames)
    anim:setFPS(info.fps)
    anim:setName(objectName)
    anim:setHotSpot(info.w/2,info.h/2)
    anim:setOrder(1)
    anim:setXY(0, 0)
    anim:attachTo(self.sprite)
    anim:setOpacity(0)
    anim:setRespondable(false)

    self.crashSprite = anim    
    
    return self.crashSprite
end
-------------------------------------------------------------------------------

function M3Item:_createUnlockAnimation(type)
    local objectName = 'lockAnim'..tostring(self.id)..'_'..tostring(self.uniqueId)
    local texture    = M3Game.TEXTURE_PATH..'Anims/iceAnim'..tostring(type)..'.png'
    
    local info = {}
    
    if type == 1 then
        info.w = 70
        info.h = 70
        info.frames = 21
        info.fps    = 24
    else
        info.w = 70
        info.h = 70
        info.frames = 24
        info.fps    = 24
    end

    local anim       = CreateSpriteEntity(texture)
    anim:setAnimationSize(info.w, info.h)
    anim:setFramesCount(info.frames)
    anim:setFPS(info.fps)
    anim:setName(objectName)
    anim:setHotSpot(info.w/2,info.h/2)
    anim:setOrder(1)
    anim:setXY(0, 0)
    anim:attachTo(self.sprite)
    anim:setOpacity(0)
    anim:setRespondable(false)

    self.iceAnim = anim   
end
-------------------------------------------------------------------------------