Class: MiniGL::Map

Inherits:
Object
  • Object
show all
Defined in:
lib/minigl/map.rb

Overview

This class provides easy control of a tile map, i.e., a map consisting of a grid of equally sized tiles. It also provides viewport control, through its camera property and methods.

Constant Summary collapse

SQRT_2_DIV_2 =

:nodoc:

Math.sqrt(2) / 2
MINUS_PI_DIV_4 =

:nodoc:

-Math::PI / 4

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(t_w, t_h, t_x_count, t_y_count, scr_w = 800, scr_h = 600, isometric = false, limit_cam = true) ⇒ Map

Creates a new map.

Parameters:

t_w

The width of the tiles.

t_h

The height of the tiles.

t_x_count

The horizontal count of tiles in the map.

t_y_count

The vertical count of tiles in the map.

scr_w

Width of the viewport for the map.

scr_h

Height of the viewport for the map.

isometric

Whether to use a isometric map. By default, an ortogonal map is used.

limit_cam

Whether the camera should respect the bounds of the map (i.e., when given coordinates that would imply regions outside the map to appear in the screen, the camera would move to the nearest position where only the map shows up in the screen).



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/minigl/map.rb', line 37

def initialize(t_w, t_h, t_x_count, t_y_count, scr_w = 800, scr_h = 600, isometric = false, limit_cam = true)
  @tile_size = Vector.new t_w, t_h
  @size = Vector.new t_x_count, t_y_count
  @cam = Rectangle.new 0, 0, scr_w, scr_h
  @limit_cam = limit_cam
  @isometric = isometric
  if isometric
    initialize_isometric
  elsif limit_cam
    @max_x = t_x_count * t_w - scr_w
    @max_y = t_y_count * t_h - scr_h
  end
  set_camera 0, 0
end

Instance Attribute Details

#camObject (readonly)

A Rectangle representing the region of the map that is currently visible.



19
20
21
# File 'lib/minigl/map.rb', line 19

def cam
  @cam
end

#sizeObject (readonly)

A Vector where x is the horizontal tile count and y the vertical count.



15
16
17
# File 'lib/minigl/map.rb', line 15

def size
  @size
end

#tile_sizeObject (readonly)

A Vector where x is the tile width and y is the tile height.



12
13
14
# File 'lib/minigl/map.rb', line 12

def tile_size
  @tile_size
end

Instance Method Details

#foreachObject

Iterates through the currently visible tiles, providing the horizontal tile index, the vertical tile index, the x-coordinate (in pixels) and the y-coordinate (in pixels), of each tile, in that order, to a given block of code.

Example:

map.foreach do |i, j, x, y|
  draw_tile tiles[i][j], x, y
end


141
142
143
144
145
146
147
148
# File 'lib/minigl/map.rb', line 141

def foreach
  for j in @min_vis_y..@max_vis_y
    for i in @min_vis_x..@max_vis_x
      pos = get_screen_pos i, j
      yield i, j, pos.x, pos.y
    end
  end
end

#get_absolute_sizeObject

Returns a Vector with the total size of the map, in pixels (x for the width and y for the height).



54
55
56
57
58
# File 'lib/minigl/map.rb', line 54

def get_absolute_size
  return Vector.new(@tile_size.x * @size.x, @tile_size.y * @size.y) unless @isometric
  avg = (@size.x + @size.y) * 0.5
  Vector.new (avg * @tile_size.x).to_i, (avg * @tile_size.y).to_i
end

#get_centerObject

Returns a Vector with the coordinates of the center of the map.



61
62
63
64
# File 'lib/minigl/map.rb', line 61

def get_center
  abs_size = get_absolute_size
  Vector.new(abs_size.x * 0.5, abs_size.y * 0.5)
end

#get_map_pos(scr_x, scr_y) ⇒ Object

Returns the tile in the map that corresponds to the given position in the screen, as a Vector, where x is the horizontal index and y the vertical index.

Parameters:

scr_x

The x-coordinate in the screen.

scr_y

The y-coordinate in the screen.



87
88
89
90
91
92
93
94
95
# File 'lib/minigl/map.rb', line 87

def get_map_pos(scr_x, scr_y)
  return Vector.new((scr_x + @cam.x) / @tile_size.x, (scr_y + @cam.y) / @tile_size.y) unless @isometric

  # Obtém a posição transformada para as coordenadas isométricas
  v = get_isometric_position scr_x, scr_y

  # Depois divide pelo tamanho do quadrado para achar a posição da matriz
  Vector.new((v.x * @inverse_square_size).to_i, (v.y * @inverse_square_size).to_i)
end

#get_screen_pos(map_x, map_y) ⇒ Object

Returns the position in the screen corresponding to the given tile indices.

Parameters:

map_x

The index of the tile in the horizontal direction. It must be in the interval 0..t_x_count.

map_y

The index of the tile in the vertical direction. It must be in the interval 0..t_y_count.



74
75
76
77
78
# File 'lib/minigl/map.rb', line 74

def get_screen_pos(map_x, map_y)
  return Vector.new(map_x * @tile_size.x - @cam.x, map_y * @tile_size.y - @cam.y) unless @isometric
  Vector.new ((map_x - map_y - 1) * @tile_size.x * 0.5) - @cam.x + @x_offset,
             ((map_x + map_y) * @tile_size.y * 0.5) - @cam.y
end

#is_in_map(v) ⇒ Object

Verifies whether a tile is inside the map.

Parameters:

v

A Vector representing the tile, with x as the horizontal index and y as the vertical index.



102
103
104
# File 'lib/minigl/map.rb', line 102

def is_in_map(v)
  v.x >= 0 && v.y >= 0 && v.x < @size.x && v.y < @size.y
end

#move_camera(x, y) ⇒ Object

Moves the viewport by the given amount of pixels.

Parameters:

x

The amount of pixels to move horizontally. Negative values will cause the camera to move to the left.

y

The amount of pixels to move vertically. Negative values will cause the camera to move up.



125
126
127
128
129
# File 'lib/minigl/map.rb', line 125

def move_camera(x, y)
  @cam.x += x
  @cam.y += y
  set_bounds
end

#set_camera(cam_x, cam_y) ⇒ Object

Sets the top left corner of the viewport to the given position of the map. Note that this is not the position in the screen.

Parameters:

cam_x

The x-coordinate inside the map, in pixels (not a tile index).

cam_y

The y-coordinate inside the map, in pixels (not a tile index).



112
113
114
115
116
# File 'lib/minigl/map.rb', line 112

def set_camera(cam_x, cam_y)
  @cam.x = cam_x
  @cam.y = cam_y
  set_bounds
end