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
- #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
111 112 113 114 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 |
# File 'ext/rgame_core/ruby/core_ext.c', line 111
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.
79 80 81 |
# File 'lib/rgame/core/app.rb', line 79 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.
69 |
# File 'lib/rgame/core/app.rb', line 69 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.
74 |
# File 'lib/rgame/core/app.rb', line 74 def audio = @audio ||= Audio.new |
#button_down(button_id) ⇒ Object
430 431 432 433 434 |
# File 'ext/rgame_core/ruby/core_ext.c', line 430
static VALUE app_default_button(VALUE self, VALUE button_id) {
(void)self;
(void)button_id;
return Qnil;
}
|
#button_up(button_id) ⇒ Object
430 431 432 433 434 |
# File 'ext/rgame_core/ruby/core_ext.c', line 430
static VALUE app_default_button(VALUE self, VALUE button_id) {
(void)self;
(void)button_id;
return Qnil;
}
|
#caption ⇒ Object
347 348 349 350 |
# File 'ext/rgame_core/ruby/core_ext.c', line 347 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
352 353 354 355 |
# File 'ext/rgame_core/ruby/core_ext.c', line 352
static VALUE app_set_caption(VALUE self, VALUE title) {
rgame_app_set_title(rgame_app_unwrap(self), StringValueCStr(title));
return title;
}
|
#close ⇒ Object
334 335 336 337 |
# File 'ext/rgame_core/ruby/core_ext.c', line 334 static VALUE app_close(VALUE self) { rgame_app_close(rgame_app_unwrap(self)); return self; } |
#draw ⇒ Object
419 420 421 422 |
# File 'ext/rgame_core/ruby/core_ext.c', line 419
static VALUE app_default_draw(VALUE self) {
(void)self;
return Qnil;
}
|
#fps ⇒ Object
397 398 399 |
# File 'ext/rgame_core/ruby/core_ext.c', line 397 static VALUE app_fps(VALUE self) { return DBL2NUM(rgame_app_fps(rgame_app_unwrap(self))); } |
#frame_begin ⇒ Object
408 409 410 411 |
# File 'ext/rgame_core/ruby/core_ext.c', line 408
static VALUE app_default_frame_begin(VALUE self) {
(void)self;
return Qnil;
}
|
#gamepad_connected(slot) ⇒ Object
443 444 445 446 447 |
# File 'ext/rgame_core/ruby/core_ext.c', line 443
static VALUE app_default_gamepad(VALUE self, VALUE slot) {
(void)self;
(void)slot;
return Qnil;
}
|
#gamepad_count ⇒ Object
389 390 391 |
# File 'ext/rgame_core/ruby/core_ext.c', line 389 static VALUE app_gamepad_count(VALUE self) { return INT2NUM(rgame_app_gamepad_count(rgame_app_unwrap(self))); } |
#gamepad_disconnected(slot) ⇒ Object
443 444 445 446 447 |
# File 'ext/rgame_core/ruby/core_ext.c', line 443
static VALUE app_default_gamepad(VALUE self, VALUE slot) {
(void)self;
(void)slot;
return Qnil;
}
|
#gamepad_name(slot) ⇒ Object
384 385 386 387 |
# File 'ext/rgame_core/ruby/core_ext.c', line 384
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
379 380 381 |
# File 'ext/rgame_core/ruby/core_ext.c', line 379
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
343 344 345 |
# File 'ext/rgame_core/ruby/core_ext.c', line 343 static VALUE app_height(VALUE self) { return INT2NUM(rgame_app_height(rgame_app_unwrap(self))); } |
#input_axis(device, axis_id) ⇒ Object
369 370 371 |
# File 'ext/rgame_core/ruby/core_ext.c', line 369
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
363 364 365 366 367 |
# File 'ext/rgame_core/ruby/core_ext.c', line 363
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
425 426 427 428 |
# File 'ext/rgame_core/ruby/core_ext.c', line 425
static VALUE app_default_needs_redraw(VALUE self) {
(void)self;
return Qtrue;
}
|
#resize(width, height) ⇒ Object
436 437 438 439 440 441 |
# File 'ext/rgame_core/ruby/core_ext.c', line 436
static VALUE app_default_resize(VALUE self, VALUE width, VALUE height) {
(void)self;
(void)width;
(void)height;
return Qnil;
}
|
#run ⇒ Object
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'ext/rgame_core/ruby/core_ext.c', line 302
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,
.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
393 394 395 |
# File 'ext/rgame_core/ruby/core_ext.c', line 393 static VALUE app_ticks_ms(VALUE self) { return UINT2NUM(rgame_app_ticks_ms(rgame_app_unwrap(self))); } |
#update(dt_seconds) ⇒ Object
413 414 415 416 417 |
# File 'ext/rgame_core/ruby/core_ext.c', line 413
static VALUE app_default_update(VALUE self, VALUE dt_seconds) {
(void)self;
(void)dt_seconds;
return Qnil;
}
|
#width ⇒ Object
339 340 341 |
# File 'ext/rgame_core/ruby/core_ext.c', line 339 static VALUE app_width(VALUE self) { return INT2NUM(rgame_app_width(rgame_app_unwrap(self))); } |