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

### Problem with drawing only the cubes on screen.

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 (543.14 KiB) Viewed 1950 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.
KSP has thaught me that if you aim for the Mun and miss, you'll crash violently into the ground.

Bogdan705
Prole
Posts: 15
Joined: Sun Aug 05, 2018 9:04 pm

### Re: Problem with drawing only the cubes on screen.

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.

Bogdan705
Prole
Posts: 15
Joined: Sun Aug 05, 2018 9:04 pm

### Re: Problem with drawing only the cubes on screen.

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
KSP has thaught me that if you aim for the Mun and miss, you'll crash violently into the ground.

Bogdan705
Prole
Posts: 15
Joined: Sun Aug 05, 2018 9:04 pm

### Re: Problem with drawing only the cubes on screen.

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.

0x72
Citizen
Posts: 51
Joined: Thu Jun 18, 2015 9:02 am

### Re: Problem with drawing only the cubes on screen.

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))

Bogdan705
Prole
Posts: 15
Joined: Sun Aug 05, 2018 9:04 pm

### Re: Problem with drawing only the cubes on screen.

Thank you a lot
KSP has thaught me that if you aim for the Mun and miss, you'll crash violently into the ground.

Bogdan705
Prole
Posts: 15
Joined: Sun Aug 05, 2018 9:04 pm

### Re: Problem with drawing only the cubes on screen.

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.

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

### Who is online

Users browsing this forum: No registered users and 38 guests