--[[
миниигра с преломлением света. надо расставить разноцветные кристаллы, чтобы попасть лучом определенного цвета на кристалл в центре
]]

light_refraction_scene08_02 = {};
local self = light_refraction_scene08_02;

function self.Reset ()
   self.params = { 
      ray_image_id = "scenes_scene08_02_minigame_ray", -- id лучика
      ray_max_length = 1000,
   	color_selected = sf.graphics.Color(255, 160, 160, 160),
   	point_size = sf.misc.FloatVector(40, 40), 
      ray_start_point = {
         pos = {
            X = 630,
            Y = 120
         },
         angle = {
            next_point = 4
         },
         cross = {1, 3, 4}
      },
      glow = {
         "crystal_glow01",
         "crystal_glow02",
         "hole_glow", -- hole_glow
         "ray_glow01" -- border_glow
      },
      crystal_type_image_id = { -- id разных типов кристаллов
         {
            "scenes_scene08_02_minigame_crystal_red01",
            "scenes_scene08_02_minigame_crystal_red02_01",
            "scenes_scene08_02_minigame_crystal_red02_02"
         },
         {
            "scenes_scene08_02_minigame_crystal_green01",
            "scenes_scene08_02_minigame_crystal_green02_01",
            "scenes_scene08_02_minigame_crystal_green02_02"
         },
         {
            "scenes_scene08_02_minigame_crystal_blue01",
            "scenes_scene08_02_minigame_crystal_blue02_01",
            "scenes_scene08_02_minigame_crystal_blue02_02"
         }
      }, 
      crystals =  -- виды доступных изначально кристаллов
      {
         {
            type = 1,
            pos = {
               X = 88,
               Y = 105
            },
            point = 0
         },
         {
            type = 1,
            pos = {
               X = 88,
               Y = 197
            },
            point = 0
         },
         {
            type = 2,
            pos = {
               X = 88,
               Y = 288
            },
            point = 0
         },
         {
            type = 2,
            pos = {
               X = 88,
               Y = 381
            },
            point = 0
         },
         {
            type = 3,
            pos = {
               X = 88,
               Y = 472
            },
            point = 0
         },
         {
            type = 3,
            pos = {
               X = 88,
               Y = 564
            },
            point = 0
         }
      },
      points = { -- позиции для кристалов
         { -- 1
            pos = { X = 719, Y = 180 }, angle =
            {
               pos = nil,
               next_point = 2
            },
            cross = {2} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 2
            pos = { X = 906, Y = 163 }, angle =
            {
               pos = nil,
               next_point = 4
            },
            cross = {4} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 3
            pos = { X = 857, Y = 259 }, angle =
            {
               pos = nil,
               next_point = 5
            },
            cross = {5, 7, 10} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 4
            pos = { X = 938, Y = 305 }, angle =
            {
               pos = nil,
               next_point = 6
            },
            cross = {6} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 5
            pos = { X = 812, Y = 343 }, angle =
            {
               pos = nil,
               next_point = 1
            },
            cross = {1} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 6
            pos = { X = 885, Y = 504 }, angle =
            {
               pos = { X = 696, Y = 766 },
               next_point = nil
            },
            cross = {} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 7
            pos = { X = 755, Y = 451 }, angle =
            {
               pos = nil,
               next_point = 8
            },
            cross = {8, 20} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 8
            pos = { X = 675, Y = 356 }, angle =
            {
               pos = nil,
               next_point = 9
            },
            cross = {9, 11} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 9
            pos = { X = 578, Y = 515 }, angle =
            {
               pos = nil,
               next_point = 10
            },
            cross = {10} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 10
            pos = { X = 696, Y = 566 }, angle =
            {
               pos = nil,
               next_point = 1
            },
            cross = {1} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 11
            pos = { X = 519, Y = 609 }, angle =
            {
               pos = nil,
               next_point = 12
            },
            cross = {12, 13, 15} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 12
            pos = { X = 435, Y = 563 }, angle =
            {
               pos = nil,
               next_point = 14
            },
            cross = {14} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 13
            pos = { X = 351, Y = 515 }, angle =
            {
               pos = nil,
               next_point = 17
            },
            cross = {17} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 14
            pos = { X = 254, Y = 604 }, angle =
            {
               pos = nil,
               next_point = 15
            },
            cross = {15, 18} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 15
            pos = { X = 251, Y = 459 }, angle =
            {
               pos = nil,
               next_point = 16
            },
            cross = {16} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 16
            pos = { X = 377, Y = 384 }, angle =
            {
               pos = nil,
               next_point = 19
            },
            cross = {19} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 17
            pos = { X = 305, Y = 291 }, angle =
            {
               stop_ray = true,
               pos = { X = 463, Y = 360 },
               next_point = nil
            },
            cross = {} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 18
            pos = { X = 240, Y = 207 }, angle =
            {
               pos = nil,
               next_point = 19
            },
            cross = {19} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 19
            pos = { X = 401, Y = 158 }, angle =
            {
               pos = nil,
               next_point = 20
            },
            cross = {20, 5} -- какие позиции пересекает луч, если проходит здесь
         },
         { -- 20
            pos = { X = 568, Y = 232 }, angle =
            {
               pos = nil,
               next_point = 10
            },
            cross = {10} -- какие позиции пересекает луч, если проходит здесь
         }
      },
      ray_colors =
      {
         white =
         {
            color = sf.graphics.Color(255, 255, 255, 255),
            name = 'white',
            next =
            {
               'red',
               'green',
               'blue'
            }
         },
         red =
         {
            color = sf.graphics.Color(255, 255, 0, 0),
            name = 'red',
            next =
            {
               'red',
               'yellow',
               'purpure'
            }
         },
         green =
         {
            color = sf.graphics.Color(255, 0, 255, 0),
            name = 'green',
            next =
            {
               'yellow',
               'green',
               'lasure'
            }
         },
         blue =
         {
            color = sf.graphics.Color(255, 0, 0, 255),
            name = 'blue',
            next =
            {
               'purpure',
               'lasure',
               'blue'
            }
         },
         yellow =
         {
            color = sf.graphics.Color(255, 255, 255, 0),
            name = 'yellow',
            next =
            {
               'yellow',
               'yellow',
               'white'
            }
         },
         purpure =
         {
            color = sf.graphics.Color(255, 255, 0, 255),
            name = 'purpure',
            next =
            {
               'purpure',
               'white',
               'purpure'
            }
         },
         lasure =
         {
            color = sf.graphics.Color(255, 0, 255, 255),
            name = 'lasure',
            next =
            {
               'white',
               'lasure',
               'lasure'
            }
         }
      },
      selected = nil,
	   win = false,
      effects = {},
      win_point = {0, 3, 7, 8, 11, 13, 17},
      win_color = 'purpure',
      win_pos = { X = 500, Y = 365 },
      win_image = "centr_glow",
      time_cristal_move = 1000,
      time_glow = 1000,
      time_win = 1000,
      time_ray_update = 500,
      put_sound = "mini_game_mini_game_light_refraction_put_01",
      select_sound = "mini_game_mini_game_light_refraction_select_01"
   }
end

function self.GetPoint (_i)
   if _i == 0 then
      return self.params.ray_start_point
   end
   return self.params.points[_i]
end

function self.SetRayLastPos (_ray_id, _pos)
   local ray = self.params.rays[_ray_id]
   local pos1 = self.GetPoint(ray.from).pos
   local pos2 = _pos
   local size = math.min (ray.widget.GetSize().Y, math.sqrt ((pos2.X - pos1.X)*(pos2.X - pos1.X) + (pos2.Y - pos1.Y)*(pos2.Y - pos1.Y)))
   ray.widget.SetSize (ray.widget.GetSize().X, size)
end

function self.CreateRay (_owner, _from)
   table.insert(self.params.rays,
   {
      from = _from,
      widget = sf.gui.CImageWidget(self.params.ray_image_id, "ray", 2, 0)      
   })
   local ray = self.params.rays[#self.params.rays]
   local from = self.GetPoint (ray.from)
   ray.widget.SetOffset (from.pos.X, from.pos.Y)
	ray.widget.SetSize(ray.widget.GetSize().X, self.params.ray_max_length)
	self.SetRotation(ray.widget, ray.from)
	_owner.AddWidget(ray.widget)
   
   -- Раскраска луча
   if #self.params.rays == 1 then
      ray.color = 'white';
   else
      local last_ray = self.params.rays[#self.params.rays - 1]
      local crystal = self.params.crystals[self.GetPoint(ray.from).crystal] 
      ray.color = self.params.ray_colors[last_ray.color].next[crystal.type]
      ray.widget.SetColor(self.params.ray_colors[ray.color].color)
   end

   -- Обрезаем предыдущий луч началом текущего
   if #self.params.rays ~= 1 then
      self.SetRayLastPos (#self.params.rays - 1, from.pos)
   end
end

function self.UpdateRay (_owner)
   if self.ray_end ~= nil then
      self.CreateEffect ("ChangeAlpha",  self.params.time_glow, { widget = self.ray_end, type  = "dec"})
      self.CreateEffect ("RemoveWidget",  self.params.time_glow, { widget = self.ray_end, owner = _owner})
      self.ray_end = nil
   end
   -- Удаляем старые лучи
	for i = 1, #self.params.rays do
      _owner.RemoveWidget(self.params.rays[i].widget)
   end
   self.params.rays = {}

   -- Создаём первый луч
   self.CreateRay (_owner, 0)
   local ray = self.params.rays[#self.params.rays]
   ray.color = 'white'
   local flag = true
   -- Проверяем возможность создания следующих лучей
   while flag do
      flag = false
      local from = self.GetPoint (ray.from)
      -- Для всех точек поворота для данного луча
      for i = 1, #from.cross do
         -- Если в данной точке стоит кристал
         if self.GetPoint (from.cross[i]).crystal ~= nil then
            -- Если через данный кристал ещё не проходил луч            
            local exist = false
            for j = 1, #self.params.rays do
               if self.params.rays[j].from == from.cross[i] then
                  exist = true
                  self.SetRayLastPos (#self.params.rays, self.GetPoint (self.params.rays[j].from).pos)
                  break
               end
            end
            if exist == false then
               -- Создать ещё один участок луча из данной точки
               self.CreateRay (_owner, from.cross[i])
               ray = self.params.rays[#self.params.rays]
                  
               local crystal = self.params.crystals[self.GetPoint (from.cross[i]).crystal]
               -- Эффект удаления старого кристала
               local pos
               pos = {
                  X = crystal.widget.GetOffset().X + crystal.widget.GetSize().Y / 2,
                  Y = crystal.widget.GetOffset().Y + crystal.widget.GetSize().Y / 2
               }
               self.CreateEffect ("RemoveWidget",  self.params.time_cristal_move, { widget = crystal.widget, owner = _owner})
               -- Сознание нового кристала
               local temp = sf.gui.CImageWidget (self.params.crystal_type_image_id[crystal.type ][3], "", 4, 0)
               pos.X = pos.X - temp.GetSize ().X / 2
               pos.Y = pos.Y - temp.GetSize ().Y / 2
               temp.SetOffset (pos.X, pos.Y)
               _owner.AddWidget (temp)
               crystal.widget = temp
               -- Эффект создания нового кристала
               self.SetAlpha (temp, 0)
               self.CreateEffect ("ChangeAlpha",   self.params.time_cristal_move, { widget = temp, type  = "inc"})
                  
               flag = true
            end
            break;
         end
      end
   end
   
   -- Проверка на кристалы через которые УЖЕ не проходит луч
   for i = 1, #self.params.crystals do
      local is = false
      for j = 1, #self.params.rays do
         if self.params.crystals[i].point == self.params.rays[j].from then
            is = true
            break
         end
      end
      if is == false then
         local crystal = self.params.crystals[i]
         -- Эффект удаления старого кристала
         local pos
         pos = {
            X = crystal.widget.GetOffset().X + crystal.widget.GetSize().Y / 2,
            Y = crystal.widget.GetOffset().Y + crystal.widget.GetSize().Y / 2
         }
         self.CreateEffect ("ChangeAlpha",   self.params.time_cristal_move, { widget = crystal.widget, type  = "dec"})
         self.CreateEffect ("RemoveWidget",  self.params.time_cristal_move, { widget = crystal.widget, owner = _owner})
         -- Сознание нового кристала
         local temp = sf.gui.CImageWidget (self.params.crystal_type_image_id[crystal.type ][2], "", 4, 0)
         pos.X = pos.X - temp.GetSize ().X / 2
         pos.Y = pos.Y - temp.GetSize ().Y / 2
         temp.SetOffset (pos.X, pos.Y)
         _owner.AddWidget (temp)
         crystal.widget = temp
         -- Эффект создания нового кристала
      end
   end
   
   self.CheckEnd(_owner)
   -- Обрезаем последний луч по краям шкатулки
   local box = sf.misc.FloatRect (197, 97, 780, 780)
   local a = self.GetPoint (self.params.rays[#self.params.rays].from).pos
   local b = self.GetAnglePoint (self.params.rays[#self.params.rays].from)
   local pos =
   {
      X = box.X,
      Y = box.Y
   }
   local k = 0
   local t = 0
   if a.X == b.X then
      if b.Y > a.Y then
         pos.Y = pos.Y + box.Height
      end
   else
      k = (b.Y - a.Y) / (b.X - a.X)
      t = b.Y - b.X * k
      if b.X > a.X then
         pos.X = pos.X + box.Width
      end
      pos.Y = k * pos.X + t
      if k ~= 0 and pos.Y < box.Y then
         pos.Y = box.Y
         pos.X = (pos.Y - t) / k
      end
   end
--   __message (tostring(pos.X)..' '..tostring(pos.Y))

   self.SetRayLastPos (#self.params.rays, pos)

   if #self.params.rays > 0 then
      local point = self.GetPoint (self.params.rays[#self.params.rays].from)
      if point.angle.stop_ray == true then
         self.SetRayLastPos (#self.params.rays, point.angle.pos)
      end
   end
   
   if self.params.rays[#self.params.rays].from ~= self.params.win_point[#self.params.win_point] then
      local clip
      clip = sf.gui.CClipWidget ("", 0, 0)
      clip.SetColor (self.params.ray_colors[self.params.rays[#self.params.rays].color].color)
      clip.GetClip().Load(self.params.glow[4], true)
      clip.SetOffset (pos.X - clip.GetClip().GetSize().X / 2,
                      pos.Y - clip.GetClip().GetSize().Y / 2)
      self.owner.AddWidget (clip)
      self.ray_end = clip
   end 
   if self.params.rays[#self.params.rays].from ~= self.params.win_point[#self.params.win_point] then
      self.SetAlpha (self.ray_end, 0)
      self.CreateEffect ("ChangeAlpha",  self.params.time_glow, { widget = self.ray_end, type  = "inc"})
   end
end

function self.GetAnglePoint (_point_id)
	local point = self.GetPoint (_point_id);
   local pos = point.angle.pos;
   if point.angle.next_point ~= nil then
      pos = self.GetPoint (point.angle.next_point).pos;
   end
   return pos;
end

function self.GetAngle (_point_id)
	local point = self.GetPoint (_point_id);
   local pos = self.GetAnglePoint (_point_id);
   local angle = nil;
   if point.pos.X == pos.X then
      if point.pos.Y <= pos.Y then
         angle = 0;
      else
         angle = math.pi;
      end
   else
      if point.pos.Y == pos.Y then
         if point.pos.X <= pos.X then
            angle = math.pi * 3 / 2;
         else
            angle = math.pi / 2;
         end
      else
         local sin = (pos.Y - point.pos.Y)/math.sqrt((point.pos.X - pos.X)*(point.pos.X - pos.X) + (point.pos.Y - pos.Y)*(point.pos.Y - pos.Y));
         local cos = (pos.X - point.pos.X)/math.sqrt((point.pos.X - pos.X)*(point.pos.X - pos.X) + (point.pos.Y - pos.Y)*(point.pos.Y - pos.Y));
         if sin >= 0 then
            if cos >= 0 then
               angle = math.asin (sin) - math.pi / 2; -- 4
            else
               angle = math.acos (cos) - math.pi / 2; -- 3
            end
         else
            if cos >= 0 then
               angle = -math.acos (cos) - math.pi / 2; -- 2 
            else
               angle = -math.asin (sin) + math.pi / 2; -- 1
            end
         end
      end
   end
   -- angle = angle + math.pi / 90; -- хорошо исправляет погрешность вычислений
   
   if angle < 0 then
		angle = angle + (math.pi * 2) * (((math.abs(angle) - (math.abs(angle) % (math.pi * 2))) / math.pi * 2) + 1)
	end
	if	angle > math.pi * 2 then
		angle = angle % (math.pi * 2)
	end
   
   return angle;
end

function self.SetRotation(_widget, _point_id)
  _widget.SetRotation(sf.misc.MatrixRotation(self.GetAngle(_point_id), 0, 0))
end 

-- проверяет клик на объект
function self.IsCrystal(_pos)
	for i = 1, #self.params.crystals do
      local crystal = self.params.crystals[i];
		if misc.GetRect(crystal.widget).IsContains(_pos.X, _pos.Y) and 
		 	sminigames.IsVisiblePoint(crystal.widget.GetImage(), _pos.X - crystal.widget.GetOffset().X, _pos.Y - crystal.widget.GetOffset().Y) then
			return i
		end
	end
	return nil
end

-- проверяет клик на позицию
function self.IsPoint(_pos)
	for i = 1, #self.params.points do
      local pos = self.params.points[i].pos
		if (_pos.X >= pos.X - self.params.point_size.X/2) and (_pos.X <= pos.X + self.params.point_size.X/2) and
			(_pos.Y >= pos.Y - self.params.point_size.Y/2) and (_pos.Y <= pos.Y + self.params.point_size.Y/2) then
			return i
		end
	end
	return nil
end 

function self.SelectCrystal(_i)
	self.DeselectCrystal()
	self.params.selected = _i
	-- выделяем цветом
	if self.params.color_selected then
      local crystal = self.params.crystals[_i].widget
      local clip
      clip = sf.gui.CClipWidget ("", 0, 0)
      if self.params.crystals[self.params.selected].point == 0 then
         clip.GetClip().Load(self.params.glow[1], true)
      else
         clip.GetClip().Load(self.params.glow[2], true)
      end
      local pos =
      {
         X = crystal.GetOffset ().X + crystal.GetSize().X / 2 - clip.GetClip().GetSize().X / 2,
         Y = crystal.GetOffset ().Y + crystal.GetSize().Y / 2 - clip.GetClip().GetSize().Y / 2
      }
      clip.SetOffset (pos.X,
                      pos.Y)
		self.owner.AddWidget (clip)
      self.select_cilp = clip
      self.SetAlpha (self.select_cilp, 0)
      self.CreateEffect ("ChangeAlpha",  self.params.time_glow, { widget = self.select_cilp, type  = "inc"})
	end
end

function self.DeselectCrystal()
	if self.params.selected then
      self.CreateEffect ("ChangeAlpha",  self.params.time_glow, { widget = self.select_cilp, type  = "dec"})
      self.CreateEffect ("RemoveWidget", self.params.time_glow, { widget = self.select_cilp, owner = self.owner })
		self.params.selected = nil
	end
end

function self.PlaceCrystal(_owner, _point_id, _crystal_id)
   local crystal = self.params.crystals[_crystal_id]
   local point = self.GetPoint(_point_id)

   -- Отчистка старого значения
   self.GetPoint(crystal.point).crystal = nil

   -- Удаляем старое изображение
   self.CreateEffect ("ChangeAlpha",  self.params.time_cristal_move, { widget = crystal.widget, type  = "dec"})
   self.CreateEffect ("RemoveWidget", self.params.time_cristal_move, { widget = crystal.widget, owner = _owner })
   
   -- Создаём новое изображение
   crystal.widget = sf.gui.CImageWidget(self.params.crystal_type_image_id[crystal.type ][2], "", 4, 0);
   self.SetAlpha (crystal.widget, 0)
   self.CreateEffect ("ChangeAlpha",  self.params.time_cristal_move, { widget = crystal.widget, type  = "inc"})
   -- вычисляем его положение
   crystal.widget.SetOffset(point.pos.X - crystal.widget.GetSize().X / 2, point.pos.Y - crystal.widget.GetSize().Y / 2)
   crystal.point = _point_id
   _owner.AddWidget(crystal.widget)
   
   -- Присвоение нового значения
   point.crystal = _crystal_id

   -- Вызов !!!полного!!! перерасчёта лучей
   self.CreateEffect ("UpdateRay",  self.params.time_ray_update, { owner = _owner })
end

function self.Init(_owner)
	sminigames.SetStandartScriptName(_owner, light_refraction_scene08_02)
	
   self.Reset ()
   self.select_point = nil
   self.select_point_clip = nil
   self.select_clip = nil
   self.ray_end = nil
   self.owner = _owner	
   self.timer = __create_timer()
   -- инициализация первого луча
	self.params.rays = {}
   self.UpdateRay (_owner)
   -- инициализация кристаллов
   for i = 1, #self.params.crystals do
		local crystal = self.params.crystals[i]
      crystal.widget = sf.gui.CImageWidget(self.params.crystal_type_image_id[crystal.type ][1], "", 4, 0);
		-- вычисляем его начальное положение
		crystal.widget.SetOffset(crystal.pos.X - crystal.widget.GetSize().X / 2, crystal.pos.Y - crystal.widget.GetSize().Y / 2)
		crystal.point = 0
		_owner.AddWidget(crystal.widget)
   end
end 

function self.OnMouseDown(_owner, _pos, _button, _keyboard_state, _broadcast)
   local crystal_id = self.IsCrystal(_pos)
	local point_id = self.IsPoint(_pos)
   if crystal_id then
		if self.params.selected == crystal_id then
			self.DeselectCrystal()
		else
         sf.core.g_Application.GetAudioManager().Play(self.params.select_sound, -2, -2, -2, -2, -2)
			self.SelectCrystal(crystal_id)
		end
	elseif point_id then
		if self.params.selected and self.params.points[point_id].crystal == nil then
         sf.core.g_Application.GetAudioManager().Play(self.params.put_sound, -2, -2, -2, -2, -2)
         self.PlaceCrystal(_owner, point_id, self.params.selected)
			self.DeselectCrystal()
		end
	end
	return true
end 

function self.OnMouseMove(_owner, _pos, _keyboard_state, _broadcast)
	local point_id = self.IsPoint(_pos)
	local crystal_id = self.IsCrystal(_pos)
   if self.select_point ~= point_id or crystal_id ~= nil then
      if self.select_point_clip ~= nil then
         self.CreateEffect ("ChangeAlpha",  self.params.time_glow, { widget = self.select_point_clip, type  = "dec"})
         self.CreateEffect ("RemoveWidget", self.params.time_glow, { widget = self.select_point_clip, owner = _owner })
         self.select_point_clip = nil
      end
   end
   if self.select_point ~= point_id and crystal_id == nil then
      self.select_point = point_id
      if self.select_point ~= nil then
         local clip
         clip = sf.gui.CClipWidget ("", 0, 0)
         clip.GetClip().Load(self.params.glow[3], true)
         local point = self.GetPoint (point_id).pos
         local pos =
         {
            X = point.X - clip.GetClip().GetSize().X / 2,
            Y = point.Y - clip.GetClip().GetSize().Y / 2
         }
         clip.SetOffset (pos.X,
                         pos.Y)
         self.SetAlpha (clip, 0);
         self.CreateEffect ("ChangeAlpha",  self.params.time_glow, { widget = clip, type  = "inc"})
         _owner.AddWidget (clip)
         self.select_point_clip = clip
      end
   end
	return true
end 

function self.CreateEffect (_type, _live_time, _params)
   local effects = self.params.effects
   local i = #effects + 1;
   effects[i] = 
   {
      params = _params,
      type =   _type,
      live_time = _live_time
   };
   effects[i].start_time = self.timer.Get().GetTime();
end

function self.SetAlpha (_widget, _alpha)
   local color = sf.graphics.Color (_widget.GetColor());
   color.Alpha = _alpha;
   _widget.SetColor(color);
end

function self.OnUpdate(_owner)
   local cur_time = self.timer.Get().GetTime()
   local remove = nil
   local effects = self.params.effects
   for i = 1, #effects do
      local time = cur_time -  effects[i].start_time;
      local dead = false
      if effects[i].live_time ~= 0 and time >= effects[i].live_time then
         time = effects[i].live_time
         if remove == nil then
            remove = {}
            remove[1] = i
         else
            remove[#remove + 1] = i
         end
         dead = true
      end
      local k = 1.0;
      if effects[i].live_time ~= 0 then
         k = time / effects[i].live_time;
      end 
      if effects[i].type == "RemoveWidget" then
         if dead then
            effects[i].params.owner.RemoveWidget (effects[i].params.widget)
         end
      end
      if effects[i].type == "ChangeAlpha" then
         local alpha = nil
         if effects[i].params.type == "inc" then
            alpha = 255.0 * k
         else
            alpha = 255.0 * (1.0 - k)
         end
         self.SetAlpha (effects[i].params.widget, alpha)
      end
      if effects[i].type == "UpdateRay" then
         if dead then
            self.UpdateRay (effects[i].params.owner)
         end
      end
      if effects[i].type == "Win" then
         if dead then
   			_owner.SetGameResult(1)
   			_owner.OnEndGame()
         end
      end
   end
   if remove ~= nil then
      for i = 1, #remove do
         local j = #remove - i + 1
         table.remove (effects, remove[j])
      end
   end
	return true
end

function self.CheckEnd(_owner)
   local is = true
	for i = 1, #self.params.rays do
		if self.params.rays[i].from ~= self.params.win_point[i] then
         is = false
		end
	end
   if is and #self.params.rays == #self.params.win_point and self.params.ray_colors[self.params.rays[#self.params.rays].color].name == self.params.win_color then 
   	-- если на всех позициях стоит кристалл, надо сравнить цвет луча с тем, который должен быть последним
      self.SetRayLastPos (#self.params.rays, self.params.win_pos)
      self.CreateEffect ("Win",  self.params.time_win, nil)

      local clip = sf.gui.CClipWidget("", 0, 0)
      clip.GetClip().Load(self.params.win_image, true)
      local pos =
      {
         X = self.params.win_pos.X - clip.GetClip().GetSize().X / 2,
         Y = self.params.win_pos.Y - clip.GetClip().GetSize().Y / 2
      }
      clip.SetOffset (pos.X, pos.Y)
      _owner.AddWidget (clip)
      self.ray_end = clip
   end
end 
