By max_n_ruby
Date 2016-11-14 23:41
Edited 2016-11-15 02:58
How does Gosu get the tiles on the screen?
While trying to write my own map class I use some code to assign every tile a pixel coordinate. Gosu then draws the tile where I want it.
But in Captain Ruby game, the Map class reads an array full of either ones or zeros and somehow knows where to put the tiles on the screen.
Here's where it creates the array the maps are in.
@tiles = Array.new(@width) do |x|
Array.new(@height) do |y|
case lines[y][x, 1]
when '"'
Tiles::Grass
when '#'
Tiles::Earth
when 'x'
@gems.push(CollectibleGem.new(gem_img, x * 50 + 25, y * 50 + 25))
nil
else
nil
end
end
end
Here we get the multi-dimensional array. It's full of 1's and 0's and nil. (I'm ignoring the gems for right now. Trying to keep things simple.)
This array becomes the raw material for the draw method:
def draw
# Very primitive drawing function:
# Draws all the tiles, some off-screen, some on-screen.
@height.times do |y|
@width.times do |x|
tile = @tiles[x][y]
if tile
# Draw the tile with an offset (tile images have some overlap)
# Scrolling is implemented here just as in the game objects.
@tileset[tile].draw(x * 50 - 5, y * 50 - 5, 0)
end
end
end
@gems.each { |c| c.draw }
end
This draw method is hard for me to understand. I don't know enough about ruby to decipher what's going on here.
What I do know:
I know the .times
method. We do 'something' @height and @width times. Where height and width are the values taken from the map text file.
I get a little fuzzy when it creates the tile
variable.
Then we get to the Gosu draw
method.
The method parameters x * 50
-5 & y * 50 -5
decide where the tiles are drawn in the window.(I think.) But I don't understand what the x and y are and why you times them by 50. I mean, I know that x
and y
represent items in the @tiles
array but... I'm confused :)
Any help to clarify would be appreciated.
By bestguigui
Date 2016-11-15 15:44
Edited 2016-11-15 15:52
Hi !
I suggest you to IRB any portion of code you don't get.
For example, if you go like :
@width = 10
@width.times do |x|
p x
end
you'll see in the output that you'll display 10 times the variable x, that will take from 0 to 9 values. It's just a way to handle every tile in the map, to make x and y take any possible value.
you could also do :
for x in 0...@width
for y in 0...@height
# handle [x][y] position
end
end
which is the way I'm pretty much always using myself.
Then you get your coordinates in tiles unit, and you need to multiply by the tile size in pixels to get the position in the screen. This is where the "* 50" is used, to get from tiles coordinates to screen coordinates.
Thanks for the reply.
That helped a lot to figure it out in IRB.
Previously I was loading the entire Map class into IRB. Breaking it down to the individual methods and processes made a difference.
By jlnr (dev)
Date 2016-11-16 23:21
Using .times
is shorter than the for ... in
loop, but I have to agree it's hard to read. Glad that you asked about it, I'll make a note to change it :)
Loading...