How to avoid drawing map every single tick

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.
munchor
Prole
Posts: 39
Joined: Sun Jun 10, 2012 4:28 pm

Re: How to avoid drawing map every single tick

Post by munchor »

Guys, I tried the canvas but it didn't really work.

http://videobin.org/+5zj/6mf.html

I made that video so you can see more or less what is happening. (I included code so that you can see the changes I make).

Thank you.
User avatar
Boolsheet
Inner party member
Posts: 780
Joined: Wed Dec 29, 2010 4:57 am
Location: Switzerland

Re: How to avoid drawing map every single tick

Post by Boolsheet »

Hm. You draw like 50 rectangles in one frame, right? That really should not be slow. I take it the setDrawRange function prevents that rectangles off-screen get rendered. Can you make sure that works correctly?

The idea was that you only draw to the Canvas when you need to update the terrain. With a sidescroller like this, it's probably not going to be much better. Of course you could do some tricks if you expect the terrain to stay that blocky, but this game should run fast without a Canvas anyway.

We need to see more code to help you out.
Shallow indentations.
munchor
Prole
Posts: 39
Joined: Sun Jun 10, 2012 4:28 pm

Re: How to avoid drawing map every single tick

Post by munchor »

Code? Attached is all code in a .love.

I am very sure that :setDrawRange is only drawing what is necessary, that was one of my first suspicions. One way to fix this would be to have 32*32 tiles instead of 16, but 32 would make it so much harder...
Attachments
slow_tilemap_drawing.love
(44.3 KiB) Downloaded 132 times
User avatar
Boolsheet
Inner party member
Posts: 780
Joined: Wed Dec 29, 2010 4:57 am
Location: Switzerland

Re: How to avoid drawing map every single tick

Post by Boolsheet »

The AdvTileLoader drawing indeed seems a bit inefficient. I don't know the format it is loading, perhaps it has to do it this way. SpriteBatches could speed it up enormously if they were compatible with that format.

However, your collision code is even slower than the drawing. At least for me.
Shallow indentations.
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: How to avoid drawing map every single tick

Post by Roland_Yonaba »

All your pain, sufferings and miseries comes from this single function:

Code: Select all

player.update()
Well, you just need to reduce the number of collisions checks made.
Say for instance you are move right. Actually player.update() will call player.collidingRight()

Code: Select all

player.collidingRight = function(map)
  for i = 1, map.TILE_SIZE - 1 do
    if map.isSolid(player.x + map.TILE_SIZE, player.y + i) then
      return true
    end
  end
  return false
end
Seems that this is really costful, in terms of operations made.
I suggest implementing a routine such as getTileXY. When passing player's x,y current position, it will return the x,y position of the player in the tile map.

Code: Select all

local function getTileXY(x,y,tileWidth,tileHeight)
    return math.ceil(x/tileWidth),math.ceil(y/tileHeight)
end
Then it all becomes simple. When moving in a direction, you just check if tile getTileXY(player.x+dx,player.y+dy,tileWidth,tileHeight) is solid before authorizing this move.
munchor
Prole
Posts: 39
Joined: Sun Jun 10, 2012 4:28 pm

Re: How to avoid drawing map every single tick

Post by munchor »

Roland_Yonaba wrote:All your pain, sufferings and miseries comes from this single function:

Code: Select all

player.update()
Well, you just need to reduce the number of collisions checks made.
Say for instance you are move right. Actually player.update() will call player.collidingRight()

Code: Select all

player.collidingRight = function(map)
  for i = 1, map.TILE_SIZE - 1 do
    if map.isSolid(player.x + map.TILE_SIZE, player.y + i) then
      return true
    end
  end
  return false
end
Seems that this is really costful, in terms of operations made.
I suggest implementing a routine such as getTileXY. When passing player's x,y current position, it will return the x,y position of the player in the tile map.

Code: Select all

local function getTileXY(x,y,tileWidth,tileHeight)
    return math.ceil(x/tileWidth),math.ceil(y/tileHeight)
end
Then it all becomes simple. When moving in a direction, you just check if tile getTileXY(player.x+dx,player.y+dy,tileWidth,tileHeight) is solid before authorizing this move.
That looks like a great idea, but what would 'dx' and 'dy' be in that context? Thanks in advance. (I realize deltax and deltay, but how would I go about calculating them, and what do they mean?)
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: How to avoid drawing map every single tick

Post by Roland_Yonaba »

munchor wrote: That looks like a great idea, but what would 'dx' and 'dy' be in that context? Thanks in advance. (I realize deltax and deltay, but how would I go about calculating them, and what do they mean?)
deltaX and deltaY, in the context, would the amount by which you would increase/decrease player's x and y coordinates each update cycle.
Actually, from what I can see in your code, if there's no collision in the moving direction along X or Y-axis, you use 1.
Example:

Code: Select all

    for i = 0, player.vx - 1 do
      if player.collidingRight(player.currentMap) then
        player.vx = 0
      else
        player.x = player.x + 1
        player.translated = player.translated + 1
      end
    end
So let deltaX and deltaY be 1.
munchor
Prole
Posts: 39
Joined: Sun Jun 10, 2012 4:28 pm

Re: How to avoid drawing map every single tick

Post by munchor »

Roland_Yonaba wrote:
munchor wrote: That looks like a great idea, but what would 'dx' and 'dy' be in that context? Thanks in advance. (I realize deltax and deltay, but how would I go about calculating them, and what do they mean?)
deltaX and deltaY, in the context, would the amount by which you would increase/decrease player's x and y coordinates each update cycle.
Actually, from what I can see in your code, if there's no collision in the moving direction along X or Y-axis, you use 1.
Example:

Code: Select all

    for i = 0, player.vx - 1 do
      if player.collidingRight(player.currentMap) then
        player.vx = 0
      else
        player.x = player.x + 1
        player.translated = player.translated + 1
      end
    end
So let deltaX and deltaY be 1.
Damn, that really improved performance. I do have more collision bugs now:

Code: Select all

player.update = function()
  player.vy = player.vy + player.y_acc

  if player.vx > 0 then
    for i = 0, player.vx - 1 do
      if currentMap.isSolid(player.getTile(player.x + 16, player.y, 16, 16)) then
        player.vx = 0
      else
        player.x = player.x + 1
        player.translated = player.translated + 1
      end
    end
  else
    for i = 0, math.abs(player.vx) - 1 do
      if currentMap.isSolid(player.getTile(player.x - 1, player.y, 16, 16)) then
        player.vx = 0
      else
        player.x = player.x - 1
        player.translated = player.translated - 1
      end
    end
  end

  if player.vy > 0 then
    for i = 0, player.vy - 1 do
      if currentMap.isSolid(player.getTile(player.x, player.y + 16, 16, 16)) then
        player.vy = 0
      else
        player.y = player.y + 1
      end
    end
  else
    for i = 0, math.abs(player.vy) - 1 do
      if currentMap.isSolid(player.getTile(player.x, player.y - 10, 16, 16)) then
        player.vy = 0
      else
        player.y = player.y - 1
      end
    end
  end
(...)
Here's a video showing the collision bugs. I really can't explain them, though.

Also, I still have some performance-dropping spikes from time to time, I feel like I still have too many loops on my collision.
Attachments
8dYG0.gif
8dYG0.gif (1.39 MiB) Viewed 715 times
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: How to avoid drawing map every single tick

Post by Roland_Yonaba »

Can you provide the full updated *.love, please ?
munchor
Prole
Posts: 39
Joined: Sun Jun 10, 2012 4:28 pm

Re: How to avoid drawing map every single tick

Post by munchor »

Roland_Yonaba wrote:Can you provide the full updated *.love, please ?
There you go :) Thanks.
Attachments
lua_temp.love
(44.34 KiB) Downloaded 135 times
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 5 guests