Having trouble randomizing simple tilesets

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
pxpper
Prole
Posts: 2
Joined: Wed Oct 14, 2020 12:44 am

Having trouble randomizing simple tilesets

Post 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?
User avatar
pgimeno
Party member
Posts: 3550
Joined: Sun Oct 18, 2015 2:58 pm

Re: Having trouble randomizing simple tilesets

Post 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.
User avatar
pxpper
Prole
Posts: 2
Joined: Wed Oct 14, 2020 12:44 am

Re: Having trouble randomizing simple tilesets

Post 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:
Happy Day :awesome:
User avatar
pgimeno
Party member
Posts: 3550
Joined: Sun Oct 18, 2015 2:58 pm

Re: Having trouble randomizing simple tilesets

Post 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
...
RNavega
Party member
Posts: 249
Joined: Sun Aug 16, 2020 1:28 pm

Re: Having trouble randomizing simple tilesets

Post 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.
User avatar
pgimeno
Party member
Posts: 3550
Joined: Sun Oct 18, 2015 2:58 pm

Re: Having trouble randomizing simple tilesets

Post 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.
Post Reply

Who is online

Users browsing this forum: No registered users and 209 guests