通过触摸平滑移动具有 3000 个元素的组(Corona sdk)

Posted

技术标签:

【中文标题】通过触摸平滑移动具有 3000 个元素的组(Corona sdk)【英文标题】:Smooth movement of a group with 3000 elements by touch (Corona sdk) 【发布时间】:2018-03-28 08:29:32 【问题描述】:

如何通过触摸大量元素(例如 3000)获得平滑移动组。

在我的普通机器人上,动作发生在轻微的抽搐中。

如果元素减少到 10 则移动平滑。

拼图需要这么多的物品。 用户将能够单击并更改任何元素。因此,任何元素都可以有不同的外观。 使用缩放,用户可以同时看到所有内容。 下面是一个生成 3600 个元素并处理组移动事件的代码示例。

示例代码:

ma​​in.lua

local composer = require( "composer" )

composer.gotoScene( "demo" )

demo.lua

local composer = require( "composer" )
local scene = composer.newScene()


local COUNT_ROWS = 60
local COUNT_CELLS = 60
local MARGIN_RECT = 3
local RECT_SIZE = 30

local viewGroup 
local rectsPreferenses = 

local cretateRectsGroup
, initRectsPrefs
, onTouch
, scalePropByWidthHeight


function scene:create(event)
    self.sceneGroup = self.view
    local bg = display.newRect(display.screenOriginX, display.screenOriginY, display.actualContentWidth, display.actualContentHeight)
    bg.anchorX = 0
    bg.anchorY = 0
    bg:setFillColor(1,1,0)
    self.sceneGroup:insert(bg)
end

function scene:destroy( event )

end

function scene:show( event )
    if event.phase == "will" then
        viewGroup = cretateRectsGroup(self.sceneGroup)

        local maxWidth = display.actualContentWidth
        local maxHeight = display.actualContentWidth
        local initScale = scalePropByWidthHeight(viewGroup, height = maxHeight, width = maxWidth)

        viewGroup.xScale = initScale
        viewGroup.yScale = initScale

    elseif event.phase == "did" then

    end

end

function scene:hide( event )

end

function cretateRectsGroup(sceneGroup)
    local group = display.newGroup()
    group.x = display.actualContentWidth/2 + display.screenOriginX
    group.y = display.actualContentHeight/2 + display.screenOriginY
    group.anchorChildren = true

    local bgW = COUNT_ROWS*RECT_SIZE + COUNT_ROWS*MARGIN_RECT
    local bgH = COUNT_CELLS*RECT_SIZE + COUNT_CELLS*MARGIN_RECT
    local bg = display.newRect(0, 0, bgW, bgH)
    bg.anchorX = 0
    bg.anchorY = 0
    bg:setFillColor(0,1,0)
    bg:addEventListener("touch", onTouch)
    group:insert(bg)

    initRectsPrefs(0,0)
    for i=1, #rectsPreferenses do

        local rectPref = rectsPreferenses[i]
        local rect = display.newRect(0, 0, rectPref.width, rectPref.height)
        rect.anchorX = 0
        rect.anchorY = 0
        rect.x = rectPref.x
        rect.y = rectPref.y
        rect:setFillColor(rectPref.fillColor[1], rectPref.fillColor[2], rectPref.fillColor[3])
        group:insert(rect)
    end

    sceneGroup:insert(group)
    return group
end

function initRectsPrefs(x, y)
    local index = 0
    local curX = x
    local curY = y

    math.randomseed(os.time())
    local rand = math.random
    for i=1, COUNT_ROWS do
        curX = x
        for j=1, COUNT_CELLS do
            index = index + 1
            local r = rand()
            local g = rand()
            local b = rand()
            local optRect = 
                  id = index
                , x = curX
                , y = curY
                , width = RECT_SIZE
                , height = RECT_SIZE
                , fillColor = r, g, b
            
            rectsPreferenses[index] = optRect
            curX = curX + RECT_SIZE + MARGIN_RECT
        end
            curY = curY + RECT_SIZE + MARGIN_RECT
    end
end

function onTouch(event)
    local group = event.target.parent
    local newTouchX, newTouchY = event.x, event.y

    if (event.phase == "began") or (group.lastTouchPosX == nil) or (group.lastTouchPosY == nil) then
        group.lastTouchPosX = newTouchX
        group.lastTouchPosY = newTouchY
        return
    end
    if (event.phase == "ended") or (event.phase == "cancelled") then
        group.lastTouchPosX = nil
        group.lastTouchPosY = nil
        return
    end

    local deltaX = (newTouchX - group.lastTouchPosX)
    local deltaY = (newTouchY - group.lastTouchPosY)
    group.x = group.x + deltaX
    group.y = group.y + deltaY

    group.lastTouchPosX = newTouchX
    group.lastTouchPosY = newTouchY
end

function scalePropByWidthHeight(target, targerTo)
    local scale = 1
    local scaleSize = target.width
    if target.height > target.width then
        scaleSize = target.height
    end

    if ( scaleSize/targerTo.width > scaleSize/targerTo.height ) then 
        scale = targerTo.width/scaleSize
    else
        scale = targerTo.height/scaleSize
    end

    return scale
end

scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )

return scene

【问题讨论】:

【参考方案1】:

找到了使用纹理输出解决此问题的方法。

texture = graphics.newTexture( type="canvas", width=textureW, height=textureH )
local imgTexture = display.newImageRect(group, texture.filename, texture.baseDir, textureW, textureH)
texture:draw(textureGroup)    
texture:invalidate( source="cache", accumulate=false )

demo.lua:

local composer = require( "composer" )
local scene = composer.newScene()


local COUNT_ROWS = 60
local COUNT_CELLS = 60
local MARGIN_RECT = 3
local RECT_SIZE = 30

local viewGroup 
local rectsPreferenses = 

local cretateRectsGroup
, initRectsPrefs
, onTouch
, scalePropByWidthHeight


function scene:create(event)
    self.sceneGroup = self.view
    local bg = display.newRect(display.screenOriginX, display.screenOriginY, display.actualContentWidth, display.actualContentHeight)
    bg.anchorX = 0
    bg.anchorY = 0
    bg:setFillColor(1,1,0)
    self.sceneGroup:insert(bg)
end

function scene:destroy( event )
    if self.sceneGroup.texture then
        self.sceneGroup.texture:removeSelf()
    end
end

function scene:show( event )
    if event.phase == "will" then
        viewGroup = cretateRectsGroup(self.sceneGroup)

        local maxWidth = display.actualContentWidth
        local maxHeight = display.actualContentWidth
        local initScale = scalePropByWidthHeight(viewGroup, height = maxHeight, width = maxWidth)

        viewGroup.xScale = initScale
        viewGroup.yScale = initScale

    elseif event.phase == "did" then

    end

end

function scene:hide( event )

end

function cretateRectsGroup(sceneGroup)
    local group = display.newGroup()
    group.x = display.actualContentWidth/2 + display.screenOriginX
    group.y = display.actualContentHeight/2 + display.screenOriginY
    group.anchorChildren = true

    local bgW = COUNT_ROWS*RECT_SIZE + COUNT_ROWS*MARGIN_RECT
    local bgH = COUNT_CELLS*RECT_SIZE + COUNT_CELLS*MARGIN_RECT
    local bg = display.newRect(0, 0, bgW, bgH)
    bg.anchorX = 0
    bg.anchorY = 0
    bg:setFillColor(0,1,0)
    bg:addEventListener("touch", onTouch)
    group:insert(bg)

    local textureGroup = display.newGroup()
    textureGroup.anchorX = 0
    textureGroup.anchorY = 0

    local bgTetxture = display.newRect(0, 0, bgW, bgH)
    bgTetxture.anchorX = 0
    bgTetxture.anchorY = 0
    bgTetxture:setFillColor(0,1,0)
    textureGroup:insert(bgTetxture)

    initRectsPrefs(0,0)
    for i=1, #rectsPreferenses do

        local rectPref = rectsPreferenses[i]
        local rect = display.newRect(0, 0, rectPref.width, rectPref.height)
        rect.anchorX = 0
        rect.anchorY = 0
        rect.x = rectPref.x
        rect.y = rectPref.y
        rect:setFillColor(rectPref.fillColor[1], rectPref.fillColor[2], rectPref.fillColor[3])
        textureGroup:insert(rect)
    end


    local textureW = bgW
    local textureH = bgH
    local texture = graphics.newTexture( type="canvas", width=textureW, height=textureH )
    sceneGroup.texture = texture
    local offsetZerroTextureX = -(textureW*0.5)
    local offsetZerroTextureY = -(textureH*0.5)

    local imgTexture = display.newImageRect(group, texture.filename, texture.baseDir, textureW, textureH)
    sceneGroup.imgTexture = imgTexture
    imgTexture.anchorX = 0
    imgTexture.anchorY = 0

    textureGroup.x = offsetZerroTextureX
    textureGroup.y = offsetZerroTextureY

    texture:draw(textureGroup)    
    texture:invalidate( source="cache", accumulate=false )
    return group
end

function initRectsPrefs(x, y)
    local index = 0
    local curX = x
    local curY = y

    math.randomseed(os.time())
    local rand = math.random
    for i=1, COUNT_ROWS do
        curX = x
        for j=1, COUNT_CELLS do
            index = index + 1
            local r = rand()
            local g = rand()
            local b = rand()
            local optRect = 
                  id = index
                , x = curX
                , y = curY
                , width = RECT_SIZE
                , height = RECT_SIZE
                , fillColor = r, g, b
            
            rectsPreferenses[index] = optRect
            curX = curX + RECT_SIZE + MARGIN_RECT
        end
            curY = curY + RECT_SIZE + MARGIN_RECT
    end
end

function onTouch(event)
    local group = event.target.parent
    local newTouchX, newTouchY = event.x, event.y

    if (event.phase == "began") or (group.lastTouchPosX == nil) or (group.lastTouchPosY == nil) then
        group.lastTouchPosX = newTouchX
        group.lastTouchPosY = newTouchY
        return
    end
    if (event.phase == "ended") or (event.phase == "cancelled") then
        group.lastTouchPosX = nil
        group.lastTouchPosY = nil
        return
    end

    local deltaX = (newTouchX - group.lastTouchPosX)
    local deltaY = (newTouchY - group.lastTouchPosY)
    group.x = group.x + deltaX
    group.y = group.y + deltaY

    group.lastTouchPosX = newTouchX
    group.lastTouchPosY = newTouchY
end

function scalePropByWidthHeight(target, targerTo)
    local scale = 1
    local scaleSize = target.width
    if target.height > target.width then
        scaleSize = target.height
    end

    if ( scaleSize/targerTo.width > scaleSize/targerTo.height ) then 
        scale = targerTo.width/scaleSize
    else
        scale = targerTo.height/scaleSize
    end

    return scale
end

scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )

return scene

【讨论】:

以上是关于通过触摸平滑移动具有 3000 个元素的组(Corona sdk)的主要内容,如果未能解决你的问题,请参考以下文章

如何跟踪触摸时的手指运动以绘制平滑曲线?

Tomcat apache 8 服务器(端口 - 8080)上的 Pentaho API 在通过不同的 Web 应用程序调用时会出现 COR 问题(反应 JS,端口 - 3000)

iOS Game Center 将排行榜和成就移动到 2 个游戏的组中

PointerEvents:检测“通过”元素的触摸

移动的 touch事件中的touchestargetTouches和changedTouches

Android自定义View Scroller与平滑滚动