yeah 0.2.2 → 0.3.3
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/LICENSE.txt +1 -1
- data/README.md +52 -20
- data/bin/yeah +30 -0
- data/lib/yeah.rb +6 -9
- data/lib/yeah/_platform/asset.rb +24 -0
- data/lib/yeah/_platform/display.rb +181 -0
- data/lib/yeah/_platform/image.rb +16 -0
- data/lib/yeah/_platform/keyboard.rb +37 -0
- data/lib/yeah/_platform/mouse.rb +30 -0
- data/lib/yeah/_platform/sound.rb +15 -0
- data/lib/yeah/_platform/ticker.rb +21 -0
- data/lib/yeah/_template/Gemfile +4 -0
- data/lib/yeah/_template/code/code.rb +4 -0
- data/lib/yeah/_template/code/game.rb +7 -0
- data/lib/yeah/_web.rb +9 -0
- data/lib/yeah/color.rb +45 -13
- data/lib/yeah/constants.rb +6 -0
- data/lib/yeah/game.rb +89 -41
- data/lib/yeah/vector.rb +122 -99
- data/lib/yeah/version.rb +3 -0
- data/lib/yeah/web/dependencies.rb +2 -0
- data/lib/yeah/web/runner.html.erb +61 -0
- data/lib/yeah/web/server.rb +60 -0
- data/lib/yeah/web/setup.rb +5 -0
- data/lib/yeah/web/start.rb +1 -0
- data/opal/yeah/web.rb +8 -0
- data/opal/yeah/web/asset.opal +38 -0
- data/opal/yeah/web/constants.opal +5 -0
- data/opal/yeah/web/display.opal +244 -0
- data/opal/yeah/web/image.opal +23 -0
- data/opal/yeah/web/keyboard.opal +139 -0
- data/opal/yeah/web/mouse.opal +58 -0
- data/opal/yeah/web/sound.opal +19 -0
- data/opal/yeah/web/ticker.opal +39 -0
- metadata +111 -19
- data/CHANGELOG.md +0 -28
- data/lib/monkey/numeric.rb +0 -6
- data/lib/yeah/basic_physics.rb +0 -11
- data/lib/yeah/desktop.rb +0 -72
- data/lib/yeah/entity.rb +0 -137
- data/lib/yeah/map.rb +0 -40
- data/lib/yeah/rectangle.rb +0 -21
- data/lib/yeah/surface.rb +0 -66
data/lib/yeah/version.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Game</title>
|
5
|
+
|
6
|
+
<style>
|
7
|
+
body {
|
8
|
+
background: black;
|
9
|
+
margin: 0;
|
10
|
+
}
|
11
|
+
|
12
|
+
.center-content {
|
13
|
+
/* Internet Explorer 10 */
|
14
|
+
display: -ms-flexbox;
|
15
|
+
-ms-flex-pack: center;
|
16
|
+
-ms-flex-align: center;
|
17
|
+
/* Firefox */
|
18
|
+
display: -moz-box;
|
19
|
+
-moz-box-pack: center;
|
20
|
+
-moz-box-align: center;
|
21
|
+
/* Safari, Opera, and Chrome */
|
22
|
+
display: -webkit-box;
|
23
|
+
-webkit-box-pack: center;
|
24
|
+
-webkit-box-align: center;
|
25
|
+
/* W3C */
|
26
|
+
display: box;
|
27
|
+
box-pack: center;
|
28
|
+
box-align: center;
|
29
|
+
}
|
30
|
+
|
31
|
+
html, body{
|
32
|
+
width: 100%;
|
33
|
+
height: 100%;
|
34
|
+
}
|
35
|
+
|
36
|
+
canvas {
|
37
|
+
max-width: 100%;
|
38
|
+
max-height: 100%;
|
39
|
+
}
|
40
|
+
|
41
|
+
.hidden {
|
42
|
+
display: none;
|
43
|
+
}
|
44
|
+
</style>
|
45
|
+
</head>
|
46
|
+
<body class="center-content">
|
47
|
+
<canvas></canvas>
|
48
|
+
|
49
|
+
<div class="hidden">
|
50
|
+
<%= @server.asset_include_tags %>
|
51
|
+
</div>
|
52
|
+
|
53
|
+
<%= javascript_include_tag 'yeah/web/dependencies' %>
|
54
|
+
<%= javascript_include_tag 'yeah/web' %>
|
55
|
+
<%= javascript_include_tag 'yeah/web/setup' %>
|
56
|
+
|
57
|
+
<%= javascript_include_tag 'code' %>
|
58
|
+
|
59
|
+
<%= javascript_include_tag 'yeah/web/start' %>
|
60
|
+
</body>
|
61
|
+
</html>
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'rack'
|
3
|
+
require 'opal'
|
4
|
+
|
5
|
+
module Yeah
|
6
|
+
module Web
|
7
|
+
|
8
|
+
# The `Web::Server` serves a game over the Internet. It can be started easily
|
9
|
+
# by entering `yeah serve` in a command-line within a game project.
|
10
|
+
class Server
|
11
|
+
# @param [Integer] port to serve game over
|
12
|
+
# Start serving the game.
|
13
|
+
def start(port = 1234)
|
14
|
+
Rack::Server.start(app: Application.new, Port: port)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
# For internal usage.
|
20
|
+
# @see Yeah::Web::Server
|
21
|
+
class Application < Opal::Server
|
22
|
+
def initialize
|
23
|
+
@index_path = gem_path.join('lib', 'yeah', 'web', 'runner.html.erb').to_s
|
24
|
+
|
25
|
+
super
|
26
|
+
|
27
|
+
# Append stdlib paths
|
28
|
+
$LOAD_PATH.each { |p| append_path(p) }
|
29
|
+
|
30
|
+
# Append Yeah paths
|
31
|
+
append_path gem_path.join('lib')
|
32
|
+
append_path gem_path.join('opal')
|
33
|
+
|
34
|
+
# Append game (working directory) paths
|
35
|
+
append_path 'assets'
|
36
|
+
append_path 'code'
|
37
|
+
end
|
38
|
+
|
39
|
+
def asset_include_tags
|
40
|
+
paths = Dir['assets/**/*'].select { |p| File.file? p }
|
41
|
+
|
42
|
+
paths.map do |path|
|
43
|
+
case path
|
44
|
+
when /\.(ogg|wav|mp3)$/
|
45
|
+
"<audio src=\"#{path}\"></audio>"
|
46
|
+
else
|
47
|
+
"<img src=\"#{path}\" />"
|
48
|
+
end
|
49
|
+
end.join("\n")
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def gem_path
|
55
|
+
@gem_path ||= Pathname.new(__FILE__).join('..', '..', '..', '..')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Game.default.new
|
data/opal/yeah/web.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module Yeah
|
2
|
+
module Web
|
3
|
+
class Asset
|
4
|
+
ASSETS_PATH = "./assets"
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def [](*args)
|
8
|
+
new(*args)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(path)
|
13
|
+
setup_native
|
14
|
+
|
15
|
+
self.path = path
|
16
|
+
end
|
17
|
+
|
18
|
+
def path
|
19
|
+
`#@native.src`.sub(/.*:\/\/.*#{ASSETS_PATH}\//i, '')
|
20
|
+
end
|
21
|
+
def path=(val)
|
22
|
+
# TODO: use Pathname#join if it is implemented in Opal
|
23
|
+
full_path = "#{ASSETS_PATH}/#{val}"
|
24
|
+
`#@native.src = #{full_path};`
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_n
|
28
|
+
@native
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def setup_native
|
34
|
+
raise NotImplementedError
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
module Yeah
|
2
|
+
module Web
|
3
|
+
class Display
|
4
|
+
attr_reader :font_family, :font_size
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
canvas_selector = options.fetch(:canvas_selector, DEFAULT_CANVAS_SELECTOR)
|
8
|
+
|
9
|
+
@canvas = `document.querySelectorAll(#{canvas_selector})[0]`
|
10
|
+
@context = `#@canvas.getContext('2d')`
|
11
|
+
self.size = options.fetch(:size, DEFAULT_DISPLAY_SIZE)
|
12
|
+
self.font_family = DEFAULT_DISPLAY_FONT_FAMILY
|
13
|
+
self.font_size = DEFAULT_DISPLAY_FONT_SIZE
|
14
|
+
@transform = [1, 0, 0, 1, 0, 0]
|
15
|
+
@transforms = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def size
|
19
|
+
V[`#@canvas.width`, `#@canvas.height`]
|
20
|
+
end
|
21
|
+
def size=(value)
|
22
|
+
`#@canvas.width = #{value.x}`
|
23
|
+
`#@canvas.height = #{value.y}`
|
24
|
+
end
|
25
|
+
|
26
|
+
def width
|
27
|
+
`#@canvas.width`
|
28
|
+
end
|
29
|
+
def width=(value)
|
30
|
+
`#@canvas.width = #{value.x}`
|
31
|
+
end
|
32
|
+
|
33
|
+
def height
|
34
|
+
`#@canvas.height`
|
35
|
+
end
|
36
|
+
def height=(value)
|
37
|
+
`#@canvas.height = #{value.x}`
|
38
|
+
end
|
39
|
+
|
40
|
+
def fill_color
|
41
|
+
C[`#@context.fillStyle`]
|
42
|
+
end
|
43
|
+
def fill_color=(color)
|
44
|
+
`#@context.fillStyle = #{color.to_hex}`
|
45
|
+
end
|
46
|
+
|
47
|
+
def stroke_color
|
48
|
+
C[`#@context.strokeStyle`]
|
49
|
+
end
|
50
|
+
def stroke_color=(color)
|
51
|
+
`#@context.strokeStyle = #{color.to_hex}`
|
52
|
+
end
|
53
|
+
|
54
|
+
def stroke_width
|
55
|
+
`#@context.lineWidth`
|
56
|
+
end
|
57
|
+
def stroke_width=(numeric)
|
58
|
+
`#@context.lineWidth = #{numeric}`
|
59
|
+
end
|
60
|
+
|
61
|
+
def font_family=(type)
|
62
|
+
@font_family= type
|
63
|
+
|
64
|
+
font = "#{@font_size}px #{@font_family}"
|
65
|
+
`#@context.font = #{font}`
|
66
|
+
end
|
67
|
+
|
68
|
+
def font_size=(size)
|
69
|
+
@font_size = size
|
70
|
+
|
71
|
+
font = "#{@font_size}px #{@font_family}"
|
72
|
+
`#@context.font = #{font}`
|
73
|
+
end
|
74
|
+
|
75
|
+
def color_at(position)
|
76
|
+
data = `#@context.getImageData(#{position.x}, #{position.y}, 1, 1).data`
|
77
|
+
C[`data[0]`, `data[1]`, `data[2]`]
|
78
|
+
end
|
79
|
+
|
80
|
+
def transformation
|
81
|
+
@transform + [0, 0, 1] # appendage to fulfill signature
|
82
|
+
end
|
83
|
+
|
84
|
+
def translate(displacement)
|
85
|
+
@transform[4] += `#{@transform[0]} * #{displacement.x} +
|
86
|
+
#{@transform[2]} * #{displacement.y}`
|
87
|
+
@transform[5] += `#{@transform[1]} * #{displacement.x} +
|
88
|
+
#{@transform[3]} * #{displacement.y}`
|
89
|
+
|
90
|
+
%x{
|
91
|
+
#@context.setTransform(#{@transform[0]}, #{@transform[1]},
|
92
|
+
#{@transform[2]}, #{@transform[3]},
|
93
|
+
#{@transform[4]}, #{@transform[5]}); }
|
94
|
+
end
|
95
|
+
|
96
|
+
def scale(multiplier)
|
97
|
+
%x{
|
98
|
+
#{@transform} = [#{@transform[0]} * #{multiplier.x},
|
99
|
+
#{@transform[1]} * #{multiplier.x},
|
100
|
+
#{@transform[2]} * #{multiplier.y},
|
101
|
+
#{@transform[3]} * #{multiplier.y},
|
102
|
+
#{@transform[4]}, #{@transform[5]}];
|
103
|
+
|
104
|
+
#@context.setTransform(#{@transform[0]}, #{@transform[1]},
|
105
|
+
#{@transform[2]}, #{@transform[3]},
|
106
|
+
#{@transform[4]}, #{@transform[5]}); }
|
107
|
+
end
|
108
|
+
|
109
|
+
def rotate(radians)
|
110
|
+
%x{
|
111
|
+
var cos = Math.cos(#{radians}),
|
112
|
+
sin = Math.sin(#{radians}),
|
113
|
+
e0 = #{@transform[0]} * cos + #{@transform[2]} * sin,
|
114
|
+
e1 = #{@transform[1]} * cos + #{@transform[3]} * sin,
|
115
|
+
e2 = #{@transform[0]} * -sin + #{@transform[2]} * cos,
|
116
|
+
e3 = #{@transform[1]} * -sin + #{@transform[3]} * cos;
|
117
|
+
|
118
|
+
#@transform = [e0, e1, e2, e3, #{@transform[4]}, #{@transform[5]}];
|
119
|
+
|
120
|
+
#@context.setTransform(#{@transform[0]}, #{@transform[1]},
|
121
|
+
#{@transform[2]}, #{@transform[3]},
|
122
|
+
#{@transform[4]}, #{@transform[5]}); }
|
123
|
+
end
|
124
|
+
|
125
|
+
def push
|
126
|
+
@transforms.push(@transform.dup)
|
127
|
+
end
|
128
|
+
|
129
|
+
def pop
|
130
|
+
@transform = @transforms.pop
|
131
|
+
|
132
|
+
%x{
|
133
|
+
#@context.setTransform(#{@transform[0]}, #{@transform[1]},
|
134
|
+
#{@transform[2]}, #{@transform[3]},
|
135
|
+
#{@transform[4]}, #{@transform[5]}); }
|
136
|
+
end
|
137
|
+
|
138
|
+
def stroke_line(start_pos, end_pos)
|
139
|
+
%x{
|
140
|
+
#@context.beginPath();
|
141
|
+
#@context.moveTo(#{start_pos.x}, #{start_pos.y});
|
142
|
+
#@context.lineTo(#{end_pos.x}, #{end_pos.y});
|
143
|
+
#@context.closePath();
|
144
|
+
#@context.stroke();
|
145
|
+
}
|
146
|
+
end
|
147
|
+
|
148
|
+
def stroke_rectangle(position, size)
|
149
|
+
`#@context.strokeRect(#{position.x}, #{position.y}, #{size.x}, #{size.y})`
|
150
|
+
end
|
151
|
+
|
152
|
+
def fill_rectangle(position, size)
|
153
|
+
`#@context.fillRect(#{position.x}, #{position.y}, #{size.x}, #{size.y})`
|
154
|
+
end
|
155
|
+
|
156
|
+
def stroke_ellipse(center, radius)
|
157
|
+
%x{
|
158
|
+
#@context.beginPath();
|
159
|
+
#@context.save();
|
160
|
+
#@context.beginPath();
|
161
|
+
#@context.translate(#{center.x} - #{radius.x},
|
162
|
+
#{center.y} - #{radius.y});
|
163
|
+
#@context.scale(#{radius.x}, #{radius.y});
|
164
|
+
#@context.arc(1, 1, 1, 0, 2 * Math.PI, false);
|
165
|
+
#@context.restore();
|
166
|
+
#@context.stroke();
|
167
|
+
}
|
168
|
+
end
|
169
|
+
|
170
|
+
def fill_ellipse(center, radius)
|
171
|
+
%x{
|
172
|
+
#@context.beginPath();
|
173
|
+
#@context.save();
|
174
|
+
#@context.beginPath();
|
175
|
+
#@context.translate(#{center.x} - #{radius.x},
|
176
|
+
#{center.y} - #{radius.y});
|
177
|
+
#@context.scale(#{radius.x}, #{radius.y});
|
178
|
+
#@context.arc(1, 1, 1, 0, 2 * Math.PI, false);
|
179
|
+
#@context.restore();
|
180
|
+
#@context.fill();
|
181
|
+
}
|
182
|
+
end
|
183
|
+
|
184
|
+
def clear
|
185
|
+
`#@context.fillRect(0, 0, #{size.x}, #{size.y})`
|
186
|
+
end
|
187
|
+
|
188
|
+
def begin_shape
|
189
|
+
`#@context.beginPath()`
|
190
|
+
end
|
191
|
+
|
192
|
+
def end_shape
|
193
|
+
`#@context.closePath()`
|
194
|
+
end
|
195
|
+
|
196
|
+
def move_to(position)
|
197
|
+
`#@context.moveTo(#{position.x}, #{position.y})`
|
198
|
+
end
|
199
|
+
|
200
|
+
def line_to(position)
|
201
|
+
`#@context.lineTo(#{position.x}, #{position.y})`
|
202
|
+
end
|
203
|
+
|
204
|
+
def curve_to(position, control)
|
205
|
+
`#@context.quadraticCurveTo(#{control.x}, #{control.y},
|
206
|
+
#{position.x}, #{position.y})`
|
207
|
+
end
|
208
|
+
|
209
|
+
def curve2_to(position, control1, control2)
|
210
|
+
`#@context.bezierCurveTo(#{control1.x}, #{control1.y},
|
211
|
+
#{control2.x}, #{control2.y},
|
212
|
+
#{position.x}, #{position.y})`
|
213
|
+
end
|
214
|
+
|
215
|
+
def stroke_shape
|
216
|
+
`#@context.stroke()`
|
217
|
+
end
|
218
|
+
|
219
|
+
def fill_shape
|
220
|
+
`#@context.fill()`
|
221
|
+
end
|
222
|
+
|
223
|
+
def image(image, position)
|
224
|
+
`#@context.drawImage(#{image.to_n}, #{position.x}, #{position.y})`
|
225
|
+
end
|
226
|
+
|
227
|
+
def image_cropped(image, position, crop_position, crop_size)
|
228
|
+
%x{#@context.drawImage(#{image.to_n},
|
229
|
+
#{crop_position.x}, #{crop_position.y},
|
230
|
+
#{crop_size.x}, #{crop_size.y},
|
231
|
+
#{position.x}, #{position.y},
|
232
|
+
#{crop_size.x}, #{crop_size.y})}
|
233
|
+
end
|
234
|
+
|
235
|
+
def fill_text(text, position)
|
236
|
+
`#@context.fillText(#{text}, #{position.x}, #{position.y})`
|
237
|
+
end
|
238
|
+
|
239
|
+
def stroke_text(text, position)
|
240
|
+
`#@context.strokeText(#{text}, #{position.x}, #{position.y})`
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Yeah
|
2
|
+
module Web
|
3
|
+
class Image < Asset
|
4
|
+
def size
|
5
|
+
V[`#@native.width`, `#@native.height`]
|
6
|
+
end
|
7
|
+
|
8
|
+
def width
|
9
|
+
`#@native.width`
|
10
|
+
end
|
11
|
+
|
12
|
+
def height
|
13
|
+
`#@native.height`
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def setup_native
|
19
|
+
`#@native = new Image();`
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|