reight 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/PULL_REQUEST_TEMPLATE.md +12 -0
- data/CONTRIBUTING.md +7 -0
- data/ChangeLog.md +76 -0
- data/README.md +6 -5
- data/Rakefile +5 -2
- data/VERSION +1 -1
- data/bin/r8 +18 -8
- data/lib/reight/all.rb +7 -2
- data/lib/reight/app/chips.rb +124 -0
- data/lib/reight/app/map/brush.rb +1 -1
- data/lib/reight/app/map/brush_base.rb +3 -3
- data/lib/reight/app/map/canvas.rb +10 -15
- data/lib/reight/app/map/editor.rb +44 -17
- data/lib/reight/app/map/line.rb +5 -5
- data/lib/reight/app/map/rect.rb +2 -2
- data/lib/reight/app/map.rb +0 -1
- data/lib/reight/app/navigator.rb +33 -47
- data/lib/reight/app/runner.rb +123 -86
- data/lib/reight/app/sound/brush.rb +32 -0
- data/lib/reight/app/sound/canvas.rb +190 -0
- data/lib/reight/app/sound/editor.rb +170 -10
- data/lib/reight/app/sound/eraser.rb +28 -0
- data/lib/reight/app/sound/tool.rb +29 -0
- data/lib/reight/app/sound.rb +4 -0
- data/lib/reight/app/sprite/canvas.rb +23 -18
- data/lib/reight/app/sprite/color.rb +3 -1
- data/lib/reight/app/sprite/editor.rb +58 -47
- data/lib/reight/app/sprite/line.rb +1 -1
- data/lib/reight/app/sprite/shape.rb +1 -1
- data/lib/reight/app/sprite.rb +0 -1
- data/lib/reight/app.rb +24 -5
- data/lib/reight/button.rb +10 -7
- data/lib/reight/chip.rb +32 -6
- data/lib/reight/context.rb +168 -0
- data/lib/reight/helpers.rb +2 -2
- data/lib/reight/index.rb +87 -0
- data/lib/reight/map.rb +141 -11
- data/lib/reight/project.rb +45 -6
- data/lib/reight/reight.rb +11 -15
- data/lib/reight/sound.rb +238 -0
- data/lib/reight/sprite.rb +42 -0
- data/lib/reight/text.rb +124 -0
- data/lib/reight.rb +7 -3
- data/reight.gemspec +7 -7
- data/res/icons.png +0 -0
- data/test/helper.rb +16 -0
- data/test/test_map.rb +7 -7
- data/test/test_map_chunk.rb +6 -6
- data/test/test_sprite.rb +28 -0
- metadata +42 -32
- data/lib/reight/app/map/chips.rb +0 -84
- data/lib/reight/app/music/editor.rb +0 -25
- data/lib/reight/app/music.rb +0 -1
- data/lib/reight/app/sprite/chips.rb +0 -92
data/lib/reight/index.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
using Reight
|
2
|
+
|
3
|
+
|
4
|
+
class Reight::Index
|
5
|
+
|
6
|
+
include Reight::Activatable
|
7
|
+
include Reight::Hookable
|
8
|
+
include Reight::HasHelp
|
9
|
+
|
10
|
+
def initialize(index = 0, min: 0, max: nil, &changed)
|
11
|
+
hook :changed
|
12
|
+
|
13
|
+
super()
|
14
|
+
@min, @max = min, max
|
15
|
+
|
16
|
+
self.changed(&changed) if changed
|
17
|
+
self.index = index
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :index
|
21
|
+
|
22
|
+
def index=(index)
|
23
|
+
index = index.clamp(@max ? (@min..@max) : (@min..))
|
24
|
+
return if index == @index
|
25
|
+
@index = index.to_i
|
26
|
+
changed! @index
|
27
|
+
end
|
28
|
+
|
29
|
+
def draw()
|
30
|
+
no_stroke
|
31
|
+
|
32
|
+
sp = sprite
|
33
|
+
w, h = sp.w, sp.h
|
34
|
+
dec = pressing? && prev?
|
35
|
+
inc = pressing? && next?
|
36
|
+
decy = dec ? 1 : 0
|
37
|
+
incy = inc ? 1 : 0
|
38
|
+
|
39
|
+
fill 220
|
40
|
+
rect 0, decy, h, h, 2 if dec
|
41
|
+
rect w - h, incy, h, h, 2 if inc
|
42
|
+
|
43
|
+
text_align CENTER, CENTER
|
44
|
+
fill 220
|
45
|
+
text '<', 0, decy + 1, h, h
|
46
|
+
text '>', w - h, incy + 1, h, h
|
47
|
+
text index, 0, 1, w, h
|
48
|
+
fill 50
|
49
|
+
text '<', 0, decy, h, h
|
50
|
+
text '>', w - h, incy, h, h
|
51
|
+
text index, 0, 0, w, h
|
52
|
+
end
|
53
|
+
|
54
|
+
def prev? = sprite.mouse_x < sprite.w / 2
|
55
|
+
|
56
|
+
def next? = !prev?
|
57
|
+
|
58
|
+
def pressed(x, y)
|
59
|
+
@pressing = true
|
60
|
+
end
|
61
|
+
|
62
|
+
def released(x, y)
|
63
|
+
@pressing = false
|
64
|
+
end
|
65
|
+
|
66
|
+
def pressing? = @pressing
|
67
|
+
|
68
|
+
def hover(x, y)
|
69
|
+
r8.flash x < (sprite.w / 2) ? 'Prev' : 'Next'
|
70
|
+
end
|
71
|
+
|
72
|
+
def clicked()
|
73
|
+
self.index += 1 if next?
|
74
|
+
self.index -= 1 if prev?
|
75
|
+
end
|
76
|
+
|
77
|
+
def sprite()
|
78
|
+
@sprite ||= RubySketch::Sprite.new(physics: false).tap do |sp|
|
79
|
+
sp.draw {draw}
|
80
|
+
sp.mouse_pressed {pressed sp.mouse_x, sp.mouse_y}
|
81
|
+
sp.mouse_released {released sp.mouse_x, sp.mouse_y}
|
82
|
+
sp.mouse_moved {hover sp.mouse_x, sp.mouse_y}
|
83
|
+
sp.mouse_clicked {clicked}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end# Index
|
data/lib/reight/map.rb
CHANGED
@@ -12,10 +12,32 @@ class Reight::Map
|
|
12
12
|
raise ArgumentError, "Invalid chunk_size: #{chunk_size}" if
|
13
13
|
chunk_size.to_i != chunk_size || chunk_size % chip_size != 0
|
14
14
|
|
15
|
-
@chip_size, @chunk_size = [chip_size, chunk_size].map
|
15
|
+
@chip_size, @chunk_size = [chip_size, chunk_size].map(&:to_i)
|
16
16
|
@chunks = {}
|
17
17
|
end
|
18
18
|
|
19
|
+
def activate(x, y, w, h, world = nil, &activated)
|
20
|
+
@sprites = nil if !activated && @sprites && @sprites.world != world
|
21
|
+
@sprites ||= SpriteArray.new(world: world) {|*a, &b| each_chunk(*a, &b)}
|
22
|
+
@sprites.activate(x, y, w, h, &activated)
|
23
|
+
@sprites
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_sprites()
|
27
|
+
map(&:to_sprite)
|
28
|
+
end
|
29
|
+
|
30
|
+
def sprites()
|
31
|
+
@sprites ||= SpriteArray.new(sprites: to_sprites)
|
32
|
+
end
|
33
|
+
|
34
|
+
alias sprites_at activate
|
35
|
+
|
36
|
+
def clear_sprites()
|
37
|
+
@chunks.each_value {_1&.clear_sprites}
|
38
|
+
@sprites = nil
|
39
|
+
end
|
40
|
+
|
19
41
|
def put(x, y, chip)
|
20
42
|
return unless chip
|
21
43
|
each_chunk x, y, chip.w, chip.h, create: true do |chunk|
|
@@ -23,16 +45,16 @@ class Reight::Map
|
|
23
45
|
end
|
24
46
|
end
|
25
47
|
|
26
|
-
def
|
48
|
+
def remove(x, y)
|
27
49
|
chip = self[x, y] or return
|
28
50
|
cx, cy, cw, ch = chip.then {[_1.pos.x, _1.pos.y, _1.w, _1.h]}
|
29
51
|
each_chunk cx, cy, cw, ch, create: false do |chunk|
|
30
|
-
each_chip_pos(cx, cy, cw, ch) {|xx, yy| chunk.
|
52
|
+
each_chip_pos(cx, cy, cw, ch) {|xx, yy| chunk.remove xx, yy}
|
31
53
|
end
|
32
54
|
end
|
33
55
|
|
34
|
-
def
|
35
|
-
|
56
|
+
def remove_chip(chip)
|
57
|
+
remove chip.pos.x, chip.pos.y
|
36
58
|
end
|
37
59
|
|
38
60
|
def each_chip(x = nil, y = nil, w = nil, h = nil, clip_by_chunk: false, &block)
|
@@ -62,18 +84,34 @@ class Reight::Map
|
|
62
84
|
chunk_at(x, y)&.[](x, y)
|
63
85
|
end
|
64
86
|
|
65
|
-
def
|
87
|
+
def inspect()
|
88
|
+
"#<#{self.class.name}:0x#{object_id}>"
|
89
|
+
end
|
90
|
+
|
91
|
+
# @private
|
92
|
+
def cmp__(o)
|
66
93
|
a = [@chip_size, @chunk_size, @chunks]
|
67
94
|
b = o.instance_eval {[@chip_size, @chunk_size, @chunks]}
|
68
95
|
a <=> b
|
69
96
|
end
|
70
97
|
|
98
|
+
# @private
|
99
|
+
def drawSprite__(context)
|
100
|
+
if @sprites
|
101
|
+
@sprites.drawSprite__ context
|
102
|
+
else
|
103
|
+
@chunks.each_value {_1.drawSprite__ context}
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
71
107
|
def self.restore(hash, source_chips)
|
72
|
-
hash
|
108
|
+
chip_size, chunk_size, chunks = hash.values_at :chip_size, :chunk_size, :chunks
|
109
|
+
#hash => {chip_size:, chunk_size:, chunks:}
|
73
110
|
new(chip_size: chip_size, chunk_size: chunk_size).tap do |obj|
|
74
111
|
obj.instance_eval do
|
75
112
|
@chunks = chunks.each.with_object({}) do |chunk_hash, result|
|
76
|
-
chunk_hash
|
113
|
+
x, y = chunk_hash.values_at :x, :y
|
114
|
+
#chunk_hash => {x:, y:}
|
77
115
|
result[[x, y]] = Chunk.restore chunk_hash, source_chips
|
78
116
|
end
|
79
117
|
end
|
@@ -135,8 +173,10 @@ class Reight::Map
|
|
135
173
|
end# Map
|
136
174
|
|
137
175
|
|
176
|
+
# @private
|
138
177
|
class Reight::Map::Chunk
|
139
178
|
|
179
|
+
include Enumerable
|
140
180
|
include Comparable
|
141
181
|
|
142
182
|
def initialize(x, y, w, h, chip_size: 8)
|
@@ -150,6 +190,14 @@ class Reight::Map::Chunk
|
|
150
190
|
|
151
191
|
attr_reader :x, :y, :w, :h
|
152
192
|
|
193
|
+
def sprites()
|
194
|
+
@sprites ||= map(&:sprite).each {_1.map_chunk = self}
|
195
|
+
end
|
196
|
+
|
197
|
+
def clear_sprites()
|
198
|
+
@sprites = nil
|
199
|
+
end
|
200
|
+
|
153
201
|
def put(x, y, chip)
|
154
202
|
x, y = align_chip_pos x, y
|
155
203
|
raise "Invalid chip size" if
|
@@ -162,15 +210,17 @@ class Reight::Map::Chunk
|
|
162
210
|
each_chip_pos x, y, chip.w, chip.h do |xx, yy|
|
163
211
|
@chips[pos2index xx, yy] = get_chip.call
|
164
212
|
end
|
213
|
+
invalidate_cache__
|
165
214
|
end
|
166
215
|
|
167
|
-
def
|
216
|
+
def remove(x, y)
|
168
217
|
chip = self[x, y] or return
|
169
218
|
each_chip_pos chip.pos.x, chip.pos.y, chip.w, chip.h do |xx, yy|
|
170
219
|
index = pos2index xx, yy
|
171
220
|
@chips[index] = nil if @chips[index]&.id == chip.id
|
172
221
|
end
|
173
222
|
delete_last_nils
|
223
|
+
invalidate_cache__
|
174
224
|
end
|
175
225
|
|
176
226
|
def each_chip(x = nil, y = nil, w = nil, h = nil, include_hidden: false, &block)
|
@@ -201,6 +251,8 @@ class Reight::Map::Chunk
|
|
201
251
|
end
|
202
252
|
end
|
203
253
|
|
254
|
+
def each(&block) = each_chip {block.call _1}
|
255
|
+
|
204
256
|
def frame = [@x, @y, @w, @h]
|
205
257
|
|
206
258
|
def to_hash()
|
@@ -216,14 +268,44 @@ class Reight::Map::Chunk
|
|
216
268
|
@chips[index]
|
217
269
|
end
|
218
270
|
|
219
|
-
def
|
271
|
+
def inspect()
|
272
|
+
"#<#{self.class.name}:0x#{object_id}>"
|
273
|
+
end
|
274
|
+
|
275
|
+
# @private
|
276
|
+
def cmp__(o)
|
220
277
|
a = [@x, @y, @w, @h, @chip_size, @chips]
|
221
278
|
b = o.instance_eval {[@x, @y, @w, @h, @chip_size, @chips]}
|
222
279
|
a <=> b
|
223
280
|
end
|
224
281
|
|
282
|
+
# @private
|
283
|
+
def invalidate_cache__()
|
284
|
+
@cached = false
|
285
|
+
end
|
286
|
+
|
287
|
+
# @private
|
288
|
+
def drawSprite__(context)
|
289
|
+
@cached ||= true.tap do
|
290
|
+
@cache ||= create_graphics @w, @h
|
291
|
+
@cache.begin_draw do |g|
|
292
|
+
g.background 0, 0
|
293
|
+
g.translate -@x, -@y
|
294
|
+
sprites.each {_1.drawSprite__ g}
|
295
|
+
end
|
296
|
+
end
|
297
|
+
context.image @cache, @x, @y
|
298
|
+
end
|
299
|
+
|
300
|
+
# @private
|
301
|
+
def delete_sprite__(sprite)
|
302
|
+
@sprites.delete sprite
|
303
|
+
invalidate_cache__
|
304
|
+
end
|
305
|
+
|
225
306
|
def self.restore(hash, source_chips)
|
226
|
-
hash
|
307
|
+
x, y, w, h, chip_size, chip_ids = hash.values_at :x, :y, :w, :h, :chip_size, :chips
|
308
|
+
#hash => {x:, y:, w:, h:, chip_size: chip_size, chips: chip_ids}
|
227
309
|
tmp_chips = {}
|
228
310
|
get_chip = -> id, x, y {
|
229
311
|
tmp_chips[[id, x, y]] ||= source_chips[id].with(pos: create_vector(x, y))
|
@@ -262,3 +344,51 @@ class Reight::Map::Chunk
|
|
262
344
|
end
|
263
345
|
|
264
346
|
end# Chunk
|
347
|
+
|
348
|
+
|
349
|
+
# @private
|
350
|
+
class Reight::Map::SpriteArray < Array
|
351
|
+
|
352
|
+
def initialize(world: nil, sprites: [], &each_chunk)
|
353
|
+
@world, @each_chunk = world, each_chunk
|
354
|
+
super(sprites)
|
355
|
+
end
|
356
|
+
|
357
|
+
attr_reader :world
|
358
|
+
|
359
|
+
def activate(x, y, w, h, &activated)
|
360
|
+
raise ArgumentError, "missing 'activated' block" if !@world && !activated
|
361
|
+
|
362
|
+
bounds, old_bounds = [x, y, w, h], @bounds
|
363
|
+
return if bounds == old_bounds
|
364
|
+
|
365
|
+
chunks, old_chunks = @each_chunk.call(x, y, w, h).to_a, @chunks || []
|
366
|
+
return if chunks == old_chunks
|
367
|
+
|
368
|
+
activateds, deactivateds = [chunks - old_chunks, old_chunks - chunks]
|
369
|
+
.map {|chunks| chunks.map(&:sprites).flatten.compact}
|
370
|
+
if activated
|
371
|
+
activated.call activateds, deactivateds
|
372
|
+
elsif @world
|
373
|
+
activateds.each {@world .add_sprite _1}
|
374
|
+
deactivateds.each {@world.remove_sprite _1}
|
375
|
+
end
|
376
|
+
|
377
|
+
@bounds, @chunks = bounds, chunks
|
378
|
+
clear.concat @chunks.map(&:sprites).flatten.compact
|
379
|
+
end
|
380
|
+
|
381
|
+
def delete(sprite)
|
382
|
+
sprite.map_chunk&.delete_sprite__ sprite
|
383
|
+
super
|
384
|
+
end
|
385
|
+
|
386
|
+
def inspect()
|
387
|
+
"#<#{self.class.name}:0x#{object_id}>"
|
388
|
+
end
|
389
|
+
|
390
|
+
def drawSprite__(context)
|
391
|
+
(@chunks&.each || each).each {_1.drawSprite__ context}
|
392
|
+
end
|
393
|
+
|
394
|
+
end# SpriteArray
|
data/lib/reight/project.rb
CHANGED
@@ -3,6 +3,8 @@ using Reight
|
|
3
3
|
|
4
4
|
class Reight::Project
|
5
5
|
|
6
|
+
include Xot::Inspectable
|
7
|
+
|
6
8
|
def initialize(project_dir)
|
7
9
|
raise 'the project directory is required' unless project_dir
|
8
10
|
@project_dir = project_dir
|
@@ -17,7 +19,9 @@ class Reight::Project
|
|
17
19
|
def code_paths = settings[__method__]&.then {[_1].flatten} || ['game.rb']
|
18
20
|
|
19
21
|
def codes()
|
20
|
-
code_paths
|
22
|
+
code_paths
|
23
|
+
.map {File.expand_path _1, project_dir}
|
24
|
+
.map {File.read _1 rescue nil}
|
21
25
|
end
|
22
26
|
|
23
27
|
def chips_json_name = settings[__method__] || 'chips.json'
|
@@ -39,7 +43,7 @@ class Reight::Project
|
|
39
43
|
def chips_image()
|
40
44
|
@chips_image ||= -> {
|
41
45
|
create_graphics(chips_image_width, chips_image_height).tap do |g|
|
42
|
-
g.begin_draw {g.background 0, 0, 0}
|
46
|
+
g.begin_draw {g.background 0, 0, 0, 0}
|
43
47
|
img = load_image chips_image_path
|
44
48
|
g.begin_draw {g.image img, 0, 0}
|
45
49
|
rescue Rays::RaysError
|
@@ -47,6 +51,17 @@ class Reight::Project
|
|
47
51
|
}.call
|
48
52
|
end
|
49
53
|
|
54
|
+
def chips_page_width = settings[__method__] || 256
|
55
|
+
|
56
|
+
def chips_page_height = settings[__method__] || 256
|
57
|
+
|
58
|
+
def chips_npages()
|
59
|
+
w = chips_image_width / chips_page_width .to_f
|
60
|
+
h = chips_image_height / chips_page_height.to_f
|
61
|
+
raise unless w == w.to_i && h == h.to_i
|
62
|
+
(w * h).to_i
|
63
|
+
end
|
64
|
+
|
50
65
|
def maps_json_name = settings[__method__] || 'maps.json'
|
51
66
|
|
52
67
|
def maps_json_path = "#{project_dir}/#{maps_json_name}"
|
@@ -55,19 +70,30 @@ class Reight::Project
|
|
55
70
|
@maps ||= load_maps
|
56
71
|
end
|
57
72
|
|
73
|
+
def sounds_json_name = settings[__method__] || 'sounds.json'
|
74
|
+
|
75
|
+
def sounds_json_path = "#{project_dir}/#{sounds_json_name}"
|
76
|
+
|
77
|
+
def sounds()
|
78
|
+
@sounds ||= load_sounds
|
79
|
+
end
|
80
|
+
|
58
81
|
def font = @font ||= create_font(nil, font_size)
|
59
82
|
|
60
83
|
def font_size = 8
|
61
84
|
|
62
|
-
def palette_colors =
|
63
|
-
|
64
|
-
|
65
|
-
|
85
|
+
def palette_colors = Reight::App::PALETTE_COLORS.dup
|
86
|
+
|
87
|
+
def clear_all_sprites()
|
88
|
+
chips.each(&:clear_sprite)
|
89
|
+
maps.each(&:clear_sprites)
|
90
|
+
end
|
66
91
|
|
67
92
|
def save()
|
68
93
|
File.write project_path, to_json_string(@settings)
|
69
94
|
save_chips
|
70
95
|
save_maps
|
96
|
+
save_sounds
|
71
97
|
end
|
72
98
|
|
73
99
|
private
|
@@ -104,6 +130,19 @@ class Reight::Project
|
|
104
130
|
end
|
105
131
|
end
|
106
132
|
|
133
|
+
def save_sounds()
|
134
|
+
File.write sounds_json_path, to_json_string(sounds.map {_1.to_hash})
|
135
|
+
end
|
136
|
+
|
137
|
+
def load_sounds()
|
138
|
+
if File.file? sounds_json_path
|
139
|
+
json = JSON.parse File.read(sounds_json_path), symbolize_names: true
|
140
|
+
json.map {Reight::Sound.restore _1}
|
141
|
+
else
|
142
|
+
[Reight::Sound.new]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
107
146
|
def to_json_string(obj, readable: true)
|
108
147
|
if readable
|
109
148
|
JSON.pretty_generate obj
|
data/lib/reight/reight.rb
CHANGED
@@ -3,32 +3,29 @@ using Reight
|
|
3
3
|
|
4
4
|
class Reight::R8
|
5
5
|
|
6
|
-
def initialize(path)
|
6
|
+
def initialize(path, edit: false)
|
7
7
|
raise if $r8__
|
8
8
|
$r8__ = self
|
9
9
|
|
10
|
-
@path
|
10
|
+
@path, @edit = path, edit
|
11
11
|
self.current = apps.first
|
12
12
|
end
|
13
13
|
|
14
14
|
attr_reader :current
|
15
15
|
|
16
|
-
def
|
17
|
-
'0.1'
|
18
|
-
end
|
16
|
+
def edit? = @edit
|
19
17
|
|
20
18
|
def project()
|
21
19
|
@project ||= Reight::Project.new @path
|
22
20
|
end
|
23
21
|
|
24
22
|
def apps()
|
25
|
-
@apps ||= [
|
26
|
-
Reight::Runner.new(project)
|
27
|
-
Reight::SpriteEditor.new(project)
|
28
|
-
Reight::MapEditor.new(project)
|
29
|
-
Reight::SoundEditor.new(project)
|
30
|
-
|
31
|
-
]
|
23
|
+
@apps ||= [].tap {|a|
|
24
|
+
a << Reight::Runner .new(project)
|
25
|
+
a << Reight::SpriteEditor.new(project) if edit?
|
26
|
+
a << Reight::MapEditor .new(project) if edit?
|
27
|
+
a << Reight::SoundEditor .new(project) if edit?
|
28
|
+
}
|
32
29
|
end
|
33
30
|
|
34
31
|
def flash(...) = current.flash(...)
|
@@ -43,16 +40,15 @@ class Reight::R8
|
|
43
40
|
end
|
44
41
|
|
45
42
|
def current=(app)
|
46
|
-
return if app == @current
|
47
43
|
@current&.deactivated
|
48
44
|
@current = app
|
49
45
|
@current.activated
|
50
46
|
|
51
47
|
set_title [
|
52
48
|
self.class.name.split('::').first,
|
53
|
-
version,
|
49
|
+
Reight::Extension.version,
|
54
50
|
'|',
|
55
|
-
current.
|
51
|
+
current.label
|
56
52
|
].join ' '
|
57
53
|
end
|
58
54
|
|