glimmer-dsl-libui 0.2.16 → 0.2.20
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/README.md +513 -92
- data/VERSION +1 -1
- data/bin/girb +0 -0
- data/examples/area_gallery.rb +11 -18
- data/examples/area_gallery2.rb +31 -7
- data/examples/area_gallery3.rb +14 -21
- data/examples/area_gallery4.rb +34 -10
- data/examples/histogram.rb +6 -13
- data/examples/meta_example.rb +3 -1
- data/examples/tetris/model/block.rb +48 -0
- data/examples/tetris/model/game.rb +308 -0
- data/examples/tetris/model/past_game.rb +39 -0
- data/examples/tetris/model/tetromino.rb +329 -0
- data/examples/tetris.rb +354 -0
- data/glimmer-dsl-libui.gemspec +0 -0
- data/lib/glimmer/dsl/libui/shape_expression.rb +1 -0
- data/lib/glimmer/libui/control_proxy/area_proxy.rb +25 -0
- data/lib/glimmer/libui/control_proxy/path_proxy.rb +19 -7
- data/lib/glimmer/libui/control_proxy/window_proxy.rb +40 -1
- data/lib/glimmer/libui/shape/figure.rb +4 -2
- data/lib/glimmer/libui/shape/polybezier.rb +45 -0
- data/lib/glimmer/libui/shape/polygon.rb +46 -0
- data/lib/glimmer/libui/shape/polyline.rb +45 -0
- data/lib/glimmer/libui/shape.rb +9 -3
- metadata +10 -2
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for LibUI 0.2.
|
1
|
+
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for LibUI 0.2.20
|
2
2
|
## Prerequisite-Free Ruby Desktop Development GUI Library
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/glimmer-dsl-libui.svg)](http://badge.fury.io/rb/glimmer-dsl-libui)
|
4
4
|
[![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
@@ -112,31 +112,24 @@ window('Area Gallery', 400, 400) {
|
|
112
112
|
fill x0: 10, y0: 10, x1: 350, y1: 350, stops: [{pos: 0.25, r: 204, g: 102, b: 204}, {pos: 0.75, r: 102, g: 102, b: 204}]
|
113
113
|
}
|
114
114
|
path { # declarative stable path
|
115
|
-
|
116
|
-
|
117
|
-
line(400, 100)
|
118
|
-
line(400, 400)
|
119
|
-
|
120
|
-
closed true
|
121
|
-
}
|
122
|
-
|
115
|
+
polygon(100, 100, 100, 400, 400, 100, 400, 400)
|
116
|
+
|
123
117
|
fill r: 202, g: 102, b: 104, a: 0.5
|
124
118
|
stroke r: 0, g: 0, b: 0
|
125
119
|
}
|
126
120
|
path { # declarative stable path
|
127
|
-
|
128
|
-
bezier(200, 100, 100, 200, 400, 100)
|
129
|
-
bezier(300, 100, 100, 300, 100, 400)
|
130
|
-
bezier(100, 300, 300, 100, 400, 400)
|
131
|
-
|
132
|
-
closed true
|
133
|
-
}
|
121
|
+
polybezier(0, 0, 200, 100, 100, 200, 400, 100, 300, 100, 100, 300, 100, 400, 100, 300, 300, 100, 400, 400)
|
134
122
|
|
135
123
|
fill r: 202, g: 102, b: 204, a: 0.5
|
136
124
|
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
137
125
|
}
|
138
126
|
path { # declarative stable path
|
139
|
-
|
127
|
+
polyline(100, 100, 400, 100, 100, 400, 400, 400, 0, 0)
|
128
|
+
|
129
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
130
|
+
}
|
131
|
+
path { # declarative stable path
|
132
|
+
arc(404, 216, 190, 90, 90, false)
|
140
133
|
|
141
134
|
# radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
|
142
135
|
fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
|
@@ -148,9 +141,9 @@ window('Area Gallery', 400, 400) {
|
|
148
141
|
fill r: 202, g: 102, b: 204, a: 0.5
|
149
142
|
stroke r: 0, g: 0, b: 0, thickness: 2
|
150
143
|
}
|
151
|
-
text(
|
144
|
+
text(161, 40, 100) { # x, y, width
|
152
145
|
string('Area Gallery') {
|
153
|
-
font family: '
|
146
|
+
font family: 'Arial', size: 14
|
154
147
|
color :black
|
155
148
|
}
|
156
149
|
}
|
@@ -284,6 +277,7 @@ Other [Glimmer](https://rubygems.org/gems/glimmer) DSL gems you might be interes
|
|
284
277
|
- [Basic Draw Text](#basic-draw-text)
|
285
278
|
- [Custom Draw Text](#custom-draw-text)
|
286
279
|
- [Method-Based Custom Keyword](#method-based-custom-keyword)
|
280
|
+
- [Tetris](#tetris)
|
287
281
|
- [Applications](#applications)
|
288
282
|
- [Manga2PDF](#manga2pdf)
|
289
283
|
- [Befunge98 GUI](#befunge98-gui)
|
@@ -376,7 +370,7 @@ gem install glimmer-dsl-libui
|
|
376
370
|
Or install via Bundler `Gemfile`:
|
377
371
|
|
378
372
|
```ruby
|
379
|
-
gem 'glimmer-dsl-libui', '~> 0.2.
|
373
|
+
gem 'glimmer-dsl-libui', '~> 0.2.20'
|
380
374
|
```
|
381
375
|
|
382
376
|
Add `require 'glimmer-dsl-libui'` at the top, and then `include Glimmer` into the top-level main object for testing or into an actual class for serious usage.
|
@@ -452,7 +446,7 @@ These are all the supported keywords. Note that some keywords do not represent c
|
|
452
446
|
Keyword(Args) | Properties | Listeners
|
453
447
|
------------- | ---------- | ---------
|
454
448
|
`about_menu_item` | None | `on_clicked`
|
455
|
-
`area` |
|
449
|
+
`area` | `auto_draw_enabled` | `on_draw(area_draw_params)`, `on_mouse_event(area_mouse_event)`, `on_mouse_down(area_mouse_event)`, `on_mouse_up(area_mouse_event)`, `on_mouse_drag_started(area_mouse_event)`, `on_mouse_dragged(area_mouse_event)`, `on_mouse_dropped(area_mouse_event)`, `on_mouse_entered`, `on_mouse_exited`, `on_key_event(area_key_event)`, `on_key_down(area_key_event)`, `on_key_up(area_key_event)`
|
456
450
|
`arc(x_center as Numeric, y_center as Numeric, radius as Numeric, start_angle as Numeric, sweep as Numeric, is_negative as Boolean)` | `x_center` (`Numeric`), `y_center` (`Numeric`), `radius` (`Numeric`), `start_angle` (`Numeric`), `sweep` (`Numeric`), `is_negative` (Boolean) | None
|
457
451
|
`background_color_column(name as String)` | None | None
|
458
452
|
`bezier(c1_x as Numeric, c1_y as Numeric, c2_x as Numeric, c2_y as Numeric, end_x as Numeric, end_y as Numeric)` | `c1_x` (`Numeric`), `c1_y` (`Numeric`), `c2_x` (`Numeric`), `c2_y` (`Numeric`), `end_x` (`Numeric`), `end_y` (`Numeric`) | None
|
@@ -462,6 +456,7 @@ Keyword(Args) | Properties | Listeners
|
|
462
456
|
`checkbox_column(name as String)` | `editable` (Boolean) | None
|
463
457
|
`checkbox_text_column(name as String)` | `editable` (Boolean), `editable_checkbox` (Boolean), `editable_text` (Boolean) | None
|
464
458
|
`checkbox_text_color_column(name as String)` | `editable` (Boolean), `editable_checkbox` (Boolean), `editable_text` (Boolean) | None
|
459
|
+
`check_menu_item(text as String)` | `checked` (Boolean) | `on_clicked`
|
465
460
|
`combobox` | `items` (`Array` of `String`), `selected` (`Integer`) | `on_selected`
|
466
461
|
`color_button` | `color` (Array of `red` as `Float`, `green` as `Float`, `blue` as `Float`, `alpha` as `Float`), `red` as `Float`, `green` as `Float`, `blue` as `Float`, `alpha` as `Float` | `on_changed`
|
467
462
|
`date_picker` | `time` (`Hash` of keys: `sec` as `Integer`, `min` as `Integer`, `hour` as `Integer`, `mday` as `Integer`, `mon` as `Integer`, `year` as `Integer`, `wday` as `Integer`, `yday` as `Integer`, `dst` as Boolean) | `on_changed`
|
@@ -484,7 +479,7 @@ Keyword(Args) | Properties | Listeners
|
|
484
479
|
`line(x as Numeric, y as Numeric)` | `x` (`Numeric`), `y` (`Numeric`) | None
|
485
480
|
`matrix(m11 = nil as Numeric, m12 = nil as Numeric, m21 = nil as Numeric, m22 = nil as Numeric, m31 = nil as Numeric, m32 = nil as Numeric)` | `m11` (`Numeric`), `m12` (`Numeric`), `m21` (`Numeric`), `m22` (`Numeric`), `m31` (`Numeric`), `m32` (`Numeric`) | None
|
486
481
|
`menu(text as String)` | None | None
|
487
|
-
`menu_item(text as String)` |
|
482
|
+
`menu_item(text as String)` | None | `on_clicked`
|
488
483
|
`message_box` (alias for `msg_box`; see for arguments) | None | None
|
489
484
|
`message_box_error` (alias for `msg_box_error`; see for arguments) | None | None
|
490
485
|
`multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
@@ -493,6 +488,9 @@ Keyword(Args) | Properties | Listeners
|
|
493
488
|
`non_wrapping_multiline_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
494
489
|
`password_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
495
490
|
`path(draw_fill_mode = :winding)` | `fill` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color), `stroke` (`Hash` of `:r` as `0`-`255`, `:g` as `0`-`255`, `:b` as `0`-`255`, `:a` as `0.0`-`1.0`, hex, or [X11](https://en.wikipedia.org/wiki/X11_color_names) color), `:cap` as (`:round`, `:square`, `:flat`), `:join` as (`:miter`, `:round`, `:bevel`), `:thickness` as `Numeric`, `:miter_limit` as `Numeric`, `:dashes` as `Array` of `Numeric` ) | None
|
491
|
+
`polygon(point_array as Array of Arrays of Numeric or Array of Numeric)` | `point_array` (`Array of Arrays of Numeric or Array of Numeric`) | None
|
492
|
+
`polyline(point_array as Array of Arrays of Numeric or Array of Numeric)` | `point_array` (`Array of Arrays of Numeric or Array of Numeric`) | None
|
493
|
+
`polybezier(point_array as Array of Arrays of Numeric or Array of Numeric)` | `point_array` (`Array of Arrays of Numeric or Array of Numeric`) | None
|
496
494
|
`preferences_menu_item` | None | `on_clicked`
|
497
495
|
`progress_bar` | `value` (`Numeric`) | None
|
498
496
|
`progress_bar_column(name as String)` | None | None
|
@@ -500,6 +498,7 @@ Keyword(Args) | Properties | Listeners
|
|
500
498
|
`radio_buttons` | `selected` (`Integer`) | `on_selected`
|
501
499
|
`rectangle(x as Numeric, y as Numeric, width as Numeric, height as Numeric)` | `x` (`Numeric`), `y` (`Numeric`), `width` (`Numeric`), `height` (`Numeric`) | None
|
502
500
|
`search_entry` | `read_only` (Boolean), `text` (`String`) | `on_changed`
|
501
|
+
`separator_menu_item` | None | None
|
503
502
|
`slider(min as Numeric, max as Numeric)` | `value` (`Numeric`) | `on_changed`
|
504
503
|
`spinbox(min as Numeric, max as Numeric)` | `value` (`Numeric`) | `on_changed`
|
505
504
|
`square(x as Numeric, y as Numeric, length as Numeric)` | `x` (`Numeric`), `y` (`Numeric`), `length` (`Numeric`) | None
|
@@ -513,7 +512,7 @@ Keyword(Args) | Properties | Listeners
|
|
513
512
|
`time_picker` | `time` (`Hash` of keys: `sec` as `Integer`, `min` as `Integer`, `hour` as `Integer`) | `on_changed`
|
514
513
|
`vertical_box` | `padded` (Boolean) | None
|
515
514
|
`vertical_separator` | None | None
|
516
|
-
`window(title as String, width as Integer, height as Integer, has_menubar as Boolean)` | `borderless` (Boolean), `content_size` (width `Numeric`, height `Numeric`), `fullscreen` (Boolean), `margined` (Boolean), `title` (`String`) | `on_closing`, `on_content_size_changed`, `on_destroy`
|
515
|
+
`window(title as String, width as Integer, height as Integer, has_menubar as Boolean)` | `borderless` (Boolean), `content_size` (width `Numeric`, height `Numeric`), `fullscreen` (Boolean), `margined` (Boolean), `title` (`String`), `resizable` (Boolean) | `on_closing`, `on_content_size_changed`, `on_destroy`
|
517
516
|
|
518
517
|
### Common Control Properties
|
519
518
|
- `enabled` (Boolean)
|
@@ -744,6 +743,9 @@ Available nested `path` shapes:
|
|
744
743
|
- `arc(x_center as Numeric, y_center as Numeric, radius as Numeric, start_angle as Numeric, sweep as Numeric, is_negative as Boolean)`
|
745
744
|
- `line(x as Numeric, y as Numeric)`
|
746
745
|
- `bezier(c1_x as Numeric, c1_y as Numeric, c2_x as Numeric, c2_y as Numeric, end_x as Numeric, end_y as Numeric)`
|
746
|
+
- `polygon(point_array as Array of Arrays of Numeric or Array of Numeric)`: closed figure of lines; can receive points as [[x1, y1], [x2, y2], ...] or [x1, y1, x2, y2, ...]
|
747
|
+
- `polyline(point_array as Array of Arrays of Numeric or Array of Numeric)`: open figure of lines; can receive points as [[x1, y1], [x2, y2], ...] or [x1, y1, x2, y2, ...]
|
748
|
+
- `polybezier(point_array as Array of Arrays of Numeric or Array of Numeric)`: open figure of beziers; can receive points as [[start_x1, start_y1], [c1_x2, c1_y2, c2_x2, c2_y2, end_x2, end_y2], [c1_x3, c1_y3, c2_x3, c2_y3, end_x3, end_y3], ...] or [start_x1, start_y1, c1_x2, c1_y2, c2_x2, c2_y2, end_x2, end_y2, c1_x3, c1_y3, c2_x3, c2_y3, end_x3, end_y3, ...]
|
747
749
|
- `figure(x=nil as Numeric, y=nil as Numeric)` (composite that can contain other shapes) (can set `closed true` to connect last point to first point automatically)
|
748
750
|
|
749
751
|
Check [examples/area_gallery.rb](#area-gallery) for an overiew of all `path` shapes.
|
@@ -798,6 +800,12 @@ Note that when nesting an `area` directly underneath `window` (without a layout
|
|
798
800
|
|
799
801
|
To redraw an `area`, you may call the `#queue_redraw_all` method, or simply `#redraw`.
|
800
802
|
|
803
|
+
`area` has the following Glimmer-added API methods/attributes:
|
804
|
+
- `request_auto_redraw`: requests auto redraw upon changes to nested stable `path` or shapes
|
805
|
+
- `pause_auto_redraw`: pause auto redraw upon changes to nested stable `path` or shapes (useful to avoid too many micro-change redraws, to group all redraws as one after many micro-changes)
|
806
|
+
- `resume_auto_redraw`: resume auto redraw upon changes to nested stable `path` or shapes
|
807
|
+
- `auto_redraw_enabled`/`auto_redraw_enabled?`/`auto_redraw_enabled=`: an attribute to disable/enable auto redraw on an `area` upon changes to nested stable `path` or shapes
|
808
|
+
|
801
809
|
A transform `matrix` can be set on a path by building a `matrix(m11 = nil, m12 = nil, m21 = nil, m22 = nil, m31 = nil, m32 = nil) {operations}` proxy object and then setting via `transform` property, or alternatively by building and setting the matrix in one call to `transform(m11 = nil, m12 = nil, m21 = nil, m22 = nil, m31 = nil, m32 = nil) {operations}` passing it the matrix arguments and/or content operations.
|
802
810
|
|
803
811
|
When instantiating a `matrix` object, it always starts with identity matrix.
|
@@ -1076,6 +1084,7 @@ window('Method-Based Custom Keyword') {
|
|
1076
1084
|
- `table` controls on Windows intentionally get an extra empty row at the end because if any row were to be deleted for the first time, double-deletion happens due to an issue in [libui](https://github.com/andlabs/libui) on Windows.
|
1077
1085
|
- `table` `progress_bar` column on Windows cannot be updated with a positive value if it started initially with `-1` (it ignores update to avoid crashing due to an issue in [libui](https://github.com/andlabs/libui) on Windows.
|
1078
1086
|
- It seems that [libui](https://github.com/andlabs/libui) does not support nesting multiple `area` controls under a `grid` as only the first one shows up in that scenario. To workaround that limitation, use a `vertical_box` with nested `horizontal_box`s instead to include multiple `area`s in a GUI.
|
1087
|
+
- As per the code of [examples/basic_transform.rb](#basic-transform), Windows requires different ordering of transforms than Mac and Linux.
|
1079
1088
|
|
1080
1089
|
### Original API
|
1081
1090
|
|
@@ -4057,31 +4066,24 @@ window('Area Gallery', 400, 400) {
|
|
4057
4066
|
fill x0: 10, y0: 10, x1: 350, y1: 350, stops: [{pos: 0.25, r: 204, g: 102, b: 204}, {pos: 0.75, r: 102, g: 102, b: 204}]
|
4058
4067
|
}
|
4059
4068
|
path { # declarative stable path
|
4060
|
-
|
4061
|
-
|
4062
|
-
line(400, 100)
|
4063
|
-
line(400, 400)
|
4064
|
-
|
4065
|
-
closed true
|
4066
|
-
}
|
4067
|
-
|
4069
|
+
polygon(100, 100, 100, 400, 400, 100, 400, 400)
|
4070
|
+
|
4068
4071
|
fill r: 202, g: 102, b: 104, a: 0.5
|
4069
4072
|
stroke r: 0, g: 0, b: 0
|
4070
4073
|
}
|
4071
4074
|
path { # declarative stable path
|
4072
|
-
|
4073
|
-
bezier(200, 100, 100, 200, 400, 100)
|
4074
|
-
bezier(300, 100, 100, 300, 100, 400)
|
4075
|
-
bezier(100, 300, 300, 100, 400, 400)
|
4076
|
-
|
4077
|
-
closed true
|
4078
|
-
}
|
4075
|
+
polybezier(0, 0, 200, 100, 100, 200, 400, 100, 300, 100, 100, 300, 100, 400, 100, 300, 300, 100, 400, 400)
|
4079
4076
|
|
4080
4077
|
fill r: 202, g: 102, b: 204, a: 0.5
|
4081
4078
|
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
4082
4079
|
}
|
4083
4080
|
path { # declarative stable path
|
4084
|
-
|
4081
|
+
polyline(100, 100, 400, 100, 100, 400, 400, 400, 0, 0)
|
4082
|
+
|
4083
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
4084
|
+
}
|
4085
|
+
path { # declarative stable path
|
4086
|
+
arc(404, 216, 190, 90, 90, false)
|
4085
4087
|
|
4086
4088
|
# radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
|
4087
4089
|
fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
|
@@ -4093,9 +4095,9 @@ window('Area Gallery', 400, 400) {
|
|
4093
4095
|
fill r: 202, g: 102, b: 204, a: 0.5
|
4094
4096
|
stroke r: 0, g: 0, b: 0, thickness: 2
|
4095
4097
|
}
|
4096
|
-
text(
|
4098
|
+
text(161, 40, 100) { # x, y, width
|
4097
4099
|
string('Area Gallery') {
|
4098
|
-
font family: '
|
4100
|
+
font family: 'Arial', size: 14
|
4099
4101
|
color :black
|
4100
4102
|
}
|
4101
4103
|
}
|
@@ -4244,18 +4246,42 @@ window('Area Gallery', 400, 400) {
|
|
4244
4246
|
end_x 400
|
4245
4247
|
end_y 400
|
4246
4248
|
}
|
4247
|
-
|
4248
|
-
closed true
|
4249
4249
|
}
|
4250
4250
|
|
4251
4251
|
fill r: 202, g: 102, b: 204, a: 0.5
|
4252
4252
|
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
4253
4253
|
}
|
4254
|
+
path { # declarative stable path
|
4255
|
+
polyline(100, 100, 400, 100, 100, 400, 400, 400, 0, 0)
|
4256
|
+
figure {
|
4257
|
+
x 100
|
4258
|
+
y 100
|
4259
|
+
|
4260
|
+
line {
|
4261
|
+
x 400
|
4262
|
+
y 100
|
4263
|
+
}
|
4264
|
+
line {
|
4265
|
+
x 100
|
4266
|
+
y 400
|
4267
|
+
}
|
4268
|
+
line {
|
4269
|
+
x 400
|
4270
|
+
y 400
|
4271
|
+
}
|
4272
|
+
line {
|
4273
|
+
x 0
|
4274
|
+
y 0
|
4275
|
+
}
|
4276
|
+
}
|
4277
|
+
|
4278
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
4279
|
+
}
|
4254
4280
|
path { # declarative stable path
|
4255
4281
|
arc {
|
4256
|
-
x_center
|
4257
|
-
y_center
|
4258
|
-
radius
|
4282
|
+
x_center 404
|
4283
|
+
y_center 216
|
4284
|
+
radius 190
|
4259
4285
|
start_angle 90
|
4260
4286
|
sweep 90
|
4261
4287
|
is_negative false
|
@@ -4276,12 +4302,12 @@ window('Area Gallery', 400, 400) {
|
|
4276
4302
|
stroke r: 0, g: 0, b: 0, thickness: 2
|
4277
4303
|
}
|
4278
4304
|
text {
|
4279
|
-
x
|
4305
|
+
x 161
|
4280
4306
|
y 40
|
4281
4307
|
width 100
|
4282
4308
|
|
4283
4309
|
string {
|
4284
|
-
font family: '
|
4310
|
+
font family: 'Arial', size: 14
|
4285
4311
|
color :black
|
4286
4312
|
|
4287
4313
|
'Area Gallery'
|
@@ -4352,42 +4378,35 @@ window('Area Gallery', 400, 400) {
|
|
4352
4378
|
path { # a dynamic path is added semi-declaratively inside on_draw block
|
4353
4379
|
square(0, 0, 100)
|
4354
4380
|
square(100, 100, 400)
|
4355
|
-
|
4381
|
+
|
4356
4382
|
fill r: 102, g: 102, b: 204
|
4357
4383
|
}
|
4358
4384
|
path { # a dynamic path is added semi-declaratively inside on_draw block
|
4359
4385
|
rectangle(0, 100, 100, 400)
|
4360
4386
|
rectangle(100, 0, 400, 100)
|
4361
|
-
|
4387
|
+
|
4362
4388
|
# linear gradient (has x0, y0, x1, y1, and stops)
|
4363
4389
|
fill x0: 10, y0: 10, x1: 350, y1: 350, stops: [{pos: 0.25, r: 204, g: 102, b: 204}, {pos: 0.75, r: 102, g: 102, b: 204}]
|
4364
4390
|
}
|
4365
4391
|
path { # a dynamic path is added semi-declaratively inside on_draw block
|
4366
|
-
|
4367
|
-
|
4368
|
-
line(400, 100)
|
4369
|
-
line(400, 400)
|
4370
|
-
|
4371
|
-
closed true
|
4372
|
-
}
|
4373
|
-
|
4392
|
+
polygon(100, 100, 100, 400, 400, 100, 400, 400)
|
4393
|
+
|
4374
4394
|
fill r: 202, g: 102, b: 104, a: 0.5
|
4375
4395
|
stroke r: 0, g: 0, b: 0
|
4376
4396
|
}
|
4377
4397
|
path { # a dynamic path is added semi-declaratively inside on_draw block
|
4378
|
-
|
4379
|
-
|
4380
|
-
bezier(300, 100, 100, 300, 100, 400)
|
4381
|
-
bezier(100, 300, 300, 100, 400, 400)
|
4382
|
-
|
4383
|
-
closed true
|
4384
|
-
}
|
4385
|
-
|
4398
|
+
polybezier(0, 0, 200, 100, 100, 200, 400, 100, 300, 100, 100, 300, 100, 400, 100, 300, 300, 100, 400, 400)
|
4399
|
+
|
4386
4400
|
fill r: 202, g: 102, b: 204, a: 0.5
|
4387
4401
|
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
4388
4402
|
}
|
4389
4403
|
path { # a dynamic path is added semi-declaratively inside on_draw block
|
4390
|
-
|
4404
|
+
polyline(100, 100, 400, 100, 100, 400, 400, 400, 0, 0)
|
4405
|
+
|
4406
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
4407
|
+
}
|
4408
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
4409
|
+
arc(404, 216, 190, 90, 90, false)
|
4391
4410
|
|
4392
4411
|
# radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
|
4393
4412
|
fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
|
@@ -4399,9 +4418,9 @@ window('Area Gallery', 400, 400) {
|
|
4399
4418
|
fill r: 202, g: 102, b: 204, a: 0.5
|
4400
4419
|
stroke r: 0, g: 0, b: 0, thickness: 2
|
4401
4420
|
}
|
4402
|
-
text(
|
4421
|
+
text(161, 40, 100) { # x, y, width
|
4403
4422
|
string('Area Gallery') {
|
4404
|
-
font family: '
|
4423
|
+
font family: 'Arial', size: 14
|
4405
4424
|
color :black
|
4406
4425
|
}
|
4407
4426
|
}
|
@@ -4516,10 +4535,10 @@ window('Area Gallery', 400, 400) {
|
|
4516
4535
|
x 400
|
4517
4536
|
y 400
|
4518
4537
|
}
|
4519
|
-
|
4538
|
+
|
4520
4539
|
closed true
|
4521
4540
|
}
|
4522
|
-
|
4541
|
+
|
4523
4542
|
fill r: 202, g: 102, b: 104, a: 0.5
|
4524
4543
|
stroke r: 0, g: 0, b: 0
|
4525
4544
|
}
|
@@ -4552,18 +4571,42 @@ window('Area Gallery', 400, 400) {
|
|
4552
4571
|
end_x 400
|
4553
4572
|
end_y 400
|
4554
4573
|
}
|
4555
|
-
|
4556
|
-
closed true
|
4557
4574
|
}
|
4558
|
-
|
4575
|
+
|
4559
4576
|
fill r: 202, g: 102, b: 204, a: 0.5
|
4560
4577
|
stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
|
4561
4578
|
}
|
4579
|
+
path { # a dynamic path is added semi-declaratively inside on_draw block
|
4580
|
+
polyline(100, 100, 400, 100, 100, 400, 400, 400, 0, 0)
|
4581
|
+
figure {
|
4582
|
+
x 100
|
4583
|
+
y 100
|
4584
|
+
|
4585
|
+
line {
|
4586
|
+
x 400
|
4587
|
+
y 100
|
4588
|
+
}
|
4589
|
+
line {
|
4590
|
+
x 100
|
4591
|
+
y 400
|
4592
|
+
}
|
4593
|
+
line {
|
4594
|
+
x 400
|
4595
|
+
y 400
|
4596
|
+
}
|
4597
|
+
line {
|
4598
|
+
x 0
|
4599
|
+
y 0
|
4600
|
+
}
|
4601
|
+
}
|
4602
|
+
|
4603
|
+
stroke r: 0, g: 0, b: 0, thickness: 2
|
4604
|
+
}
|
4562
4605
|
path { # a dynamic path is added semi-declaratively inside on_draw block
|
4563
4606
|
arc {
|
4564
|
-
x_center
|
4565
|
-
y_center
|
4566
|
-
radius
|
4607
|
+
x_center 404
|
4608
|
+
y_center 216
|
4609
|
+
radius 190
|
4567
4610
|
start_angle 90
|
4568
4611
|
sweep 90
|
4569
4612
|
is_negative false
|
@@ -4584,12 +4627,12 @@ window('Area Gallery', 400, 400) {
|
|
4584
4627
|
stroke r: 0, g: 0, b: 0, thickness: 2
|
4585
4628
|
}
|
4586
4629
|
text {
|
4587
|
-
x
|
4630
|
+
x 161
|
4588
4631
|
y 40
|
4589
4632
|
width 100
|
4590
4633
|
|
4591
4634
|
string {
|
4592
|
-
font family: '
|
4635
|
+
font family: 'Arial', size: 14
|
4593
4636
|
color :black
|
4594
4637
|
|
4595
4638
|
'Area Gallery'
|
@@ -4906,20 +4949,13 @@ end
|
|
4906
4949
|
|
4907
4950
|
# method-based custom control representing a graph path
|
4908
4951
|
def graph_path(width, height, should_extend, &block)
|
4909
|
-
locations = point_locations(width, height)
|
4952
|
+
locations = point_locations(width, height).flatten
|
4910
4953
|
path {
|
4911
|
-
|
4912
|
-
|
4913
|
-
|
4914
|
-
|
4915
|
-
|
4916
|
-
if should_extend
|
4917
|
-
line(width, height)
|
4918
|
-
line(0, height)
|
4919
|
-
|
4920
|
-
closed true
|
4921
|
-
end
|
4922
|
-
}
|
4954
|
+
if should_extend
|
4955
|
+
polygon(locations + [width, height, 0, height])
|
4956
|
+
else
|
4957
|
+
polyline(locations)
|
4958
|
+
end
|
4923
4959
|
|
4924
4960
|
# apply a transform to the coordinate space for this path so (0, 0) is the top-left corner of the graph
|
4925
4961
|
transform {
|
@@ -6198,6 +6234,391 @@ window('Method-Based Custom Keyword') {
|
|
6198
6234
|
}.show
|
6199
6235
|
```
|
6200
6236
|
|
6237
|
+
### Tetris
|
6238
|
+
|
6239
|
+
Glimmer Tetris utilizes many small areas to represent Tetromino blocks because this ensures smaller redraws per tetromino block color change, thus higher performance than having one area that gets redrawn on every little change.
|
6240
|
+
|
6241
|
+
[examples/tetris.rb](examples/tetris.rb)
|
6242
|
+
|
6243
|
+
Run with this command from the root of the project if you cloned the project:
|
6244
|
+
|
6245
|
+
```
|
6246
|
+
ruby -r './lib/glimmer-dsl-libui' examples/tetris.rb
|
6247
|
+
```
|
6248
|
+
|
6249
|
+
Run with this command if you installed the [Ruby gem](https://rubygems.org/gems/glimmer-dsl-libui):
|
6250
|
+
|
6251
|
+
```
|
6252
|
+
ruby -r glimmer-dsl-libui -e "require 'examples/tetris'"
|
6253
|
+
```
|
6254
|
+
|
6255
|
+
Mac
|
6256
|
+
|
6257
|
+
![glimmer-dsl-libui-mac-tetris.png](images/glimmer-dsl-libui-mac-tetris.png)
|
6258
|
+
|
6259
|
+
![glimmer-dsl-libui-mac-tetris-game-over.png](images/glimmer-dsl-libui-mac-tetris-game-over.png)
|
6260
|
+
|
6261
|
+
![glimmer-dsl-libui-mac-tetris-high-scores.png](images/glimmer-dsl-libui-mac-tetris-high-scores.png)
|
6262
|
+
|
6263
|
+
New [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui) Version:
|
6264
|
+
|
6265
|
+
```ruby
|
6266
|
+
require 'glimmer-dsl-libui'
|
6267
|
+
|
6268
|
+
require_relative 'tetris/model/game'
|
6269
|
+
|
6270
|
+
class Tetris
|
6271
|
+
include Glimmer
|
6272
|
+
|
6273
|
+
BLOCK_SIZE = 25
|
6274
|
+
BEVEL_CONSTANT = 20
|
6275
|
+
COLOR_GRAY = {r: 192, g: 192, b: 192}
|
6276
|
+
|
6277
|
+
def initialize
|
6278
|
+
@game = Model::Game.new
|
6279
|
+
end
|
6280
|
+
|
6281
|
+
def launch
|
6282
|
+
create_gui
|
6283
|
+
register_observers
|
6284
|
+
@game.start!
|
6285
|
+
@main_window.show
|
6286
|
+
end
|
6287
|
+
|
6288
|
+
def create_gui
|
6289
|
+
menu_bar
|
6290
|
+
|
6291
|
+
@main_window = window('Glimmer Tetris') {
|
6292
|
+
content_size Model::Game::PLAYFIELD_WIDTH * BLOCK_SIZE, Model::Game::PLAYFIELD_HEIGHT * BLOCK_SIZE + 98
|
6293
|
+
resizable false
|
6294
|
+
|
6295
|
+
vertical_box {
|
6296
|
+
label { # filler
|
6297
|
+
stretchy false
|
6298
|
+
}
|
6299
|
+
|
6300
|
+
score_board(block_size: BLOCK_SIZE) {
|
6301
|
+
stretchy false
|
6302
|
+
}
|
6303
|
+
|
6304
|
+
@playfield_blocks = playfield(playfield_width: Model::Game::PLAYFIELD_WIDTH, playfield_height: Model::Game::PLAYFIELD_HEIGHT, block_size: BLOCK_SIZE)
|
6305
|
+
}
|
6306
|
+
}
|
6307
|
+
end
|
6308
|
+
|
6309
|
+
def register_observers
|
6310
|
+
Glimmer::DataBinding::Observer.proc do |game_over|
|
6311
|
+
if game_over
|
6312
|
+
@pause_menu_item.enabled = false
|
6313
|
+
show_game_over_dialog
|
6314
|
+
else
|
6315
|
+
@pause_menu_item.enabled = true
|
6316
|
+
start_moving_tetrominos_down
|
6317
|
+
end
|
6318
|
+
end.observe(@game, :game_over)
|
6319
|
+
|
6320
|
+
Model::Game::PLAYFIELD_HEIGHT.times do |row|
|
6321
|
+
Model::Game::PLAYFIELD_WIDTH.times do |column|
|
6322
|
+
Glimmer::DataBinding::Observer.proc do |new_color|
|
6323
|
+
Glimmer::LibUI.queue_main do
|
6324
|
+
color = Glimmer::LibUI.interpret_color(new_color)
|
6325
|
+
block = @playfield_blocks[row][column]
|
6326
|
+
block[:background_square].fill = color
|
6327
|
+
block[:top_bevel_edge].fill = {r: color[:r] + 4*BEVEL_CONSTANT, g: color[:g] + 4*BEVEL_CONSTANT, b: color[:b] + 4*BEVEL_CONSTANT}
|
6328
|
+
block[:right_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
|
6329
|
+
block[:bottom_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
|
6330
|
+
block[:left_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
|
6331
|
+
block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : color
|
6332
|
+
end
|
6333
|
+
end.observe(@game.playfield[row][column], :color)
|
6334
|
+
end
|
6335
|
+
end
|
6336
|
+
|
6337
|
+
Model::Game::PREVIEW_PLAYFIELD_HEIGHT.times do |row|
|
6338
|
+
Model::Game::PREVIEW_PLAYFIELD_WIDTH.times do |column|
|
6339
|
+
Glimmer::DataBinding::Observer.proc do |new_color|
|
6340
|
+
Glimmer::LibUI.queue_main do
|
6341
|
+
color = Glimmer::LibUI.interpret_color(new_color)
|
6342
|
+
block = @preview_playfield_blocks[row][column]
|
6343
|
+
block[:background_square].fill = color
|
6344
|
+
block[:top_bevel_edge].fill = {r: color[:r] + 4*BEVEL_CONSTANT, g: color[:g] + 4*BEVEL_CONSTANT, b: color[:b] + 4*BEVEL_CONSTANT}
|
6345
|
+
block[:right_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
|
6346
|
+
block[:bottom_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
|
6347
|
+
block[:left_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
|
6348
|
+
block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : color
|
6349
|
+
end
|
6350
|
+
end.observe(@game.preview_playfield[row][column], :color)
|
6351
|
+
end
|
6352
|
+
end
|
6353
|
+
|
6354
|
+
Glimmer::DataBinding::Observer.proc do |new_score|
|
6355
|
+
Glimmer::LibUI.queue_main do
|
6356
|
+
@score_label.text = new_score.to_s
|
6357
|
+
end
|
6358
|
+
end.observe(@game, :score)
|
6359
|
+
|
6360
|
+
Glimmer::DataBinding::Observer.proc do |new_lines|
|
6361
|
+
Glimmer::LibUI.queue_main do
|
6362
|
+
@lines_label.text = new_lines.to_s
|
6363
|
+
end
|
6364
|
+
end.observe(@game, :lines)
|
6365
|
+
|
6366
|
+
Glimmer::DataBinding::Observer.proc do |new_level|
|
6367
|
+
Glimmer::LibUI.queue_main do
|
6368
|
+
@level_label.text = new_level.to_s
|
6369
|
+
end
|
6370
|
+
end.observe(@game, :level)
|
6371
|
+
end
|
6372
|
+
|
6373
|
+
def menu_bar
|
6374
|
+
menu('Game') {
|
6375
|
+
@pause_menu_item = check_menu_item('Pause') {
|
6376
|
+
enabled false
|
6377
|
+
|
6378
|
+
on_clicked do
|
6379
|
+
@game.paused = @pause_menu_item.checked?
|
6380
|
+
end
|
6381
|
+
}
|
6382
|
+
menu_item('Restart') {
|
6383
|
+
on_clicked do
|
6384
|
+
@game.restart!
|
6385
|
+
end
|
6386
|
+
}
|
6387
|
+
separator_menu_item
|
6388
|
+
menu_item('Exit') {
|
6389
|
+
on_clicked do
|
6390
|
+
exit(0)
|
6391
|
+
end
|
6392
|
+
}
|
6393
|
+
quit_menu_item if OS.mac?
|
6394
|
+
}
|
6395
|
+
|
6396
|
+
menu('View') {
|
6397
|
+
menu_item('Show High Scores') {
|
6398
|
+
on_clicked do
|
6399
|
+
show_high_scores
|
6400
|
+
end
|
6401
|
+
}
|
6402
|
+
menu_item('Clear High Scores') {
|
6403
|
+
on_clicked {
|
6404
|
+
@game.clear_high_scores!
|
6405
|
+
}
|
6406
|
+
}
|
6407
|
+
}
|
6408
|
+
|
6409
|
+
menu('Options') {
|
6410
|
+
radio_menu_item('Instant Down on Up Arrow') {
|
6411
|
+
on_clicked do
|
6412
|
+
@game.instant_down_on_up = true
|
6413
|
+
end
|
6414
|
+
}
|
6415
|
+
radio_menu_item('Rotate Right on Up Arrow') {
|
6416
|
+
on_clicked do
|
6417
|
+
@game.rotate_right_on_up = true
|
6418
|
+
end
|
6419
|
+
}
|
6420
|
+
radio_menu_item('Rotate Left on Up Arrow') {
|
6421
|
+
on_clicked do
|
6422
|
+
@game.rotate_left_on_up = true
|
6423
|
+
end
|
6424
|
+
}
|
6425
|
+
}
|
6426
|
+
|
6427
|
+
menu('Help') {
|
6428
|
+
if OS.mac?
|
6429
|
+
about_menu_item {
|
6430
|
+
on_clicked do
|
6431
|
+
show_about_dialog
|
6432
|
+
end
|
6433
|
+
}
|
6434
|
+
end
|
6435
|
+
menu_item('About') {
|
6436
|
+
on_clicked do
|
6437
|
+
show_about_dialog
|
6438
|
+
end
|
6439
|
+
}
|
6440
|
+
}
|
6441
|
+
end
|
6442
|
+
|
6443
|
+
def playfield(playfield_width: , playfield_height: , block_size: , &extra_content)
|
6444
|
+
blocks = []
|
6445
|
+
vertical_box {
|
6446
|
+
padded false
|
6447
|
+
|
6448
|
+
playfield_height.times.map do |row|
|
6449
|
+
blocks << []
|
6450
|
+
horizontal_box {
|
6451
|
+
padded false
|
6452
|
+
|
6453
|
+
playfield_width.times.map do |column|
|
6454
|
+
blocks.last << block(row: row, column: column, block_size: block_size)
|
6455
|
+
end
|
6456
|
+
}
|
6457
|
+
end
|
6458
|
+
|
6459
|
+
extra_content&.call
|
6460
|
+
}
|
6461
|
+
blocks
|
6462
|
+
end
|
6463
|
+
|
6464
|
+
def block(row: , column: , block_size: , &extra_content)
|
6465
|
+
block = {}
|
6466
|
+
bevel_pixel_size = 0.16 * block_size.to_f
|
6467
|
+
color = Glimmer::LibUI.interpret_color(Model::Block::COLOR_CLEAR)
|
6468
|
+
area {
|
6469
|
+
block[:background_square] = path {
|
6470
|
+
square(0, 0, block_size)
|
6471
|
+
|
6472
|
+
fill color
|
6473
|
+
}
|
6474
|
+
block[:top_bevel_edge] = path {
|
6475
|
+
polygon(0, 0, block_size, 0, block_size - bevel_pixel_size, bevel_pixel_size, bevel_pixel_size, bevel_pixel_size)
|
6476
|
+
|
6477
|
+
fill r: color[:r] + 4*BEVEL_CONSTANT, g: color[:g] + 4*BEVEL_CONSTANT, b: color[:b] + 4*BEVEL_CONSTANT
|
6478
|
+
}
|
6479
|
+
block[:right_bevel_edge] = path {
|
6480
|
+
polygon(block_size, 0, block_size - bevel_pixel_size, bevel_pixel_size, block_size - bevel_pixel_size, block_size - bevel_pixel_size, block_size, block_size)
|
6481
|
+
|
6482
|
+
fill r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT
|
6483
|
+
}
|
6484
|
+
block[:bottom_bevel_edge] = path {
|
6485
|
+
polygon(block_size, block_size, 0, block_size, bevel_pixel_size, block_size - bevel_pixel_size, block_size - bevel_pixel_size, block_size - bevel_pixel_size)
|
6486
|
+
|
6487
|
+
fill r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT
|
6488
|
+
}
|
6489
|
+
block[:left_bevel_edge] = path {
|
6490
|
+
polygon(0, 0, 0, block_size, bevel_pixel_size, block_size - bevel_pixel_size, bevel_pixel_size, bevel_pixel_size)
|
6491
|
+
|
6492
|
+
fill r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT
|
6493
|
+
}
|
6494
|
+
block[:border_square] = path {
|
6495
|
+
square(0, 0, block_size)
|
6496
|
+
|
6497
|
+
stroke COLOR_GRAY
|
6498
|
+
}
|
6499
|
+
|
6500
|
+
on_key_down do |key_event|
|
6501
|
+
case key_event
|
6502
|
+
in ext_key: :down
|
6503
|
+
@game.down!
|
6504
|
+
in key: ' '
|
6505
|
+
@game.down!(instant: true)
|
6506
|
+
in ext_key: :up
|
6507
|
+
case @game.up_arrow_action
|
6508
|
+
when :instant_down
|
6509
|
+
@game.down!(instant: true)
|
6510
|
+
when :rotate_right
|
6511
|
+
@game.rotate!(:right)
|
6512
|
+
when :rotate_left
|
6513
|
+
@game.rotate!(:left)
|
6514
|
+
end
|
6515
|
+
in ext_key: :left
|
6516
|
+
@game.left!
|
6517
|
+
in ext_key: :right
|
6518
|
+
@game.right!
|
6519
|
+
in modifier: :shift
|
6520
|
+
@game.rotate!(:right)
|
6521
|
+
in modifier: :control
|
6522
|
+
@game.rotate!(:left)
|
6523
|
+
else
|
6524
|
+
# Do Nothing
|
6525
|
+
end
|
6526
|
+
end
|
6527
|
+
|
6528
|
+
extra_content&.call
|
6529
|
+
}
|
6530
|
+
block
|
6531
|
+
end
|
6532
|
+
|
6533
|
+
def score_board(block_size: , &extra_content)
|
6534
|
+
vertical_box {
|
6535
|
+
horizontal_box {
|
6536
|
+
label # filler
|
6537
|
+
@preview_playfield_blocks = playfield(playfield_width: Model::Game::PREVIEW_PLAYFIELD_WIDTH, playfield_height: Model::Game::PREVIEW_PLAYFIELD_HEIGHT, block_size: block_size)
|
6538
|
+
label # filler
|
6539
|
+
}
|
6540
|
+
|
6541
|
+
horizontal_box {
|
6542
|
+
label # filler
|
6543
|
+
grid {
|
6544
|
+
stretchy false
|
6545
|
+
|
6546
|
+
label('Score') {
|
6547
|
+
left 0
|
6548
|
+
top 0
|
6549
|
+
halign :fill
|
6550
|
+
}
|
6551
|
+
@score_label = label {
|
6552
|
+
left 0
|
6553
|
+
top 1
|
6554
|
+
halign :center
|
6555
|
+
}
|
6556
|
+
|
6557
|
+
label('Lines') {
|
6558
|
+
left 1
|
6559
|
+
top 0
|
6560
|
+
halign :fill
|
6561
|
+
}
|
6562
|
+
@lines_label = label {
|
6563
|
+
left 1
|
6564
|
+
top 1
|
6565
|
+
halign :center
|
6566
|
+
}
|
6567
|
+
|
6568
|
+
label('Level') {
|
6569
|
+
left 2
|
6570
|
+
top 0
|
6571
|
+
halign :fill
|
6572
|
+
}
|
6573
|
+
@level_label = label {
|
6574
|
+
left 2
|
6575
|
+
top 1
|
6576
|
+
halign :center
|
6577
|
+
}
|
6578
|
+
}
|
6579
|
+
label # filler
|
6580
|
+
}
|
6581
|
+
|
6582
|
+
extra_content&.call
|
6583
|
+
}
|
6584
|
+
end
|
6585
|
+
|
6586
|
+
def start_moving_tetrominos_down
|
6587
|
+
Glimmer::LibUI.timer(@game.delay) do
|
6588
|
+
@game.down! if !@game.game_over? && !@game.paused?
|
6589
|
+
end
|
6590
|
+
end
|
6591
|
+
|
6592
|
+
def show_game_over_dialog
|
6593
|
+
Glimmer::LibUI.queue_main do
|
6594
|
+
msg_box('Game Over!', "Score: #{@game.high_scores.first.score}\nLines: #{@game.high_scores.first.lines}\nLevel: #{@game.high_scores.first.level}")
|
6595
|
+
@game.restart!
|
6596
|
+
end
|
6597
|
+
end
|
6598
|
+
|
6599
|
+
def show_high_scores
|
6600
|
+
Glimmer::LibUI.queue_main do
|
6601
|
+
if @game.high_scores.empty?
|
6602
|
+
high_scores_string = "No games have been scored yet."
|
6603
|
+
else
|
6604
|
+
high_scores_string = @game.high_scores.map do |high_score|
|
6605
|
+
"#{high_score.name} | Score: #{high_score.score} | Lines: #{high_score.lines} | Level: #{high_score.level}"
|
6606
|
+
end.join("\n")
|
6607
|
+
end
|
6608
|
+
msg_box('High Scores', high_scores_string)
|
6609
|
+
end
|
6610
|
+
end
|
6611
|
+
|
6612
|
+
def show_about_dialog
|
6613
|
+
Glimmer::LibUI.queue_main do
|
6614
|
+
msg_box('About', 'Glimmer Tetris - Glimmer DSL for LibUI Example - Copyright (c) 2021 Andy Maleh')
|
6615
|
+
end
|
6616
|
+
end
|
6617
|
+
end
|
6618
|
+
|
6619
|
+
Tetris.new.launch
|
6620
|
+
```
|
6621
|
+
|
6201
6622
|
## Applications
|
6202
6623
|
|
6203
6624
|
Here are some applications built with [Glimmer DSL for LibUI](https://rubygems.org/gems/glimmer-dsl-libui)
|