Dynamically wrapping image from one side to other side

Picture a scenario where you have a Train and the user can touch part of it and drag the whole thing left or right.  Any portion of the train that is off the viewing area should seamlessly appear on the other side of the Viewing area.

I’d rather not create two copies of the train because there could be animations / transitions happening - this is the current work around I’m doing but I know this is going to lead to problems down the road as this gets more complex.

So the question is can you clip a portion of a DisplayGroup and have a real-time duplicate appear somewhere else.  

Thanks

Hi @roygon,

Could your train image potentially “repeat” as tiles across the view area? If so, you may be able to simply offset the fill as explained in this tutorial:

https://coronalabs.com/blog/2013/11/07/tutorial-repeating-fills-in-graphics-2-0/

Take care,

Brent

Hi Brent, thanks for looking into it - I went through the example but I don’t think it’s going to work for what I’m doing.  I think the best thing for me to do is put together a simple sample showing the problem I’m having.    

Thanks

roygon

Ok, here is a simplified demo with some comments to explain what’s going on

I’d really appreciate a push in the right direction

--Note: Each object is in its own display group --to keep consistent with the real app where this --is necessary and also using a lot of hard coded --numbers for simplicity local MainView = display.newGroup() --Using bounding box as edges where object should wrap local BoundingBox = display.newRect(MainView,160,240,300,300) BoundingBox:setFillColor(1,1,1) --Setup 3 objects that will move together local DG1 = display.newGroup() local DG1Obj = display.newCircle(DG1,0,0,20) DG1Obj:setFillColor(0,1,0) DG1.x = 160 DG1.y = 240 MainView:insert(DG1) local DG2 = display.newGroup() local DG2Obj = display.newRect(DG2,0,0,40,40) DG2Obj:setFillColor(1,0,0) DG2.x = 120 DG2.y = 240 MainView:insert(DG2) local DG3 = display.newGroup() local DG3Obj = display.newText(DG3, "ABC",0,0) DG3Obj:setFillColor(0,0,1) DG3.x = 80 DG3.y = 240 MainView:insert(DG3) --Create invisible rectangle to capture touch events local HitTestRectangle = display.newRect(MainView,160,240,320,40) HitTestRectangle.alpha = 0 HitTestRectangle.isHitTestable = true --Event called when touched local function HitTestTouched(event)     if event.phase == "began" then         --     elseif event.phase == "moved" then         local x = (event.x - event.xStart)         --move each object with drag         DG1.x = 160 + x         DG2.x = 120 + x         DG3.x = 80 + x                  --if object goes completely over edge then position at left side         --what really should happen is the portion of the object that goes         --past the right side should be redrawn on the left side         if DG1.x \>= 330 then DG1.x = x - 140 end         if DG2.x \>= 330 then DG2.x = x - 180 end         if DG3.x \>= 330 then DG3.x = x - 220 end         --I have had some success drawing a copy of the end element and placing         --it on the left side and moving it along until the "real" object takes         --its place but these object are going to be animating and transitioning         --all the time so manually making sure the copy matches will get ugly.         --Hoping there is a more elegant approach              elseif event.phase == "ended" or event.phase == "cancelled" then         DG1.x = 160         DG2.x = 120         DG3.x = 80     end     end HitTestRectangle:addEventListener("touch", HitTestTouched)

It sounds like a canvas would work here. (I seem to be saying this a lot lately.  :P) Put your display objects in one of those and regularly invalidate it to pick up the animations. You could then apply the canvas to 1, 2, or 4 display objects, according to how many ways it’s split. Likewise, make as many dummy touch objects.

Hi @roygon,

Could your train image potentially “repeat” as tiles across the view area? If so, you may be able to simply offset the fill as explained in this tutorial:

https://coronalabs.com/blog/2013/11/07/tutorial-repeating-fills-in-graphics-2-0/

Take care,

Brent

Hi Brent, thanks for looking into it - I went through the example but I don’t think it’s going to work for what I’m doing.  I think the best thing for me to do is put together a simple sample showing the problem I’m having.    

Thanks

roygon

Ok, here is a simplified demo with some comments to explain what’s going on

I’d really appreciate a push in the right direction

--Note: Each object is in its own display group --to keep consistent with the real app where this --is necessary and also using a lot of hard coded --numbers for simplicity local MainView = display.newGroup() --Using bounding box as edges where object should wrap local BoundingBox = display.newRect(MainView,160,240,300,300) BoundingBox:setFillColor(1,1,1) --Setup 3 objects that will move together local DG1 = display.newGroup() local DG1Obj = display.newCircle(DG1,0,0,20) DG1Obj:setFillColor(0,1,0) DG1.x = 160 DG1.y = 240 MainView:insert(DG1) local DG2 = display.newGroup() local DG2Obj = display.newRect(DG2,0,0,40,40) DG2Obj:setFillColor(1,0,0) DG2.x = 120 DG2.y = 240 MainView:insert(DG2) local DG3 = display.newGroup() local DG3Obj = display.newText(DG3, "ABC",0,0) DG3Obj:setFillColor(0,0,1) DG3.x = 80 DG3.y = 240 MainView:insert(DG3) --Create invisible rectangle to capture touch events local HitTestRectangle = display.newRect(MainView,160,240,320,40) HitTestRectangle.alpha = 0 HitTestRectangle.isHitTestable = true --Event called when touched local function HitTestTouched(event)     if event.phase == "began" then         --     elseif event.phase == "moved" then         local x = (event.x - event.xStart)         --move each object with drag         DG1.x = 160 + x         DG2.x = 120 + x         DG3.x = 80 + x                  --if object goes completely over edge then position at left side         --what really should happen is the portion of the object that goes         --past the right side should be redrawn on the left side         if DG1.x \>= 330 then DG1.x = x - 140 end         if DG2.x \>= 330 then DG2.x = x - 180 end         if DG3.x \>= 330 then DG3.x = x - 220 end         --I have had some success drawing a copy of the end element and placing         --it on the left side and moving it along until the "real" object takes         --its place but these object are going to be animating and transitioning         --all the time so manually making sure the copy matches will get ugly.         --Hoping there is a more elegant approach              elseif event.phase == "ended" or event.phase == "cancelled" then         DG1.x = 160         DG2.x = 120         DG3.x = 80     end     end HitTestRectangle:addEventListener("touch", HitTestTouched)

It sounds like a canvas would work here. (I seem to be saying this a lot lately.  :P) Put your display objects in one of those and regularly invalidate it to pick up the animations. You could then apply the canvas to 1, 2, or 4 display objects, according to how many ways it’s split. Likewise, make as many dummy touch objects.