rubysketch-solitaire 0.1.0 → 0.9.0
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/workflows/test.yml +3 -0
- data/.gitignore +2 -0
- data/.hooks/post-commit +37 -0
- data/.hooks/pre-commit +69 -0
- data/ChangeLog.md +27 -0
- data/Gemfile.lock +10 -10
- data/Podfile.lock +33 -33
- data/README.md +8 -0
- data/Rakefile +107 -10
- data/RubySolitaire/Ad.swift +88 -0
- data/RubySolitaire/Assets.xcassets/AppIcon.appiconset/AppIcon.png +0 -0
- data/RubySolitaire/Assets.xcassets/AppIcon.appiconset/Contents.json +3 -87
- data/RubySolitaire/Base.lproj/Localizable.strings +6 -0
- data/RubySolitaire/Extensions.swift +5 -0
- data/RubySolitaire/GameView.swift +75 -13
- data/RubySolitaire/Helper.swift +70 -0
- data/RubySolitaire/MenuScreen.swift +141 -0
- data/RubySolitaire/RubySolitaireApp.swift +188 -1
- data/RubySolitaire/SafariView.swift +16 -0
- data/RubySolitaire/Strings.swift +48 -0
- data/RubySolitaire/ja.lproj/InfoPlist.strings +4 -0
- data/RubySolitaire/ja.lproj/Localizable.strings +6 -0
- data/VERSION +1 -1
- data/data/card.png +0 -0
- data/data/classicPSPWave.glsl +94 -0
- data/data/colorfulUnderwaterBubbles2.glsl +113 -0
- data/data/cosmic2.glsl +121 -0
- data/data/reflectiveHexes.glsl +219 -0
- data/fastlane/Fastfile +76 -0
- data/fastlane/metadata/copyright.txt +1 -0
- data/fastlane/metadata/en-US/apple_tv_privacy_policy.txt +1 -0
- data/fastlane/metadata/en-US/description.txt +5 -0
- data/fastlane/metadata/en-US/keywords.txt +1 -0
- data/fastlane/metadata/en-US/marketing_url.txt +1 -0
- data/fastlane/metadata/en-US/name.txt +1 -0
- data/fastlane/metadata/en-US/privacy_url.txt +1 -0
- data/fastlane/metadata/en-US/promotional_text.txt +1 -0
- data/fastlane/metadata/en-US/release_notes.txt +1 -0
- data/fastlane/metadata/en-US/subtitle.txt +1 -0
- data/fastlane/metadata/en-US/support_url.txt +1 -0
- data/fastlane/metadata/ja/apple_tv_privacy_policy.txt +1 -0
- data/fastlane/metadata/ja/description.txt +5 -0
- data/fastlane/metadata/ja/keywords.txt +1 -0
- data/fastlane/metadata/ja/marketing_url.txt +1 -0
- data/fastlane/metadata/ja/name.txt +1 -0
- data/fastlane/metadata/ja/privacy_url.txt +1 -0
- data/fastlane/metadata/ja/promotional_text.txt +1 -0
- data/fastlane/metadata/ja/release_notes.txt +1 -0
- data/fastlane/metadata/ja/subtitle.txt +1 -0
- data/fastlane/metadata/ja/support_url.txt +1 -0
- data/fastlane/metadata/primary_category.txt +1 -0
- data/fastlane/metadata/primary_first_sub_category.txt +1 -0
- data/fastlane/metadata/primary_second_sub_category.txt +1 -0
- data/fastlane/metadata/review_information/demo_password.txt +1 -0
- data/fastlane/metadata/review_information/demo_user.txt +1 -0
- data/fastlane/metadata/review_information/email_address.txt +1 -0
- data/fastlane/metadata/review_information/first_name.txt +0 -0
- data/fastlane/metadata/review_information/last_name.txt +0 -0
- data/fastlane/metadata/review_information/notes.txt +1 -0
- data/fastlane/metadata/review_information/phone_number.txt +0 -0
- data/fastlane/metadata/secondary_category.txt +1 -0
- data/fastlane/metadata/secondary_first_sub_category.txt +1 -0
- data/fastlane/metadata/secondary_second_sub_category.txt +1 -0
- data/lib/rubysketch/solitaire/background.rb +115 -12
- data/lib/rubysketch/solitaire/card.rb +10 -87
- data/lib/rubysketch/solitaire/common/animation.rb +34 -34
- data/lib/rubysketch/solitaire/common/button.rb +49 -19
- data/lib/rubysketch/solitaire/common/dialog.rb +78 -21
- data/lib/rubysketch/solitaire/common/scene.rb +15 -4
- data/lib/rubysketch/solitaire/common/settings.rb +15 -3
- data/lib/rubysketch/solitaire/common/timer.rb +2 -2
- data/lib/rubysketch/solitaire/common/transitions.rb +12 -6
- data/lib/rubysketch/solitaire/common/utils.rb +15 -0
- data/lib/rubysketch/solitaire/klondike.rb +382 -81
- data/lib/rubysketch/solitaire/places.rb +12 -102
- data/lib/rubysketch/solitaire/skin.rb +151 -0
- data/lib/rubysketch/solitaire.rb +33 -9
- data/main.rb +1 -0
- data/project.yml +85 -4
- metadata +55 -2
@@ -0,0 +1 @@
|
|
1
|
+
「宇宙ソリティア」で最高のソリティア体験をお楽しみください!鮮やかなグラフィック、シンプルな操作性、そして中毒性の高いゲームプレイがあなたを待っています。時間を忘れて、ストレスを解消しながらカードを並べましょう。ソリティア愛好家のための最適な選択です。
|
@@ -0,0 +1 @@
|
|
1
|
+
- 最初のベータバージョン
|
@@ -0,0 +1 @@
|
|
1
|
+
選べるカードデザイン、選べるゲーム背景
|
@@ -0,0 +1 @@
|
|
1
|
+
https://xord.org/rubysolitaire/
|
@@ -0,0 +1 @@
|
|
1
|
+
GAMES
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
xordog@gmail.com
|
File without changes
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
GAMES_CARD
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -1,34 +1,137 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
1
2
|
using RubySketch
|
2
3
|
|
3
4
|
|
4
5
|
class Background < Scene
|
5
6
|
|
6
|
-
|
7
|
+
TYPES = {
|
8
|
+
checker: {
|
9
|
+
name: 'Checker'
|
10
|
+
},
|
11
|
+
checker2: {
|
12
|
+
name: 'Checker (No Scroll)'
|
13
|
+
},
|
14
|
+
cosmic2: {
|
15
|
+
name: 'Cosmic 2',
|
16
|
+
author: 'huwb',
|
17
|
+
url: 'https://www.shadertoy.com/view/XllGzN'
|
18
|
+
},
|
19
|
+
classicPSPWave: {
|
20
|
+
name: 'Classic PSP Wave',
|
21
|
+
author: 'ParkingLotGames',
|
22
|
+
url: 'https://www.shadertoy.com/view/ddV3DK'
|
23
|
+
},
|
24
|
+
reflectiveHexes: {
|
25
|
+
name: 'Reflective hexes',
|
26
|
+
author: 'mrange',
|
27
|
+
url: 'https://www.shadertoy.com/view/ds2XRt'
|
28
|
+
},
|
29
|
+
colorfulUnderwaterBubbles2: {
|
30
|
+
name: 'Colorful underwater bubbles II',
|
31
|
+
author: 'mrange',
|
32
|
+
url: 'https://www.shadertoy.com/view/mlBSWc'
|
33
|
+
},
|
34
|
+
}
|
35
|
+
|
36
|
+
def initialize(type = nil)
|
7
37
|
super
|
8
|
-
@start
|
38
|
+
@start = now
|
39
|
+
@canvas = createGraphics width, height
|
40
|
+
set type || settings['background']&.intern|| types.first
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :type
|
44
|
+
|
45
|
+
def types()
|
46
|
+
TYPES.keys
|
47
|
+
end
|
48
|
+
|
49
|
+
def name()
|
50
|
+
TYPES[type][:name]
|
51
|
+
end
|
52
|
+
|
53
|
+
def author()
|
54
|
+
TYPES[type][:author]
|
55
|
+
end
|
56
|
+
|
57
|
+
def url()
|
58
|
+
TYPES[type][:url]
|
59
|
+
end
|
60
|
+
|
61
|
+
def nextType()
|
62
|
+
index = types.index(@type) || 0
|
63
|
+
types[(index + 1) % types.size]
|
64
|
+
end
|
65
|
+
|
66
|
+
def set(type)
|
67
|
+
type = types.first unless types.include?(type)
|
68
|
+
case type
|
69
|
+
when :checker, :checker2
|
70
|
+
@shader = createShader nil, checker
|
71
|
+
when :cosmic2
|
72
|
+
@shader = createShader nil, cosmic2
|
73
|
+
when :classicPSPWave
|
74
|
+
@shader = createShader nil, classicPSPWave
|
75
|
+
when :reflectiveHexes
|
76
|
+
@shader = createShader nil, reflectiveHexes
|
77
|
+
when :colorfulUnderwaterBubbles2
|
78
|
+
@shader = createShader nil, colorfulUnderwaterBubbles2
|
79
|
+
end
|
80
|
+
settings['background'] = @type = type
|
9
81
|
end
|
10
82
|
|
11
83
|
def draw()
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
84
|
+
@canvas.beginDraw do |g|
|
85
|
+
sh = @shader
|
86
|
+
case type
|
87
|
+
when :checker, :checker2
|
88
|
+
colors = skin.backgroundCheckerColors
|
89
|
+
sh.set :iTime, (type == :checker2 ? 0.0 : now - @start)
|
90
|
+
sh.set :color1, *colors[0].map {|n| n / 255.0}
|
91
|
+
sh.set :color2, *colors[1].map {|n| n / 255.0}
|
92
|
+
else
|
93
|
+
sh.set :iTime, now - @start
|
94
|
+
sh.set :iResolution, width, height
|
95
|
+
end
|
96
|
+
g.shader sh
|
97
|
+
g.translate 0, g.height
|
98
|
+
g.scale 1, -1
|
99
|
+
g.rect 0, 0, g.width, g.height
|
16
100
|
end
|
101
|
+
copy @canvas, 0, 0, @canvas.width, @canvas.height, 0, 0, width, height
|
17
102
|
end
|
18
103
|
|
19
104
|
private
|
20
105
|
|
21
106
|
def checker()
|
22
|
-
|
107
|
+
<<~END
|
23
108
|
varying vec4 vertTexCoord;
|
24
|
-
uniform float
|
109
|
+
uniform float iTime;
|
110
|
+
uniform vec4 color1;
|
111
|
+
uniform vec4 color2;
|
25
112
|
void main() {
|
26
|
-
float t = mod(
|
27
|
-
float x = mod(vertTexCoord.x + t, 32.
|
28
|
-
float y = mod(vertTexCoord.y + t, 32.
|
29
|
-
gl_FragColor = x != y ?
|
113
|
+
float t = mod(iTime, 32.) * 8.;
|
114
|
+
float x = mod( vertTexCoord.x + t, 32.) < 16. ? 1. : 0.;
|
115
|
+
float y = mod(-vertTexCoord.y + t, 32.) < 16. ? 1. : 0.;
|
116
|
+
gl_FragColor = x != y ? color1 : color2;
|
30
117
|
}
|
31
118
|
END
|
32
119
|
end
|
33
120
|
|
121
|
+
def cosmic2()
|
122
|
+
File.read(dataPath 'cosmic2.glsl').gsub('iMouse', 'vec2(0.)')
|
123
|
+
end
|
124
|
+
|
125
|
+
def classicPSPWave()
|
126
|
+
File.read(dataPath 'classicPSPWave.glsl')
|
127
|
+
end
|
128
|
+
|
129
|
+
def reflectiveHexes()
|
130
|
+
File.read(dataPath 'reflectiveHexes.glsl')
|
131
|
+
end
|
132
|
+
|
133
|
+
def colorfulUnderwaterBubbles2()
|
134
|
+
File.read(dataPath 'colorfulUnderwaterBubbles2.glsl')
|
135
|
+
end
|
136
|
+
|
34
137
|
end# Background
|
@@ -90,7 +90,7 @@ class Card
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def color()
|
93
|
-
|
93
|
+
skin.markColor mark
|
94
94
|
end
|
95
95
|
|
96
96
|
def count()
|
@@ -111,11 +111,13 @@ class Card
|
|
111
111
|
end
|
112
112
|
|
113
113
|
def sprite()
|
114
|
-
@sprite ||= Sprite.new(
|
114
|
+
@sprite ||= Sprite.new(
|
115
|
+
0, 0, *skin.cardSpriteSize, image: skin.closedImage
|
116
|
+
).tap do |sp|
|
115
117
|
sp.pivot = [rand, rand]
|
116
118
|
sp.angle = rand -5.0..5.0
|
117
119
|
sp.update do
|
118
|
-
sp.image = @open > 90 ? openedImage : closedImage
|
120
|
+
sp.image = @open > 90 ? skin.openedImage(mark, number) : skin.closedImage
|
119
121
|
end
|
120
122
|
sp.draw do |&draw|
|
121
123
|
push do
|
@@ -134,12 +136,17 @@ class Card
|
|
134
136
|
image sp.image, 0, 0, w, h
|
135
137
|
end
|
136
138
|
sp.mousePressed do
|
139
|
+
next if $dragging
|
140
|
+
$dragging = self
|
137
141
|
mousePressed sp.mouseX, sp.mouseY
|
138
142
|
end
|
139
143
|
sp.mouseReleased do
|
144
|
+
next unless $dragging.object_id == self.object_id
|
140
145
|
mouseReleased sp.mouseX, sp.mouseY, sp.clickCount
|
146
|
+
$dragging = nil
|
141
147
|
end
|
142
148
|
sp.mouseDragged do
|
149
|
+
next unless $dragging.object_id == self.object_id
|
143
150
|
x, y = sp.mouseX, sp.mouseY
|
144
151
|
mouseDragged x, y, x - sp.pmouseX, y - sp.pmouseY
|
145
152
|
end
|
@@ -169,88 +176,4 @@ class Card
|
|
169
176
|
self.pos += createVector x - @startPos.x, y - @startPos.y if @startPos
|
170
177
|
end
|
171
178
|
|
172
|
-
def openedImage()
|
173
|
-
@openedImage ||= createGraphics(*self.class.cardSize).tap do |g|
|
174
|
-
c, w, h, m = self.class, g.width, g.height, 16# margin
|
175
|
-
image = c.cardImage
|
176
|
-
nx, ny, nw, nh = c.numberRect number
|
177
|
-
mx, my, mw, mh = c.markRect mark
|
178
|
-
mnh = m + nh
|
179
|
-
mxx, myy = (w - mw) / 2, mnh + ((h - mnh) - mh) / 2
|
180
|
-
g.beginDraw
|
181
|
-
g.angleMode DEGREES
|
182
|
-
g.translate w / 2, h / 2
|
183
|
-
g.rotate 180
|
184
|
-
g.translate -w / 2, -h / 2
|
185
|
-
g.copy image, 896, 0, w, h, 0, 0, w, h
|
186
|
-
g.tint *c.markColor(mark)
|
187
|
-
g.copy image, nx, ny, nw, nh, m, m, nw, nh
|
188
|
-
g.copy image, mx, my, mw, mh, mxx, myy, mw, mh
|
189
|
-
g.endDraw
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
def closedImage()
|
194
|
-
self.class.closedImages[3]
|
195
|
-
end
|
196
|
-
|
197
|
-
def spriteSize()
|
198
|
-
self.class.spriteSize
|
199
|
-
end
|
200
|
-
|
201
|
-
def self.closedImages()
|
202
|
-
@closedImages ||= (0..3).map {|n| n * 256}.map do |x|
|
203
|
-
createGraphics(*cardSize).tap do |g|
|
204
|
-
w, h = g.width, g.height
|
205
|
-
g.beginDraw
|
206
|
-
g.copy cardImage, x, 256, w, h, 0, 0, w, h
|
207
|
-
g.endDraw
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
def self.cardImage()
|
213
|
-
@cardImage ||= loadImage dataPath 'card.png'
|
214
|
-
end
|
215
|
-
|
216
|
-
def self.cardSize()
|
217
|
-
[164, 252]
|
218
|
-
end
|
219
|
-
|
220
|
-
def self.spriteSize()
|
221
|
-
@spriteSize ||= cardSize.then do |cw, ch|
|
222
|
-
ncolumns = 7
|
223
|
-
size = [width, height].min
|
224
|
-
cardWidth = (size - margin * (ncolumns + 1)) / ncolumns
|
225
|
-
[cardWidth, cardWidth * (ch.to_f / cw.to_f)]
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
def self.margin()
|
230
|
-
@marin ||= [width, height].min * 0.02
|
231
|
-
end
|
232
|
-
|
233
|
-
def self.markRect(mark)
|
234
|
-
w = h = 128
|
235
|
-
[MARKS.index(mark) * w, 0, w, h]
|
236
|
-
end
|
237
|
-
|
238
|
-
def self.numberRect(number)
|
239
|
-
w = h = 64
|
240
|
-
[(number - 1) * w, 128, w, h]
|
241
|
-
end
|
242
|
-
|
243
|
-
def self.markColor(mark)
|
244
|
-
MARKS[0, 2].include?(mark) ? [255, 111, 61] : [62, 79, 60]
|
245
|
-
end
|
246
|
-
|
247
|
-
def __find_or_last_and_prev(card = nil)
|
248
|
-
prev, it = nil, self
|
249
|
-
while it.next
|
250
|
-
break if it == card
|
251
|
-
prev, it = it, it.next
|
252
|
-
end
|
253
|
-
return it, prev
|
254
|
-
end
|
255
|
-
|
256
179
|
end# Card
|
@@ -2,40 +2,40 @@ using RubySketch
|
|
2
2
|
|
3
3
|
|
4
4
|
EASINGS = {
|
5
|
-
linear: lambda {
|
6
|
-
sineIn: lambda {
|
7
|
-
sineOut: lambda {
|
8
|
-
|
9
|
-
quadIn: lambda {
|
10
|
-
cubicIn: lambda {
|
11
|
-
quartIn: lambda {
|
12
|
-
quintIn: lambda {
|
13
|
-
circIn: lambda {
|
14
|
-
backIn: lambda {
|
15
|
-
expoIn: lambda {
|
16
|
-
elasticIn: lambda {
|
17
|
-
bounceIn: lambda {
|
18
|
-
|
19
|
-
quadOut: lambda {
|
20
|
-
cubicOut: lambda {
|
21
|
-
quartOut: lambda {
|
22
|
-
quintOut: lambda {
|
23
|
-
circOut: lambda {
|
24
|
-
backOut: lambda {
|
25
|
-
expoOut: lambda {
|
26
|
-
elasticOut: lambda {
|
27
|
-
bounceOut: lambda {
|
28
|
-
|
29
|
-
sineInOut: lambda {
|
30
|
-
quadInOut: lambda {
|
31
|
-
cubicInOut: lambda {
|
32
|
-
quartInOut: lambda {
|
33
|
-
quintInOut: lambda {
|
34
|
-
circInOut: lambda {
|
35
|
-
backInOut: lambda {
|
36
|
-
expoInOut: lambda {
|
37
|
-
elasticInOut: lambda {
|
38
|
-
bounceInOut: lambda {
|
5
|
+
linear: lambda {|x| x},
|
6
|
+
sineIn: lambda {|x| 1.0 - Math.cos(x * Math::PI / 2)},
|
7
|
+
sineOut: lambda {|x| Math.sin(x * Math::PI / 2)},
|
8
|
+
|
9
|
+
quadIn: lambda {|x| quadIn x},
|
10
|
+
cubicIn: lambda {|x| cubicIn x},
|
11
|
+
quartIn: lambda {|x| quartIn x},
|
12
|
+
quintIn: lambda {|x| quintIn x},
|
13
|
+
circIn: lambda {|x| circIn x},
|
14
|
+
backIn: lambda {|x| backIn x},
|
15
|
+
expoIn: lambda {|x| expoIn x},
|
16
|
+
elasticIn: lambda {|x| elasticIn x},
|
17
|
+
bounceIn: lambda {|x| 1.0 - bounceOut(1.0 - x)},
|
18
|
+
|
19
|
+
quadOut: lambda {|x| 1.0 - quadIn(1.0 - x)},
|
20
|
+
cubicOut: lambda {|x| 1.0 - cubicIn(1.0 - x)},
|
21
|
+
quartOut: lambda {|x| 1.0 - quartIn(1.0 - x)},
|
22
|
+
quintOut: lambda {|x| 1.0 - quintIn(1.0 - x)},
|
23
|
+
circOut: lambda {|x| 1.0 - curcIn(1.0 - x)},
|
24
|
+
backOut: lambda {|x| 1.0 - backIn(1.0 - x)},
|
25
|
+
expoOut: lambda {|x| 1.0 - expoIn(1.0 - x)},
|
26
|
+
elasticOut: lambda {|x| 1.0 - elasticIn(1.0 - x)},
|
27
|
+
bounceOut: lambda {|x| bounceOut x},
|
28
|
+
|
29
|
+
sineInOut: lambda {|x| x < 0.5 ? sineIn(x) : sineOut(x)},
|
30
|
+
quadInOut: lambda {|x| x < 0.5 ? quadIn(x) : quadOut(x)},
|
31
|
+
cubicInOut: lambda {|x| x < 0.5 ? cubicIn(x) : cubicOut(x)},
|
32
|
+
quartInOut: lambda {|x| x < 0.5 ? quartIn(x) : quartOut(x)},
|
33
|
+
quintInOut: lambda {|x| x < 0.5 ? quintIn(x) : quintOut(x)},
|
34
|
+
circInOut: lambda {|x| x < 0.5 ? circIn(x) : circOut(x)},
|
35
|
+
backInOut: lambda {|x| x < 0.5 ? backIn(x) : backOut(x)},
|
36
|
+
expoInOut: lambda {|x| x < 0.5 ? expoIn(x) : expoOut(x)},
|
37
|
+
elasticInOut: lambda {|x| x < 0.5 ? elasticIn(x) : elasticOut(x)},
|
38
|
+
bounceInOut: lambda {|x| x < 0.5 ? bounceIn(x) : bounceOut(x)}
|
39
39
|
}
|
40
40
|
|
41
41
|
def quadIn(x)
|
@@ -6,10 +6,14 @@ class Button < Sprite
|
|
6
6
|
include CanDisable
|
7
7
|
|
8
8
|
def initialize(
|
9
|
-
label, *args,
|
9
|
+
label = nil, *args,
|
10
|
+
icon: nil, rgb: nil, width: 1, fontSize: 24, round: 5, **kwargs,
|
11
|
+
&block)
|
12
|
+
|
13
|
+
raise if !label && !icon
|
10
14
|
|
11
15
|
super 0, 0, 44 * width, 44, *args, **kwargs, &block
|
12
|
-
@label, @rgb, @fontSize, @round = label,
|
16
|
+
@label, @icon, @rgb, @fontSize, @round = label, icon, rgb, fontSize, round
|
13
17
|
@click = nil
|
14
18
|
setup
|
15
19
|
end
|
@@ -23,31 +27,53 @@ class Button < Sprite
|
|
23
27
|
|
24
28
|
def setup()
|
25
29
|
pressing = false
|
26
|
-
|
27
|
-
|
30
|
+
|
31
|
+
mousePressed do
|
32
|
+
next if $dragging
|
33
|
+
$dragging = self
|
34
|
+
pressing = true
|
35
|
+
end
|
36
|
+
|
37
|
+
mouseReleased do
|
38
|
+
next unless $dragging.object_id == self.object_id
|
39
|
+
pressing = false
|
40
|
+
if includeMouse?
|
41
|
+
if enabled?
|
42
|
+
@click&.call
|
43
|
+
else
|
44
|
+
shake
|
45
|
+
end
|
46
|
+
sound.play gain: 0.5
|
47
|
+
end
|
48
|
+
$dragging = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
mouseDragged do
|
52
|
+
next unless $dragging.object_id == self.object_id
|
53
|
+
pressing = includeMouse?
|
54
|
+
end
|
28
55
|
|
29
56
|
draw do
|
30
57
|
offset = 5
|
58
|
+
light = [@rgb || skin.buttonColor].flatten
|
59
|
+
dark = light.map {|n| n - 32}
|
31
60
|
y = pressing ? (offset - (enabled? ? 2 : 3.5)) : 0
|
32
61
|
h = self.h - y
|
33
62
|
offset -= y
|
34
|
-
fill
|
63
|
+
fill *dark
|
35
64
|
rect 0, y, w, h, *@round
|
36
|
-
fill
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
@
|
47
|
-
else
|
48
|
-
shake
|
65
|
+
fill *light
|
66
|
+
h -= offset
|
67
|
+
rect 0, y, w, h, *@round
|
68
|
+
fill *(enabled? ? [255] : dark)
|
69
|
+
if @label
|
70
|
+
textAlign CENTER, CENTER
|
71
|
+
textSize @fontSize
|
72
|
+
text @label, 0, y, w, h
|
73
|
+
elsif @icon
|
74
|
+
imageMode CENTER
|
75
|
+
drawImage @icon, w / 2, y + h / 2, @icon.width / 2, @icon.height / 2
|
49
76
|
end
|
50
|
-
sound.play gain: 0.5
|
51
77
|
end
|
52
78
|
end
|
53
79
|
|
@@ -64,4 +90,8 @@ class Button < Sprite
|
|
64
90
|
@sound ||= loadSound dataPath 'button.mp3'
|
65
91
|
end
|
66
92
|
|
93
|
+
def includeMouse?()
|
94
|
+
(0...width).include?(mouseX) && (0...height).include?(mouseY)
|
95
|
+
end
|
96
|
+
|
67
97
|
end# Button
|
@@ -3,42 +3,66 @@ using RubySketch
|
|
3
3
|
|
4
4
|
class Dialog < Scene
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
class Label < Sprite
|
7
|
+
attr_accessor :label
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(background: 0, alpha: 100, z: 1000, &block)
|
8
11
|
@background, @alpha = background, 0
|
12
|
+
@elements = []
|
13
|
+
super
|
9
14
|
overlay.z = z
|
15
|
+
group :vertical, &block if block
|
10
16
|
animate 0.2 do |t|
|
11
17
|
@alpha = alpha * t
|
12
18
|
end
|
13
19
|
end
|
14
20
|
|
21
|
+
def group(flow = :horizontal, space: nil, &block)
|
22
|
+
old, @group = @group, []
|
23
|
+
block.call self
|
24
|
+
ensure
|
25
|
+
(old || @elements).push({
|
26
|
+
elements: @group,
|
27
|
+
flow: flow,
|
28
|
+
space: space || MARGIN
|
29
|
+
})
|
30
|
+
@group = old
|
31
|
+
updateLayout
|
32
|
+
end
|
33
|
+
|
15
34
|
def addElement(sprite)
|
16
|
-
elements.push sprite
|
35
|
+
(@group || @elements).push sprite
|
36
|
+
sprite.z = overlay.z
|
17
37
|
addSprite sprite if active?
|
18
38
|
updateLayout
|
39
|
+
sprite
|
19
40
|
end
|
20
41
|
|
21
|
-
def addLabel(label, rgb: [255], fontSize: 24, align: CENTER)
|
42
|
+
def addLabel(label, rgb: [255], alpha: nil, fontSize: 24, align: CENTER, &block)
|
22
43
|
bounds = textFont.textBounds label, 0, 0, fontSize
|
23
|
-
addElement
|
24
|
-
sp.
|
44
|
+
addElement Label.new(0, 0, width - MARGIN * 2, bounds.h).tap {|sp|
|
45
|
+
sp.label = label
|
25
46
|
sp.draw do
|
47
|
+
r, g, b, a = skin.translucentBackgroundColor
|
48
|
+
fill r, g, b, alpha || (a * 3)
|
49
|
+
rect 0, -MARGIN / 2, sp.w, sp.h + MARGIN
|
26
50
|
textAlign align, CENTER
|
27
51
|
textSize fontSize
|
28
52
|
fill *rgb
|
29
|
-
text label, 0, 0, sp.w, sp.h
|
53
|
+
text sp.label, 0, 0, sp.w, sp.h
|
30
54
|
end
|
55
|
+
sp.mouseClicked &block
|
31
56
|
}
|
32
57
|
end
|
33
58
|
|
34
|
-
def addButton(
|
35
|
-
addElement Button.new(
|
36
|
-
b.z = overlay.z
|
59
|
+
def addButton(*args, **kwargs, &block)
|
60
|
+
addElement Button.new(*args, **kwargs).tap {|b|
|
37
61
|
b.clicked &block
|
38
62
|
}
|
39
63
|
end
|
40
64
|
|
41
|
-
def addSpace(height)
|
65
|
+
def addSpace(height = 0)
|
42
66
|
addElement Sprite.new(0, 0, 1, height).tap {|sp|
|
43
67
|
sp.draw {}
|
44
68
|
}
|
@@ -53,18 +77,30 @@ class Dialog < Scene
|
|
53
77
|
end
|
54
78
|
|
55
79
|
def elements()
|
56
|
-
|
80
|
+
f = -> es {es.map {|e| ((e in {elements:})) ? f[elements] : e}}
|
81
|
+
f.call(@elements).flatten
|
57
82
|
end
|
58
83
|
|
59
84
|
def draw()
|
60
|
-
sprite overlay
|
85
|
+
sprite overlay
|
61
86
|
super
|
87
|
+
sprite *elements
|
62
88
|
end
|
63
89
|
|
64
90
|
def resized(w, h)
|
65
91
|
updateLayout
|
66
92
|
end
|
67
93
|
|
94
|
+
def activated()
|
95
|
+
super
|
96
|
+
parent.pause
|
97
|
+
end
|
98
|
+
|
99
|
+
def deactivated()
|
100
|
+
parent.resume
|
101
|
+
super
|
102
|
+
end
|
103
|
+
|
68
104
|
private
|
69
105
|
|
70
106
|
MARGIN = 10
|
@@ -84,19 +120,40 @@ class Dialog < Scene
|
|
84
120
|
|
85
121
|
def cancelButton()
|
86
122
|
@cancelButton ||= Button.new('CLOSE', width: 3, fontSize: 28).tap do |sp|
|
87
|
-
sp.z = overlay.z
|
88
123
|
sp.clicked {close}
|
89
124
|
end
|
90
125
|
end
|
91
126
|
|
92
127
|
def updateLayout()
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
128
|
+
element = {elements: @elements, flow: :vertical, space: MARGIN}
|
129
|
+
w, h = getSize element
|
130
|
+
setPosition element, (width - w) / 2, (height - h) / 2, w, h
|
131
|
+
end
|
132
|
+
|
133
|
+
def getSize(element)
|
134
|
+
if element in {elements:, flow:, space:}
|
135
|
+
v = flow == :vertical
|
136
|
+
sizes = elements.map {|e| getSize e}
|
137
|
+
sum = sizes.map {|size| size[v ? 1 : 0]}.reduce {|a, b| a + space + b} || 0
|
138
|
+
max = sizes.map {|size| size[v ? 0 : 1]}.max || 0
|
139
|
+
v ? [max, sum] : [sum, max]
|
140
|
+
else
|
141
|
+
[element.w, element.h]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def setPosition(element, x, y, w, h)
|
146
|
+
if element in {elements:, flow:, space:}
|
147
|
+
v = flow == :vertical
|
148
|
+
elements.each do |e|
|
149
|
+
ew, eh = getSize e
|
150
|
+
ex, ey = v ? [x + (w - ew) / 2, y] : [x, y + (h - eh) / 2]
|
151
|
+
setPosition e, ex, ey, ew, eh
|
152
|
+
x += ew + space if !v
|
153
|
+
y += eh + space if v
|
154
|
+
end
|
155
|
+
else
|
156
|
+
element.x, element.y = x, y
|
100
157
|
end
|
101
158
|
end
|
102
159
|
|