类似炉石传说 箭头效果(3D立体改进版)

直接上代码吧,逻辑差不多,不过优化了一些公式。

local M = {}
--图片大小
local rectW,rectH = 55,95
--最大间距和最小间距
local maxSpaceY,minSpaceY = 40,30
--最大最小宽
local maxW,minW = rectW,45
--最小高度,最大高度被最大宽按比例控制,不需要设置
local minH = 30

M.tRect = {}
--抛物线
local function parabolaFunction( sum,x,min,max )
	local p = sum/2
	local a = (min-max)/math.pow(-p,2)
	local y = a*math.pow(x-p,2)+max
	return y
end
--根据数组长度分段类等腰三角形一次函数/\
local function linearFunction( sum,x,min,max )
	local center = sum/2
	local y
	if x>sum/2 then   --下部
		y = (max-min)/(center-sum)*x+max-(max-min)/(center-sum)*center
	else
		y = ((max-min)/center)*x+min
		
	end
	return y
end
--间距
local function computerSpaceY( sum,x )
	local spaceY = linearFunction(sum,x,minSpaceY,maxSpaceY)
	-- spaceY = 20
	return spaceY
end
-- 位移
local offset,speed = 0,0
--设置矩形y坐标
local function setRectY( ... )
	if #M.tRect<=0 then
		return
	end
	-- 设置y
	local height = 0
	for k,imgRect in pairs(M.tRect) do
		--矩形之间间隙
		local spaceY = computerSpaceY(M.distanceXY,height)
		local imgH = imgRect.img.height
		height = height+imgH+spaceY
		imgRect.y = (height + offset)%(M.distanceXY)
		imgRect:setShape()
		imgRect.alpha = 1
		if imgRect.y<=M.distanceXY and imgRect.y>=M.distanceXY-rectH then
			-- imgRect.alpha = (M.distanceXY-imgRect.y)/rectH
		end
		if imgRect.y>=0 and imgRect.y<=rectH then
			-- imgRect.alpha = imgRect.y/rectH
		end
		
	end
	offset = offset - speed
	
end
--移除所有矩形
local function removeAllRect( ... )
	for i,imgRect in pairs(M.tRect) do
		display.remove(imgRect)
		imgRect = nil
	end
	M.tRect = {}
end
--计算矩形高度
local function computerRectHeight( sum,x )
	--图片高度
	local height = linearFunction(sum,x,minH,rectH/rectW*maxW)
	return height
end
--计算M.distanceXY应该创建多少个矩形
local function getAllCount( ... )
	if M.distanceXY<=rectH then
		return 0
	end
	--架设矩形个数在1-20之间反复检测,满足条件就返回
	--i为创建个数
	for i=1,20 do
		local height = 0
		for j=1,i do
			--矩形之间间隙
			local spaceY = computerSpaceY(M.distanceXY,height)
			local imgH = computerRectHeight(M.distanceXY,height)
			height = height+imgH+spaceY
			if height>=M.distanceXY then
				return i-1
			end
		end
	end
	return 20
end

local function newRect( index )
	local gRect = display.newGroup()
	M.gRects:insert(gRect)
	gRect.index = index
	gRect.anchorY = 1
	gRect.anchorChildren = true
	local top = display.newImage( gRect, "arrow/edge.png")
	top.anchorY = 1
	local bottom = display.newImage( gRect, "arrow/edge.png")
	bottom.anchorY = 0
	local img = display.newImage( gRect, "arrow/rect.png")
	gRect.img =img
	local txt = display.newText( gRect, index, 0, 0, nil ,26 )


	function gRect:setHeight()
		img.height = computerRectHeight(M.distanceXY,gRect.y)
		--前两个需要控制高度,因为y和height相互影响,会产生跳跃
		if #M.tRect<=2 then
			img.height = rectH/2
		end
		top.y = img.y-img.height/2
		bottom.y = img.y+img.height/2
		local max,min = 15,2
		top.height = math.max(min,2*(max-min)/M.distanceXY*gRect.y+max-2*(max-min))
		bottom.height = math.max(2*(min-max)/M.distanceXY*gRect.y+max,min)
	end
	function gRect:setWidth()
		local topWidth = parabolaFunction(M.distanceXY,gRect.y-img.height,minW,maxW)
		local bottomWidth = parabolaFunction(M.distanceXY,gRect.y,minW,maxW)
		top.width = topWidth
		bottom.width = bottomWidth
		if gRect.y>M.distanceXY/2 then   --下部
			img.path.x2 = (rectW-bottomWidth)/2
			img.path.x3 = -(rectW-bottomWidth)/2

			img.path.x1 = (rectW-topWidth)/2
			img.path.x4 = -(rectW-topWidth)/2
		else  --上部
			img.path.x2 = (rectW-bottomWidth)/2
			img.path.x3 = -(rectW-bottomWidth)/2

			img.path.x1 = (rectW-topWidth)/2
			img.path.x4 = -(rectW-topWidth)/2
		end
	end
	-- 设置形状
	function gRect:setShape( ... )
		gRect:setHeight()
		gRect:setWidth()
	end

	return gRect
end
--创建矩形组
local function createRect( ... )
	local count = getAllCount()-#M.tRect
	offset=0
	speed=0
	if count>0 then
		
		for i=1,count do
			local imgRect = newRect(#M.tRect+1)
			table.insert(M.tRect,imgRect)
		end
	elseif count<0 then
		for i=1,-count do
			local imgRect = table.remove(M.tRect)
			display.remove(imgRect)
			imgRect = nil
		end
	end
end

--设置角度,高度,图形的变形
local function setCoordinate( startX,startY,endX,endY,distanceX,distanceY )
	M.imgCenter.x,M.imgCenter.y = endX,endY
	M.imgArrow.x,M.imgArrow.y = endX,endY
	M.imgArrow.rotation = math.atan2(distanceY,distanceX)*180/math.pi+90

	M.gRects.x,M.gRects.y = startX,startY
    M.gRects.rotation = math.atan2(distanceY,distanceX)*180/math.pi+90
end
--touch事件监听
local function touchListener( event )
	local phase = event.phase
	local self = event.target
	local endX,endY =  event.x-M.gTouch.x,event.y-M.gTouch.y
	local startX,startY = event.xStart-M.gTouch.x,event.yStart-M.gTouch.y
	local distanceX,distanceY = endX-startX,endY-startY
	M.distanceXY = math.sqrt(math.pow((distanceY),2)+math.pow((distanceX),2))

	if phase == "began" then
        display.getCurrentStage():setFocus( self )
        self.isFocus = true
        M.imgCenter.isVisible = true
        M.imgArrow.isVisible = true
        M.gRects.isVisible = M.distanceXY>=rectH
        setCoordinate(startX,startY,endX,endY,distanceX,distanceY)
    elseif ( self.isFocus ) then
        if phase == "moved" then
        	M.gRects.isVisible = M.distanceXY>=rectH
        	createRect()
        	if M.timer then
        		timer.cancel( M.timer )
        		M.timer = nil
        	end
        	M.timer = timer.performWithDelay( 10, function( ... )
        		speed = 0
        	end)
        	setCoordinate(startX,startY,endX,endY,distanceX,distanceY)
        elseif phase == "ended" or phase == "cancelled" then
            display.getCurrentStage():setFocus( nil )
            self.isFocus = nil
            M.distanceXY = 0
            M.imgCenter.isVisible = false
            M.imgArrow.isVisible = false
            M.gRects.isVisible = false
            removeAllRect()
            offset = 0
            if M.timer then
        		timer.cancel( M.timer )
        		M.timer = nil
        	end
        end
    end
    return true
end
function M.addListener( sceneGroup )
	M.gTouch = display.newGroup()
	M.gTouch.x,M.gTouch.y = display.contentWidth/2,display.contentHeight/2
	-- 底图
    local imgBg = display.newRect( M.gTouch, 0,0, display.contentWidth,display.contentHeight )
    --背景
    local imgBg = display.newImage( M.gTouch, "bg.png")

    --靶心
	M.imgCenter = display.newImage( M.gTouch, "arrow/center.png")
	M.imgCenter.isVisible = false
	--矩形条组
	M.gRects = display.newGroup()
	M.gTouch:insert(M.gRects)
	M.gRects.anchorY = 1
	M.gRects.anchorChildren = true
	M.gRects.isVisible = false
	--箭头
	M.imgArrow = display.newImage( M.gTouch, "arrow/arrow.png")
	M.imgArrow.anchorY = -3
	M.imgArrow.isVisible = false

	
	
	M.gTouch:addEventListener( "touch", touchListener )
	Runtime:addEventListener( "enterFrame", setRectY )
	return M.gTouch
end
return M

效果如图:

bf47cf32fae4e3bab1b092e49fee2275924.jpgfc901d379bc33090cc6697ff7e415509335.jpg

123da7d971d51feb5d12e78b4dfe9864ae0.jpga96cda1af169a9df1090bd5f97d6767d22f.jpg

资源:

96654a482e2ba74336264663ad662d17900.jpg

34cbeb986213ad5cf7e10b0fefe44d96cf2.jpg

763cea3260651c67ca8ae2e0a0114e091cf.jpg

fc2b14a8bac7013c47c51d601820c571fdc.jpg

转载于:https://my.oschina.net/u/3891480/blog/1942252

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值