rubysketch-solitaire 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.bundle/config +2 -0
- data/.github/workflows/release-gem.yml +62 -0
- data/.github/workflows/test.yml +23 -0
- data/.github/workflows/utils.rb +56 -0
- data/.gitignore +11 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +284 -0
- data/LICENSE +21 -0
- data/Podfile +31 -0
- data/Podfile.lock +59 -0
- data/README.md +21 -0
- data/Rakefile +100 -0
- data/RubySolitaire/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
- data/RubySolitaire/Assets.xcassets/AppIcon.appiconset/Contents.json +98 -0
- data/RubySolitaire/Assets.xcassets/Contents.json +6 -0
- data/RubySolitaire/BridgingHeader.h +10 -0
- data/RubySolitaire/GameView.swift +47 -0
- data/RubySolitaire/Preview Content/Preview Assets.xcassets/Contents.json +6 -0
- data/RubySolitaire/RubySolitaireApp.swift +10 -0
- data/RubySolitaireTests/RubySolitaireTests.swift +28 -0
- data/RubySolitaireUITests/RubySolitaireUITests.swift +35 -0
- data/RubySolitaireUITests/RubySolitaireUITestsLaunchTests.swift +25 -0
- data/VERSION +1 -0
- data/data/button.mp3 +0 -0
- data/data/card.png +0 -0
- data/data/deal1.mp3 +0 -0
- data/data/deal2.mp3 +0 -0
- data/data/deal3.mp3 +0 -0
- data/data/flip.mp3 +0 -0
- data/data/noop.mp3 +0 -0
- data/lib/rubysketch/solitaire/background.rb +34 -0
- data/lib/rubysketch/solitaire/card.rb +256 -0
- data/lib/rubysketch/solitaire/common/animation.rb +116 -0
- data/lib/rubysketch/solitaire/common/button.rb +67 -0
- data/lib/rubysketch/solitaire/common/dialog.rb +103 -0
- data/lib/rubysketch/solitaire/common/history.rb +94 -0
- data/lib/rubysketch/solitaire/common/particle.rb +71 -0
- data/lib/rubysketch/solitaire/common/scene.rb +128 -0
- data/lib/rubysketch/solitaire/common/score.rb +37 -0
- data/lib/rubysketch/solitaire/common/settings.rb +31 -0
- data/lib/rubysketch/solitaire/common/shake.rb +48 -0
- data/lib/rubysketch/solitaire/common/sound.rb +6 -0
- data/lib/rubysketch/solitaire/common/timer.rb +35 -0
- data/lib/rubysketch/solitaire/common/transitions.rb +149 -0
- data/lib/rubysketch/solitaire/common/utils.rb +89 -0
- data/lib/rubysketch/solitaire/extension.rb +25 -0
- data/lib/rubysketch/solitaire/klondike.rb +676 -0
- data/lib/rubysketch/solitaire/places.rb +177 -0
- data/lib/rubysketch/solitaire/start.rb +19 -0
- data/lib/rubysketch/solitaire.rb +80 -0
- data/main.rb +1 -0
- data/project.yml +91 -0
- data/solitaire.gemspec +28 -0
- metadata +137 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
$timers = {}
|
2
|
+
|
3
|
+
def startTimer(name = unique, seconds, &block)
|
4
|
+
$timers[name] = [now + seconds, block]
|
5
|
+
name
|
6
|
+
end
|
7
|
+
|
8
|
+
def startInterval(name = unique, seconds, now: false, &block)
|
9
|
+
block.call if now
|
10
|
+
startTimer name, seconds do
|
11
|
+
block.call
|
12
|
+
startInterval name, seconds, &block
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def stopTimer(name)
|
17
|
+
$timers.delete name
|
18
|
+
end
|
19
|
+
|
20
|
+
def getTimer(name)
|
21
|
+
$timers[name]
|
22
|
+
end
|
23
|
+
|
24
|
+
def delay(&block)
|
25
|
+
startTimer 0, &block
|
26
|
+
end
|
27
|
+
|
28
|
+
def fireTimers()
|
29
|
+
now_ = now
|
30
|
+
blocks = []
|
31
|
+
$timers.delete_if do |_, (time, block)|
|
32
|
+
(now_ >= time).tap { blocks.push block if _1 }
|
33
|
+
end
|
34
|
+
blocks.each { _1.call }
|
35
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
using RubySketch
|
2
|
+
|
3
|
+
|
4
|
+
class TransitionEffect < Scene
|
5
|
+
|
6
|
+
def initialize(
|
7
|
+
nextScene, sec: 1,
|
8
|
+
secOut: nil, secIn: nil,
|
9
|
+
easeOut: :expoOut, easeIn: :expoIn,
|
10
|
+
&block)
|
11
|
+
|
12
|
+
super()
|
13
|
+
@nextScene, @easeOut, @easeIn = nextScene, easeOut, easeIn
|
14
|
+
@secOut = secOut || sec / 2.0
|
15
|
+
@secIn = secIn || sec / 2.0
|
16
|
+
@phase = :out
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :phase
|
20
|
+
|
21
|
+
def effect(t)
|
22
|
+
end
|
23
|
+
|
24
|
+
def activated()
|
25
|
+
super
|
26
|
+
start do
|
27
|
+
case @phase
|
28
|
+
when :out
|
29
|
+
pa = parent
|
30
|
+
pa.remove self
|
31
|
+
@phase = :in
|
32
|
+
@nextScene.add self
|
33
|
+
pa.transition @nextScene
|
34
|
+
when :in
|
35
|
+
parent.remove self
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def start(&block)
|
43
|
+
sec = out? ? @secOut : @secIn
|
44
|
+
ease = out? ? @easeOut : @easeIn
|
45
|
+
animate sec, ease: ease do |t, finished|
|
46
|
+
effect (out? ? t : 1.0 - t)
|
47
|
+
block.call if finished
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def out?()
|
52
|
+
@phase == :out
|
53
|
+
end
|
54
|
+
|
55
|
+
end# TransitionEffect
|
56
|
+
|
57
|
+
|
58
|
+
class Fade < TransitionEffect
|
59
|
+
|
60
|
+
def initialize(*args, rgb: 0, **kwargs, &block)
|
61
|
+
super(*args, easeIn: :expoOut, **kwargs)
|
62
|
+
@rgb, @alpha = rgb, 0
|
63
|
+
end
|
64
|
+
|
65
|
+
def effect(t)
|
66
|
+
@alpha = 255 * t
|
67
|
+
end
|
68
|
+
|
69
|
+
def draw()
|
70
|
+
super
|
71
|
+
fill *@rgb, @alpha
|
72
|
+
noStroke
|
73
|
+
rect 0, 0, width, height
|
74
|
+
end
|
75
|
+
|
76
|
+
end# Fade
|
77
|
+
|
78
|
+
|
79
|
+
class Curtain < TransitionEffect
|
80
|
+
|
81
|
+
def initialize(*args, rgb: 0, **kwargs, &block)
|
82
|
+
super(*args, easeIn: :expoOut, **kwargs)
|
83
|
+
@rgb = rgb
|
84
|
+
@y = @h = 0
|
85
|
+
end
|
86
|
+
|
87
|
+
def effect(t)
|
88
|
+
@y, @h =
|
89
|
+
case phase
|
90
|
+
when :out then [height * (1.0 - t), height]
|
91
|
+
when :in then [0, height * t]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def draw()
|
96
|
+
super
|
97
|
+
fill *@rgb
|
98
|
+
noStroke
|
99
|
+
rect 0, @y, width, @h
|
100
|
+
end
|
101
|
+
|
102
|
+
end# Fade
|
103
|
+
|
104
|
+
|
105
|
+
class Pixelate < TransitionEffect
|
106
|
+
|
107
|
+
def initialize(*args, **kwargs, &block)
|
108
|
+
super *args, sec: 1, easeOut: :cubicOut, easeIn: :cubicIn, **kwargs, &block
|
109
|
+
end
|
110
|
+
|
111
|
+
def activated()
|
112
|
+
super
|
113
|
+
filter pixelate
|
114
|
+
end
|
115
|
+
|
116
|
+
def deactivated()
|
117
|
+
super
|
118
|
+
filter nil
|
119
|
+
end
|
120
|
+
|
121
|
+
def effect(t)
|
122
|
+
pixelate.set :resolution, width, height
|
123
|
+
pixelate.set :pixelateSize, map(t, 0.0, 1.0, 1, 32)
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def pixelate()
|
129
|
+
@checker ||= createShader nil, <<~END
|
130
|
+
uniform sampler2D texMap;
|
131
|
+
uniform vec3 texMax;
|
132
|
+
uniform vec2 resolution;
|
133
|
+
uniform float pixelateSize;
|
134
|
+
varying vec4 vertTexCoord;
|
135
|
+
varying vec4 vertColor;
|
136
|
+
void main() {
|
137
|
+
vec2 r = resolution;
|
138
|
+
float ps = pixelateSize;
|
139
|
+
vec2 coord = (floor(vertTexCoord.xy * r / ps) + 0.5) * ps / r;
|
140
|
+
if (coord.x >= texMax.x) coord.x = texMax.x - 1. / r.x;
|
141
|
+
if (coord.y >= texMax.y) coord.y = texMax.y - 1. / r.y;
|
142
|
+
|
143
|
+
vec4 col = texture2D(texMap, coord);
|
144
|
+
gl_FragColor = vec4(col.rgb, 1.) * vertColor;
|
145
|
+
}
|
146
|
+
END
|
147
|
+
end
|
148
|
+
|
149
|
+
end# Pixelate
|
@@ -0,0 +1,89 @@
|
|
1
|
+
def now()
|
2
|
+
Time.now.to_f
|
3
|
+
end
|
4
|
+
|
5
|
+
def unique()
|
6
|
+
Object.new.object_id
|
7
|
+
end
|
8
|
+
|
9
|
+
def dataPath(path)
|
10
|
+
File.expand_path "../../../../data/#{path}", __dir__
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
module Processing
|
15
|
+
class Vector
|
16
|
+
def xy()
|
17
|
+
self.class.new x, y
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
module CanDisable
|
24
|
+
|
25
|
+
def initialize(*a, **k, &b)
|
26
|
+
super
|
27
|
+
@enabled = true
|
28
|
+
end
|
29
|
+
|
30
|
+
def enable(state = true)
|
31
|
+
return if state == @enabled
|
32
|
+
@enabled = state
|
33
|
+
@enabled ? enabled : disabled
|
34
|
+
end
|
35
|
+
|
36
|
+
def disable(&block)
|
37
|
+
old = enabled?
|
38
|
+
enable false
|
39
|
+
if block
|
40
|
+
begin
|
41
|
+
block.call
|
42
|
+
ensure
|
43
|
+
enable old
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def enabled?()
|
49
|
+
@enabled
|
50
|
+
end
|
51
|
+
|
52
|
+
def disabled?()
|
53
|
+
!enabled?
|
54
|
+
end
|
55
|
+
|
56
|
+
def enabled()
|
57
|
+
end
|
58
|
+
|
59
|
+
def disabled()
|
60
|
+
end
|
61
|
+
|
62
|
+
end# CanDisable
|
63
|
+
|
64
|
+
|
65
|
+
module HasSprite
|
66
|
+
|
67
|
+
extend Forwardable
|
68
|
+
|
69
|
+
def_delegators :sprite,
|
70
|
+
:pos, :pos=, :x, :x=, :y, :y=, :z, :z=, :center, :center=,
|
71
|
+
:left, :left=, :top, :top=, :right, :right=, :bottom, :bottom=,
|
72
|
+
:size, :width, :width=, :height, :height=, :depth, :w, :w=, :h, :h=, :d,
|
73
|
+
:angle, :angle=
|
74
|
+
|
75
|
+
alias l left
|
76
|
+
alias l= left=
|
77
|
+
alias t top
|
78
|
+
alias t= top=
|
79
|
+
alias r right
|
80
|
+
alias r= right=
|
81
|
+
alias b bottom
|
82
|
+
alias b= bottom=
|
83
|
+
|
84
|
+
def hit?(x, y)
|
85
|
+
s = sprite
|
86
|
+
s.x <= x && x < (s.x + s.w) && s.y <= y && y < (s.y + s.h)
|
87
|
+
end
|
88
|
+
|
89
|
+
end# HasSprite
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RubySketch
|
2
|
+
|
3
|
+
module Solitaire
|
4
|
+
|
5
|
+
module Extension
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def name()
|
10
|
+
super.split('::')[-2]
|
11
|
+
end
|
12
|
+
|
13
|
+
def version()
|
14
|
+
File.read(root_dir 'VERSION')[/[\d\.]+/]
|
15
|
+
end
|
16
|
+
|
17
|
+
def root_dir(path = '')
|
18
|
+
File.expand_path "../../../#{path}", __dir__
|
19
|
+
end
|
20
|
+
|
21
|
+
end# Extension
|
22
|
+
|
23
|
+
end# Solitaire
|
24
|
+
|
25
|
+
end# RubySketch
|