简体   繁体   中英

Smooth movement of a group with 3000 elements by touch (Corona sdk)

How to get a smooth moving group with by touch with a large number of elements for example 3000.

On my average android, the movement takes place in small jerks.

If the elements are reduced to 10 then move be smooth.

Such a large number of items are needed for the puzzle. The user will be able to click and change any an element. Therefore, any element can have a different appearance. Using zoom, the user can see everything at the same time. Below is an example of a code with the generation of 3600 elements and processing the event on the movements of group.

Sample code:

main.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

I found a solution to this problem using the output to the texture.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM