Problem with drawing only the cubes on screen.

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
Bogdan705
Prole
Posts: 15
Joined: Sun Aug 05, 2018 9:04 pm

Problem with drawing only the cubes on screen.

Post by Bogdan705 »

So I decided to optimize my game by only drawing cubes that are visible ( already been doing that, and by that I will explain in a bit ) and those that are on screen. Problem is, there are only so many cubes on the screen at a time, yet it tells me it draws around 900+ of them.
love 2018-08-08 21-34-01-166.jpg
love 2018-08-08 21-34-01-166.jpg (543.14 KiB) Viewed 5275 times
When I'm zoomed in at 100% ( default zoom and above ) it's around 900+. At 200% or when I'm at the edge, around 700+. At some point, the number of drawn cubes caps at 1200+ when I zoom out enough.
Now by visible I mean cubes that should theoretically be visible from the isometric point of view. Cubes that have a neighbor to the top, left and right are "not visible". If any of those three conditions is not met, then it "is visible".
After that I use two functions I made, normalToIsoX and normalToIsoY to find out the x,y coordinates of the cube, based on its x,y,z coordinate on the grid. After that I use cam:cameraCoords() on isoX and isoY to find the cubes x,y on the screen ( I use hump.camera )
Now here is the code :

Code: Select all

t.cubeIsVisible = function(x,y,z)
  local xE = false
  local yE = false
  local zE = false
  if (x + 1) > #grid then xE = true end
  if (y + 1) > #grid[x] then yE = true end
  if (z + 1) > #grid[x][y] then zE = true end
  if xE or yE or zE then return true end
  local n = 0
  if grid[x + 1][y][z] ~= 0 then n = n + 1 end
  if grid[x][(y + 1)][z] ~= 0 then n = n + 1 end
  if grid[x][y][(z + 1)] ~= 0 then n = n + 1 end
  local screenX, screenY = cam:cameraCoords(gridFuncs.normalToIsoX(x,y),gridFuncs.normalToIsoY(x,y,z,3))
  if n == 3 then
    return false
  elseif not (((screenX < -100*zoom) or (screenX > wW + 100*zoom)) and ((screenY < -100*zoom) or (screenY > wH + 100*zoom))) then
    return true
  end
end
I have no idea what is causing this problem. Could anyone help me please? Thank you. :rofl:
KSP has thaught me that if you aim for the Mun and miss, you'll crash violently into the ground.
User avatar
Bogdan705
Prole
Posts: 15
Joined: Sun Aug 05, 2018 9:04 pm

Re: Problem with drawing only the cubes on screen.

Post by Bogdan705 »

I realized that the edge xE,yE and zE might be making the game draw cubes on the border of the map so I decided to scrap and change the function. Now it still draws around 800+ at 100%, but only 400+ at 200%. One significant change though ( for the worse ), is that the game runs way slower now. Here is the new code :

Code: Select all

t.cubeIsVisible = function(x,y,z) -- checks if a cube is visible ( in this case covered up by other cubes )
  local screenX, screenY = cam:cameraCoords(gridFuncs.normalToIsoX(x,y),gridFuncs.normalToIsoY(x,y,z,3))
  if not (((screenX < -150) or (screenX > wW + 150)) and ((screenY < -150) or (screenY > wH + 150))) then
    local n = 0
    if gridFuncs.gridCheck(x+1,y,z,0,false) then n = n + 1 end
    if gridFuncs.gridCheck(x,y+1,z,0,false) then n = n + 1 end
    if gridFuncs.gridCheck(x,y,z+1,0,false) then n = n + 1 end
    if n == 3 then return false else return true end
  else return false end
end
And here is gridCheck()

Code: Select all

t.gridCheck = function(x,y,z,v,t) -- checks the grid for something, if search is outside the grid then it produces an error
  return pcall(function()
            if t then
              if grid[x][y][z] == v then else print(haha + ahah) end
            elseif not t then
              if grid[x][y][z] ~= v then else print(haha + ahah) end
            end end)
end
These two functions get called in another function that loops through the grid called gridDraw(), and gridDraw() in term gets called in love.draw. Also, in love.update I have this :

Code: Select all

  if camCycle >= 0.1 then
    -- zoom
    clientFuncs.camZoom()
    cam:zoomTo(zoom)
    -- get cam pos
    local x,y = cam:position()
    -- get the diff between the target pos and current pos
    local xDiff,yDiff = math.abs(isoX - x), math.abs(isoY - y)
    -- slow down if jumping or falling
    local m = 1
    if player.data.jumping or 
       gridFuncs.gridCheck(player.entity.pos.x,
                           player.entity.pos.y,
                           player.entity.pos.z - 1,0,true) then m = 0.3 end
    if xDiff < 5 then xDiff = 0 else xDiff = xDiff / (20 / (settings.camSpeed/10*player.entity.stats.speed*m)) end
    if yDiff < 5 then yDiff = 0 else yDiff = yDiff / (20 / (settings.camSpeed/10*player.entity.stats.speed*m)) end
    camCycle = 0
    -- move cam x pos
    if isoX > x then
      cam:lookAt(x + xDiff,y)
    else
      cam:lookAt(x - xDiff,y)
    end
    -- update cam pos
    local x,y = cam:position()
    -- move cam y pos
    if isoY > y then
      cam:lookAt(x,y + yDiff)
    else
      cam:lookAt(x,y - yDiff)
    end
  end
And this :

Code: Select all

camCycle = camCycle + 1*dt*settings.camSpeed
And I think I created some sort of feedback loop, and that in turn slows down the game.
KSP has thaught me that if you aim for the Mun and miss, you'll crash violently into the ground.
User avatar
Bogdan705
Prole
Posts: 15
Joined: Sun Aug 05, 2018 9:04 pm

Re: Problem with drawing only the cubes on screen.

Post by Bogdan705 »

Nevermind I managed to make the camera run smooth again, but it still says it renders 800+ cubes. Here is a .love file
ooga.love
(505.07 KiB) Downloaded 222 times
KSP has thaught me that if you aim for the Mun and miss, you'll crash violently into the ground.
User avatar
Bogdan705
Prole
Posts: 15
Joined: Sun Aug 05, 2018 9:04 pm

Re: Problem with drawing only the cubes on screen.

Post by Bogdan705 »

I looked at my memory usage and it says love uses 60mb. Is that a lot or not much in terms of Love2D standards ?
KSP has thaught me that if you aim for the Mun and miss, you'll crash violently into the ground.
User avatar
0x72
Citizen
Posts: 55
Joined: Thu Jun 18, 2015 9:02 am

Re: Problem with drawing only the cubes on screen.

Post by 0x72 »

Code: Select all

 not (((screenX < -150) or (screenX > wW + 150)) and ((screenY < -150) or (screenY > wH + 150)))  
renders 1,3,5,7,9:

Code: Select all

region #5 is your viewport and everything else is not visible:

1|2|3
-+-+-
4|5|6
-+-+-
7|8|9
You want to render only 5 (viewport) so try changing and keyword to an or.

Code: Select all

 not ((screenX < -150) or (screenX > wW + 150)) or ((screenY < -150) or (screenY > wH + 150))  
or express differently:

Code: Select all

  ((-150 < screenX) and (screenX < wW + 150)) and ((-150 < screenY) and (screenY < wH + 150)) -- "inside" instead "not outside"  
Also: this solution you have iterates over all the cubes each frame. If it ever become a performance issue read about spatial hashing.
It depends on the size of your world, but I'm already not getting steady 60 with the map you have there - 20181 cubes. cubeIsVisible is responsible for more then 91% time in the gridDraw (after fixing the condition and actually rendering around 60 cubes).

Also: it looks like your coords are anchored to corners so 150 might not be perfect value: this one worked for me better:

Code: Select all

  ((-250 < screenX) and (screenX < wW)) and ((-250 < screenY) and (screenY < wH))
User avatar
Bogdan705
Prole
Posts: 15
Joined: Sun Aug 05, 2018 9:04 pm

Re: Problem with drawing only the cubes on screen.

Post by Bogdan705 »

:awesome: :awesome: :awesome: Thank you a lot
KSP has thaught me that if you aim for the Mun and miss, you'll crash violently into the ground.
User avatar
Bogdan705
Prole
Posts: 15
Joined: Sun Aug 05, 2018 9:04 pm

Re: Problem with drawing only the cubes on screen.

Post by Bogdan705 »

I will try your solution + spatial hashing + capping the framerate and see what the result is.
KSP has thaught me that if you aim for the Mun and miss, you'll crash violently into the ground.
pedrosgali
Party member
Posts: 107
Joined: Wed Oct 15, 2014 5:00 pm
Location: Yorkshire, England

Re: Problem with drawing only the cubes on screen.

Post by pedrosgali »

I'd also suggest drawing your cubes to a canvas and checking each frame if you need to redraw it. So if the camera moves redraw but otherwise just draw the previous render to the screen. I posted an isometric map generation example on another thread on here, I'd leave a link here but I'm on my phone so you'll have to do a search if you want to download it for the code. But using the above method I got a consistent 60 fps regardless of how many tiles I needed on screen (Until I moved the camera at which point it could get a bit laggy if there were too many objects to render.) Since you have players moving you can just draw them after the canvas render.

Code: Select all

if not wearTheseGlasses() then
  chewing_on_trashcan = true
end
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 39 guests