Long levels...

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
baconhawka7x
Party member
Posts: 491
Joined: Mon Nov 21, 2011 7:05 am
Location: Oregon, USA
Contact:

Long levels...

Post by baconhawka7x »

I'm making even more progress on my game thanks to the love forums. I am on my first level, (yes i know lol), I finally figured out how the collision detection process. But theres one thing i dont understand...The game is top-view, I want to make levels (obviously) but the only problem is I do not know how to make a level any larger than the window length. I wouldnt mind having the camera follow the character throughout the entire level, Or having seperate rooms inside of each level. Either way will work, as long as it actually works!:D, All tips are appreciated:)
User avatar
Jasoco
Inner party member
Posts: 3725
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Long levels...

Post by Jasoco »

You need to devise, or use an existing Camera library. I use my own for my games. The gist of how it would work:

The map grid is say 50 x 50, but the screen for all intents and purposes can safely hold 20 x 15 tiles. So your camera system needs to...

Figure out the boundaries of what tiles should be on the screen. You figure out what tile the Camera X and Y (Which will usually be the player's X and Y) is located in. (By taking the X or Y, divide it by the tile width and floor it and you have your tile X and Y) Then subtract the screen tile half width (In this case 20 / 2 = 10) and half height (15 / 2 = 7.5 round up to 8) for the Lower X and Y Bounds and then add the screen tile width plus 1 and tile height plus 1 to these values for the Upper Bounds.

You then use these Lower and Upper bounds when drawing the tiles. Instead of drawing all the grid, only draw the portion within the bounds.

Now, you decide whether you want the map to stop at the edge, or let the camera scroll past the edge into the blackness. If you want to stop it at the edge you need to check the Lower bounds (Left and Top of map) is greater than the lowest tile value. (Usually 0) and if it's less than that, you make the Lower bounds that number and the upper bounds the screen tile width or height plus 1. And check the other directions (Right and Bottom of map) by making sure the Lower X and Y are less than the Map Tile Width or Height minus the screen Width or Height. And if they are more, make the Lower the Width or Height minus Screen Tile Width or Height and the Upper bounds those numbers plus the screen tile width or heights.

I know it probably sounds confusing, but it's not really. Here's sample code from my Camera library.

Code: Select all

camera = {
  x, y,
  lockedge = true, --Lock Edge means the map will never scroll off the edge of the map_ 
                     Change to false and it will always keep the map centered to the camera.
  bounds = { lx, ux, ly, uy }, -- Lower and Upper X and Y bounds to be used to determine which tiles to draw.
  update = function()
    camera.x = math.floor(-player_x + screen_w/2)
    camera.y = math.floor(-player_y + screen_h/2)

    if camera.lockedge then
      if camera.x > 0 then camera.x = 0 end
      if camera.y > 0 then camera.y = 0 end
      if camera.x < -(game_map_w-screen_w) then 
        camera.x = -(game_map_w-screen_w) 
      end
      if camera.y < -((game_map_h-screen_h) - (screen_tile_size * 2)) then
        camera.y = -((game_map_h-screen_h) - (screen_tile_size * 2))
      end
    end

    camera.bounds.lx = -(math.ceil((camera.x) / screen_tile_size))
    camera.bounds.ly = -(math.ceil((camera.y) / screen_tile_size))

    if camera.bounds.lx < 0 then camera.bounds.lx = 0 end
    if camera.bounds.ly < 0 then camera.bounds.ly = 0 end
    if camera.bounds.lx > (game_map_w / screen_tile_size) - (screen_w / screen_tile_size) then
      camera.bounds.lx = math.floor((game_map_w / screen_tile_size) - (screen_w / screen_tile_size))
    end
    if camera.bounds.ly > (game_map_h / screen_tile_size) - (screen_h / screen_tile_size) then
      camera.bounds.ly = math.floor((game_map_h / screen_tile_size) - (screen_h / screen_tile_size)) 
    end

    camera.bounds.ux = camera.bounds.lx + math.ceil(screen_w / screen_tile_size)
    camera.bounds.uy = camera.bounds.ly + math.ceil(screen_h / screen_tile_size)
    if camera.bounds.ux > game_map_tw-1 then camera.bounds.ux = game_map_tw-1 end
    if camera.bounds.uy > game_map_th-1 then camera.bounds.uy = game_map_th-1 end
  end
}
Note: The camera value should be negative and not positive since it's an offset to draw the map. Also, this works best when used in tandem with love.graphics.push(), love.graphics.translate() and love.graphics.pop(). This allows you to offset the drawing coordinate system to make it easier to use with a camera system. You would basically call the camera.update() function, then use love.graphics.translate(camera.x, camera.y) which would then let you draw to the correct pixel coordinate without having to also offset the drawing for every single draw call. Saves a looooot of work.

Then out in the drawing part of the code you'd do something like:

Code: Select all

for x = camera.bounds.lx, camera.bounds.ux do
  for y = camera.bounds.ly, camera.bounds.uy do
    --DRAW STUFF USING THE X AND Y FOR THE TILE GRID TILES
  end
end
Remember that this only helps with the logic. You'll want to make your own or use an established library. It works the same way for any scrolling grid-based map.
Last edited by Jasoco on Thu Nov 24, 2011 3:42 am, edited 5 times in total.
coffee
Party member
Posts: 1206
Joined: Wed Nov 02, 2011 9:07 pm

Re: Long levels...

Post by coffee »

Jasoco wrote:I know it probably sounds confusing, but it's not really. Here's sample code from my Camera library.
Actually the explanation was quite good and also I relearned "camera" in a more didactic way than my usual try-error approaches. Perhaps the only thing that could make him confuse should be the "update = function(game) game = gamestate.game" lines for now. Nice tutorial Jasoco.
User avatar
Jasoco
Inner party member
Posts: 3725
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Long levels...

Post by Jasoco »

Ah, yes. I tried to make it ambiguous but I missed some lines. I'll edit to try and ambiguize it.

Edit: Code has been ambiguized. I made it so variables with underscores (_) are going to be needed to be changed to match your game since this is stuff that can be different for everyone. The camera variable needs to be global for obvious reasons so don't localize it if you put it in its own file.
User avatar
Kazagha
Prole
Posts: 40
Joined: Tue Oct 04, 2011 7:05 am

Re: Long levels...

Post by Kazagha »

This is very very helpful, although I am not up to this stage in my own game yet I know it's something that I will have struggled with in the future.

-Kazagha
User avatar
T-Bone
Inner party member
Posts: 1492
Joined: Thu Jun 09, 2011 9:03 am

Re: Long levels...

Post by T-Bone »

There are of course a multitude of options for how this can be done. Some are simpler than others. Simply storing two variables for the camera position, say camerax and camary, and using a combination of love.graphics.push, love.graphics.translate and love.graphics.pop in the drawing may be enough in some games as long as you always update camerax and cameray.
Post Reply

Who is online

Users browsing this forum: No registered users and 42 guests