Page 1 of 1

Having trouble randomizing simple tilesets

Posted: Wed Oct 14, 2020 1:05 am
by pxpper
Hello!
I'm new to love2d, and to this forum. I followed this tutorial https://love2d.org/wiki/Tutorial:Gridlocked_Player and now i want to create random simple tilesets (is that the term?). I used math.random, but I've been having trouble. It's not as... randomized as I want it? I'm not sure how to explain it, but I will provide the code.

Code: Select all

function love.load()
  
  math.randomseed(os.clock()*100000000000)
  math.random(); math.random(); math.random()
  
  v = math.random()
  

  if v >= 0.499999999999 then
    v = math.ceil(v)
    print(v)
  elseif v <= 0.499999999999 then
    v = math.floor(v)
    print(v)
  end
  
	player = {
		grid_x = 256,
		grid_y = 256,
		act_x = 200,
		act_y = 200,
		speed = 15
	}
	map = {
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
		{ 1, v, v, v, v, v, v, v, v, v, v, v, v, 1 },
		{ 1, v, v, v, v, v, v, v, v, v, v, v, v, 1 },
		{ 1, v, v, v, v, v, v, v, v, v, v, v, v, 1 },
		{ 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1 },
		{ 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
		{ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
	}
end
 
function love.update(dt)
	player.act_y = player.act_y - ((player.act_y - player.grid_y) * player.speed * dt)
	player.act_x = player.act_x - ((player.act_x - player.grid_x) * player.speed * dt)
end
 
function love.draw()
	love.graphics.rectangle("fill", player.act_x, player.act_y, 32, 32)
	for y=1, #map do
		for x=1, #map[y] do
			if map[y][x] == 1 then
				love.graphics.rectangle("line", x * 32, y * 32, 32, 32)
			end
		end
	end
end
 
function love.keypressed(key)
	if key == "up" then
		if testMap(0, -1) then
			player.grid_y = player.grid_y - 32
		end
	elseif key == "down" then
		if testMap(0, 1) then
			player.grid_y = player.grid_y + 32
		end
	elseif key == "left" then
		if testMap(-1, 0) then
			player.grid_x = player.grid_x - 32
		end
	elseif key == "right" then
		if testMap(1, 0) then
			player.grid_x = player.grid_x + 32
		end
	end
end
 
function testMap(x, y)
	if map[(player.grid_y / 32) + y][(player.grid_x / 32) + x] == 1 then
		return false
	end
	return true
end


Sometimes there is a huge chunk of blocks, others not...? Am I using math.random() correctly? Can somebody help?

Re: Having trouble randomizing simple tilesets

Posted: Wed Oct 14, 2020 11:52 am
by pgimeno
Hi, welcome to the forums. You're setting a variable to a random number, and then using that number multiple times in your map. This means that you're not actually generating a different number per tile; that would require calling the random function once per tile.

For brevity, I suggest this:

Code: Select all

function love.load()
  local function r()
    return love.math.random(0, 1)
  end
  ...
  map = {
    { 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1 },
    { 1,r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),  1 },
    { 1,r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),  1 }, 
    { 1,r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),  1 }, 
    { 1,  1,  0,  1,  0,  1,  1,  1,  1,  0,  0,  0,  0,  1 }, 
    { 1,  0,  0,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,  1 }, 
    { 1,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1 }, 
    { 1,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1 }, 
    { 1,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1 }, 
    { 1,  0,  0,  1,  0,  0,  0,  0,  1,  1,  1,  1,  0,  1 }, 
    { 1,  0,  0,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,  1 }, 
    { 1,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  1 }, 
    { 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1 }
  }
  ...
end

...
love.math.random comes pre-initialized for you.

Re: Having trouble randomizing simple tilesets

Posted: Wed Oct 14, 2020 12:25 pm
by pxpper
pgimeno wrote: Wed Oct 14, 2020 11:52 am Hi, welcome to the forums. You're setting a variable to a random number, and then using that number multiple times in your map. This means that you're not actually generating a different number per tile; that would require calling the random function once per tile.

For brevity, I suggest this:

Code: Select all

function love.load()
  local function r()
    return love.math.random(0, 1)
  end
  ...
  map = {
    { 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1 },
    { 1,r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),  1 },
    { 1,r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),  1 }, 
    { 1,r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),r(),  1 }, 
    { 1,  1,  0,  1,  0,  1,  1,  1,  1,  0,  0,  0,  0,  1 }, 
    { 1,  0,  0,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,  1 }, 
    { 1,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1 }, 
    { 1,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1 }, 
    { 1,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1 }, 
    { 1,  0,  0,  1,  0,  0,  0,  0,  1,  1,  1,  1,  0,  1 }, 
    { 1,  0,  0,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,  1 }, 
    { 1,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  1 }, 
    { 1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1 }
  }
  ...
end

...
love.math.random comes pre-initialized for you.

Just getting this, thank you so much!!
This helps a lot! The Love2d forums are so friendly! :awesome:

Re: Having trouble randomizing simple tilesets

Posted: Wed Oct 14, 2020 3:02 pm
by pgimeno
I just had this funny idea. Note that for the sake of clarity, I certainly don't recommend doing this, but I wanted to post it for fun. It's actually possible to use your original map constructor; note that this is a sort of advanced use of Lua.

Code: Select all

function love.load()
  ...
  local saveGMT = getmetatable(_G)

  -- This code makes the global variable 'v' take a different
  -- value every time it's read.
  setmetatable(_G, {__index = function(t, k)
    if k == 'v' then return love.math.random(0, 1) end
    return rawget(t, k)
  end})

  map = {
    { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    { 1, v, v, v, v, v, v, v, v, v, v, v, v, 1 },
    { 1, v, v, v, v, v, v, v, v, v, v, v, v, 1 },
    { 1, v, v, v, v, v, v, v, v, v, v, v, v, 1 },
    { 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1 },
    { 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
    { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
  }

  setmetatable(_G, saveGMT) -- restore global metatable
  ...
end
...

Re: Having trouble randomizing simple tilesets

Posted: Wed Oct 14, 2020 8:13 pm
by RNavega
@pgimeno wow, cool stuff!

You are (temporarily) setting a metatable to the '_G' global names table, whose '__index' metamethod will get the result of that random number function wherever you place the name "v" in your code.
This relies on you never setting any global variable named "v" so that the '__index' metamethod can be called.
The syntatic sugar makes it look cleaner than having the several calls to a "r()" function despite the end result being the same, calling a function.

Re: Having trouble randomizing simple tilesets

Posted: Thu Oct 15, 2020 8:50 am
by pgimeno
Yes, though I wouldn't really call it cleaner, actually. In my opinion, inventing dialects hinders readability. I'd only use that construct if accompanied by a bigger comment than the one I've used, and only if justified by the savings. In this case, I think the savings are too small to justify it, but I thought the idea was funny.