Class: RGame::Core::Image
- Inherits:
-
Object
- Object
- RGame::Core::Image
- Defined in:
- lib/rgame/core/image.rb,
ext/rgame_core/ruby/image_ext.c
Overview
A picture on the GPU, and the sprites cut out of it.
img = RGame::Core::Image.new(app, 'hero.png')
img.width # => 64
frame = img.subimage(0, 0, 16, 16)
walk = RGame::Core::Image.load_tiles(app, 'hero.png', 16, 16)
Everything below the constructor is a view: subimage, tile and
load_tiles share the one texture the file was decoded into, so slicing a
sheet into a hundred frames costs a hundred small objects and no extra
video memory. The texture is released when the last view of it is
collected, in whatever order that happens.
Images are always sampled nearest-neighbour: this engine draws pixel art, and there is no setting to blur it.
The class itself is defined in C (ext/rgame_core/ruby/image_ext.c); what is added here is the sheet-slicing convenience, which is a loop and belongs in Ruby.
Class Method Summary collapse
- .debug_live_textures ⇒ Object
-
.load_tiles(app, path, tile_width, tile_height) ⇒ Object
Every whole
tile_widthxtile_heighttile of an image file, in reading order: left to right, then top to bottom.
Instance Method Summary collapse
-
#each_tile(tile_width, tile_height) ⇒ Object
Yields each tile in turn, without building the Array.
- #height ⇒ Object
- #initialize(app, path) ⇒ Object constructor
- #inspect ⇒ Object
- #subimage(x, y, width, height) ⇒ Object
- #tile(tile_width, tile_height, index) ⇒ Object
- #tile_count(tile_width, tile_height) ⇒ Object
-
#tiles(tile_width, tile_height) ⇒ Object
This image sliced into whole tiles, as an Array.
- #width ⇒ Object
Constructor Details
#initialize(app, path) ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'ext/rgame_core/ruby/image_ext.c', line 105
static VALUE image_initialize(VALUE self, VALUE app, VALUE path) {
rgame_image_ref *ref;
TypedData_Get_Struct(self, rgame_image_ref, &image_data_type, ref);
/* Unwrapping raises TypeError on anything that is not an App, so there is
* no separate type check to keep in step with this one. */
rgame_app *engine_app = rgame_app_unwrap(app);
const char *path_str = StringValueCStr(path);
char error[256] = {0};
rgame_image *image = rgame_image_load(engine_app, path_str, error, sizeof(error));
if (!image) {
rb_raise(rb_const_get(cImage, rb_intern("LoadError")), "%s", error);
}
ref->image = image;
ref->app = app;
return self;
}
|
Class Method Details
.debug_live_textures ⇒ Object
208 209 210 211 |
# File 'ext/rgame_core/ruby/image_ext.c', line 208
static VALUE image_s_debug_live_textures(VALUE klass) {
(void)klass;
return LONG2NUM(rgame_texture_live_sheets());
}
|
.load_tiles(app, path, tile_width, tile_height) ⇒ Object
Every whole tile_width x tile_height tile of an image file, in
reading order: left to right, then top to bottom. A partial tile along
the right or bottom edge is padding and is skipped.
The file is decoded and uploaded exactly once however many tiles come out of it — the returned images are views of that single texture.
33 34 35 |
# File 'lib/rgame/core/image.rb', line 33 def self.load_tiles(app, path, tile_width, tile_height) new(app, path).tiles(tile_width, tile_height) end |
Instance Method Details
#each_tile(tile_width, tile_height) ⇒ Object
Yields each tile in turn, without building the Array.
46 47 48 49 50 51 52 |
# File 'lib/rgame/core/image.rb', line 46 def each_tile(tile_width, tile_height) return enum_for(:each_tile, tile_width, tile_height) unless block_given? tile_count(tile_width, tile_height).times do |index| yield tile(tile_width, tile_height, index) end end |
#height ⇒ Object
137 138 139 |
# File 'ext/rgame_core/ruby/image_ext.c', line 137
static VALUE image_height(VALUE self) {
return INT2NUM(rgame_image_height(image_ref_unwrap(self)->image));
}
|
#inspect ⇒ Object
188 189 190 191 192 193 194 195 196 197 |
# File 'ext/rgame_core/ruby/image_ext.c', line 188
static VALUE image_inspect(VALUE self) {
rgame_image_ref *ref;
TypedData_Get_Struct(self, rgame_image_ref, &image_data_type, ref);
if (!ref->image) {
return rb_sprintf("#<%" PRIsVALUE " (uninitialized)>", rb_obj_class(self));
}
return rb_sprintf("#<%" PRIsVALUE " %dx%d>", rb_obj_class(self),
rgame_image_width(ref->image), rgame_image_height(ref->image));
}
|
#subimage(x, y, width, height) ⇒ Object
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'ext/rgame_core/ruby/image_ext.c', line 149
static VALUE image_subimage(VALUE self, VALUE x, VALUE y, VALUE width, VALUE height) {
rgame_image_ref *ref = image_ref_unwrap(self);
rgame_image *sub = rgame_image_subimage(ref->image, NUM2INT(x), NUM2INT(y), NUM2INT(width),
NUM2INT(height));
if (!sub) {
rb_raise(rb_eArgError,
"subimage %" PRIsVALUE ",%" PRIsVALUE " %" PRIsVALUE "x%" PRIsVALUE
" does not fit in a %dx%d image",
x, y, width, height, rgame_image_width(ref->image),
rgame_image_height(ref->image));
}
return image_wrap(sub, ref->app);
}
|
#tile(tile_width, tile_height, index) ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'ext/rgame_core/ruby/image_ext.c', line 172
static VALUE image_tile(VALUE self, VALUE tile_width, VALUE tile_height, VALUE index) {
rgame_image_ref *ref = image_ref_unwrap(self);
rgame_image *tile = rgame_image_tile(ref->image, NUM2INT(tile_width), NUM2INT(tile_height),
NUM2INT(index));
if (!tile) {
rb_raise(rb_eIndexError, "tile %" PRIsVALUE " is out of range (%d tiles of %" PRIsVALUE
"x%" PRIsVALUE ")",
index,
rgame_image_tile_count(ref->image, NUM2INT(tile_width), NUM2INT(tile_height)),
tile_width, tile_height);
}
return image_wrap(tile, ref->app);
}
|
#tile_count(tile_width, tile_height) ⇒ Object
166 167 168 169 |
# File 'ext/rgame_core/ruby/image_ext.c', line 166
static VALUE image_tile_count(VALUE self, VALUE tile_width, VALUE tile_height) {
return INT2NUM(rgame_image_tile_count(image_ref_unwrap(self)->image, NUM2INT(tile_width),
NUM2INT(tile_height)));
}
|
#tiles(tile_width, tile_height) ⇒ Object
This image sliced into whole tiles, as an Array. load_tiles is the
same thing starting from a path.
39 40 41 42 43 |
# File 'lib/rgame/core/image.rb', line 39 def tiles(tile_width, tile_height) Array.new(tile_count(tile_width, tile_height)) do |index| tile(tile_width, tile_height, index) end end |
#width ⇒ Object
133 134 135 |
# File 'ext/rgame_core/ruby/image_ext.c', line 133
static VALUE image_width(VALUE self) {
return INT2NUM(rgame_image_width(image_ref_unwrap(self)->image));
}
|