Class: Chingu::GameObjectMap

Inherits:
Object
  • Object
show all
Defined in:
lib/chingu/game_object_map.rb

Overview

** This class is under heavy development, API will most likely change! **

GameObjectMap can map any set of game objects into a 2D-array for fast lookup. You can choose gridsize with the :grid-parameter, defaults to [32,32]. The smaller the grid the more memory GameObjectMap will eat.

The game objects sent to GameObjectMap must respond to #bb (as provided by trait :bounding_box) This is needed to calcuate what cells in the grid each game object covers.

Basic usage:

@map = GameObjectMap.new(:game_objects => TerrainObject.all, :grid => [32, 32])
@map.at(100, 100)         # returns one TerrainObject at x/y: 100/100
@map.game_object(player)  # returns one TerrainObject which collides with player.bounding_box

A GameObjectMap is ment to be used for static non-moving objects, where a map can be calculated once and then used for fast lookups. This makes GameObjectMap very well suited for terrain for a player to walk on / collide with.

One cell in the GameObjectMap can only be occupied by one game object. If you need many objects at the same cell, use 2 GameObjectMaps, something like:

@terrain = GameObjectMap.new(:game_objects => Terrain.all)
@mines = GameObjectMap.new(:game_objects => Mine.all)

@player.stop_falling  if @terrain.at(@player.x, @player)
@player.die           if @mine.at(@player.x, @player)

Take note, since there can be only 1 game object per cell a huge game object could very well “cover out” another smaller game objects occupying the same cells.

** This class is under heavy development, API will most likely change! **

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ GameObjectMap

Returns a new instance of GameObjectMap.



57
58
59
60
61
62
# File 'lib/chingu/game_object_map.rb', line 57

def initialize(options = {})
  @game_objects = options[:game_objects]
  @grid = options[:grid] || [32,32]
  @debug = options[:debug]
  create_map
end

Instance Attribute Details

#game_object_positionsObject (readonly)

Returns the value of attribute game_object_positions.



55
56
57
# File 'lib/chingu/game_object_map.rb', line 55

def game_object_positions
  @game_object_positions
end

#mapObject (readonly)

Returns the value of attribute map.



55
56
57
# File 'lib/chingu/game_object_map.rb', line 55

def map
  @map
end

Instance Method Details

#at(x, y) ⇒ Object

Gets game object from map that resides on real world coordinates x/y



126
127
128
129
130
# File 'lib/chingu/game_object_map.rb', line 126

def at(x, y)
  lookup_x = (x / @grid[0]).to_i
  lookup_y = (y / @grid[1]).to_i
  @map[lookup_x][lookup_y]  rescue nil  # Benchmark this against @map[lookup_x] && @map[lookup_x][lookup_y] => prob faster
end

#clear_at(x, y) ⇒ Object

Clear the game object residing in the cell given by real world coordinates x/y



117
118
119
120
121
# File 'lib/chingu/game_object_map.rb', line 117

def clear_at(x, y)
  lookup_x = (x / @grid[0]).to_i
  lookup_y = (y / @grid[1]).to_i
  @map[lookup_x][lookup_y] = nil
end

#create_mapObject

Creates a “tilemap” of game objects using @grid and @game_objects Useful for faster collision detection on a grid-based freeform map created with the Edit game state.



68
69
70
71
72
73
74
75
76
# File 'lib/chingu/game_object_map.rb', line 68

def create_map
  @map = []
  @game_object_positions = {}
        
  @game_objects.each do |game_object|
    puts "#{game_object.class} @ #{game_object.x}/#{game_object.y} - #{game_object.bb}" if @debug
    insert(game_object)                
  end
end

#delete(game_object) ⇒ Object Also known as: clear_game_object

Removes a specific game object from the map, replace the cell-value with nil



102
103
104
105
106
107
108
109
110
111
# File 'lib/chingu/game_object_map.rb', line 102

def delete(game_object)
  range_x, range_y = @game_object_positions[game_object]
  return unless range_x && range_y
  
  range_x.each do |x|
    range_y.each do |y|
      @map[x][y] = nil
    end
  end
end

#each_collision(game_object) ⇒ Object

Yields all game objects occupying any of the cells that given ‘game_object’ covers



154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/chingu/game_object_map.rb', line 154

def each_collision(game_object)
  start_x = (game_object.bb.left / @grid[0]).to_i
  stop_x =  (game_object.bb.right / @grid[0]).to_i
  
  (start_x ... stop_x).each do |x|
    start_y = (game_object.bb.top / @grid[1]).to_i
    stop_y =  (game_object.bb.bottom / @grid[1]).to_i
      
    (start_y ... stop_y).each do |y|
      yield @map[x][y]   if @map[x] && @map[x][y] && @map[x][y] != game_object  # Don't yield collisions with itself
    end
  end
end

#from_game_object(game_object) ⇒ Object

Return the first game object occupying any of the cells that given ‘game_object’ covers



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/chingu/game_object_map.rb', line 135

def from_game_object(game_object)
  start_x = (game_object.bb.left / @grid[0]).to_i
  stop_x =  (game_object.bb.right / @grid[0]).to_i
  
  (start_x .. stop_x).each do |x|
    start_y = (game_object.bb.top / @grid[1]).to_i
    stop_y =  (game_object.bb.bottom / @grid[1]).to_i
      
    (start_y .. stop_y).each do |y|
      return @map[x][y]   if @map[x] && @map[x][y]
    end
    
  end
  return nil
end

#insert(game_object) ⇒ Object

Insert game_object into the map



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/chingu/game_object_map.rb', line 81

def insert(game_object)
  start_x = ( game_object.bb.left / @grid[0] ).to_i
  stop_x =  ( game_object.bb.right / @grid[0] ).to_i
  
  (start_x ... stop_x).each do |x|
    start_y = ( game_object.bb.top / @grid[1] ).to_i
    stop_y =  ( game_object.bb.bottom / @grid[1] ).to_i
      
    @game_object_positions[game_object] = [(start_x ... stop_x), (start_y ... stop_y)]
      
    @map[x] ||= []
    (start_y ... stop_y).each do |y|
      @map[x][y] = game_object
      puts "#{game_object.class} => map[#{x}][#{y}]" if @debug
    end
  end      
end