Class: Ruby2D::Tileset
- Inherits:
-
Object
- Object
- Ruby2D::Tileset
- Includes:
- Renderable
- Defined in:
- lib/ruby2d/tileset.rb
Overview
An image containing multiple tiles that can be drawn at various positions
Constant Summary collapse
Constants included from Interactive
Interactive::OBJECT_EVENTS, Interactive::OBJECT_EVENT_FILTER_PREDICATES
Instance Attribute Summary
Attributes included from Renderable
#color, #height, #padding_bottom, #padding_left, #padding_right, #padding_top, #visible, #width, #x, #x_align, #y, #y_align, #z
Instance Method Summary collapse
-
#[](x, y) ⇒ Object
Look up the tile name placed at (x, y), or nil if none.
-
#[]=(x, y, name) ⇒ Object
Place a single tile at (x, y), replacing any existing placement.
-
#clear ⇒ Object
Remove all placements.
-
#define(name, x, y, rotate: 0, flip: nil) ⇒ Object
Define a named tile type at the given grid position in the tileset image.
-
#delete(x, y) ⇒ Object
Remove the placement at (x, y).
-
#initialize(path, tile_width: 32, tile_height: 32, z: 0, padding: 0, spacing: 0, scale: 1, add: true, visible: true) ⇒ Tileset
constructor
Create a tileset from an image.
-
#place(name, coordinates) ⇒ Object
Place a named tile at one or more world coordinates.
-
#render ⇒ Object
(also: #_render_scene)
Render the tileset.
-
#tint ⇒ Object
The tint color, multiplied against the texture.
- #tint=(c) ⇒ Object
Methods included from Renderable
#_alignment_anchor_dx, #_alignment_anchor_dy, #_apply_padding, #_extract_alignment, #_point_in_polygon?, #_point_on_segment?, #_require_numeric_position, #_resolve_alignment, #_unrotate, #_validate_dimensions, #add, #colour=, #contains?, flatten_color, flatten_per_vertex, flatten_points, flatten_resolved_color, #hide, #opacity, #opacity=, #padding=, #remove, resolve_color_or_default, resolve_single_color, #show
Methods included from Interactive
#_fire_event, #interactive?, #off, #on
Constructor Details
#initialize(path, tile_width: 32, tile_height: 32, z: 0, padding: 0, spacing: 0, scale: 1, add: true, visible: true) ⇒ Tileset
Create a tileset from an image
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/ruby2d/tileset.rb', line 28 def initialize(path, tile_width: 32, tile_height: 32, z: 0, padding: 0, spacing: 0, scale: 1, add: true, visible: true) # `scale` and the tile dimensions feed the UV denominator # (`@scaled_*` sizes); a non-positive value collapses them to zero and # divides into NaN/Inf texture coordinates, so reject it up front. unless scale.is_a?(Numeric) && scale.positive? raise ArgumentError, "Tileset scale must be positive, got #{scale}" end unless tile_width.is_a?(Numeric) && tile_width.positive? raise ArgumentError, "Tileset tile_width must be positive, got #{tile_width}" end unless tile_height.is_a?(Numeric) && tile_height.positive? raise ArgumentError, "Tileset tile_height must be positive, got #{tile_height}" end @path = path.to_s # Initialize the tileset texture image (not added to the window) @texture = Image.new(@path, add: false) # The tile UV coordinates are normalized against the source texture's # true pixel dimensions, so `@width`/`@height` always track the texture. @width = @texture.width @height = @texture.height @z = z @tiles = {} @tile_definitions = {} # Cached per-frame draw batch (geometry only; tint is applied separately # in C each frame). Rebuilt lazily in `render` whenever a placement # changes — see `mark_batch_dirty`. @coords_batch = [] @tex_coords_batch = [] @batch_dirty = true @padding = padding @spacing = spacing @x = 0 @y = 0 @tile_width = tile_width @tile_height = tile_height @scale = scale calculate_scaled_sizes @visible = visible self.add if add end |
Instance Method Details
#[](x, y) ⇒ Object
Look up the tile name placed at (x, y), or nil if none
94 95 96 97 |
# File 'lib/ruby2d/tileset.rb', line 94 def [](x, y) placement = @tiles[[x, y]] placement && placement.fetch(:name) end |
#[]=(x, y, name) ⇒ Object
Place a single tile at (x, y), replacing any existing placement
89 90 91 |
# File 'lib/ruby2d/tileset.rb', line 89 def []=(x, y, name) place_one(name, x, y) end |
#clear ⇒ Object
Remove all placements
107 108 109 110 |
# File 'lib/ruby2d/tileset.rb', line 107 def clear @tiles = {} mark_batch_dirty end |
#define(name, x, y, rotate: 0, flip: nil) ⇒ Object
Define a named tile type at the given grid position in the tileset image
77 78 79 |
# File 'lib/ruby2d/tileset.rb', line 77 def define(name, x, y, rotate: 0, flip: nil) @tile_definitions[name] = { x: x, y: y, rotate: rotate, flip: flip } end |
#delete(x, y) ⇒ Object
Remove the placement at (x, y)
100 101 102 103 104 |
# File 'lib/ruby2d/tileset.rb', line 100 def delete(x, y) removed = @tiles.delete([x, y]) mark_batch_dirty if removed removed end |
#place(name, coordinates) ⇒ Object
Place a named tile at one or more world coordinates. coordinates is an
array of [x, y] pairs. Existing placements at the same coordinate are
replaced.
84 85 86 |
# File 'lib/ruby2d/tileset.rb', line 84 def place(name, coordinates) coordinates.each { |x, y| place_one(name, x, y) } end |
#render ⇒ Object Also known as: _render_scene
Render the tileset. Called with no arguments from the scene-graph loop, or from a render block for one-shot rendering.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/ruby2d/tileset.rb', line 114 def render Window.render_ready_check return if @tiles.empty? # Batch every placed tile into one draw call: they share the source # texture and tint, so the per-tile geometry (memoized in each Vertices) # is collected and handed to a single `SDL_RenderGeometry` pass. The # collected batch is cached and only rebuilt when a placement changes, # so a static tile field costs nothing per frame beyond the native draw # — worth ~2.6× on the `tiles_static` render slice, so keep the guard. if @batch_dirty @coords_batch.clear @tex_coords_batch.clear @tiles.each_value do |placement| vertices = placement.fetch(:vertices) @coords_batch << vertices.coordinates @tex_coords_batch << vertices.texture_coordinates end @batch_dirty = false end Ext.image_draw_quads(@texture, @coords_batch, @tex_coords_batch, tint) end |
#tint ⇒ Object
The tint color, multiplied against the texture. Defaults to white.
Copy DEFAULT_TINT on first read so each instance owns its tint —
otherwise two default-tinted tilesets would share (and mutate) the
single class-level Color.
19 20 21 |
# File 'lib/ruby2d/tileset.rb', line 19 def tint @tint ||= Color.new(DEFAULT_TINT) end |