Class: RGame::Core::Recording
- Inherits:
-
Object
- Object
- RGame::Core::Recording
- Defined in:
- lib/rgame/core/recording.rb,
ext/rgame_core/ruby/recording_ext.c
Overview
A block of drawing baked once and replayed cheaply.
ground = renderer.record do
tiles.each { |tile| renderer.image(tile.image, tile.x, tile.y) }
end
def draw
ground.draw(-camera.x, -camera.y)
end
A screen of tiles is a couple of thousand quads that have not changed since the level loaded. Baking them turns the per-frame cost from "walk every tile and transform four corners" into one call per texture — the work happens at bake time and never again.
Recordings come from Renderer#record; there is no new.
What is baked in and what is not
Positions, texture coordinates and colours are baked, and so are any transforms applied inside the block. The transform in effect when the recording is drawn is applied on top, which is what lets a baked layer scroll under a camera without being rebuilt.
Clipping is not baked — it happens when pixels are rasterised, so a clip
rectangle captured in one place would be wrong everywhere else the
recording is drawn. Pushing a clip inside a record block raises. Clip
the replay instead:
renderer.clipped(0, 0, 400, 600) { ground.draw(0, 0) }
Constant Summary collapse
Class Method Summary collapse
Instance Method Summary collapse
- #batch_count ⇒ Object
-
#draw(x = 0, y = 0, z: 0, color: nil) ⇒ Object
Replays everything that was recorded, with the recording's origin at (x, y).
- #draw_at(x, y, z, color) ⇒ Object
- #empty? ⇒ Boolean
- #height ⇒ Object
- #inspect ⇒ Object
- #vertex_count ⇒ Object
- #width ⇒ Object
Class Method Details
.new(*args) ⇒ Object
167 168 169 170 171 172 |
# File 'ext/rgame_core/ruby/recording_ext.c', line 167
static VALUE recording_s_new(int argc, VALUE *argv, VALUE klass) {
(void)argc;
(void)argv;
rb_raise(rb_eNoMethodError, "%" PRIsVALUE " is created by Renderer#record, not by .new",
klass);
}
|
Instance Method Details
#batch_count ⇒ Object
127 128 129 |
# File 'ext/rgame_core/ruby/recording_ext.c', line 127
static VALUE recording_batch_count(VALUE self) {
return UINT2NUM(rgame_recording_batch_count(recording_unwrap(self)->recording));
}
|
#draw(x = 0, y = 0, z: 0, color: nil) ⇒ Object
Replays everything that was recorded, with the recording's origin at (x, y).
color tints what was baked: each recorded colour is multiplied by it,
so white (the default) draws the recording unchanged and a colour with
alpha fades the whole layer out at once.
47 48 49 |
# File 'lib/rgame/core/recording.rb', line 47 def draw(x = 0, y = 0, z: 0, color: nil) draw_at(x, y, z, Color.coerce(color).packed) end |
#draw_at(x, y, z, color) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'ext/rgame_core/ruby/recording_ext.c', line 109
static VALUE recording_draw_at(VALUE self, VALUE x, VALUE y, VALUE z, VALUE color) {
rgame_recording_ref *ref = recording_unwrap(self);
/* The app that owns these textures has to be the one mid-frame. Anything
* else would append to a canvas nobody is about to submit, and draw
* nothing at all. */
if (!rgame_app_is_drawing(ref->app)) {
rb_raise(rb_eRuntimeError,
"drawing is only allowed inside #draw (the frame is not open)");
}
rgame_app_draw_recording(ref->app, ref->recording, (float)NUM2DBL(x), (float)NUM2DBL(y),
(unsigned int)(NUM2ULONG(color) & 0xFFFFFFFFul), NUM2DBL(z));
return self;
}
|
#empty? ⇒ Boolean
135 136 137 |
# File 'ext/rgame_core/ruby/recording_ext.c', line 135
static VALUE recording_empty_p(VALUE self) {
return rgame_recording_vertex_count(recording_unwrap(self)->recording) == 0 ? Qtrue : Qfalse;
}
|
#height ⇒ Object
147 148 149 150 151 |
# File 'ext/rgame_core/ruby/recording_ext.c', line 147
static VALUE recording_height(VALUE self) {
float min_y = 0.0f, max_y = 0.0f;
rgame_recording_bounds(recording_unwrap(self)->recording, NULL, &min_y, NULL, &max_y);
return DBL2NUM((double)(max_y - min_y));
}
|
#inspect ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 |
# File 'ext/rgame_core/ruby/recording_ext.c', line 153
static VALUE recording_inspect(VALUE self) {
rgame_recording_ref *ref;
TypedData_Get_Struct(self, rgame_recording_ref, &recording_data_type, ref);
if (!ref->recording) {
return rb_sprintf("#<%" PRIsVALUE " (uninitialized)>", rb_obj_class(self));
}
return rb_sprintf("#<%" PRIsVALUE " %u batches, %u vertices>", rb_obj_class(self),
rgame_recording_batch_count(ref->recording),
rgame_recording_vertex_count(ref->recording));
}
|
#vertex_count ⇒ Object
131 132 133 |
# File 'ext/rgame_core/ruby/recording_ext.c', line 131
static VALUE recording_vertex_count(VALUE self) {
return UINT2NUM(rgame_recording_vertex_count(recording_unwrap(self)->recording));
}
|
#width ⇒ Object
141 142 143 144 145 |
# File 'ext/rgame_core/ruby/recording_ext.c', line 141
static VALUE recording_width(VALUE self) {
float min_x = 0.0f, max_x = 0.0f;
rgame_recording_bounds(recording_unwrap(self)->recording, &min_x, NULL, &max_x, NULL);
return DBL2NUM((double)(max_x - min_x));
}
|