Page 2 of 3

Re: How to avoid drawing map every single tick

Posted: Thu Aug 23, 2012 9:30 am
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.

Re: How to avoid drawing map every single tick

Posted: Thu Aug 23, 2012 1:19 pm
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.

Re: How to avoid drawing map every single tick

Posted: Thu Aug 23, 2012 1:36 pm
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...

Re: How to avoid drawing map every single tick

Posted: Thu Aug 23, 2012 2:51 pm
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.

Re: How to avoid drawing map every single tick

Posted: Thu Aug 23, 2012 2:57 pm
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.

Re: How to avoid drawing map every single tick

Posted: Thu Aug 23, 2012 5:41 pm
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?)

Re: How to avoid drawing map every single tick

Posted: Thu Aug 23, 2012 6:20 pm
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.

Re: How to avoid drawing map every single tick

Posted: Thu Aug 23, 2012 7:17 pm
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.

Re: How to avoid drawing map every single tick

Posted: Thu Aug 23, 2012 7:42 pm
by Roland_Yonaba
Can you provide the full updated *.love, please ?

Re: How to avoid drawing map every single tick

Posted: Thu Aug 23, 2012 8:05 pm
by munchor
Roland_Yonaba wrote:Can you provide the full updated *.love, please ?
There you go :) Thanks.