dxopal 1.0.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 +7 -0
- data/.gitignore +5 -0
- data/.ignore +5 -0
- data/.nojekyll +4 -0
- data/CHANGELOG.md +90 -0
- data/DEVELOPMENT.md +57 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +39 -0
- data/README.md +22 -0
- data/Rakefile +66 -0
- data/TODO.md +278 -0
- data/build/dxopal.js +46590 -0
- data/build/dxopal.min.js +1 -0
- data/config.ru +39 -0
- data/doc/api/DXOpal.html +129 -0
- data/doc/api/DXOpal/Font.html +485 -0
- data/doc/api/DXOpal/Image.html +2533 -0
- data/doc/api/DXOpal/Input.html +1086 -0
- data/doc/api/DXOpal/Input/MouseCodes.html +146 -0
- data/doc/api/DXOpal/RemoteResource.html +641 -0
- data/doc/api/DXOpal/Sound.html +568 -0
- data/doc/api/DXOpal/SoundEffect.html +444 -0
- data/doc/api/DXOpal/SoundEffect/WaveTypes.html +130 -0
- data/doc/api/DXOpal/Sprite.html +1419 -0
- data/doc/api/DXOpal/Window.html +1915 -0
- data/doc/api/_index.html +228 -0
- data/doc/api/class_list.html +51 -0
- data/doc/api/css/common.css +1 -0
- data/doc/api/css/full_list.css +58 -0
- data/doc/api/css/style.css +492 -0
- data/doc/api/file.CHANGELOG.html +162 -0
- data/doc/api/file.README.html +124 -0
- data/doc/api/file_list.html +61 -0
- data/doc/api/frames.html +17 -0
- data/doc/api/index.html +124 -0
- data/doc/api/js/app.js +248 -0
- data/doc/api/js/full_list.js +216 -0
- data/doc/api/js/jquery.js +4 -0
- data/doc/api/method_list.html +939 -0
- data/doc/api/top-level-namespace.html +110 -0
- data/doc/en/index.html +93 -0
- data/doc/ja/index.html +92 -0
- data/dxopal.gemspec +29 -0
- data/exe/dxopal +44 -0
- data/index.html +56 -0
- data/opal/dxopal.rb +54 -0
- data/opal/dxopal/constants/colors.rb +16 -0
- data/opal/dxopal/font.rb +20 -0
- data/opal/dxopal/image.rb +301 -0
- data/opal/dxopal/input.rb +170 -0
- data/opal/dxopal/input/key_codes.rb +168 -0
- data/opal/dxopal/remote_resource.rb +65 -0
- data/opal/dxopal/sound.rb +53 -0
- data/opal/dxopal/sound_effect.rb +84 -0
- data/opal/dxopal/sprite.rb +94 -0
- data/opal/dxopal/sprite/collision_area.rb +288 -0
- data/opal/dxopal/sprite/collision_check.rb +106 -0
- data/opal/dxopal/sprite/collision_checker.rb +169 -0
- data/opal/dxopal/sprite/physics.rb +82 -0
- data/opal/dxopal/version.rb +3 -0
- data/opal/dxopal/window.rb +173 -0
- data/template/index.html +13 -0
- data/template/main.rb +9 -0
- metadata +191 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
module DXOpal
|
2
|
+
module Constants
|
3
|
+
# Pre-defined ARGB colors
|
4
|
+
module Colors
|
5
|
+
C_BLACK = [255, 0, 0, 0]
|
6
|
+
C_RED = [255, 255, 0, 0]
|
7
|
+
C_GREEN = [255, 0, 255, 0]
|
8
|
+
C_BLUE = [255, 0, 0, 255]
|
9
|
+
C_YELLOW = [255, 255, 255, 0]
|
10
|
+
C_CYAN = [255, 0, 255, 255]
|
11
|
+
C_MAGENTA = [255, 255, 0, 255]
|
12
|
+
C_WHITE = [255, 255, 255, 255]
|
13
|
+
C_DEFAULT = [0, 0, 0, 0]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/opal/dxopal/font.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module DXOpal
|
2
|
+
class Font
|
3
|
+
def self.default; @@default ||= Font.new(24); end
|
4
|
+
def self.default=(f); @@default = f; end
|
5
|
+
|
6
|
+
def initialize(size, fontname=nil, option={})
|
7
|
+
@size = size
|
8
|
+
@orig_fontname = fontname
|
9
|
+
@fontname = fontname || "sans-serif"
|
10
|
+
end
|
11
|
+
|
12
|
+
def size; @size; end
|
13
|
+
def fontname; @orig_fontname; end
|
14
|
+
|
15
|
+
# Return a string like "48px serif"
|
16
|
+
def _spec_str
|
17
|
+
"#{@size}px #{@fontname}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,301 @@
|
|
1
|
+
require 'dxopal/remote_resource'
|
2
|
+
|
3
|
+
module DXOpal
|
4
|
+
class Image < RemoteResource
|
5
|
+
RemoteResource.add_class(Image)
|
6
|
+
|
7
|
+
# Load remote image (called via Window.load_resources)
|
8
|
+
def self._load(path_or_url)
|
9
|
+
raw_img = `new Image()`
|
10
|
+
img_promise = %x{
|
11
|
+
new Promise(function(resolve, reject) {
|
12
|
+
raw_img.onload = function() {
|
13
|
+
resolve(raw_img);
|
14
|
+
};
|
15
|
+
raw_img.src = path_or_url;
|
16
|
+
});
|
17
|
+
}
|
18
|
+
|
19
|
+
img = new(0, 0)
|
20
|
+
%x{
|
21
|
+
#{img_promise}.then(function(raw_img){
|
22
|
+
img.$_resize(raw_img.width, raw_img.height);
|
23
|
+
img.$_draw_raw_image(0, 0, raw_img);
|
24
|
+
});
|
25
|
+
}
|
26
|
+
return img, img_promise
|
27
|
+
end
|
28
|
+
|
29
|
+
# Create an instance of Image
|
30
|
+
def initialize(width, height, color=C_DEFAULT, canvas: nil)
|
31
|
+
@width, @height = width, height
|
32
|
+
@canvas = canvas || `document.createElement("canvas")`
|
33
|
+
@ctx = `#{@canvas}.getContext('2d')`
|
34
|
+
_resize(@width, @height)
|
35
|
+
box_fill(0, 0, @width, @height, color)
|
36
|
+
end
|
37
|
+
attr_reader :ctx, :canvas, :width, :height
|
38
|
+
|
39
|
+
# Set size of this image
|
40
|
+
def _resize(w, h)
|
41
|
+
@width, @height = w, h
|
42
|
+
%x{
|
43
|
+
#{@canvas}.width = w;
|
44
|
+
#{@canvas}.height = h;
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Draw an Image on this image
|
49
|
+
def draw(x, y, image)
|
50
|
+
%x{
|
51
|
+
#{@ctx}.drawImage(#{image.canvas}, x, y);
|
52
|
+
}
|
53
|
+
return self
|
54
|
+
end
|
55
|
+
|
56
|
+
# Draw an Image on this image with rotation
|
57
|
+
# - angle: Rotation angle (radian)
|
58
|
+
# - center_x, center_y: Rotation center in the `image` (default: center of the `image`)
|
59
|
+
def draw_rot(x, y, image, angle, center_x=nil, center_y=nil)
|
60
|
+
draw_ex(x, y, image, angle: angle, center_x: center_x, center_y: center_y)
|
61
|
+
end
|
62
|
+
|
63
|
+
def draw_ex(x, y, image, options={})
|
64
|
+
scale_x = options[:scale_x] || 1
|
65
|
+
scale_y = options[:scale_y] || 1
|
66
|
+
center_x = options[:center_x] || image.width/2
|
67
|
+
center_y = options[:center_y] || image.height/2
|
68
|
+
# TODO: alpha
|
69
|
+
# TODO: blend
|
70
|
+
angle = options[:angle] || 0
|
71
|
+
|
72
|
+
cx = x + center_x
|
73
|
+
cy = y + center_y
|
74
|
+
%x{
|
75
|
+
#{@ctx}.translate(cx, cy);
|
76
|
+
#{@ctx}.rotate(angle * Math.PI / 180.0);
|
77
|
+
#{@ctx}.scale(scale_x, scale_y);
|
78
|
+
#{@ctx}.drawImage(#{image.canvas}, x-cx, y-cy);
|
79
|
+
#{@ctx}.setTransform(1, 0, 0, 1, 0, 0); // reset
|
80
|
+
}
|
81
|
+
return self
|
82
|
+
end
|
83
|
+
|
84
|
+
# Draw some text on this image
|
85
|
+
def draw_font(x, y, string, font, color=[255,255,255])
|
86
|
+
ctx = @ctx
|
87
|
+
%x{
|
88
|
+
ctx.font = #{font._spec_str};
|
89
|
+
ctx.textBaseline = 'top';
|
90
|
+
ctx.fillStyle = #{_rgba(color)};
|
91
|
+
ctx.fillText(string, x, y);
|
92
|
+
}
|
93
|
+
return self
|
94
|
+
end
|
95
|
+
|
96
|
+
# Get a pixel as ARGB array
|
97
|
+
def [](x, y)
|
98
|
+
ctx = @ctx
|
99
|
+
ret = nil
|
100
|
+
%x{
|
101
|
+
var pixel = ctx.getImageData(x, y, 1, 1);
|
102
|
+
var rgba = pixel.data;
|
103
|
+
ret = [rgba[3], rgba[0], rgba[1], rgba[2]];
|
104
|
+
}
|
105
|
+
return ret
|
106
|
+
end
|
107
|
+
|
108
|
+
# Put a pixel on this image
|
109
|
+
def []=(x, y, color)
|
110
|
+
box_fill(x, y, x, y, color)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Return true if the pixel at `(x, y)` has the `color`
|
114
|
+
def compare(x, y, color)
|
115
|
+
ctx = @ctx
|
116
|
+
rgba1 = _rgba_ary(color)
|
117
|
+
rgba2 = nil
|
118
|
+
ret = nil
|
119
|
+
%x{
|
120
|
+
var pixel = ctx.getImageData(x, y, 1, 1);
|
121
|
+
rgba2 = pixel.data;
|
122
|
+
// TODO: what is the right way to compare an Array and an Uint8ClampedArray?
|
123
|
+
ret = rgba1[0] == rgba2[0] &&
|
124
|
+
rgba1[1] == rgba2[1] &&
|
125
|
+
rgba1[2] == rgba2[2] &&
|
126
|
+
rgba1[3] == rgba2[3]
|
127
|
+
}
|
128
|
+
return ret
|
129
|
+
end
|
130
|
+
|
131
|
+
# Draw a line on this image
|
132
|
+
def line(x1, y1, x2, y2, color)
|
133
|
+
ctx = @ctx
|
134
|
+
%x{
|
135
|
+
ctx.beginPath();
|
136
|
+
ctx.strokeStyle = #{_rgba(color)};
|
137
|
+
ctx.moveTo(x1, y1);
|
138
|
+
ctx.lineTo(x2, y2);
|
139
|
+
ctx.stroke();
|
140
|
+
}
|
141
|
+
return self
|
142
|
+
end
|
143
|
+
|
144
|
+
# Draw a rectangle on this image
|
145
|
+
def box(x1, y1, x2, y2, color)
|
146
|
+
ctx = @ctx
|
147
|
+
%x{
|
148
|
+
ctx.beginPath();
|
149
|
+
ctx.strokeStyle = #{_rgba(color)};
|
150
|
+
ctx.rect(x1, y1, x2-x1+1, y2-y1+1);
|
151
|
+
ctx.stroke();
|
152
|
+
}
|
153
|
+
return self
|
154
|
+
end
|
155
|
+
|
156
|
+
# Draw a filled box on this image
|
157
|
+
def box_fill(x1, y1, x2, y2, color)
|
158
|
+
ctx = @ctx
|
159
|
+
%x{
|
160
|
+
ctx.beginPath();
|
161
|
+
ctx.fillStyle = #{_rgba(color)};
|
162
|
+
ctx.fillRect(x1, y1, x2-x1+1, y2-y1+1);
|
163
|
+
}
|
164
|
+
return self
|
165
|
+
end
|
166
|
+
|
167
|
+
# Draw a circle on this image
|
168
|
+
def circle(x, y, r, color)
|
169
|
+
ctx = @ctx
|
170
|
+
%x{
|
171
|
+
ctx.beginPath();
|
172
|
+
ctx.strokeStyle = #{_rgba(color)};
|
173
|
+
ctx.arc(x, y, r, 0, Math.PI*2, false)
|
174
|
+
ctx.stroke();
|
175
|
+
}
|
176
|
+
return self
|
177
|
+
end
|
178
|
+
|
179
|
+
# Draw a filled circle on this image
|
180
|
+
def circle_fill(x, y, r, color)
|
181
|
+
ctx = @ctx
|
182
|
+
%x{
|
183
|
+
ctx.beginPath();
|
184
|
+
ctx.fillStyle = #{_rgba(color)};
|
185
|
+
ctx.arc(x, y, r, 0, Math.PI*2, false)
|
186
|
+
ctx.fill();
|
187
|
+
}
|
188
|
+
return self
|
189
|
+
end
|
190
|
+
|
191
|
+
# Draw a triangle on this image
|
192
|
+
def triangle(x1, y1, x2, y2, x3, y3, color)
|
193
|
+
ctx = @ctx
|
194
|
+
%x{
|
195
|
+
ctx.beginPath();
|
196
|
+
ctx.strokeStyle = #{_rgba(color)};
|
197
|
+
ctx.moveTo(x1, y1);
|
198
|
+
ctx.lineTo(x2, y2);
|
199
|
+
ctx.lineTo(x3, y3);
|
200
|
+
ctx.lineTo(x1, y1);
|
201
|
+
ctx.stroke();
|
202
|
+
}
|
203
|
+
return self
|
204
|
+
end
|
205
|
+
|
206
|
+
# Draw a filled triangle on this image
|
207
|
+
def triangle_fill(x1, y1, x2, y2, x3, y3, color)
|
208
|
+
ctx = @ctx
|
209
|
+
%x{
|
210
|
+
ctx.beginPath();
|
211
|
+
ctx.fillStyle = #{_rgba(color)};
|
212
|
+
ctx.moveTo(x1, y1);
|
213
|
+
ctx.lineTo(x2, y2);
|
214
|
+
ctx.lineTo(x3, y3);
|
215
|
+
ctx.fill();
|
216
|
+
}
|
217
|
+
return self
|
218
|
+
end
|
219
|
+
|
220
|
+
# Fill this image with `color`
|
221
|
+
def fill(color)
|
222
|
+
box_fill(0, 0, @width-1, @height-1, color)
|
223
|
+
end
|
224
|
+
|
225
|
+
# Clear this image (i.e. fill with `[0,0,0,0]`)
|
226
|
+
def clear
|
227
|
+
fill([0, 0, 0, 0])
|
228
|
+
end
|
229
|
+
|
230
|
+
# Return an Image which is a copy of the specified area
|
231
|
+
def slice(x, y, width, height)
|
232
|
+
newimg = Image.new(width, height)
|
233
|
+
data = _image_data(x, y, width, height)
|
234
|
+
newimg._put_image_data(data, 0, 0)
|
235
|
+
return newimg
|
236
|
+
end
|
237
|
+
|
238
|
+
# Slice this image into xcount*ycount tiles
|
239
|
+
def slice_tiles(xcount, ycount)
|
240
|
+
tile_w = @width / xcount
|
241
|
+
tile_h = @height / ycount
|
242
|
+
return (0...ycount).flat_map{|v|
|
243
|
+
(0...xcount).map{|u|
|
244
|
+
slice(tile_w * u, tile_h * v, tile_w, tile_h)
|
245
|
+
}
|
246
|
+
}
|
247
|
+
end
|
248
|
+
|
249
|
+
# Copy an <img> onto this image
|
250
|
+
def _draw_raw_image(x, y, raw_img)
|
251
|
+
%x{
|
252
|
+
#{@ctx}.drawImage(#{raw_img}, x, y)
|
253
|
+
}
|
254
|
+
end
|
255
|
+
|
256
|
+
# Return .getImageData
|
257
|
+
def _image_data(x=0, y=0, w=@width, h=@height)
|
258
|
+
return `#{@ctx}.getImageData(x, y, w, h)`
|
259
|
+
end
|
260
|
+
|
261
|
+
# Call .putImageData
|
262
|
+
def _put_image_data(image_data, x, y)
|
263
|
+
`#{@ctx}.putImageData(image_data, x, y)`
|
264
|
+
end
|
265
|
+
|
266
|
+
# Return a string like 'rgb(255, 255, 255)'
|
267
|
+
# `color` is 3 or 4 numbers
|
268
|
+
def _rgb(color)
|
269
|
+
case color.length
|
270
|
+
when 4
|
271
|
+
# Just ignore alpha
|
272
|
+
rgb = color[1, 3]
|
273
|
+
when 3
|
274
|
+
rgb = color
|
275
|
+
else
|
276
|
+
raise "invalid color: #{color.inspect}"
|
277
|
+
end
|
278
|
+
return "rgb(" + rgb.join(', ') + ")";
|
279
|
+
end
|
280
|
+
|
281
|
+
# Return a string like 'rgba(255, 255, 255, 128)'
|
282
|
+
# `color` is 3 or 4 numbers
|
283
|
+
def _rgba(color)
|
284
|
+
return "rgba(" + _rgba_ary(color).join(', ') + ")"
|
285
|
+
end
|
286
|
+
|
287
|
+
# Return an array like `[255, 255, 255, 128]`
|
288
|
+
def _rgba_ary(color)
|
289
|
+
case color.length
|
290
|
+
when 4
|
291
|
+
# color is ARGB in DXRuby, so move A to the last
|
292
|
+
color[1, 3] + [color[0]/255.0]
|
293
|
+
when 3
|
294
|
+
# Complement 255 as alpha
|
295
|
+
color + [1.0]
|
296
|
+
else
|
297
|
+
raise "invalid color: #{color.inspect}"
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
module DXOpal
|
2
|
+
module Input
|
3
|
+
module MouseCodes
|
4
|
+
M_LBUTTON = 1
|
5
|
+
M_RBUTTON = 2
|
6
|
+
M_MBUTTON = 4
|
7
|
+
# DXOpal extention
|
8
|
+
M_4TH_BUTTON = 8
|
9
|
+
M_5TH_BUTTON = 16
|
10
|
+
end
|
11
|
+
|
12
|
+
def self._pressing_keys; @@pressing_keys; end
|
13
|
+
|
14
|
+
# Internal setup for Input class
|
15
|
+
def self._init(canvas)
|
16
|
+
@@tick = 0
|
17
|
+
@@pressing_keys = `new Object()`
|
18
|
+
@@mouse_info = `{x: 0, y: 0}`
|
19
|
+
@@pressing_mouse_buttons = `new Object()`
|
20
|
+
|
21
|
+
rect = `canvas.getBoundingClientRect()`
|
22
|
+
@@canvas_x = `rect.left + window.pageXOffset`
|
23
|
+
@@canvas_y = `rect.top + window.pageYOffset`
|
24
|
+
|
25
|
+
self._init_mouse_events
|
26
|
+
self.keyevent_target = `window` unless Input.keyevent_target
|
27
|
+
end
|
28
|
+
|
29
|
+
# Called on every frame from Window
|
30
|
+
def self._on_tick
|
31
|
+
@@tick += 1
|
32
|
+
end
|
33
|
+
|
34
|
+
# Return 1 if 'right', -1 if 'left'
|
35
|
+
def self.x(pad_number=0)
|
36
|
+
ret = 0
|
37
|
+
ret += 1 if key_down?(K_RIGHT)
|
38
|
+
ret -= 1 if key_down?(K_LEFT)
|
39
|
+
ret
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return 1 if 'down', -1 if 'up'
|
43
|
+
def self.y(pad_number=0)
|
44
|
+
ret = 0
|
45
|
+
ret += 1 if key_down?(K_DOWN)
|
46
|
+
ret -= 1 if key_down?(K_UP)
|
47
|
+
ret
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Keyboard
|
52
|
+
#
|
53
|
+
|
54
|
+
# Return true if the key is being pressed
|
55
|
+
def self.key_down?(code)
|
56
|
+
return `#{@@pressing_keys}[code] > 0`
|
57
|
+
end
|
58
|
+
|
59
|
+
# Return true if the key is just pressed
|
60
|
+
def self.key_push?(code)
|
61
|
+
return `#{@@pressing_keys}[code] == #{@@tick}-1`
|
62
|
+
end
|
63
|
+
|
64
|
+
# Return true if the key is just released
|
65
|
+
def self.key_release?(code)
|
66
|
+
return `#{@@pressing_keys}[code] == -(#{@@tick}-1)`
|
67
|
+
end
|
68
|
+
|
69
|
+
# (private) JS keydown event handler
|
70
|
+
ON_KEYDOWN_ = %x{
|
71
|
+
function(ev){
|
72
|
+
#{Input._pressing_keys}[ev.keyCode] = #{@@tick};
|
73
|
+
ev.preventDefault();
|
74
|
+
ev.stopPropagation();
|
75
|
+
}
|
76
|
+
}
|
77
|
+
# (private) JS keyup event handler
|
78
|
+
ON_KEYUP_ = %x{
|
79
|
+
function(ev){
|
80
|
+
#{Input._pressing_keys}[ev.keyCode] = -#{@@tick};
|
81
|
+
ev.preventDefault();
|
82
|
+
ev.stopPropagation();
|
83
|
+
}
|
84
|
+
}
|
85
|
+
# Set DOM element to receive keydown/keyup event
|
86
|
+
#
|
87
|
+
# By default, `window` is set to this (i.e. all key events are
|
88
|
+
# stolen by DXOpal.) If canvas element is set to this, only key events
|
89
|
+
# happend on canvas are processed by DXOpal.
|
90
|
+
def self.keyevent_target=(target)
|
91
|
+
if @@keyevent_target
|
92
|
+
%x{
|
93
|
+
#{@@keyevent_target}.removeEventListener('keydown', #{ON_KEYDOWN_});
|
94
|
+
#{@@keyevent_target}.removeEventListener('keyup', #{ON_KEYUP_});
|
95
|
+
}
|
96
|
+
end
|
97
|
+
@@keyevent_target = target
|
98
|
+
%x{
|
99
|
+
if (#{@@keyevent_target}.tagName == "CANVAS") {
|
100
|
+
#{@@keyevent_target}.setAttribute('tabindex', 0);
|
101
|
+
}
|
102
|
+
#{@@keyevent_target}.addEventListener('keydown', #{ON_KEYDOWN_});
|
103
|
+
#{@@keyevent_target}.addEventListener('keyup', #{ON_KEYUP_});
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
# Return DOM element set by `keyevent_target=`
|
108
|
+
def self.keyevent_target; @@keyevent_target; end
|
109
|
+
|
110
|
+
#
|
111
|
+
# Mouse
|
112
|
+
#
|
113
|
+
|
114
|
+
# (internal) initialize mouse events
|
115
|
+
def self._init_mouse_events
|
116
|
+
%x{
|
117
|
+
document.addEventListener('mousemove', function(ev){
|
118
|
+
#{@@mouse_info}.x = ev.pageX - #{@@canvas_x};
|
119
|
+
#{@@mouse_info}.y = ev.pageY - #{@@canvas_y};
|
120
|
+
});
|
121
|
+
document.addEventListener('mousedown', function(ev){
|
122
|
+
#{@@mouse_info}.x = ev.pageX - #{@@canvas_x};
|
123
|
+
#{@@mouse_info}.y = ev.pageY - #{@@canvas_y};
|
124
|
+
for (var k=1; k<=16; k<<=1) {
|
125
|
+
if (ev.buttons & k) {
|
126
|
+
#{@@pressing_mouse_buttons}[k] = #{@@tick};
|
127
|
+
}
|
128
|
+
}
|
129
|
+
});
|
130
|
+
document.addEventListener('mouseup', function(ev){
|
131
|
+
#{@@mouse_info}.x = ev.pageX - #{@@canvas_x};
|
132
|
+
#{@@mouse_info}.y = ev.pageY - #{@@canvas_y};
|
133
|
+
for (var k=1; k<=16; k<<=1) {
|
134
|
+
if ((ev.buttons & k) == 0 && #{@@pressing_mouse_buttons}[k]) {
|
135
|
+
#{@@pressing_mouse_buttons}[k] = -#{@@tick};
|
136
|
+
}
|
137
|
+
}
|
138
|
+
});
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
142
|
+
# Return position of mouse cursor
|
143
|
+
# (0, 0) is the top-left corner of the canvas
|
144
|
+
def self.mouse_x
|
145
|
+
return `#{@@mouse_info}.x`
|
146
|
+
end
|
147
|
+
def self.mouse_y
|
148
|
+
return `#{@@mouse_info}.y`
|
149
|
+
end
|
150
|
+
class << self
|
151
|
+
alias mouse_pos_x mouse_x
|
152
|
+
alias mouse_pos_y mouse_y
|
153
|
+
end
|
154
|
+
|
155
|
+
# Return true if the mouse button is being pressed
|
156
|
+
def self.mouse_down?(mouse_code)
|
157
|
+
return `#{@@pressing_mouse_buttons}[mouse_code] > 0`
|
158
|
+
end
|
159
|
+
|
160
|
+
# Return true if the mouse button is pressed in the last tick
|
161
|
+
def self.mouse_push?(mouse_code)
|
162
|
+
return `#{@@pressing_mouse_buttons}[mouse_code] == -(#{@@tick}-1)`
|
163
|
+
end
|
164
|
+
|
165
|
+
# Return true if the mouse button is released in the last tick
|
166
|
+
def self.mouse_release?(mouse_code)
|
167
|
+
return `#{@@pressing_mouse_buttons}[mouse_code] == -(#{@@tick}-1)`
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|