2017-10-16 10 views
0

Comment obtenir un groupe mobile lisse en contact avec un grand nombre d'éléments, par exemple 3000.mouvement lisse d'un groupe avec 3000 éléments par contact (Corona sdk)

Sur mon Android moyenne, le mouvement a lieu en petits saccades.

Si les éléments sont réduits à 10, les mouvements doivent être lisses.

Un si grand nombre d'éléments est nécessaire pour le puzzle. L'utilisateur pourra cliquer et modifier n'importe quel élément. Par conséquent, n'importe quel élément peut avoir une apparence différente. En utilisant le zoom, l'utilisateur peut tout voir en même temps. Voici un exemple de code avec la génération de 3600 éléments et le traitement de l'événement sur les mouvements de groupe.

Exemple de 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 

Répondre

0

Je trouvé une solution à ce problème en utilisant la sortie à la 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