Class: RGame::Core::App
- Inherits:
-
Object
- Object
- RGame::Core::App
- Defined in:
- lib/rgame/core/app.rb,
ext/rgame_core/ruby/core_ext.c
Overview
The two things a game needs one of, owned by the app that needs them and built on first use.
Lazily, and that is the point on both counts: an app that draws only primitives builds no asset manager, and one that never plays a sound never opens a device — which is also the right moment to open it, since asking for a sound is the first thing that needs one.
Instance Attribute Summary collapse
-
#media_root ⇒ Object
readonly
Where #assets resolves relative paths from.
Instance Method Summary collapse
-
#assets ⇒ Object
This app's asset manager, rooted at the
media_root:it was made with. -
#audio ⇒ Object
This app's sound device.
- #button_down(button_id) ⇒ Object
- #button_up(button_id) ⇒ Object
- #caption ⇒ Object
- #caption=(title) ⇒ Object
- #close ⇒ Object
- #draw ⇒ Object
- #fps ⇒ Object
- #frame_begin ⇒ Object
- #frame_end ⇒ Object
- #gamepad_connected(slot) ⇒ Object
- #gamepad_count ⇒ Object
- #gamepad_disconnected(slot) ⇒ Object
- #gamepad_name(slot) ⇒ Object
- #gamepad_present?(slot) ⇒ Object
- #height ⇒ Object
- #initialize(*args) ⇒ Object constructor
- #input_axis(device, axis_id) ⇒ Object
- #input_down?(device, button_id) ⇒ Object
- #needs_redraw? ⇒ Object
- #resize(width, height) ⇒ Object
- #run ⇒ Object
- #ticks_ms ⇒ Object
- #update(dt_seconds) ⇒ Object
- #width ⇒ Object
Constructor Details
#initialize(*args) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'ext/rgame_core/ruby/core_ext.c', line 115
static VALUE app_initialize(int argc, VALUE *argv, VALUE self) {
VALUE opts = Qnil;
rb_scan_args(argc, argv, "0:", &opts); /* no positional args, keywords only */
if (NIL_P(opts)) {
rb_raise(rb_eArgError, "missing keywords: :width, :height, :caption");
}
const ID keys[4] = { id_width, id_height, id_caption, id_media_root };
VALUE values[4];
/* 3 required, 1 optional: raises on a missing or unknown keyword. An absent
* optional comes back as Qundef. */
rb_get_kwargs(opts, keys, 3, 1, values);
rgame_app *app = rgame_app_create(NUM2INT(values[0]), NUM2INT(values[1]),
StringValueCStr(values[2]));
if (!app) {
rb_raise(rb_eRuntimeError, "failed to create rgame app");
}
/* Store the pointer into the already-wrapped object. */
RTYPEDDATA_DATA(self) = app;
/* Where App#assets resolves relative paths from. It means nothing to the C
* engine — no file is read here — so it is kept as a plain Ruby ivar and
* lib/rgame/core/app.rb owns everything that reads it. It is a keyword here
* rather than a writer so that a game says it once, in the same call that
* makes the window, and cannot set it after an asset has already loaded. */
rb_iv_set(self, "@media_root",
values[3] == Qundef ? rb_str_new_cstr("media") : StringValue(values[3]));
return self;
}
|
Instance Attribute Details
#media_root ⇒ Object (readonly)
Where #assets resolves relative paths from. Set once, as a keyword to the constructor; there is deliberately no writer, because changing it after an asset has loaded would leave a cache keyed against two roots.
81 82 83 |
# File 'lib/rgame/core/app.rb', line 81 def media_root @media_root end |
Instance Method Details
#assets ⇒ Object
This app's asset manager, rooted at the media_root: it was made with.
class MyGame < RGame::Core::App
def initialize = super(width: 640, height: 480, caption: 'demo', media_root: MEDIA)
end
app.assets.image('space.png')
A game never constructs one. An Image belongs to one GL context and
has to be told which, so something has to hold the app — and since the
asset manager is the only thing in the engine that loads from a path,
that something is here, once, rather than threaded through every
constructor that ends up owning an image.
71 |
# File 'lib/rgame/core/app.rb', line 71 def assets = @assets ||= AssetManager.new(root: @media_root, app: self) |
#audio ⇒ Object
This app's sound device. Not tied to the window in any way — audio has no GL context and survives one being recreated — it lives here because a game wants exactly one, the same way it wants one asset manager.
76 |
# File 'lib/rgame/core/app.rb', line 76 def audio = @audio ||= Audio.new |
#button_down(button_id) ⇒ Object
444 445 446 447 448 |
# File 'ext/rgame_core/ruby/core_ext.c', line 444
static VALUE app_default_button(VALUE self, VALUE button_id) {
(void)self;
(void)button_id;
return Qnil;
}
|
#button_up(button_id) ⇒ Object
444 445 446 447 448 |
# File 'ext/rgame_core/ruby/core_ext.c', line 444
static VALUE app_default_button(VALUE self, VALUE button_id) {
(void)self;
(void)button_id;
return Qnil;
}
|
#caption ⇒ Object
356 357 358 359 |
# File 'ext/rgame_core/ruby/core_ext.c', line 356 static VALUE app_caption(VALUE self) { const char *title = rgame_app_title(rgame_app_unwrap(self)); return rb_utf8_str_new_cstr(title ? title : ""); } |
#caption=(title) ⇒ Object
361 362 363 364 |
# File 'ext/rgame_core/ruby/core_ext.c', line 361
static VALUE app_set_caption(VALUE self, VALUE title) {
rgame_app_set_title(rgame_app_unwrap(self), StringValueCStr(title));
return title;
}
|
#close ⇒ Object
343 344 345 346 |
# File 'ext/rgame_core/ruby/core_ext.c', line 343 static VALUE app_close(VALUE self) { rgame_app_close(rgame_app_unwrap(self)); return self; } |
#draw ⇒ Object
428 429 430 431 |
# File 'ext/rgame_core/ruby/core_ext.c', line 428
static VALUE app_default_draw(VALUE self) {
(void)self;
return Qnil;
}
|
#fps ⇒ Object
406 407 408 |
# File 'ext/rgame_core/ruby/core_ext.c', line 406 static VALUE app_fps(VALUE self) { return DBL2NUM(rgame_app_fps(rgame_app_unwrap(self))); } |
#frame_begin ⇒ Object
417 418 419 420 |
# File 'ext/rgame_core/ruby/core_ext.c', line 417
static VALUE app_default_frame_begin(VALUE self) {
(void)self;
return Qnil;
}
|
#frame_end ⇒ Object
433 434 435 436 |
# File 'ext/rgame_core/ruby/core_ext.c', line 433
static VALUE app_default_frame_end(VALUE self) {
(void)self;
return Qnil;
}
|
#gamepad_connected(slot) ⇒ Object
457 458 459 460 461 |
# File 'ext/rgame_core/ruby/core_ext.c', line 457
static VALUE app_default_gamepad(VALUE self, VALUE slot) {
(void)self;
(void)slot;
return Qnil;
}
|
#gamepad_count ⇒ Object
398 399 400 |
# File 'ext/rgame_core/ruby/core_ext.c', line 398 static VALUE app_gamepad_count(VALUE self) { return INT2NUM(rgame_app_gamepad_count(rgame_app_unwrap(self))); } |
#gamepad_disconnected(slot) ⇒ Object
457 458 459 460 461 |
# File 'ext/rgame_core/ruby/core_ext.c', line 457
static VALUE app_default_gamepad(VALUE self, VALUE slot) {
(void)self;
(void)slot;
return Qnil;
}
|
#gamepad_name(slot) ⇒ Object
393 394 395 396 |
# File 'ext/rgame_core/ruby/core_ext.c', line 393
static VALUE app_gamepad_name(VALUE self, VALUE slot) {
const char *name = rgame_app_gamepad_name(rgame_app_unwrap(self), NUM2INT(slot));
return name ? rb_utf8_str_new_cstr(name) : Qnil;
}
|
#gamepad_present?(slot) ⇒ Object
388 389 390 |
# File 'ext/rgame_core/ruby/core_ext.c', line 388
static VALUE app_gamepad_present_p(VALUE self, VALUE slot) {
return rgame_app_gamepad_connected(rgame_app_unwrap(self), NUM2INT(slot)) ? Qtrue : Qfalse;
}
|
#height ⇒ Object
352 353 354 |
# File 'ext/rgame_core/ruby/core_ext.c', line 352 static VALUE app_height(VALUE self) { return INT2NUM(rgame_app_height(rgame_app_unwrap(self))); } |
#input_axis(device, axis_id) ⇒ Object
378 379 380 |
# File 'ext/rgame_core/ruby/core_ext.c', line 378
static VALUE app_input_axis(VALUE self, VALUE device, VALUE axis_id) {
return DBL2NUM(rgame_app_input_axis(rgame_app_unwrap(self), NUM2INT(device), NUM2INT(axis_id)));
}
|
#input_down?(device, button_id) ⇒ Object
372 373 374 375 376 |
# File 'ext/rgame_core/ruby/core_ext.c', line 372
static VALUE app_input_down_p(VALUE self, VALUE device, VALUE button_id) {
return rgame_app_input_down(rgame_app_unwrap(self), NUM2INT(device), NUM2INT(button_id))
? Qtrue
: Qfalse;
}
|
#needs_redraw? ⇒ Object
439 440 441 442 |
# File 'ext/rgame_core/ruby/core_ext.c', line 439
static VALUE app_default_needs_redraw(VALUE self) {
(void)self;
return Qtrue;
}
|
#resize(width, height) ⇒ Object
450 451 452 453 454 455 |
# File 'ext/rgame_core/ruby/core_ext.c', line 450
static VALUE app_default_resize(VALUE self, VALUE width, VALUE height) {
(void)self;
(void)width;
(void)height;
return Qnil;
}
|
#run ⇒ Object
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
# File 'ext/rgame_core/ruby/core_ext.c', line 310
static VALUE app_run(VALUE self) {
rgame_app *app = rgame_app_unwrap(self);
run_state rs = { self, app, 0, Qnil };
rgame_app_callbacks callbacks = {
.frame_begin = tramp_frame_begin,
.update = tramp_update,
.needs_redraw = tramp_needs_redraw,
.draw = tramp_draw,
.frame_end = tramp_frame_end,
.button_down = tramp_button_down,
.button_up = tramp_button_up,
.resize = tramp_resize,
.gamepad_connected = tramp_gamepad_connected,
.gamepad_disconnected = tramp_gamepad_disconnected,
.userdata = &rs,
};
rgame_app_run(app, &callbacks);
/* A callback unwound: the loop has now exited on its own terms, so it is
* safe to raise. Class, message and backtrace are the original ones. */
if (rs.failed) {
rb_exc_raise(rs.exception);
}
return self;
}
|
#ticks_ms ⇒ Object
402 403 404 |
# File 'ext/rgame_core/ruby/core_ext.c', line 402 static VALUE app_ticks_ms(VALUE self) { return UINT2NUM(rgame_app_ticks_ms(rgame_app_unwrap(self))); } |
#update(dt_seconds) ⇒ Object
422 423 424 425 426 |
# File 'ext/rgame_core/ruby/core_ext.c', line 422
static VALUE app_default_update(VALUE self, VALUE dt_seconds) {
(void)self;
(void)dt_seconds;
return Qnil;
}
|
#width ⇒ Object
348 349 350 |
# File 'ext/rgame_core/ruby/core_ext.c', line 348 static VALUE app_width(VALUE self) { return INT2NUM(rgame_app_width(rgame_app_unwrap(self))); } |