Render stop working after chenge in .each loop

2
votes

Posted by: siery on 06/08/2018 | Add Revision

The error occurs in Map class responsible for drawing all the tiles to the screen. It was working fine, so long i did not change the conversion of reading map data from the file. I made additional notation to the file so each tile is now represented with two characters (tile code handled by Tile class and item code handled by Item class). The exemplar file may look like this:

0.2.0.0.0.0.0.0.0.0.0.0.2.0.
0.1.1.1.1.1.1.1.1.1.1.1.1.0.
0.1.0.1.1.1.1.1.1.1.1.0.1.0.
0.1.1.1.1.1.1.1.1.1.1.1.1.0.
0.1.1.1.1.1.1.1.1.1.1.1.1.0.
0.1.0.1.1.1.1.1.1.1.1.0.1.0.
0.1.1.1.1.1.1.1.1.1.1.1.1.0.
0.1.1.1.1.1.1.1.1.1.1.1.1.0.
0.1.0.1.1.1.1.1.1.1.1.0.1.0.
0.1.1.1.1.1.1.1.1.1.1.1.1.0.
0.0.0.0.0.0.1.1.0.0.0.0.0.0.

So I try to keep the loading simple for now, and write loading map data from file into RAM in Map's constructor:

File.foreach(f_map).with_index do |line, y|
  line.each_char.lazy.each_slice(2).map(&:first).with_index do |char, x|
    if char != ?\n and char.to_s != ' '
      @tiles[[x, y]] = Tile.new(x * @tile_size, y * @tile_size,
                                @tileset, char)
      @width = x
    end
  end
  @height = y
end

And the draw function in Map reminds the same:

def draw
  for y in 0..@width
    for x in 0..@height
      @tiles[[x, y]].draw
    end
  end
end

Then I get error when calling .draw:

[..]lib/map.rb:41:in `block (2 levels) in draw': undefined method `draw' for nil:NilClass (NoMethodError)

I did spend already few hours trying to solve this problem and get no clue what can be wrong. The data seems to bee good, here is state of @tiles[[0, 0]] inside Map.draw before calling Tile.draw:

@tiles[[0, 0]]
=> #<Tile:0x0000558e053b2688
 @code="0",
 @spirite=
  #<Spirite:0x0000558e053b2660
   @color=#<Gosu::Color:ARGB=0xff_ffffff>,
   @img=#<Gosu::Image:0x0000558e053b3380 @__swigtype__="_p_Gosu__Image">,
   @texture_pack=
    [#<Gosu::Image:0x0000558e053b3380 @__swigtype__="_p_Gosu__Image">,
     #<Gosu::Image:0x0000558e053b3330 @__swigtype__="_p_Gosu__Image">,
     #<Gosu::Image:0x0000558e053b32e0 @__swigtype__="_p_Gosu__Image">,
     #<Gosu::Image:0x0000558e053b3268 @__swigtype__="_p_Gosu__Image">,
     #<Gosu::Image:0x0000558e053b3218 @__swigtype__="_p_Gosu__Image">],
   @type="0",
   @x=0,
   @y=0,
   @zorder=0>>

Maybe explaining what the .draw actually do will be useful as well. So Tile.draw simply calls it's instance of @spirite.draw (Spirite class). The draw function in Spirite is pretty simple:

@img.draw(@x, @y, @zorder, 1, 1, @color, :add)

And @img is simply something like:

@texture_pack = Gosu::Image.load_tiles(
  "../data/graphics/texturepack_dungeon.png", 32, 32 )
@img = @texture_pack[@type.to_i]

Visit Website