Re: [library] bump.lua v3.1.4 - Collision Detection
Posted: Mon Aug 17, 2015 10:26 am
Hi Sarcose,
You are asking several questions, let me try to answer each one.
The player should collide with the solid blocks "by default", ignoring the non-solid ones. You can customize this and add more collisions types later.
The trickiest step is 2.a.1. You have to use TILE_WIDTH & TILE_HEIGHT to do this. The drawing code probably knows how to do this already.
I am going to assume that you are using a camera system which implements scroll by using love.graphics.translate. If you are implementing the scroll in other ways (for example, modifying the coordinates of all the tiles 1 pixel up every time the scroll goes 1 pixel down), I recommend you to stop doing this: it makes things much more difficult to calculate. Your tiles location should not be changed just because you are moving - changing the "origin of coordinates from which we draw" is much simpler. All camera systems in the forums do this, no one modifies the tiles.
In order to query the rectangle like that, you need to give the world a rectangle representing "the screen coordinates": for example, you have moved the scroll 1000 points to the left and 500 points down, and your screen is 640 x 480, to get "everything on the screen" you could do something like this:
'items' is a list of game objects which you have inserted into the world: tiles, the player, projectiles, explosions, etc. 'len' is the length of that list (so you can parse it easily with a loop).
Then there is the matter of "how to draw those". That can mean two different things: "properly draw them" (with the images and stuff) or "draw debug information about them". Let's start with the later.
The bump world does not know a lot about the items it holds. It only knows their left-top corner, and their width and height. It knows that about everything you insert on it - the player, or the tiles. So you can draw "a rectangle for each item returned by world:queryRect" like this:
If you are using some kind of scroll, this code needs to be executed "while the camera is active" - after it does the first love.camera.translate. Otherwise the rectangles will not "move with the scroll".
But this will draw only rectangles. It is useful to "debug that your map is aligned with your world". If you want to "properly draw the map", you need more information which the world does not have. For example, you need to know that the grass tiles use this particular image or quad. Or that the player is on this animation frame. You can't do that with the world alone. This will depend on how your game entities (the tiles, the player) are coded. I usually like to make them objects, and give them a "draw" method, so each object knows how to draw itself. That way I can do just this:
This might be a bit too advanced for you, if you are not familiar with object-oriented programming. A more crude (but easier to understand) method for drawing everything would be this:
In this case, all your grass tiles need to have a boolean called is_grass_tile set to true, all your wall tiles need a is_wall_tile, etc. So instead of building each tile like this:
you build it like this:
You are asking several questions, let me try to answer each one.
The link you supplied seems to be dead, but the approach is always the same: In order to produce collisions with a tile-based map, the simplest way is:Sarcose wrote:Hey there, I have a noob question. How would I integrate this with, say, the Fine_Tile_Based_Scrolling tutorial?
Code: Select all
Assumptions:
* The width and height of your tiles are stored in TILE_WIDTH & TILE_HEIGHT.
* Your map has one (probably small) table per tile.
Steps:
1. Create a new bump world, as big as the map is (in pixels)
2. Go over each tile in the world with a loop, and for each tile:
2.a If the tile is solid,
2.a.1 Get the coordinates of the top-left corner of the tile in the world.
2.a.2 Introduce the tile in the world with something like this:
world:add(tile, top, left, TILE_WIDTH, TILE_HEIGHT)
3. Introduce the player in the world
4. Copy the player movement code from the simple demo.
The trickiest step is 2.a.1. You have to use TILE_WIDTH & TILE_HEIGHT to do this. The drawing code probably knows how to do this already.
This question has two parts. The first one is about queries. You can "query" a rectangular zone, a line or a dot. That will return a list with the items which collide with the rectangle, line or dot, respectively. The rectangular query can be used to only draw the stuff that is on the screen.Sarcose wrote:I read about using world to query positions. Would it be possible to use world to draw the map directly? And how would that look?
I am going to assume that you are using a camera system which implements scroll by using love.graphics.translate. If you are implementing the scroll in other ways (for example, modifying the coordinates of all the tiles 1 pixel up every time the scroll goes 1 pixel down), I recommend you to stop doing this: it makes things much more difficult to calculate. Your tiles location should not be changed just because you are moving - changing the "origin of coordinates from which we draw" is much simpler. All camera systems in the forums do this, no one modifies the tiles.
In order to query the rectangle like that, you need to give the world a rectangle representing "the screen coordinates": for example, you have moved the scroll 1000 points to the left and 500 points down, and your screen is 640 x 480, to get "everything on the screen" you could do something like this:
Code: Select all
local items, len = world:queryRect(1000, 500, 640, 480)
Then there is the matter of "how to draw those". That can mean two different things: "properly draw them" (with the images and stuff) or "draw debug information about them". Let's start with the later.
The bump world does not know a lot about the items it holds. It only knows their left-top corner, and their width and height. It knows that about everything you insert on it - the player, or the tiles. So you can draw "a rectangle for each item returned by world:queryRect" like this:
Code: Select all
local items, len = world:queryRect(1000, 500, 640, 480)
for i=1, len do
local x,y,w,h = world:getRect(items[i])
love.graphics.rectangle('line', x,y,w,h)
end
But this will draw only rectangles. It is useful to "debug that your map is aligned with your world". If you want to "properly draw the map", you need more information which the world does not have. For example, you need to know that the grass tiles use this particular image or quad. Or that the player is on this animation frame. You can't do that with the world alone. This will depend on how your game entities (the tiles, the player) are coded. I usually like to make them objects, and give them a "draw" method, so each object knows how to draw itself. That way I can do just this:
Code: Select all
local items, len = world:queryRect(1000, 500, 640, 480)
for i=1, len do
items[i]:draw()
end
Code: Select all
local items, len = world:queryRect(1000, 500, 640, 480)
for i=1, len do
local item = items[i]
if item.is_grass_tile then
draw_grass_tile(item)
elseif item.is_wall_tile then
draw_wall_tile(item)
elseif item.is_player then
draw_player(item)
...
end
end
Code: Select all
local tile = {x=..., y=...}
Code: Select all
local tile = {x=..., y=..., is_grass_tile=true} -- or is_wall_tile or is_player