Class: Chingu::GameObjectMap
- Inherits:
-
Object
- Object
- Chingu::GameObjectMap
- 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
-
#game_object_positions ⇒ Object
readonly
Returns the value of attribute game_object_positions.
-
#map ⇒ Object
readonly
Returns the value of attribute map.
Instance Method Summary collapse
-
#at(x, y) ⇒ Object
Gets game object from map that resides on real world coordinates x/y.
-
#clear_at(x, y) ⇒ Object
Clear the game object residing in the cell given by real world coordinates x/y.
-
#create_map ⇒ Object
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.
-
#delete(game_object) ⇒ Object
(also: #clear_game_object)
Removes a specific game object from the map, replace the cell-value with nil.
-
#each_collision(game_object) ⇒ Object
Yields all game objects occupying any of the cells that given ‘game_object’ covers.
-
#from_game_object(game_object) ⇒ Object
Return the first game object occupying any of the cells that given ‘game_object’ covers.
-
#initialize(options = {}) ⇒ GameObjectMap
constructor
A new instance of GameObjectMap.
-
#insert(game_object) ⇒ Object
Insert game_object into the map.
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( = {}) @game_objects = [:game_objects] @grid = [:grid] || [32,32] @debug = [:debug] create_map end |
Instance Attribute Details
#game_object_positions ⇒ Object (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 |
#map ⇒ Object (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_map ⇒ Object
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 |