-- миниигра птички-рыбки
switch_figures_chapter06 = {} -- название таблицы миниигры, должно совпадать с имненем файла
local self = switch_figures_chapter06 

self.params = 
{
	speed = 230, -- скорость движения, пиксели в секунду
	pos_width = 70,  -- ширина позиции фишки
	pos_height = 70, -- высота позиции фишки
	sound_id = "", -- звук движения фишки
	sound_place = "shift_item", -- звук, когда кладем фишку на место
	sound_select = "shift_item", -- звук на выделение
	clip_select = 
	{-- клип выделения фишки
		{type = "stone01", id = "stone_select", layer = 4}, 
		{type = "stone02", id = "stone_select", layer = 4}, 
		{type = "stone03", id = "stone_select", layer = 4}, 
		{type = "fire", id = "fire_select", layer = 4}, 
		{type = "earth", id = "earth_select", layer = 4}, 
		{type = "water", id = "water_select", layer = 4}
	},
	win_shine_time = 1000, -- время показа победной подсветки
	clip_fade_time = 500, -- за сколько времени прячется клип
	wrong_clip = "hole_wrong", -- мигание клетки, в которую низя пройти
	right_clip = "hole_right",  -- мигание клетки, в которую идем 
	shadow = "scenes_chapter06_scene05_minigame_shadow", -- img с тенью от летящей фишки
	shadow_layer = 1, -- Слой тени
	fly_layer = 4, -- на каком слое летит фишка
	lay_layer = 2, -- на каком слое лежит
	line_selections =
	{ -- выделения на ребра, клипы из dsfrontend
		{pos1 = 1, pos2 = 4, id = "line01"}, -- вершина1, вершина2, id клипа
		{pos1 = 1, pos2 = 6, id = "line02"},
		{pos1 = 2, pos2 = 5, id = "line03"},
		{pos1 = 2, pos2 = 7, id = "line04"},
		{pos1 = 3, pos2 = 6, id = "line05"},
		{pos1 = 3, pos2 = 8, id = "line06"},
		{pos1 = 4, pos2 = 7, id = "line07"},
		{pos1 = 5, pos2 = 8, id = "line08"}
	} ,
	positions = { -- описание точек, в которых может находиться фишка
		{ -- номер позиции: 1
			state =  "earth", -- состояние позиции: "" - свободна, иначе нет
			end_state = "", -- в каком состоянии должна находиться позиция на момент окончания игры: "" - не важно, иначе должно быть какой-то конкретно 
			pos = sf.misc.FloatVector(363, 133), -- положение фишки на экране
			neighbours = { -- список позиций, в которые можно перейти из данной
				4, 6
			}
		},
		{ -- номер позиции: 2
			state =  "fire", -- состояние позиции: "" - свободна, иначе нет
			end_state = "", -- в каком состоянии должна находиться позиция на момент окончания игры: "" - не важно, иначе должно быть какой-то конкретно 
			pos = sf.misc.FloatVector(537, 74), -- положение фишки на экране
			neighbours = { -- список позиций, в которые можно перейти из данной
				5, 7
			}
		},
		{ -- номер позиции: 3
			state =  "water", -- состояние позиции: "" - свободна, иначе нет
			end_state = "", -- в каком состоянии должна находиться позиция на момент окончания игры: "" - не важно, иначе должно быть какой-то конкретно 
			pos = sf.misc.FloatVector(733, 125), -- положение фишки на экране
			neighbours = { -- список позиций, в которые можно перейти из данной
				6, 8
			}
		},
		{ -- номер позиции: 4
			state =  "", -- состояние позиции: "" - свободна, иначе нет
			end_state = "fire", -- в каком состоянии должна находиться позиция на момент окончания игры: "" - не важно, иначе должно быть какой-то конкретно 
			pos = sf.misc.FloatVector(803, 296), -- положение фишки на экране
			neighbours = { -- список позиций, в которые можно перейти из данной
				1, 7
			}
		},
		{ -- номер позиции: 5
			state =  "stone01", -- состояние позиции: "" - свободна, иначе нет
			end_state = "", -- в каком состоянии должна находиться позиция на момент окончания игры: "" - не важно, иначе должно быть какой-то конкретно 
			pos = sf.misc.FloatVector(745, 471), -- положение фишки на экране
			neighbours = { -- список позиций, в которые можно перейти из данной
				2, 8
			}
		},
		{ -- номер позиции: 6
			state =  "stone02", -- состояние позиции: "" - свободна, иначе нет
			end_state = "earth", -- в каком состоянии должна находиться позиция на момент окончания игры: "" - не важно, иначе должно быть какой-то конкретно 
			pos = sf.misc.FloatVector(567, 526), -- положение фишки на экране
			neighbours = { -- список позиций, в которые можно перейти из данной
				1, 3
			}
		},
		{ -- номер позиции: 7
			state =  "stone03", -- состояние позиции: "" - свободна, иначе нет
			end_state = "", -- в каком состоянии должна находиться позиция на момент окончания игры: "" - не важно, иначе должно быть какой-то конкретно 
			pos = sf.misc.FloatVector(397, 482), -- положение фишки на экране
			neighbours = { -- список позиций, в которые можно перейти из данной
				2, 4
			}
		},
		{ -- номер позиции: 8
			state =  "", -- состояние позиции: "" - свободна, иначе нет
			end_state = "water", -- в каком состоянии должна находиться позиция на момент окончания игры: "" - не важно, иначе должно быть какой-то конкретно 
			pos = sf.misc.FloatVector(321, 322), -- положение фишки на экране
			neighbours = { -- список позиций, в которые можно перейти из данной
				3, 5
			}
		}
	}	
}
-- проверка, закончилась ли у нас игра
function self.CheckEnd(_owner)
	if self.cant_win then return end
	
	local alright = true;
	-- надо проверить, находятся ли все позиции в своем финальном положении
	for i = 1, #self.params.positions do
		if (self.params.positions[i].end_state ~= "" and
			self.position_state[i] ~= self.params.positions[i].end_state) then
			-- положение i-ой фишки не совпало с ее конечным положением, игра не завершена
				alright = false;
				break
		end
	end
	
	if (alright == true) then
	-- закончить миниигру
		self.win = true
	--	self.start_win = self.timer.Get().GetTime()
		
		
	end
end

function self.ShowWinClips(_owner)
	self.win_shining = {}
	-- подсветка всех фишек
	for i, obj in ipairs(self.objects) do
		local offset = obj.image.GetOffset()
		
		local dib_type = obj.object_type
		local id = self.params.clip_select[1].id
		local layer = 0
		for j, sel in ipairs(self.params.clip_select) do
			if sel.type == dib_type then
				id = sel.id
				layer = sel.layer
				break
			end
		end
		local clip = sf.gui.CClipWidget("", 0, 0)
		clip.GetClip().Load(id, true)
		--__message("i= "..i.." id = "..id)
		local size = clip.GetClip().GetViewSize()
		local width, height = obj.image.GetSize().X, obj.image.GetSize().Y
		local center = { -- центр позиции совпадает с серединой нижнего края фишки
			X = offset.X + width/2,
			Y = offset.Y + height/2
		} 
		-- теперь ищем позицию, которая приблизительно такая же, как найденная
		local num = self.FindPos(center)
		if num > 0 then
			clip.SetOffset(self.params.positions[num].pos.X - size.X/2, 
				self.params.positions[num].pos.Y - size.Y/2) -- запускаем эффект для выделения фишки
			clip.SetLayer(layer)
			_owner.AddWidget(clip)
			table.insert(self.win_shining, clip)
		end
	end
	-- показываем все линии
	for i, info in ipairs(self.lines_shine) do
		info.clip.RemFlags(sf.gui.CWidget.FlagHidden)
	end
	-- подсветка всех лунок
	for i, pos in ipairs(self.params.positions) do
		local pos_clip_x, pos_clip_y = pos.pos.X, pos.pos.Y
		local clip = sf.gui.CClipWidget("", 1, 0)
		clip.GetClip().Load(self.params.right_clip, true)
		clip.SetOffset(pos_clip_x - self.on_move_size.X/2, pos_clip_y - self.on_move_size.Y/2)
		clip.SetSize(self.on_move_size.X, self.on_move_size.Y)
		_owner.AddWidget(clip)
		table.insert(self.win_shining, clip)
	end
end

function self.Init(_owner) -- функция, инициализирующая миниигру; в ней стоит инициализировать все переменные, нужные миниигре
	sminigames.SetStandartScriptName(_owner, switch_figures_chapter06) 
	
	-- инициализация переменных
	-- создаем таблицу состояний позиций
	self.position_state = {}
	for i = 1, #self.params.positions do
		local state = self.params.positions[i].state
		if sminigames.save then
			state = sminigames.save[i]
		end

		table.insert(self.position_state, state)
	end
	if not sminigames.save then
		sminigames.save = {}
		for i = 1, #self.params.positions do
			table.insert(sminigames.save, self.position_state[i])
		end
	end
--------------изображения	
	self.objects = {}
	-- создаем объекты 
	local i = 1
	local initialized = {}
	for i = 1, #self.params.positions do
		if self.position_state[i] ~= "" then
			local image_widget =  __cast(_owner.GetWidget(self.position_state[i], true), sf.gui.CClipWidget)
			if not image_widget then 
				break 
			end
			
			-- создаем объект для птички
			local o = {image = image_widget, object_type = self.position_state[i]}
			table.insert(self.objects, o)
			local width, height = self.objects[#self.objects].image.GetSize().X, self.objects[#self.objects].image.GetSize().Y
			self.objects[#self.objects].image.SetOffset(self.params.positions[i].pos.X - width/2, self.params.positions[i].pos.Y - height/2)
		end
	end
	self.shadow = sf.gui.CImageWidget(self.params.shadow, "", 0, 0)
	self.shadow.SetLayer(self.params.shadow_layer)
	self.shadow.AddFlags(sf.gui.CWidget.FlagHidden)
	_owner.AddWidget(self.shadow)
---------------------- клипы выделения линий между лунками
	self.lines_shine = {}
	for i, info in ipairs(self.params.line_selections) do
		local widget = __cast(_owner.GetWidget(info.id, true), sf.gui.CClipWidget)
		if widget then
			widget.AddFlags(sf.gui.CWidget.FlagHidden)
			local object =
			{
				pos1 = info.pos1,
				pos2 = info.pos2,
				clip = widget
			}
			table.insert(self.lines_shine, object)
		end
	end
------------------------клипы выделения фишек и лунок
	-- подсветка ячейки, в которую идем
	self.clip_on_move = sf.gui.CClipWidget("", 1, 0)
	self.clip_on_move.GetClip().Load(self.params.right_clip, true)
	self.on_move_size = self.clip_on_move.GetClip().GetViewSize()
	self.clip_on_move.SetOffset(0, 0)
	self.clip_on_move.SetSize(0, 0)
	_owner.AddWidget(self.clip_on_move) 
    -- подсветка фишки
	self.clip_dib = sf.gui.CClipWidget("", 0, 1)

	self.clip_dib.SetOffset(0, 0)
	self.clip_dib.AddFlags(sf.gui.CWidget.FlagHidden)

	_owner.AddWidget(self.clip_dib) 
-- проигрывается, когда нельзя идти
	self.clip_error = sf.gui.CClipWidget("", 0, 0) 
	self.clip_error.GetClip().Load(self.params.wrong_clip, true)
	self.error_size = self.clip_error.GetClip().GetViewSize()
	self.clip_error.SetOffset(0, 0)
	self.clip_error.SetSize(0, 0)
	_owner.AddWidget(self.clip_error)

-------------------------------вспомогательные 
	self.selected = -1 -- сейчас не выделена фишка (номер выделенного объекта)
	self.sel_pos = -1 -- номер выделенной позиции
	
	self.cur_way = {} -- по какому пути движется объект
	self.cur_line = -1 -- по какому участку пути сейчас двигаемся
	self.moving = -1 -- какой объект движется
	self.obj_pos = {x = 0, y = 0} -- позиция движущегося объекта
	self.last_start = 0 -- начало движения от последней точки
	self.last_length = 0 -- сколько должны двигаться от этой точки
	
	self.timer = __create_timer("", "qe_level") -- создаем таймер, который будет использоваться для движения объекта
		
	self.win = false -- победили?
	
	self.sound = 0
	
	self.CheckEnd(_owner)
	if (self.win) then -- пометка о победе меняется в начале движения, а игра должна закончиться только после окончания последнего перемещения
		self.start_win = self.timer.Get().GetTime()
		self.ShowWinClips(_owner)
	end
	
	self.enabled_shines = {}
	for i, pos in ipairs(self.params.positions) do
		local pos_clip_x, pos_clip_y = pos.pos.X, pos.pos.Y
		local clip = sf.gui.CClipWidget("", 1, 0)
		clip.GetClip().Load(self.params.right_clip, true)
		clip.SetOffset(pos_clip_x - self.on_move_size.X/2, pos_clip_y - self.on_move_size.Y/2)
		clip.SetSize(self.on_move_size.X, self.on_move_size.Y)
		_owner.AddWidget(clip)
		table.insert(self.enabled_shines, clip)
		clip.AddFlags(sf.gui.CWidget.FlagHidden)
	end
end

-- ищет фишку, в ктороую попадают заданные координаты; если фишка не найдена, возвращает nil
function self.FindDibByPos(_x, _y)
	local i
	for i = 1, #self.objects do
		local pos = self.objects[i].image.GetOffset()
		local width, height = self.objects[i].image.GetSize().X, self.objects[i].image.GetSize().Y

		if (math.abs(pos.X + width/2 - _x) < self.params.pos_width/2) and (math.abs(pos.Y + height/2 - _y) < self.params.pos_height/2) then
			return i
		end
		
	end	
end
--  находит все ребра из self.lines_shine, в которые можно дойти из _i, 
function self.FindAllLines(_i)
	local list = {}
	if not _i or _i <= 0 then return list end

	-- если надо подсвечивать все доступные ребра на любом расстоянии
	--[[local matr = self.MakeTransitionMatrix(_i)
	for i = 1, #self.params.positions do
		if i ~= _i then
			-- если туда можно пройти, значит все ребра этого пути нам понадобятся
			local way = self.FindWay(matr, _i, i)
			if (way ~= nil) then
				-- запихиваем все ребра в массив без повторений
				local j, n = 1, #way
				while j + 1 <= n do
					local num = self.FindSingleLine(way[j], way[j + 1])
					if num and not self.ListHasObject(list, num) then
						table.insert(list, num)
					end

					j = j + 1
				end
			end
		end
	end]]
	-- если надо просматривать только соседние вершины
	for k = 1, #self.params.positions[_i].neighbours do
		local neigh = self.params.positions[_i].neighbours[k]
		local num = self.FindSingleLine(_i, neigh) 
		if num and self.position_state[neigh] == "" then
			table.insert(list, num)
		end
	end
	
	return list
end
-- возвращает индекс в self.lines_shine для ребра с вершинами _i и _j
function self.FindSingleLine(_i, _j)
	for i, info in ipairs(self.lines_shine) do
		if info.pos1 == _i and info.pos2 == _j or
			info.pos1 == _j and info.pos2 == _i then
				return i
		end
	end
	return nil
end

function self.OnMouseMove(_this, _pos, _state, _broadcast)
	if (self.moving > 0) or self.win then return false end
	local dib_in_pos = self.FindDibByPos(_pos.X, _pos.Y) -- попали в какую-нибудь фишку?
	local i = nil
	if not dib_in_pos then 
		i = -1
	else
		local pos_x, pos_y  = self.objects[dib_in_pos].image.GetOffset().X, self.objects[dib_in_pos].image.GetOffset().Y
		local width, height = self.objects[dib_in_pos].image.GetSize().X, self.objects[dib_in_pos].image.GetSize().Y
		local center = { -- центр позиции совпадает с серединой нижнего края фишки
			X = pos_x + width/2,
			Y = pos_y + height/2
		} 
		-- теперь ищем позицию, в которой стоит эта фишка
		i = self.FindPos(center)
	end
	
	local list = self.FindAllLines(i)
	
	for k, shine in ipairs(self.enabled_shines) do
		shine.AddFlags(sf.gui.CWidget.FlagHidden)
	end
	
	for j, info in ipairs(self.lines_shine) do
		if self.ListHasObject(list, j) then
			info.clip.RemFlags(sf.gui.CWidget.FlagHidden)
			local pos = nil
			if  info.pos1 == i then
				pos = info.pos2
			else
				pos = info.pos1
			end
			if pos then
				self.enabled_shines[pos].RemFlags(sf.gui.CWidget.FlagHidden)
			end
		else
			info.clip.AddFlags(sf.gui.CWidget.FlagHidden)
			
		end
	end
	
	return true
end

-- проверяет, есть ли объект _obj в списке _list 
function self.ListHasObject(_list, _obj)
	for i, obj in ipairs(_list) do
		if obj == _obj then 
			return i
		end
	end
	return false
end
-- ищем лунку с такими координатами
function self.FindPos(_pos)
	for i = 1, #self.params.positions do
		local posi = self.params.positions[i].pos
		if (math.abs(posi.X - _pos.X) < self.params.pos_width/2 ) and 
			(math.abs(posi.Y - _pos.Y) < self.params.pos_height/2) then
				return i
		end
	end
	return -1
end

-- обработка нажатия кнопки мыши
function self.OnMouseDown(_owner, _pos, _button, _keyboard_state, _broadcast)
	-- если фишка двигается, то не обрабатываем клик
	if _broadcast or self.moving >= 0 or self.win then return false end
	
	-- анализируем, во что мы попали
	local dib_in_pos = self.FindDibByPos(_pos.X, _pos.Y) -- попали в какую-нибудь фишку?
	if dib_in_pos then
		-- попали в фишку - надо определить, на какой она позиции стоит
		local pos_x, pos_y  = self.objects[dib_in_pos].image.GetOffset().X, self.objects[dib_in_pos].image.GetOffset().Y
		local width, height = self.objects[dib_in_pos].image.GetSize().X, self.objects[dib_in_pos].image.GetSize().Y
		local center = { -- центр позиции совпадает с серединой нижнего края фишки
			X = pos_x + width/2,
			Y = pos_y + height/2
		} 
		-- теперь ищем позицию, которая приблизительно такая же, как найденная
		local i = self.FindPos(center)
		if i > 0 then
			-- мы попали в эту позицию
			self.selected = dib_in_pos
			self.sel_pos = i
			local dib_type = self.objects[dib_in_pos].object_type
			local id = self.params.clip_select[1].id
			local layer = 0
			for i, sel in ipairs(self.params.clip_select) do
				if sel.type == dib_type then
					id = sel.id
					layer = sel.layer
					break
				end
			end
			self.clip_dib.GetClip().Load(id, true)
			
			local size = self.clip_dib.GetClip().GetViewSize()
			self.clip_dib.SetOffset(self.params.positions[i].pos.X - size.X/2, 
				self.params.positions[i].pos.Y - size.Y/2) -- запускаем эффект для выделения фишки
			self.clip_dib.RemFlags(sf.gui.CWidget.FlagHidden)
			self.clip_dib.SetLayer(layer)
			
			if self.params.sound_select then
				sound(self.params.sound_select)
			end
		end
	else
		-- попали не в фишку... значит могли попасть в позицию
		local i = self.FindPos(_pos)
		if i > 0 then
			-- мы попали в эту позицию
			if self.selected ~= -1 then
				--  надо генерить путь от выделенной фишки к этой позиции
				local matr = self.MakeTransitionMatrix(self.sel_pos)

				local way = self.FindWay(matr, self.sel_pos, i)
				if (way == nil) then
					-- нет пути - ошибка. потом надо будет заменить на клип 
					local pos_clip_x, pos_clip_y = self.params.positions[i].pos.X, self.params.positions[i].pos.Y
					self.clip_error.SetOffset(pos_clip_x - self.error_size.X/2, pos_clip_y - self.error_size.Y/2)
					self.clip_error.SetSize(self.error_size.X, self.error_size.Y)
					self.clip_error.GetClip().SetTime(0)
					self.clip_error.GetClip().Play()
				else
					-- инициализировать движение и изменить состояние selected на free, а i на object_type
					if #way > 1 then
						local pos_clip_x, pos_clip_y = self.params.positions[way[1]].pos.X, self.params.positions[way[1]].pos.Y
						self.clip_on_move.SetOffset(pos_clip_x - self.on_move_size.X/2, pos_clip_y - self.on_move_size.Y/2)
						self.clip_on_move.SetSize(self.on_move_size.X, self.on_move_size.Y)
						self.objects[self.selected].image.SetLayer(self.params.fly_layer)
						
						local w = self.ReverseArray(way)
						self.position_state[self.sel_pos] = ""
						self.position_state[i] = self.objects[self.selected].object_type
						
						sminigames.save[self.sel_pos] = ""
						sminigames.save[i] = self.objects[self.selected].object_type
						
						self.sel_pos = w[#w]
				
						self.cur_way = w -- указываем, по какому пути мы идем
						self.moving = self.selected -- движется выбранный объект
						self.cur_line = 1
						self.obj_pos.x = self.objects[self.selected].image.GetOffset().X + self.objects[self.selected].image.GetSize().X/2
						self.obj_pos.y = self.objects[self.selected].image.GetOffset().Y + self.objects[self.selected].image.GetSize().Y/2
				
						self.UpdateMovingTimer()
						
						-- запихиваем все ребра в массив без повторений
						local j, n = 1, #way
						while j + 1 <= n do
							local num = self.FindSingleLine(way[j], way[j + 1])
							if num then
								self.lines_shine[num].clip.RemFlags(sf.gui.CWidget.FlagHidden)
							end

							j = j + 1
						end
					end
				end
			end
		end
	end
	
	self.CheckEnd(_owner)
	return true
end


-- поиск пути между позициями _start_pos и _end_pos
-- _adj_matr - матрица смежности
-- ! путь выводится, начиная с _end_pos
function self.FindWay(_adj_matr, _start_pos, _end_pos)
	local isSeen = {} -- просматривали ли вершину
	local last = {} -- номер последней помеченой вершины
	local dst = {} -- текущие кратчайшие расстояния от start_pos до end_pos
	local pos_amount = #self.params.positions
	for j = 1, pos_amount do
		table.insert(isSeen, 0)
		table.insert(dst, -100) -- бесконечность
	end

	dst[_start_pos] = 0
	isSeen[_start_pos] = 1
	last = _start_pos
	-- поиск кратчайших расстояний от start_pos до остальных вершин графа (алгоритм Дейкстры)
	for j = 1, (pos_amount-1) do
		for i = 1, pos_amount do
			if (isSeen[i] == 0 and _adj_matr[last][i] == 1) then -- не помечена и связана с последней вершиной
				if (dst[i] < 0) then
					dst[i] = dst[last] + 1
				else
					dst[i] = math.min((dst[last] + 1), dst[i])
				end
			end
		end
		local min_dist = -100
		for x = 1, pos_amount do
			if (isSeen[x] == 0) then
				if (min_dist < 0) then
					min_dist = dst[x]
					last = x
				else
					if (dst[x] >= 0) then
						if (min_dist > dst[x]) then
							min_dist = dst[x]
							last = x
						end
					end
				end
			end
		end
		isSeen[last] = 1
	end
	
	-- построим сам путь
	if (dst[_end_pos] >= 0) then --если путь существует
		local way = {_end_pos} -- первым элементом будет последний элемент
		local verse = _end_pos
		while (verse ~= _start_pos) do
			for i = 1, pos_amount do
				if (dst[i] + 1 == dst[verse] and _adj_matr[i][way[#way]] == 1) then -- мы пришли сюда из этой вершины
					table.insert(way, i)
					verse = i
					break
				end
			end
		end
		
		return way -- построили список вершин в пути
	else
		return nil
	end
end

--создает матрицу смежности для текущего состояния поля
-- _selected_pos - для какой вершины надо сделать исключение
function self.MakeTransitionMatrix(_selected_pos)
	local matr = {}
	local pos_amount = #self.params.positions
	-- заполняем нулями
	for i = 1, pos_amount do
		table.insert(matr, {})
		for j = 1, pos_amount do
			table.insert(matr[i], 0)
		end
	end
	-- выставляем единички в нужных местах
	for i = 1, pos_amount do
		if (self.position_state[i] == "" or i == _selected_pos) then
			local j = 1
			while (self.params.positions[i].neighbours[j]) do
				if (self.position_state[self.params.positions[i].neighbours[j]] == "" or self.params.positions[i].neighbours[j] == _selected_pos) then
					matr[i][self.params.positions[i].neighbours[j]] = 1
					matr[self.params.positions[i].neighbours[j]][i] = 1
				end
				j = j +1
			end
		end
	end
	
	return matr
end

-- выдает массив  _arr в обратном порядке
function self.ReverseArray(_arr)
	local size = #_arr
	local res = {}
	while (size > 0) do
		table.insert(res, _arr[size])
		size = size - 1
	end
	return res
end

-- обновление миниигры 
function self.OnUpdate(_owner)
	if  sf.core.g_Application.GetTimeManager().GetTimer(_T("qe_level")).GetK() < 0.01 then
		return
	end

	if self.start_fade then
		local now = self.timer.Get().GetTime()
		local cur_time = (now - self.start_fade)/self.params.clip_fade_time
		if  cur_time > 1  then
			cur_time = 1
		end
		local alpha = 255 * (1 - cur_time)
		local color = sf.graphics.Color(self.clip_on_move.GetColor())
		if self.last_fade then
			color.Alpha = alpha
			self.clip_on_move.SetColor(color)
		end
		local color1 = sf.graphics.Color(self.lines_shine[self.fade_line].clip.GetColor())
		color1.Alpha = alpha
		self.lines_shine[self.fade_line].clip.SetColor(color1)
		if cur_time == 1 then
			if self.last_fade then
				self.clip_on_move.SetOffset(0, 0)
				self.clip_on_move.SetSize(0, 0)
				self.last_fade = nil
			end
			color.Alpha = 255
			self.clip_on_move.SetColor(color)
			self.start_fade = nil
			
			self.lines_shine[self.fade_line].clip.AddFlags(sf.gui.CWidget.FlagHidden)
			color1.Alpha = 255
			self.lines_shine[self.fade_line].clip.SetColor(color1)
			self.fade_line = nil
		end
	end
	
	if self.start_win then
		local now = self.timer.Get().GetTime()
		if now - self.start_win > self.params.win_shine_time then
			_owner.OnEndGame()
		end
	end
	
	if (self.moving <= 0) then return end
	
	if self.params.sound_id then
		sound(self.params.sound_id)
	end
	self.shadow.RemFlags(sf.gui.CWidget.FlagHidden)
	local ind_end = self.cur_way[self.cur_line + 1]
	local ind_start = self.cur_way[self.cur_line]
	
	local width, height = self.objects[self.moving].image.GetSize().X, self.objects[self.moving].image.GetSize().Y
	local current_time = (self.timer.Get().GetTime() - self.last_start)/self.last_length
    if current_time > 1 then 
		current_time = 1  -- мы не можем зайти дальше точки 
	end
    -- вычисляем новую координату  объекта по величине сдвига
	local start_pos = self.params.positions[ind_start].pos
	local end_pos = self.params.positions[ind_end].pos

	self.obj_pos.x = start_pos.X + (end_pos.X - start_pos.X )*current_time 
	self.obj_pos.y = start_pos.Y + (end_pos.Y - start_pos.Y)*current_time 
    self.objects[self.moving].image.SetOffset(self.obj_pos.x - width/2, self.obj_pos.y - height/2)
	local size = self.clip_dib.GetClip().GetViewSize()
	self.clip_dib.SetOffset(self.obj_pos.x -  size.X/2, self.obj_pos.y - size.Y/2) 
	
	local sz = self.shadow.GetSize()
	self.shadow.SetOffset(self.obj_pos.x - sz.X/4, self.obj_pos.y - sz.Y/2)

	local now = self.timer.Get().GetTime()
	if (now  >= self.last_length +  self.last_start) then -- идем дольше, чем рассчитанное время пути в этом отрезке?
		local num = self.FindSingleLine(self.cur_way[self.cur_line], self.cur_way[self.cur_line+1])
		self.fade_line = num
		self.start_fade = now
		
		self.cur_line = self.cur_line + 1 -- перемещаемся на следующий отрезок пути
		if (self.cur_line == #self.cur_way) then
			-- дошли до конца пути, надо убрать информацию о движении
			local new_x = self.params.positions[self.cur_way[self.cur_line]].pos.X - width/2
			local new_y = self.params.positions[self.cur_way[self.cur_line]].pos.Y - height/2
			self.objects[self.moving].image.SetOffset(new_x, new_y)
			self.objects[self.moving].image.SetLayer(self.params.lay_layer)
			self.clip_dib.AddFlags(sf.gui.CWidget.FlagHidden) -- прячем эффект выделения фишки
			
		--	self.clip_on_move.SetOffset(0, 0)
	--		self.clip_on_move.SetSize(0, 0)
			
		--	self.start_fade = now
			self.last_fade = true
			self.cur_way = {} -- по какому пути движется объект
			self.cur_line = -1 -- по какому участку пути сейчас двигаемся
			self.moving = -1 -- какой объект движется
			self.obj_pos = {x = 0, y = 0} -- позиция движущегося объекта
			self.selected = -1
			self.sel_pos = -1
			self.sound  = 0
			if self.params.sound_place then
				sound(self.params.sound_place)
			end
			self.shadow.AddFlags(sf.gui.CWidget.FlagHidden)
			if (self.win) then -- пометка о победе меняется в начале движения, а игра должна закончиться только после окончания последнего перемещения
				--_owner.SetGameResult(1)
				--_owner.OnEndGame()
				self.start_win = now
				self.ShowWinClips(_owner)
			end
		else -- пересчитать следующую длину
			self.UpdateMovingTimer()
		end
	end
end

-- запоминает момент начала движения от точки и вычисляет время движения до следующей точки отрезка
function self.UpdateMovingTimer()
	self.last_start = self.timer.Get().GetTime() -- начало движения		
	local 	end_pos = self.params.positions[self.cur_way[self.cur_line + 1]].pos
	local distance_sqr1 = (self.obj_pos.x - end_pos.X)*(self.obj_pos.x - end_pos.X)
	local distance_sqr2 = (self.obj_pos.y - end_pos.Y)*(self.obj_pos.y - end_pos.Y)
	
	self.last_length = 1000*math.sqrt(distance_sqr1 + distance_sqr2) / self.params.speed
end
