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. When working with GameObject, Sprite and Effect inside a Map, you should provide the map instance as parameter to the draw method of these; when using Gosu’s Image, you’ll need to manually subtract the coordinates of the camera from the position of the image, like this: img.draw(x - map.cam.x, y - map.cam.y, z)

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).



42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/minigl/map.rb', line 42

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.



24
25
26
# File 'lib/minigl/map.rb', line 24

def cam
  @cam
end

#sizeObject (readonly)

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



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

def size
  @size
end

#tile_sizeObject (readonly)

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



17
18
19
# File 'lib/minigl/map.rb', line 17

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


146
147
148
149
150
151
152
153
# File 'lib/minigl/map.rb', line 146

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).



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

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.



66
67
68
69
# File 'lib/minigl/map.rb', line 66

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.



92
93
94
95
96
97
98
99
100
# File 'lib/minigl/map.rb', line 92

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

  # Gets the position transformed to isometric coordinates
  v = get_isometric_position scr_x, scr_y

  # divides by the square size to find the position in the matrix
  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.



79
80
81
82
83
# File 'lib/minigl/map.rb', line 79

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.



107
108
109
# File 'lib/minigl/map.rb', line 107

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.



130
131
132
133
134
# File 'lib/minigl/map.rb', line 130

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).



117
118
119
120
121
# File 'lib/minigl/map.rb', line 117

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