rubysketch 0.5.3 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,128 +1,750 @@
1
1
  module RubySketch
2
2
 
3
3
 
4
+ # Sprite object.
5
+ #
4
6
  class Sprite
5
7
 
6
- extend Forwardable
8
+ include Xot::Inspectable
7
9
 
8
- def initialize(x = 0, y = 0, w = nil, h = nil, image: nil, offset: nil, dynamic: false)
9
- w ||= image&.width || 0
10
- h ||= image&.height || 0
11
- raise 'invalid size' unless w >= 0 && h >= 0
10
+ # Initialize sprite object.
11
+ #
12
+ # @overload new(image: img)
13
+ # pos: [0, 0], size: [image.width, image.height]
14
+ # @param [Image] img sprite image
15
+ #
16
+ # @overload new(x, y, image: img)
17
+ # pos: [x, y], size: [image.width, image.height]
18
+ # @param [Numeric] x x of sprite position
19
+ # @param [Numeric] y y of sprite position
20
+ # @param [Image] img sprite image
21
+ #
22
+ # @overload new(x, y, w, h)
23
+ # pos(x, y), size: [w, h]
24
+ # @param [Numeric] x x of sprite position
25
+ # @param [Numeric] y y of sprite position
26
+ # @param [Numeric] w width of sprite
27
+ # @param [Numeric] h height of sprite
28
+ #
29
+ # @overload new(x, y, w, h, image: img, offset: off)
30
+ # pos: [x, y], size: [w, h], offset: [offset.x, offset.x]
31
+ # @param [Numeric] x x of sprite position
32
+ # @param [Numeric] y y of sprite position
33
+ # @param [Numeric] w width of sprite
34
+ # @param [Numeric] h height of sprite
35
+ # @param [Image] img sprite image
36
+ # @param [Vector] off offset of sprite image
37
+ #
38
+ def initialize(
39
+ x = 0, y = 0, w = nil, h = nil, image: nil, offset: nil,
40
+ context: nil)
12
41
 
13
- @image__, @offset__ = image, offset
14
- @view__ = View.new self, x: x, y: y, w: w, h: h, back: :white, dynamic: dynamic
42
+ w ||= (image&.width || 0)
43
+ h ||= (image&.height || 0)
44
+ raise 'invalid size' unless w >= 0 && h >= 0
45
+ raise 'invalid image' if image && !image.getInternal__.is_a?(Rays::Image)
46
+
47
+ @context__ = context || Context.context__
48
+ @view__ = SpriteView.new(
49
+ self, x: x, y: y, w: w, h: h,
50
+ static: true, density: 1, friction: 0, restitution: 0,
51
+ back: :white)
52
+
53
+ self.image = image if image
54
+ self.offset = offset if offset
15
55
  end
16
56
 
17
- def_delegators :@view__,
18
- :x, :x=,
19
- :y, :y=,
20
- :w, :h,
21
- :width, :height,
22
- :dynamic?, :dynamic=,
23
- :density, :density=,
24
- :friction, :friction=,
25
- :restitution, :restitution=
57
+ # Returns the position of the sprite.
58
+ #
59
+ # @return [Vector] position
60
+ #
61
+ def position()
62
+ @view__.position.toVector
63
+ end
26
64
 
27
- def update(&block)
28
- @view__.on_update = block
65
+ # Sets the position of the sprite.
66
+ #
67
+ # @overload position=(vec)
68
+ # @param [Vector] vec position vector
69
+ #
70
+ # @overload position=(ary)
71
+ # @param [Array<Numeric>] ary an array of positionX and positionY
72
+ #
73
+ # @return [Vector] position
74
+ #
75
+ def position=(arg)
76
+ @view__.position = arg.is_a?(Vector) ? arg.getInternal__ : arg
77
+ arg
29
78
  end
30
79
 
31
- def contact(&block)
32
- @view__.on_contact = block
80
+ # Returns the x-coordinate position of the sprite.
81
+ #
82
+ # @return [Numeric] sprite position x
83
+ #
84
+ def x()
85
+ @view__.x
33
86
  end
34
87
 
35
- def contact?(&block)
36
- @view__.will_contact = block
88
+ # Set the x-coordinate position of the sprite.
89
+ #
90
+ # @param [Numeric] n sprite position x
91
+ #
92
+ # @return [Numeric] sprite position x
93
+ #
94
+ def x=(n)
95
+ @view__.x = n
96
+ n
37
97
  end
38
98
 
39
- def position()
40
- @view__.position.toVector
99
+ # Returns the y-coordinate position of the sprite.
100
+ #
101
+ # @return [Numeric] sprite position y
102
+ #
103
+ def y()
104
+ @view__.y
41
105
  end
42
106
 
43
- def position=(vector)
44
- @view__.position = vector.getInternal__
107
+ # Set the y-coordinate position of the sprite.
108
+ #
109
+ # @param [Numeric] n sprite position y
110
+ #
111
+ # @return [Numeric] sprite position y
112
+ #
113
+ def y=(n)
114
+ @view__.y = n
115
+ n
45
116
  end
46
117
 
118
+ alias pos position
119
+ alias pos= position=
120
+
121
+ # Returns the size of the sprite.
122
+ #
123
+ # @return [Vector] size
124
+ #
47
125
  def size()
48
126
  @view__.size.toVector
49
127
  end
50
128
 
51
- def image()
52
- @image__
129
+ # Returns the width of the sprite.
130
+ #
131
+ # @return [Numeric] width
132
+ #
133
+ def width()
134
+ @view__.width
53
135
  end
54
136
 
55
- def offset()
56
- @offset__
137
+ # Returns the height of the sprite.
138
+ #
139
+ # @return [Numeric] height
140
+ #
141
+ def height()
142
+ @view__.height
57
143
  end
58
144
 
145
+ alias w width
146
+ alias h height
147
+
148
+ # Returns the rotation angle of sprite.
149
+ #
150
+ # @return [Numeric] radians or degrees depending on angleMode()
151
+ #
152
+ def angle()
153
+ a, c = @view__.angle, @context__
154
+ c ? c.fromDegrees__(a) : a * Processing::GraphicsContext::DEG2RAD__
155
+ end
156
+
157
+ # Sets the rotation angle of sprite.
158
+ #
159
+ # @param [Numeric] angle radians or degrees depending on angleMode()
160
+ #
161
+ # @return [Numeric] angle
162
+ #
163
+ def angle=(angle)
164
+ c = @context__
165
+ @view__.angle =
166
+ c ? c.toAngle__(angle) : angle * Processing::GraphicsContext::RAD2DEG__
167
+ angle
168
+ end
169
+
170
+ # Returns the rotation center of sprite.
171
+ #
172
+ # @return [Array<Numeric>] [pivotX, pivotY]
173
+ #
174
+ def pivot()
175
+ @view__.pivot.to_a[0, 2]
176
+ end
177
+
178
+ # Sets the rotation center of sprite.
179
+ # [0.0, 0.0] is the left-top, [1.0, 1.0] is the right-bottom, and [0.5, 0.5] is the center.
180
+ #
181
+ # @param [Array<Numeric>] ary an array of pivotX and pivotY
182
+ #
183
+ # @return [Array<Numeric>] [pivotX, pivotY]
184
+ #
185
+ def pivot=(array)
186
+ @view__.pivot = array
187
+ pivot
188
+ end
189
+
190
+ # Returns the velocity of the sprite.
191
+ #
192
+ # @return [Vector] velocity
193
+ #
59
194
  def velocity()
60
195
  @view__.velocity.toVector
61
196
  end
62
197
 
63
- def velocity=(vector)
64
- @view__.velocity = vector.getInternal__
198
+ # Sets the velocity of the sprite.
199
+ #
200
+ # @overload velocity=(vec)
201
+ # @param [Vector] vec velocity vector
202
+ #
203
+ # @overload velocity=(ary)
204
+ # @param [Array<Numeric>] ary an array of velocityX and velocityY
205
+ #
206
+ # @return [Vector] velocity
207
+ #
208
+ def velocity=(arg)
209
+ @view__.velocity = arg.is_a?(Vector) ? arg.getInternal__ : arg
210
+ arg
65
211
  end
66
212
 
213
+ # Returns the x-axis velocity of the sprite.
214
+ #
215
+ # @return [Numeric] velocity.x
216
+ #
67
217
  def vx()
68
218
  @view__.velocity.x
69
219
  end
70
220
 
71
- def vx=(value)
72
- @view__.velocity = @view__.velocity.tap {|v| v.x = value}
73
- value
221
+ # Sets the x-axis velocity of the sprite.
222
+ #
223
+ # @param [Numeric] n x-axis velocity
224
+ #
225
+ # @return [Numeric] velocity.x
226
+ #
227
+ def vx=(n)
228
+ @view__.velocity = @view__.velocity.tap {|v| v.x = n}
229
+ n
74
230
  end
75
231
 
232
+ # Returns the y-axis velocity of the sprite.
233
+ #
234
+ # @return [Numeric] velocity.y
235
+ #
76
236
  def vy()
77
237
  @view__.velocity.y
78
238
  end
79
239
 
80
- def vy=(value)
81
- @view__.velocity = @view__.velocity.tap {|v| v.y = value}
82
- value
240
+ # Sets the y-axis velocity of the sprite.
241
+ #
242
+ # @param [Numeric] n y-axis velocity
243
+ #
244
+ # @return [Numeric] velocity.y
245
+ #
246
+ def vy=(n)
247
+ @view__.velocity = @view__.velocity.tap {|v| v.y = n}
248
+ n
249
+ end
250
+
251
+ alias vel velocity
252
+ alias vel= velocity=
253
+
254
+ # Returns the image of the sprite.
255
+ #
256
+ # @return [Image] sprite image
257
+ #
258
+ def image()
259
+ @image__
260
+ end
261
+
262
+ # Sets the sprite image.
263
+ #
264
+ # @param [Image] img sprite image
265
+ #
266
+ # @return [Image] sprite image
267
+ #
268
+ def image=(img)
269
+ @image__ = img
270
+ end
271
+
272
+ # Returns the offset of the sprite image.
273
+ #
274
+ # @return [Vector] offset of the sprite image
275
+ #
276
+ def offset()
277
+ @offset__
278
+ end
279
+
280
+ # Sets the offset of the sprite image.
281
+ #
282
+ # @overload offset=(vec)
283
+ # @param [Vector] vec offset
284
+ #
285
+ # @overload velocity=(ary)
286
+ # @param [Array<Numeric>] ary an array of offsetX and offsetY
287
+ #
288
+ # @return [Vector] offset of the sprite image
289
+ #
290
+ def offset=(arg)
291
+ @offset__ =
292
+ case arg
293
+ when Vector then arg
294
+ when Array then Vector.new(arg[0] || 0, arg[1] || 0)
295
+ when nil then nil
296
+ else raise ArgumentError
297
+ end
298
+ @offset__
299
+ end
300
+
301
+ # Returns the x-axis offset of the sprite image.
302
+ #
303
+ # @return [Numeric] offset.x
304
+ #
305
+ def ox()
306
+ @offset__&.x || 0
307
+ end
308
+
309
+ # Sets the x-axis offset of the sprite image.
310
+ #
311
+ # @param [Numeric] n x-axis offset
312
+ #
313
+ # @return [Numeric] offset.x
314
+ #
315
+ def ox=(n)
316
+ self.offset = [n, oy]
317
+ n
318
+ end
319
+
320
+ # Returns the y-axis offset of the sprite image.
321
+ #
322
+ # @return [Numeric] offset.y
323
+ #
324
+ def oy()
325
+ @offset__&.y || 0
326
+ end
327
+
328
+ # Sets the y-axis offset of the sprite image.
329
+ #
330
+ # @param [Numeric] n y-axis offset
331
+ #
332
+ # @return [Numeric] offset.y
333
+ #
334
+ def oy=(n)
335
+ self.offset = [ox, n]
336
+ end
337
+
338
+ # Returns whether the sprite is movable by the physics engine.
339
+ #
340
+ # @return [Boolean] true if dynamic
341
+ #
342
+ def dynamic?()
343
+ @view__.dynamic?
344
+ end
345
+
346
+ # Sets whether the sprite is movable by the physics engine.
347
+ #
348
+ # @param [Boolean] bool movable or not
349
+ #
350
+ # @return [Boolean] true if dynamic
351
+ #
352
+ def dynamic=(bool)
353
+ @view__.dynamic = bool
354
+ bool
355
+ end
356
+
357
+ # Returns the density of the sprite.
358
+ #
359
+ # @return [Numeric] density
360
+ #
361
+ def density()
362
+ @view__.density
363
+ end
364
+
365
+ # Sets the density of the sprite.
366
+ #
367
+ # @param [Numeric] n density
368
+ #
369
+ # @return [Numeric] density
370
+ #
371
+ def density=(n)
372
+ @view__.density = n
373
+ n
374
+ end
375
+
376
+ # Returns the friction of the sprite.
377
+ #
378
+ # @return [Numeric] friction
379
+ #
380
+ def friction()
381
+ @view__.friction
382
+ end
383
+
384
+ # Sets the friction of the sprite.
385
+ #
386
+ # @param [Numeric] n friction
387
+ #
388
+ # @return [Numeric] friction
389
+ #
390
+ def friction=(n)
391
+ @view__.friction = n
392
+ n
393
+ end
394
+
395
+ # Returns the restitution of the sprite.
396
+ #
397
+ # @return [Numeric] restitution
398
+ #
399
+ def restitution()
400
+ @view__.restitution
401
+ end
402
+
403
+ # Sets the restitution of the sprite.
404
+ #
405
+ # @param [Numeric] n restitution
406
+ #
407
+ # @return [Numeric] restitution
408
+ #
409
+ def restitution=(n)
410
+ @view__.restitution = n
411
+ n
83
412
  end
84
413
 
85
- alias pos position
86
- alias pos= position=
87
- alias vel velocity
88
- alias vel= velocity=
89
414
  alias dens density
90
415
  alias dens= density=
91
416
  alias fric friction
92
- alias fric= friction
417
+ alias fric= friction=
93
418
  alias rest restitution
94
419
  alias rest= restitution=
95
420
 
421
+ # Returns the x-position of the mouse in the sprite coordinates.
422
+ #
423
+ # @return [Numeric] x position
424
+ #
425
+ def mouseX()
426
+ @view__.mouseX
427
+ end
428
+
429
+ # Returns the y-position of the mouse in the sprite coordinates.
430
+ #
431
+ # @return [Numeric] y position
432
+ #
433
+ def mouseY()
434
+ @view__.mouseY
435
+ end
436
+
437
+ # Returns the previous x-position of the mouse in the sprite coordinates.
438
+ #
439
+ # @return [Numeric] x position
440
+ #
441
+ def pmouseX()
442
+ @view__.pmouseX
443
+ end
444
+
445
+ # Returns the previous y-position of the mouse in the sprite coordinates.
446
+ #
447
+ # @return [Numeric] y position
448
+ #
449
+ def pmouseY()
450
+ @view__.pmouseY
451
+ end
452
+
453
+ # Returns the mouse button clicked on the sprite.
454
+ #
455
+ # @return [LEFT, RIGHT, CENTER] mouse button
456
+ #
457
+ def mouseButton()
458
+ @view__.mouseButton
459
+ end
460
+
461
+ # Returns the touch objects touched on the sprite.
462
+ #
463
+ # @return [Array<Touch>] touches
464
+ #
465
+ def touches()
466
+ @view__.touches
467
+ end
468
+
469
+ # Defines update block.
470
+ #
471
+ # @example vx is updated every frame
472
+ # sprite.update do
473
+ # self.vx *= 0.9
474
+ # end
475
+ #
476
+ # @return [nil] nil
477
+ #
478
+ def update(&block)
479
+ @view__.update = block
480
+ end
481
+
482
+ # Defines draw block.
483
+ #
484
+ # @example Draw on your own before and after default drawing
485
+ # sprite.draw do |&defaultDrawSprite|
486
+ # rect 0, 0, 10, 10
487
+ # defaultDrawSprite.call
488
+ # text :hello, 10, 20
489
+ # end
490
+ #
491
+ # @return [nil] nil
492
+ #
493
+ def draw(&block)
494
+ @drawBlock__ = block
495
+ nil
496
+ end
497
+
498
+ # Defines mousePressed block.
499
+ #
500
+ # @example Print mouse states on mouse press
501
+ # sprite.mousePressed do
502
+ # p [sprite.mouseX, sprite.mouseY, sprite.mouseButton]
503
+ # end
504
+ #
505
+ # @return [nil] nil
506
+ #
507
+ def mousePressed(&block)
508
+ @view__.mousePressed = block
509
+ nil
510
+ end
511
+
512
+ # Defines mouseReleased block.
513
+ #
514
+ # @example Print mouse states on mouse release
515
+ # sprite.mouseReleased do
516
+ # p [sprite.mouseX, sprite.mouseY, sprite.mouseButton]
517
+ # end
518
+ #
519
+ # @return [nil] nil
520
+ #
521
+ def mouseReleased(&block)
522
+ @view__.mouseReleased = block
523
+ nil
524
+ end
525
+
526
+ # Defines mouseMoved block.
527
+ #
528
+ # @example Print mouse states on mouse move
529
+ # sprite.mouseMoved do
530
+ # p [sprite.mouseX, sprite.mouseY, sprite.pmouseX, sprite.pmouseY]
531
+ # end
532
+ #
533
+ # @return [nil] nil
534
+ #
535
+ def mouseMoved(&block)
536
+ @view__.mouseMoved = block
537
+ nil
538
+ end
539
+
540
+ # Defines mouseDragged block.
541
+ #
542
+ # @example Print mouse states on mouse drag
543
+ # sprite.mouseDragged do
544
+ # p [sprite.mouseX, sprite.mouseY, sprite.pmouseX, sprite.pmouseY]
545
+ # end
546
+ #
547
+ # @return [nil] nil
548
+ #
549
+ def mouseDragged(&block)
550
+ @view__.mouseDragged = block
551
+ nil
552
+ end
553
+
554
+ # Defines mouseClicked block.
555
+ #
556
+ # @example Print mouse states on mouse click
557
+ # sprite.mouseClicked do
558
+ # p [sprite.mouseX, sprite.mouseY, sprite.mouseButton]
559
+ # end
560
+ #
561
+ # @return [nil] nil
562
+ #
563
+ def mouseClicked(&block)
564
+ @view__.mouseClicked = block
565
+ nil
566
+ end
567
+
568
+ # Defines touchStarted block.
569
+ #
570
+ # @example Print touches on touch start
571
+ # sprite.touchStarted do
572
+ # p sprite.touches
573
+ # end
574
+ #
575
+ # @return [nil] nil
576
+ #
577
+ def touchStarted(&block)
578
+ @view__.touchStarted = block
579
+ nil
580
+ end
581
+
582
+ # Defines touchEnded block.
583
+ #
584
+ # @example Print touches on touch end
585
+ # sprite.touchEnded do
586
+ # p sprite.touches
587
+ # end
588
+ #
589
+ # @return [nil] nil
590
+ #
591
+ def touchEnded(&block)
592
+ @view__.touchEnded = block
593
+ nil
594
+ end
595
+
596
+ # Defines touchMoved block.
597
+ #
598
+ # @example Print touches on touch move
599
+ # sprite.touchMoved do
600
+ # p sprite.touches
601
+ # end
602
+ #
603
+ # @return [nil] nil
604
+ #
605
+ def touchMoved(&block)
606
+ @view__.touchMoved = block
607
+ nil
608
+ end
609
+
610
+ # Defines contact block.
611
+ #
612
+ # @example Score increases when the player sprite touches a coin
613
+ # playerSprite.contact do |o|
614
+ # score += 1 if o.coin?
615
+ # end
616
+ #
617
+ # @return [nil] nil
618
+ #
619
+ def contact(&block)
620
+ @view__.contact = block
621
+ end
622
+
623
+ # Defines contact? block.
624
+ #
625
+ # @example Only collide with an enemy
626
+ # playerSprite.contact? do |o|
627
+ # o.enemy?
628
+ # end
629
+ #
630
+ # @return [nil] nil
631
+ #
632
+ def contact?(&block)
633
+ @view__.will_contact = block
634
+ end
635
+
96
636
  # @private
97
637
  def getInternal__()
98
638
  @view__
99
639
  end
100
640
 
101
- class View < Reflex::View
102
- attr_accessor :update, :contact, :will_contact
103
- attr_reader :sprite
641
+ end# Sprite
104
642
 
105
- def initialize(sprite, *a, **k, &b)
106
- @sprite = sprite
107
- super(*a, **k, &b)
108
- end
109
643
 
110
- def on_update(e)
111
- @update.call if @update
112
- end
644
+ # @private
645
+ class SpriteView < Reflex::View
646
+
647
+ attr_accessor :update,
648
+ :mousePressed, :mouseReleased, :mouseMoved, :mouseDragged, :mouseClicked,
649
+ :touchStarted, :touchEnded, :touchMoved,
650
+ :contact, :will_contact
651
+
652
+ attr_reader :sprite, :touches
653
+
654
+ def initialize(sprite, *a, **k, &b)
655
+ @sprite = sprite
656
+ super(*a, **k, &b)
657
+
658
+ @pointerPos =
659
+ @pointerPrevPos = Rays::Point.new 0
660
+ @pointersPressed = []
661
+ @pointersReleased = []
662
+ @touches = []
663
+ end
664
+
665
+ def mouseX()
666
+ @pointerPos.x
667
+ end
668
+
669
+ def mouseY()
670
+ @pointerPos.y
671
+ end
672
+
673
+ def pmouseX()
674
+ @pointerPrevPos.x
675
+ end
676
+
677
+ def pmouseY()
678
+ @pointerPrevPos.y
679
+ end
680
+
681
+ def mouseButton()
682
+ ((@pointersPressed + @pointersReleased) & [LEFT, RIGHT, CENTER]).last
683
+ end
684
+
685
+ def on_update(e)
686
+ @update&.call
687
+ end
688
+
689
+ def on_pointer_down(e)
690
+ updatePointerStates e, true
691
+ @pointerDownStartPos = @pointerPos.dup
692
+ (@touchStarted || @mousePressed)&.call
693
+ end
113
694
 
114
- def on_contact(e)
115
- v = e.view
116
- @contact.call v.sprite, e.action if @contact && v.is_a?(View)
695
+ def on_pointer_up(e)
696
+ updatePointerStates e, false
697
+ (@touchEnded || @mouseReleased)&.call
698
+ if startPos = @pointerDownStartPos
699
+ @mouseClicked&.call if (@pointerPos - startPos).length < 3
700
+ @pointerDownStartPos = nil
117
701
  end
702
+ @pointersReleased.clear
703
+ end
704
+
705
+ def on_pointer_move(e)
706
+ updatePointerStates e
707
+ (@touchMoved || (e.drag? ? @mouseDragged : @mouseMoved))&.call
708
+ end
118
709
 
119
- def will_contact?(v)
120
- return true if !@will_contact || !v.is_a?(View)
121
- @will_contact.call v.sprite
710
+ def on_pointer_cancel(e)
711
+ on_pointer_up e
712
+ end
713
+
714
+ def on_contact(e)
715
+ v = e.view
716
+ @contact.call v.sprite, e.action if @contact && v.respond_to?(:sprite)
717
+ end
718
+
719
+ def will_contact?(v)
720
+ return true unless @will_contact && v.respond_to?(:sprite)
721
+ @will_contact.call v.sprite
722
+ end
723
+
724
+ private
725
+
726
+ MOUSE_BUTTON_MAP = {
727
+ mouse_left: Processing::GraphicsContext::LEFT,
728
+ mouse_right: Processing::GraphicsContext::RIGHT,
729
+ mouse_middle: Processing::GraphicsContext::CENTER
730
+ }
731
+
732
+ def updatePointerStates(event, pressed = nil)
733
+ @pointerPrevPos = @pointerPos
734
+ @pointerPos = event.pos.dup
735
+ @touches = event.pointers.map {|p| Touch.new(p.id, *p.pos.to_a)}
736
+ if pressed != nil
737
+ event.types
738
+ .tap {|types| types.delete :mouse}
739
+ .map {|type| MOUSE_BUTTON_MAP[type] || type}
740
+ .each do |type|
741
+ (pressed ? @pointersPressed : @pointersReleased).push type
742
+ @pointersPressed.delete type unless pressed
743
+ end
122
744
  end
123
745
  end
124
746
 
125
- end# Sprite
747
+ end# SpriteView
126
748
 
127
749
 
128
750
  end# RubySketch