How can I prevent random spawning of multiple object to the same location?

I have created a grid and have multiple spawning objects on the grid. How could I prevent from a new spawing object to spawn over an existing object.

Here is the code I use to setup my random reference to my grid:


math.randomseed( os.time() )

local function shuffleTable( t )
    local rand = math.random
    assert( t, “shuffleTable() expected a table, got nil” )
    local iterations = #t
    local j
    
    for i = iterations, 2, -1 do
        j = rand(i)
        t[i], t[j] = t[j], t[i]
    end
end

shuffleTable( spawnRandomX )
shuffleTable( spawnRandomY )

for i = 1, 9 do
    print( spawnRandomX[i] )
end
for i = 1, 5 do
    print( spawnRandomY[i] )
end


And this is how I setup the grid (Both of these I learned in tutorials modifing as needed):


for vVal = 1, 4 do
    for hVal = 1, 8 do
        idx = idx + 1
        square = display.newImageRect(“images/Square.png”, 64, 64)
        square.x = (hVal * 65)-23
        square.y = vVal * 65
        square:addEventListener ( “tap”, squareTapped )
        squares[idx] = square
        squares[idx].idx = idx
    end
end

later in the program a run this, which allows me to drop an object on to the grid:

        squareNewBack.x = spawnRandomX[math.random(1,8)]
        squareNewBack.y = spawnRandomY[math.random(1,4)]

and then change it slightly to spawn another one:

        squareNewBack2.x = spawnRandomX[math.random(1,8)]
        squareNewBack2.y = spawnRandomY[math.random(1,4)]

My problem is some times they want to occupy the same location on the grid. How can I account for the position of the objects already on the grid so that any spawning object finds a random open spot?

Is there a better way for me to make a grid for this?

Mahalo (thanks),

Kaleo

There’s basically two ways you can do that

A: Hold a list of your grid tiles, and when adding something to the grid, update the grid tile with a state indicating it’s occupied

B: Hold a list of objects that have been added to the grid, and store the grid coordinates on each object

… then, regardless of which option you choose: When adding a new object, roll your random x/y coords, check if the new object would be at an occupied spot, and if it would, keep rerolling until you get a free spot.

Thanks for the reply. I had to re-look at my grid and learn a little more about it. I made some changes that have improved it however I have not been able to figure out how to do what you suggested. I get what your saying and the concept make total sense but I’m having a hard time figuring out how to make it happen in lua.

Do you know of any links to tutorials or sample code that will show the process?

Are you by any chance confusing an object’s x, y position on the screen vs it’s position in the grid?   Each of your squares is 64 pixels wide/high.  Your code as written is likely trying to draw newSquareBack near the top left corner (where the center of that 64x64 image is being drawn between x = 1 to 8, etc.

You’re currently calculating the grid, but you also need to compute the actual x, y of the display object.  You can use .x and .y for both.  .x and .y are pixel based.  You might want to store the return from spawnRandomX and spawnRandomY to something like:

obj.gridX = spanRandomX(1,8)

Rob

I maybe am. Below is the grid mods I made before my last post.

local myGridObjs = {}
local squareWidth = 64
local squareHeight = 64
local colSpace = 0
local rowSpace = 0
local numCols = 8
local numRows = 4
local xPos = centerX - (numCols * squareWidth + numCols * colSpace) / 2
local yPos = centerY - (numRows * squareHeight + numRows * rowSpace) / 2

for col = 1, numCols do
    for row = 1, numRows do
        square = display.newImageRect(“images/Square.png”,squareWidth,squareHeight)
        square.width = squareWidth
        square.height = squareHeight
        square.x = xPos + col * (squareWidth + colSpace) - squareWidth/2 - colSpace
        square.y = yPos + row * (squareHeight + rowSpace) - squareHeight/2 - rowSpace
        square.gridPos = {x=col, y=row}
        square:addEventListener ( “tap”, squareTapped )
        myGridObjs[idx] = square
        myGridObjs[idx].idx = idx
        idx = idx + 1
    end
end

local function hideObj (x,y)
    local idx = ((x-1) * numRows) + y
    myGridObjs[idx].alpha = 0
end

local function idxFix()
    idx = idx - 1
    print("idx fixed, now " … idx)
end  – I found that the grid style I decided to try caused the grid idx to be one over the actual grid count. So this is how I fix it.

I tried to create a table in a table so each grid idx point would have a true/false key (starting with false and changing to true during the random spawn) but I just couldn’t get it to work. I will look over it on your recommendation and hopefully I’ll see it.

Mahalo,

Kaleo

maybe the simplest thing to do is, spawn all the squares at once, randomly. Show them all in a nice grid formation. Make them invisible, and save their indexes into an table array in the order they were spawned.  Then loop thru that table, and set that cell/square to visible.  So say, they first random index is 11. That cell becomes visible, you do not have to even work with the {x, y} value and such. Easy-Peasy!

But, not knowing what you are ultimately trying to do… this answer may be off base. If this is not going to work for what you are trying to do, maybe more detail as to the game play may be needed.

BUT, I will assume some things (probably wrongly) here:

The squares are to be visible  at all times, in the positions as they are created and the ‘spawned’ objects are some other images you create and randomly place onto the grids???

If so, try this idea:

Maybe not the best way to do it. But it will work.

In the nested loop where you create the grid images(squares); add a flag to the image as such:

myGridObjs[idx].isOccupied = false

As each image in the grid is in essence a ‘cell’, each with a unique idx, I would pull a random cell like so:

spawnPick = math.rand( numCols * numRows)

Then check if it’s isOccupied flag is false:

if myGridObjs = math.rand( numCols * numRows)

If false, spawn the object/picture or whatever.  Otherwise, increment positive or negative thru  the array of ‘cells’(grid images) till, ‘isOccupied’ is false.  The plot/spawn the image in that cell. 

I would actually try 3 or 4 times to pull a random cell that has isOccupied set to false, and after 3 or 4 tries where random cell is already occupied, I would then increment the spawnPick and traverse the cells either positive or negative. Normally a random cell that is not occupied will get found unless/until most are already filled.

Of course (not knowing the extent of your game) you may need to check to see if all the cells are occupied, otherwise the traversing would loop for ever,

Each time you spawn to a cell be sure to mark that cell ‘isOccupied’ true and if you ever remove a spawned object, mark the isOccupied to false again.  SO, be sure each spawned object has a flag itself, that gets the idx of the cell it is in. Then when you destroy or hide or remove said object you can pull it’s idx reference and mark the cell it was in as isOccupied = false

Again this is a quick and easy way to do it.  Everything depends on how detailed the game is and other game play factors.  

Food for thought; something to stir your creative side:

What if your ‘cells’ of the grid were display groups or containers themselves.  Imagine, that each display group/container holds the ‘square’ image as it’s base, and each spawned object is a image that is inserted into that cell(display group/container) and displayed on top of that square. You could, using the same random check of the cell indexes noted above, check the grid for a cell that has only one child(that is the square image), if it has 2 children that means it has a spawned object. You will have to pay attention to the order the children are inserted into each cell(display group / container) when adding or removing spawned objects.

Good luck

Thanks. Awesome thoughts.

I think the first suggestion could work for what I’m doing and am exited to try that.

Last night I worked hard on something like the isOccupied method but will little success. I think it’s just my understanding of lua at this time as concepts make sense but just have a hard time putting it in code. However, I am learning a whole lot along the way and enjoying it though the frustration.

I really like the food for thought too.

Mahalo,

Kaleo

just fyi,

I made a typo in my response earlier… the line below :

‘Then check if it’s isOccupied flag is false:’

if myGridObjs = math.rand( numCols * numRows)

 

should be:

if myGridObjs[idx] == false then

Thanks, I thought you meant something else. I think this is were my problem lies. I didn’t realize I could have the ture/false right off of myGridObjs[idx].

I though I needed to do myGridObjs[idx].isOccupied == false

More so though I think there’s an issue with my program when it fines the grid idx to be true. I haven’t had a chance to work on it yet today but I will definitely put everyone’s notes to work soon.

Looks like you’re still learning the basics of Lua, so maybe code is more useful than words. Here’s a sample using approach “A” I described above. Just drop it in some folder as main.lua and run it.

math.randomseed(os.time()) local GRID\_COLS = 4 local GRID\_ROWS = 6 local GRID\_SPACING = 40 local grid = {} -- set up the grid for i = 1, GRID\_ROWS do grid[i] = {} for j = 1, GRID\_COLS do local tile = display.newCircle(j \* GRID\_SPACING, i \* GRID\_SPACING, 4) tile.isOccupied = false grid[i][j] = tile end end -- make a list of unoccupied grid tiles local findFreeTiles = function() local freeTiles = {} for i = 1, #grid do for j = 1, #grid[i] do if not grid[i][j].isOccupied then table.insert(freeTiles, grid[i][j]) end end end return freeTiles end -- spawn a thing on top of a grid tile local spawnThing = function(tile) local thing = display.newCircle(tile.x, tile.y, 20) thing:setFillColor(1, 0, 0) thing:toFront() tile.isOccupied = true end -- spawn a thing and place it on a random free grid tile local placeRandomThing = function() local freeTiles = findFreeTiles() if #freeTiles == 0 then print("No more room available, can't spawn more things!") return end local randomTile = freeTiles[math.random(1, #freeTiles)] spawnThing(randomTile) end -- make a button that spawns things local button = display.newText("Spawn Thing", display.contentCenterX, 10, native.systemFont, 16) button:addEventListener("tap", placeRandomThing)

For what it’s worth, this weeks tutorial is about working with grids in games:

https://coronalabs.com/blog/2015/04/07/tutorial-working-with-a-grid-layout/

Rob

Thanks _memo, thanks Rob

I been stuck on duty and haven’t had a chance to work on my game but can’t wait to look through the code and tutorial. Yes I am new to this kind of programming and lua. Coming from a SCADA, PLC background the logic and concepts make sense but learning to understand the language is where I am at. I actually started using a drag and drop program first as it’s was very close to my SCADA work but learned about Corona shortly after, which is more or the route I was looking for. Thanks again guys as I have been learning a lot here and through the various tutorials you have available.

Mahalo,

Kaleo

Finally got to work on the project. I checked out the code and can see where I went wrong. Also started blending the other aspects of my game with the code you provided and edited a little of your code as needed. Thanks again.

Still working out some kinks but I’m on my way.

Mahalo,

Kaleo

There’s basically two ways you can do that

A: Hold a list of your grid tiles, and when adding something to the grid, update the grid tile with a state indicating it’s occupied

B: Hold a list of objects that have been added to the grid, and store the grid coordinates on each object

… then, regardless of which option you choose: When adding a new object, roll your random x/y coords, check if the new object would be at an occupied spot, and if it would, keep rerolling until you get a free spot.

Thanks for the reply. I had to re-look at my grid and learn a little more about it. I made some changes that have improved it however I have not been able to figure out how to do what you suggested. I get what your saying and the concept make total sense but I’m having a hard time figuring out how to make it happen in lua.

Do you know of any links to tutorials or sample code that will show the process?

Are you by any chance confusing an object’s x, y position on the screen vs it’s position in the grid?   Each of your squares is 64 pixels wide/high.  Your code as written is likely trying to draw newSquareBack near the top left corner (where the center of that 64x64 image is being drawn between x = 1 to 8, etc.

You’re currently calculating the grid, but you also need to compute the actual x, y of the display object.  You can use .x and .y for both.  .x and .y are pixel based.  You might want to store the return from spawnRandomX and spawnRandomY to something like:

obj.gridX = spanRandomX(1,8)

Rob

I maybe am. Below is the grid mods I made before my last post.

local myGridObjs = {}
local squareWidth = 64
local squareHeight = 64
local colSpace = 0
local rowSpace = 0
local numCols = 8
local numRows = 4
local xPos = centerX - (numCols * squareWidth + numCols * colSpace) / 2
local yPos = centerY - (numRows * squareHeight + numRows * rowSpace) / 2

for col = 1, numCols do
    for row = 1, numRows do
        square = display.newImageRect(“images/Square.png”,squareWidth,squareHeight)
        square.width = squareWidth
        square.height = squareHeight
        square.x = xPos + col * (squareWidth + colSpace) - squareWidth/2 - colSpace
        square.y = yPos + row * (squareHeight + rowSpace) - squareHeight/2 - rowSpace
        square.gridPos = {x=col, y=row}
        square:addEventListener ( “tap”, squareTapped )
        myGridObjs[idx] = square
        myGridObjs[idx].idx = idx
        idx = idx + 1
    end
end

local function hideObj (x,y)
    local idx = ((x-1) * numRows) + y
    myGridObjs[idx].alpha = 0
end

local function idxFix()
    idx = idx - 1
    print("idx fixed, now " … idx)
end  – I found that the grid style I decided to try caused the grid idx to be one over the actual grid count. So this is how I fix it.

I tried to create a table in a table so each grid idx point would have a true/false key (starting with false and changing to true during the random spawn) but I just couldn’t get it to work. I will look over it on your recommendation and hopefully I’ll see it.

Mahalo,

Kaleo

maybe the simplest thing to do is, spawn all the squares at once, randomly. Show them all in a nice grid formation. Make them invisible, and save their indexes into an table array in the order they were spawned.  Then loop thru that table, and set that cell/square to visible.  So say, they first random index is 11. That cell becomes visible, you do not have to even work with the {x, y} value and such. Easy-Peasy!

But, not knowing what you are ultimately trying to do… this answer may be off base. If this is not going to work for what you are trying to do, maybe more detail as to the game play may be needed.

BUT, I will assume some things (probably wrongly) here:

The squares are to be visible  at all times, in the positions as they are created and the ‘spawned’ objects are some other images you create and randomly place onto the grids???

If so, try this idea:

Maybe not the best way to do it. But it will work.

In the nested loop where you create the grid images(squares); add a flag to the image as such:

myGridObjs[idx].isOccupied = false

As each image in the grid is in essence a ‘cell’, each with a unique idx, I would pull a random cell like so:

spawnPick = math.rand( numCols * numRows)

Then check if it’s isOccupied flag is false:

if myGridObjs = math.rand( numCols * numRows)

If false, spawn the object/picture or whatever.  Otherwise, increment positive or negative thru  the array of ‘cells’(grid images) till, ‘isOccupied’ is false.  The plot/spawn the image in that cell. 

I would actually try 3 or 4 times to pull a random cell that has isOccupied set to false, and after 3 or 4 tries where random cell is already occupied, I would then increment the spawnPick and traverse the cells either positive or negative. Normally a random cell that is not occupied will get found unless/until most are already filled.

Of course (not knowing the extent of your game) you may need to check to see if all the cells are occupied, otherwise the traversing would loop for ever,

Each time you spawn to a cell be sure to mark that cell ‘isOccupied’ true and if you ever remove a spawned object, mark the isOccupied to false again.  SO, be sure each spawned object has a flag itself, that gets the idx of the cell it is in. Then when you destroy or hide or remove said object you can pull it’s idx reference and mark the cell it was in as isOccupied = false

Again this is a quick and easy way to do it.  Everything depends on how detailed the game is and other game play factors.  

Food for thought; something to stir your creative side:

What if your ‘cells’ of the grid were display groups or containers themselves.  Imagine, that each display group/container holds the ‘square’ image as it’s base, and each spawned object is a image that is inserted into that cell(display group/container) and displayed on top of that square. You could, using the same random check of the cell indexes noted above, check the grid for a cell that has only one child(that is the square image), if it has 2 children that means it has a spawned object. You will have to pay attention to the order the children are inserted into each cell(display group / container) when adding or removing spawned objects.

Good luck

Thanks. Awesome thoughts.

I think the first suggestion could work for what I’m doing and am exited to try that.

Last night I worked hard on something like the isOccupied method but will little success. I think it’s just my understanding of lua at this time as concepts make sense but just have a hard time putting it in code. However, I am learning a whole lot along the way and enjoying it though the frustration.

I really like the food for thought too.

Mahalo,

Kaleo

just fyi,

I made a typo in my response earlier… the line below :

‘Then check if it’s isOccupied flag is false:’

if myGridObjs = math.rand( numCols * numRows)

 

should be:

if myGridObjs[idx] == false then