Shubhro
Shubhro

Reputation: 75

Want to improve the love2d code for performance

I am making a platformer where i am generating level with below code:

function LevelMaker.generateLevel3(width, height)
    local tiles = {}
    local objects = {}
    local entities = {}

    for y = 1, height do
        table.insert(tiles, {})
        for x = 1, width do
            if y == 9 and (x > 5 and x < 12) then
                table.insert(tiles[y], Tile(x, y, math.random(1, 3)))
            elseif (y == 12) and (x > 11 and x < 30) then
                table.insert(tiles[y], Tile(x, y, math.random(1, 3)))
            elseif (y == 3) and (x == 13) then
                table.insert(tiles[y], Tile(x, y, math.random(1, 3)))
            elseif (y == 17) and (x > 15 and x < 28) then
                table.insert(tiles[y], Tile(x, y, math.random(1, 3)))
            elseif (y == 9) and (x > 31 and x < 35) then
                table.insert(tiles[y], Tile(x, y, math.random(1, 3)))
            elseif (y == 6) and (x > 25 and x < 29) then
                table.insert(tiles[y], Tile(x, y, math.random(1, 3)))
            elseif (y > 1 and y < 7) and (x == 26) then
                table.insert(tiles[y], Tile(x, y, math.random(1, 3)))
            elseif (y == 0) and (x > 3 and x < 10) then
                table.insert(tiles[y], Tile(x, y, math.random(1, 3)))
            elseif (y == 13) and (x > 22 and x < 30) then
                table.insert(tiles[y], Tile(x, y, SKY))
                table.insert(objects, 
                    GameObject{
                        texture = 'spikes',
                        x = (x - 1) * TILE_SIZE, y = (y - 1) * TILE_SIZE,
                        width = TILE_SIZE, height = TILE_SIZE,
                        frame = 2,
                        collidable = true,
                        solid = true,
                        deadly = true
                    }
                )
            elseif (y == 3)  and (x == 12) then
                table.insert(tiles[y], Tile(x, y, SKY))
                table.insert(objects, 
                    GameObject{
                        texture = 'spikes',
                        x = (x - 1) * TILE_SIZE, y = (y - 1) * TILE_SIZE,
                        width = TILE_SIZE, height = TILE_SIZE,
                        frame = 4,
                        collidable = true,
                        solid = true,
                        deadly = true
                    }
                )
            elseif (y == 2 or y == 4) and (x == 13) then
                table.insert(tiles[y], Tile(x, y, SKY))
                table.insert(objects, 
                    GameObject{
                        texture = 'spikes',
                        x = (x - 1) * TILE_SIZE, y = (y - 1) * TILE_SIZE,
                        width = TILE_SIZE, height = TILE_SIZE,
                        frame = y == 2 and 1 or 2,
                        collidable = true,
                        solid = true,
                        deadly = true
                    }
                )
            elseif (y == 8) and (x == 10 or x == 11) then
                table.insert(tiles[y], Tile(x, y, SKY))
                table.insert(objects, 
                    GameObject{
                        texture = 'spikes',
                        x = (x - 1) * TILE_SIZE, y = (y - 1) * TILE_SIZE,
                        width = TILE_SIZE, height = TILE_SIZE,
                        frame = 1,
                        collidable = true,
                        solid = true,
                        deadly = true
                    }
                )
            elseif (y > 1 and y < 7) and (x == 25) then
                table.insert(tiles[y], Tile(x, y, SKY))
                table.insert(objects, 
                GameObject{
                    texture = 'spikes',
                    x = (x - 1) * TILE_SIZE, y = (y - 1) * TILE_SIZE,
                    width = TILE_SIZE, height = TILE_SIZE,
                    frame = 4,
                    collidable = true,
                    solid = true,
                    deadly = true
                }
            )
            elseif (y == 8) and (x == 34) then
                table.insert(tiles[y], Tile(x, y, SKY))
                table.insert(objects, 
                GameObject{
                    texture = 'spikes',
                    x = (x - 1) * TILE_SIZE, y = (y - 1) * TILE_SIZE,
                    width = TILE_SIZE, height = TILE_SIZE,
                    frame = 1,
                    collidable = true,
                    solid = true,
                    deadly = true
                }
            )
            elseif (y == 1) and (x > 3 and x < 10) then
                table.insert(tiles[y], Tile(x, y, SKY))
                table.insert(objects, 
                GameObject{
                    texture = 'spikes',
                    x = (x - 1) * TILE_SIZE, y = (y - 1) * TILE_SIZE,
                    width = TILE_SIZE, height = TILE_SIZE,
                    frame = 2,
                    collidable = true,
                    solid = true,
                    deadly = true
                }
            )
            else
                table.insert(tiles[y], Tile(x, y, SKY))
            end
        end
    end

    table.insert(objects,
        GameObject{
            texture = 'house',
            x = (16 - 1) * TILE_SIZE, y = (13 - 1) * TILE_SIZE,
            width = 36, height = 44,
            frame = 1,
        }
    )

    table.insert(objects,
        GameObject{
            texture = 'gems',
            x = (28 - 1) * TILE_SIZE, y = (5 - 1) * TILE_SIZE,
            width = 15, height = 11,
            frame = {1,2,3,4,5},
        }
    )

    local map = TileMap(width, height)
    map.tiles = tiles

    return GameLevel(entities, objects, map)
end

Is there a way to improve the same above code (improve time complexity) When the player dies over and over within 1-2 sec the game freezes. I want to load the level as fast as possible

Upvotes: 1

Views: 210

Answers (1)

Luatic
Luatic

Reputation: 11191

What sticks out to me is that you're running two nested for loops over X and Y just to draw a couple lines, then checking whether the points are on the line using range checks to eventually place tiles; the only thing that seems to be randomized is the tile type, but not the tile position. You should store a list of lines and draw each line on the screen with randomized tiles:

for y = 1, height do -- prepare the grid
        table.insert(tiles, {})
end
local lines = {{from = 6, to = 11, y = 9}, {from = ..., to = ...}, {...}, ...}
for _, line in pairs(lines) do -- draw lines
        if line.y then
                for x = line.from, line.to do
                        table.insert(tiles[line.y], Tile(x, line.y, math.random(1, 3)))
                end
        elseif line.x then
                for y = line.from, line.to do
                        table.insert(tiles[y], Tile(line.x, y, math.random(1, 3)))
                end
        end
end

the fixed sky/spikes/house/gems tiles can benefit from the same technique; you'll have to store a line tile type with each line and use it instead of the random tile though. These seem to be static though - why can't you just reuse the old level and replace only the randomized tiles using the described "line drawing" technique?

Upvotes: 1

Related Questions