Random Scrolling Background from multiple random images in a controlled fashion (simple scroll example code included)

*****SOLVED**** you can look at my last post at bottom for the fix :slight_smile:

This is really basic. It’s a scrolling background that moves along, using 6 images. It has logic that prevents other pieces from overlapping etc. No big deal.

What I really want to do is create multiple random sets of images, and pick an image from each set to match with another set.  For example, in this sample you’ll see random images flying across the screen like 1,6,3,4,2,5,3,3,4,5,2,5,6,1,4,2,3,4 etc.

Right now, it’s a single for loop that goes through 6 images. Let’s say I had 12 images, and I wanted to pick images from 1 through 6, from the first set, then an image from 7 through 12 at random, then put the two together.

So a number is picked from first set - a 3. Then the second set a number is picked, lets say 7

so on screen I would want to have it scroll [3][7] , I don’t want to select from a random number from 1 to 12 - if that was the case I could just change my code’s for loop for r = 1,12 do and be done with it. I need a way to get the data from different areas and string them together like I’m already doing in this example.

I’m sitting here trying to explain it. Hopefully it makes some what sense. For those of you who are looking for some scrolling code, here you go. Some of it is borrowed from all over the place but provided a good jump off point for me. 

Here is the lua code

--takes away the display bar at the top of the screen display.setStatusBar(display.HiddenStatusBar) math.randomseed( os.time() ) -- placeholder for future use. --Shortcut vars for width and height. local \_W = display.contentWidth local \_H = display.contentHeight --Create display group(s) local roads = display.newGroup() local hillPosition = 1220 -- the Y position of the roads local groundLevel = hillPosition local speed = 10 --adjust this to speed up slow down scrolling. --for loop to generate the road pieces for r = 1, 10 do --make sure if you change 1, # - # being the number, you have to change --specifically here \> newX = (roads[#]).x + 100 - speed --Notice in this example it's 10, and in the updateRoads () it's also 10. roadComplete = false local randomNumberGen = math.random(6) -- this isn't perfect, it chooses a random set of numbers and will use the same set over -- and over again. have to incorporate randomSeed into the mix to truly get this to work. --remember if you change math.random(#) this should match the # of images you have. if(randomNumberGen == 1 and roadComplete == false) then newRoad = display.newImageRect("ground1.png", 100,100) roadComplete = true end if(randomNumberGen == 2 and roadComplete == false) then newRoad = display.newImageRect("ground2.png", 100,100) roadComplete = true end if(randomNumberGen == 3 and roadComplete == false) then newRoad = display.newImageRect("ground3.png", 100,100) roadComplete = true end if(randomNumberGen == 4 and roadComplete == false) then newRoad = display.newImageRect("ground4.png", 100,100) roadComplete = true end if(randomNumberGen == 5 and roadComplete == false) then newRoad = display.newImageRect("ground5.png", 100,100) roadComplete = true end if(randomNumberGen == 6 and roadComplete == false) then newRoad = display.newImageRect("ground6.png", 100,100) roadComplete = true end --Give the road pieces a name newRoad.name = ("roadPiece" .. r) newRoad.x = (r \* 100) - 100 newRoad.y = groundLevel roads:insert(newRoad) end local function update( event ) updateroads() end function updateroads() for r = 1, roads.numChildren, 1 do if(r \> 1) then newX = (roads[r - 1]).x + 100 else newX = (roads[10]).x + 100 - speed end if((roads[r]).x \< 300) then (roads[r]).x, (roads[r]).y = newX, (roads[r]).y else (roads[r]):translate(speed \* -1, 0) end end end timer.performWithDelay(1, update, -1) --Memory check - use this to test for leaks between reloads, retrys, exits etc. function checkMemory() collectgarbage( "collect" ) local memUsage\_str = string.format( "MEMORY = %.3f KB", collectgarbage( "count" ) ) print( memUsage\_str, "TEXTURE KB= "..(system.getInfo("textureMemoryUsed") / (1024 \* 1024)) ) end timer.performWithDelay( 100, checkMemory, 0 )

I’m not sure I understand where the problem lies.

If you want a random number from 1-6, and a random number from 7-12 why not just make 2 separate math.random calls:

local randomNumberGen1 = math.random(1, 6) local randomNumberGen2 = math.random(7, 12)

And to save you having lots of if statements, why not concatenate the image name using your random number:

newRoad1 = display.newImageRect("ground"..randomNumberGen1.."png", 100, 100) newRoad2 = display.newImageRect("ground"..randomNumberGen2.."png", 100, 100)

I’ve taken that suggestions about the additional math.random and concatenation to heart and put it aside for now as I have a bigger need that came up during my design process. 

  • Currently what I have is great to put as many images as I want together and randomly select from it.

  • What I would like to do is re tool for at least 3 sets of different size images. For example, lets say I have 3 image sizes:

    •   8px, 256px, 512px - I want to string those together scrolling, so that the textures are put end to end perfectly as they are now in the current code. So for example Ground1 would be 128px, Ground2 would be 256px and Ground3 would be 512. 

One glaring issue is I have is this: 

newRoad.x = (r \* 100) - 100

As you can see, it’s using the width of the image (in this case they are set to 100 by 100) to string them along.I changed ground1 and ground2 to 50 by 100 and made this change, just a quick test to see what it would do (replacing the above code):

newRoad.x = (r \* newRoad.width) - newRoad.width&nbsp; &nbsp;

But that didn’t quite work out - it will still scroll everything, but the images that were 50px wide would show a gap. I figured that would happen, it was a really quick try solution just to see how it would react.  

I’m thinking that I’m close, I need some logic / help to dynamically string them along.

As I said earlier, yes I’ll concatenate the statements, I also know I’ll need to pre load images to get them into texture memory, among other things. That’s all much later when I optimize, right now just trying to bang out the core logic. 

Thanks for any assistance that can be given :slight_smile:

-Nick

--Here is how we do it. Thanks to @\_kyleyamamoto - he came up with a simple solution. The --following still needs math.randomseed to truly get random terrain (its not implemented here) but--- this will give you an idea... --takes away the display bar at the top of the screen display.setStatusBar(display.HiddenStatusBar) math.randomseed( os.time() ) -- placeholder for future use. require ("physics") physics.start() physics.setGravity(0,10) physics.setDrawMode("hybrid") physics.setPositionIterations(8) physics.setVelocityIterations(8) --Shortcut vars for width and height. local \_W = display.contentWidth local \_H = display.contentHeight local currentX = 0 local prevX = 0 --Create display group(s) local roads = display.newGroup() local hillPosition = 500 -- the Y position of the roads local groundLevel = hillPosition local speed = 5--adjust this to speed up slow down scrolling. --for loop to generate the road pieces for r = 1, 10 do --make sure if you change 1, # - # being the number, you have to change --specifically here \> newX = (roads[#]).x + 100 - speed --Notice in this example it's 10, and in the updateRoads () it's also 10. --local randomNumberGen1 = math.random(1, 3) --local randomNumberGen2 = math.random(4, 6) local randomNumberGen = math.random(6) -- this isn't perfect, it chooses a random set of numbers and will use the same set over -- and over again. have to incorporate randomSeed into the mix to truly get this to work. --remember if you change math.random(#) this should match the # of images you have. local newRoad = nil if(randomNumberGen == 1) then newRoad = display.newImageRect("ground1.png", 50,100) newRoad.size = 50 elseif (randomNumberGen == 2) then newRoad = display.newImageRect("ground2.png", 50,100) newRoad.size = 50 elseif (randomNumberGen == 3) then newRoad = display.newImageRect("ground3.png", 100,100) newRoad.size = 100 elseif (randomNumberGen == 4) then newRoad = display.newImageRect("ground4.png", 100,100) newRoad.size = 100 elseif (randomNumberGen == 5) then newRoad = display.newImageRect("ground5.png", 200,100) newRoad.size = 200 elseif (randomNumberGen == 6) then newRoad = display.newImageRect("ground6.png", 200,100) newRoad.size = 200 end --Give the road pieces a name newRoad.name = ("roadPiece" .. r) currentX = currentX + prevX\*0.5 + newRoad.size\*0.5 newRoad.x = currentX --(r \* 100) - 100 newRoad.y = groundLevel roads:insert(newRoad) prevX = newRoad.size end local function update( event ) updateroads() end function updateroads() for r = 1, roads.numChildren do if(r \> 1) then newX = roads[r-1].x + roads[r-1].size\*0.5 + roads[r].size\*0.5--widthref else newX = roads[10].x + roads[10].size\*0.5 + roads[1].size\*0.5 - speed --widthref end if(roads[r].x \< 0) then roads[r].x, roads[r].y = newX, roads[r].y else roads[r]:translate(speed \* -1, 0) end end end timer.performWithDelay(1, update, -1) --Memory check - use this to test for leaks between reloads, retrys, exits etc. function checkMemory() collectgarbage( "collect" ) local memUsage\_str = string.format( "MEMORY = %.3f KB", collectgarbage( "count" ) ) print( memUsage\_str, "TEXTURE KB= "..(system.getInfo("textureMemoryUsed") / (1024 \* 1024)) ) end --timer.performWithDelay( 100, checkMemory, 0 )

I’m not sure I understand where the problem lies.

If you want a random number from 1-6, and a random number from 7-12 why not just make 2 separate math.random calls:

local randomNumberGen1 = math.random(1, 6) local randomNumberGen2 = math.random(7, 12)

And to save you having lots of if statements, why not concatenate the image name using your random number:

newRoad1 = display.newImageRect("ground"..randomNumberGen1.."png", 100, 100) newRoad2 = display.newImageRect("ground"..randomNumberGen2.."png", 100, 100)

I’ve taken that suggestions about the additional math.random and concatenation to heart and put it aside for now as I have a bigger need that came up during my design process. 

  • Currently what I have is great to put as many images as I want together and randomly select from it.

  • What I would like to do is re tool for at least 3 sets of different size images. For example, lets say I have 3 image sizes:

    •   8px, 256px, 512px - I want to string those together scrolling, so that the textures are put end to end perfectly as they are now in the current code. So for example Ground1 would be 128px, Ground2 would be 256px and Ground3 would be 512. 

One glaring issue is I have is this: 

newRoad.x = (r \* 100) - 100

As you can see, it’s using the width of the image (in this case they are set to 100 by 100) to string them along.I changed ground1 and ground2 to 50 by 100 and made this change, just a quick test to see what it would do (replacing the above code):

newRoad.x = (r \* newRoad.width) - newRoad.width&nbsp; &nbsp;

But that didn’t quite work out - it will still scroll everything, but the images that were 50px wide would show a gap. I figured that would happen, it was a really quick try solution just to see how it would react.  

I’m thinking that I’m close, I need some logic / help to dynamically string them along.

As I said earlier, yes I’ll concatenate the statements, I also know I’ll need to pre load images to get them into texture memory, among other things. That’s all much later when I optimize, right now just trying to bang out the core logic. 

Thanks for any assistance that can be given :slight_smile:

-Nick

--Here is how we do it. Thanks to @\_kyleyamamoto - he came up with a simple solution. The --following still needs math.randomseed to truly get random terrain (its not implemented here) but--- this will give you an idea... --takes away the display bar at the top of the screen display.setStatusBar(display.HiddenStatusBar) math.randomseed( os.time() ) -- placeholder for future use. require ("physics") physics.start() physics.setGravity(0,10) physics.setDrawMode("hybrid") physics.setPositionIterations(8) physics.setVelocityIterations(8) --Shortcut vars for width and height. local \_W = display.contentWidth local \_H = display.contentHeight local currentX = 0 local prevX = 0 --Create display group(s) local roads = display.newGroup() local hillPosition = 500 -- the Y position of the roads local groundLevel = hillPosition local speed = 5--adjust this to speed up slow down scrolling. --for loop to generate the road pieces for r = 1, 10 do --make sure if you change 1, # - # being the number, you have to change --specifically here \> newX = (roads[#]).x + 100 - speed --Notice in this example it's 10, and in the updateRoads () it's also 10. --local randomNumberGen1 = math.random(1, 3) --local randomNumberGen2 = math.random(4, 6) local randomNumberGen = math.random(6) -- this isn't perfect, it chooses a random set of numbers and will use the same set over -- and over again. have to incorporate randomSeed into the mix to truly get this to work. --remember if you change math.random(#) this should match the # of images you have. local newRoad = nil if(randomNumberGen == 1) then newRoad = display.newImageRect("ground1.png", 50,100) newRoad.size = 50 elseif (randomNumberGen == 2) then newRoad = display.newImageRect("ground2.png", 50,100) newRoad.size = 50 elseif (randomNumberGen == 3) then newRoad = display.newImageRect("ground3.png", 100,100) newRoad.size = 100 elseif (randomNumberGen == 4) then newRoad = display.newImageRect("ground4.png", 100,100) newRoad.size = 100 elseif (randomNumberGen == 5) then newRoad = display.newImageRect("ground5.png", 200,100) newRoad.size = 200 elseif (randomNumberGen == 6) then newRoad = display.newImageRect("ground6.png", 200,100) newRoad.size = 200 end --Give the road pieces a name newRoad.name = ("roadPiece" .. r) currentX = currentX + prevX\*0.5 + newRoad.size\*0.5 newRoad.x = currentX --(r \* 100) - 100 newRoad.y = groundLevel roads:insert(newRoad) prevX = newRoad.size end local function update( event ) updateroads() end function updateroads() for r = 1, roads.numChildren do if(r \> 1) then newX = roads[r-1].x + roads[r-1].size\*0.5 + roads[r].size\*0.5--widthref else newX = roads[10].x + roads[10].size\*0.5 + roads[1].size\*0.5 - speed --widthref end if(roads[r].x \< 0) then roads[r].x, roads[r].y = newX, roads[r].y else roads[r]:translate(speed \* -1, 0) end end end timer.performWithDelay(1, update, -1) --Memory check - use this to test for leaks between reloads, retrys, exits etc. function checkMemory() collectgarbage( "collect" ) local memUsage\_str = string.format( "MEMORY = %.3f KB", collectgarbage( "count" ) ) print( memUsage\_str, "TEXTURE KB= "..(system.getInfo("textureMemoryUsed") / (1024 \* 1024)) ) end --timer.performWithDelay( 100, checkMemory, 0 )