Class: Smalruby::Character

Inherits:
Sprite
  • Object
show all
Extended by:
Forwardable, Mutex_m
Defined in:
lib/smalruby/character.rb

Overview

キャラクターを表現するクラス

Direct Known Subclasses

Canvas, Console

動き collapse

Instance Attribute Summary collapse

動き collapse

見た目 collapse

調べる collapse

collapse

ハードウェア collapse

Instance Method Summary collapse

Constructor Details

#initialize(option = {}) ⇒ Character

Returns a new instance of Character.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/smalruby/character.rb', line 28

def initialize(option = {})
  defaults = {
    x: 0,
    y: 0,
    costume: nil,
    angle: 0,
    visible: true,
    rotation_style: :free
  }
  opt = process_optional_arguments(option, defaults)

  # TODO: コスチュームの配列に対応する
  if opt[:costume].is_a?(String)
    opt[:costume] = Image.load(asset_path(opt[:costume]))
  end
  super(opt[:x], opt[:y], opt[:costume])

  @event_handlers = {}
  @threads = []
  @checking_hit_targets = []
  @angle = 0 unless Util.windows?

  self.scale_x = 1.0
  self.scale_y = 1.0
  @vector = { x: 1, y: 0 }

  [:visible].each do |k|
    if opt.key?(k)
      send("#{k}=", opt[k])
    end
  end

  self.angle = opt[:angle] if opt[:angle] != 0

  self.rotation_style = opt[:rotation_style]

  # HACK: Windows XP SP3の環境でワーカースレッドで音声を読み込めな
  # い不具合が発生した。このためメインスレッドでプリロードしておく。
  %w(do re mi fa so ra si do_2).each do |n|
    new_sound("piano_#{n}.wav")
  end

  World.instance.objects << self
end

Instance Attribute Details

#angleObject

角度



125
126
127
# File 'lib/smalruby/character.rb', line 125

def angle
  @angle
end

#checking_hit_targetsObject

Returns the value of attribute checking_hit_targets.



24
25
26
# File 'lib/smalruby/character.rb', line 24

def checking_hit_targets
  @checking_hit_targets
end

#event_handlersObject

Returns the value of attribute event_handlers.



22
23
24
# File 'lib/smalruby/character.rb', line 22

def event_handlers
  @event_handlers
end

#rotation_styleObject

Returns the value of attribute rotation_style.



26
27
28
# File 'lib/smalruby/character.rb', line 26

def rotation_style
  @rotation_style
end

#threadsObject

Returns the value of attribute threads.



23
24
25
# File 'lib/smalruby/character.rb', line 23

def threads
  @threads
end

Instance Method Details

#alive?Boolean

Returns:

  • (Boolean)


398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
# File 'lib/smalruby/character.rb', line 398

def alive?
  @threads.delete_if { |t|
    if t.alive?
      false
    else
      begin
        t.join
      rescue => e
        Util.print_exception(e)
        exit(1)
      end
      true
    end
  }
  @threads.length > 0
end

#button(pin) ⇒ Object

ボタン



284
285
286
# File 'lib/smalruby/character.rb', line 284

def button(pin)
  Hardware.create_hardware(Hardware::Button, pin)
end

#button_down(pin) ⇒ Object



391
392
393
394
395
396
# File 'lib/smalruby/character.rb', line 391

def button_down(pin)
  @event_handlers[:button_down].try(:each) do |h|
    next unless h.options.include?(pin)
    @threads << h.call
  end
end

#button_up(pin) ⇒ Object



384
385
386
387
388
389
# File 'lib/smalruby/character.rb', line 384

def button_up(pin)
  @event_handlers[:button_up].try(:each) do |h|
    next unless h.options.include?(pin)
    @threads << h.call
  end
end

#click(buttons) ⇒ Object



355
356
357
358
359
360
361
362
# File 'lib/smalruby/character.rb', line 355

def click(buttons)
  @event_handlers[:click].try(:each) do |h|
    if h.options.length > 0 && !h.options.any? { |b| buttons.include?(b) }
      next
    end
    @threads << h.call(Input.mouse_pos_x, Input.mouse_pos_y)
  end
end

#distance(x, y) ⇒ Object

距離



217
218
219
220
# File 'lib/smalruby/character.rb', line 217

def distance(x, y)
  Math.sqrt((self.x + center_x - x).abs**2 +
            (self.y + center_y - y).abs**2).to_i
end

#drawObject



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'lib/smalruby/character.rb', line 295

def draw
  draw_balloon

  if self.x < 0
    self.x = 0
  elsif self.x + image.width >= Window.width
    self.x = Window.width - image.width
  end
  if self.y < 0
    self.y = 0
  elsif self.y + image.height >= Window.height
    self.y = Window.height - image.height
  end
  super
end

#hitObject



364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/smalruby/character.rb', line 364

def hit
  # TODO: なんでもいいからキャラクターに当たった場合に対応する
  @checking_hit_targets &= World.instance.objects
  objects = check(@checking_hit_targets)
  return if objects.empty?
  @event_handlers[:hit].try(:each) do |h|
    if h.options.length > 0 && !h.options.any? { |o| objects.include?(o) }
      next
    end
    @threads << h.call(h.options & objects)
  end
end

#hit?(other) ⇒ Boolean

Returns:

  • (Boolean)


237
238
239
# File 'lib/smalruby/character.rb', line 237

def hit?(other)
  check([other]).length > 0
end

#joinObject



415
416
417
# File 'lib/smalruby/character.rb', line 415

def join
  @threads.each(&:join)
end

#key_down(keys) ⇒ Object



337
338
339
340
341
342
343
344
# File 'lib/smalruby/character.rb', line 337

def key_down(keys)
  @event_handlers[:key_down].try(:each) do |h|
    if h.options.length > 0 && !h.options.any? { |k| keys.include?(k) }
      next
    end
    @threads << h.call
  end
end

#key_push(keys) ⇒ Object



346
347
348
349
350
351
352
353
# File 'lib/smalruby/character.rb', line 346

def key_push(keys)
  @event_handlers[:key_push].try(:each) do |h|
    if h.options.length > 0 && !h.options.any? { |k| keys.include?(k) }
      next
    end
    @threads << h.call
  end
end

#led(pin) ⇒ Object

LED



259
260
261
# File 'lib/smalruby/character.rb', line 259

def led(pin)
  Hardware.create_hardware(Hardware::Led, pin)
end

#loopObject



419
420
421
422
423
424
# File 'lib/smalruby/character.rb', line 419

def loop
  Kernel.loop do
    yield
    Smalruby.await
  end
end

#move(val = 1) ⇒ Object

( )歩動かす



76
77
78
79
# File 'lib/smalruby/character.rb', line 76

def move(val = 1)
  self.x += @vector[:x] * val
  self.y += @vector[:y] * val
end

#move_back(val = 1) ⇒ Object

( )歩後ろに動かす



82
83
84
# File 'lib/smalruby/character.rb', line 82

def move_back(val = 1)
  move(-val)
end

#on(event, *options, &block) ⇒ Object



311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/smalruby/character.rb', line 311

def on(event, *options, &block)
  event = event.to_sym
  @event_handlers[event] ||= []
  h = EventHandler.new(self, options, &block)
  @event_handlers[event] << h

  case event
  when :start
    @threads << h.call if Smalruby.started?
  when :hit
    @checking_hit_targets << options
    @checking_hit_targets.flatten!
    @checking_hit_targets.uniq!
  when :sensor_change
    sensor(options.first)
  when :button_up, :button_down
    button(options.first)
  end
end

#play(option = {}) ⇒ Object



245
246
247
248
249
250
251
252
# File 'lib/smalruby/character.rb', line 245

def play(option = {})
  defaults = {
    name: 'piano_do.wav'
  }
  opt = process_optional_arguments(option, defaults)

  new_sound(opt[:name]).play
end

#point_towards(target) ⇒ Object

( )に向ける



154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/smalruby/character.rb', line 154

def point_towards(target)
  if target == :mouse
    tx = Input.mouse_pos_x
    ty = Input.mouse_pos_y
  else
    tx = target.x
    ty = target.y
  end
  dx = tx - x
  dy = ty - y
  self.angle = Math.atan2(dy, dx) * 180 / Math::PI
end

#reach_left_or_right_wall?Boolean

左右の端に着いた?

Returns:

  • (Boolean)


228
229
230
# File 'lib/smalruby/character.rb', line 228

def reach_left_or_right_wall?
  self.x < 0 || self.x >= (Window.width - image.width)
end

#reach_top_or_bottom_wall?Boolean

上下の端に着いた?

Returns:

  • (Boolean)


233
234
235
# File 'lib/smalruby/character.rb', line 233

def reach_top_or_bottom_wall?
  self.y < 0 || self.y >= (Window.height - image.height)
end

#reach_wall?Boolean

端に着いた?

Returns:

  • (Boolean)


223
224
225
# File 'lib/smalruby/character.rb', line 223

def reach_wall?
  reach_left_or_right_wall? || reach_top_or_bottom_wall?
end

#rgb_led_anode(pin) ⇒ Object

RGB LED(アノード)



264
265
266
# File 'lib/smalruby/character.rb', line 264

def rgb_led_anode(pin)
  Hardware.create_hardware(Hardware::RgbLedAnode, pin)
end

#rgb_led_cathode(pin) ⇒ Object

RGB LED(カソード)



269
270
271
# File 'lib/smalruby/character.rb', line 269

def rgb_led_cathode(pin)
  Hardware.create_hardware(Hardware::RgbLedCathode, pin)
end

#rotate(angle) ⇒ Object

( )度回転する



115
116
117
# File 'lib/smalruby/character.rb', line 115

def rotate(angle)
  self.angle += angle
end

#say(options = {}) ⇒ Object



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/smalruby/character.rb', line 171

def say(options = {})
  defaults = {
    message: '',
    second: 0,
  }
  opts = process_optional_arguments(options, defaults)

  if @balloon
    @balloon.vanish
    @balloon = nil
  end

  message = opts[:message].to_s
  return if message.empty?

  lines = message.to_s.lines.map { |l| l.scan(/.{1,10}/) }.flatten
  font = new_font(16)
  width = lines.map { |l| font.get_width(l) }.max
  height = lines.length * (font.size + 1)
  frame_size = 3
  margin_size = 3
  image = Image.new(width + (frame_size + margin_size) * 2,
                    height + (frame_size + margin_size) * 2)
  image.box_fill(0,
                 0,
                 width + (frame_size + margin_size) * 2 - 1,
                 height + (frame_size + margin_size) * 2 - 1,
                 [125, 125, 125])
  image.box_fill(frame_size,
                 frame_size,
                 width + (frame_size + margin_size) + margin_size - 1,
                 height + (frame_size + margin_size) + margin_size - 1,
                 [255, 255, 255])
  lines.each.with_index do |line, row|
    image.draw_font(frame_size + margin_size,
                    frame_size + margin_size + (font.size + 1) * row,
                    line, font, [0, 0, 0])
  end
  @balloon = Sprite.new(self.x, self.y, image)
end

#sensor(pin) ⇒ Object

汎用的なセンサー



289
290
291
# File 'lib/smalruby/character.rb', line 289

def sensor(pin)
  Hardware.create_hardware(Hardware::Sensor, pin)
end

#sensor_change(pin, value) ⇒ Object



377
378
379
380
381
382
# File 'lib/smalruby/character.rb', line 377

def sensor_change(pin, value)
  @event_handlers[:sensor_change].try(:each) do |h|
    next unless h.options.include?(pin)
    @threads << h.call(value)
  end
end

#servo(pin) ⇒ Object

サーボモーター



274
275
276
# File 'lib/smalruby/character.rb', line 274

def servo(pin)
  Hardware.create_hardware(Hardware::Servo, pin)
end

#startObject



331
332
333
334
335
# File 'lib/smalruby/character.rb', line 331

def start
  @event_handlers[:start].try(:each) do |h|
    @threads << h.call
  end
end

#turnObject

くるっと振り返る



87
88
89
# File 'lib/smalruby/character.rb', line 87

def turn
  sync_angle(@vector[:x] * -1, @vector[:y] * -1)
end

#turn_if_reach_wallObject

もし端に着いたら、跳ね返る



102
103
104
105
106
107
108
109
110
111
112
# File 'lib/smalruby/character.rb', line 102

def turn_if_reach_wall
  lr = reach_left_or_right_wall?
  tb = reach_top_or_bottom_wall?
  if lr && tb
    turn
  elsif lr
    turn_x
  elsif tb
    turn_y
  end
end

#turn_xObject

横に振り返る



92
93
94
# File 'lib/smalruby/character.rb', line 92

def turn_x
  sync_angle(@vector[:x] * -1, @vector[:y])
end

#turn_yObject

縦に振り返る



97
98
99
# File 'lib/smalruby/character.rb', line 97

def turn_y
  sync_angle(@vector[:x], @vector[:y] * -1)
end

#two_wheel_drive_car(pin) ⇒ Object

2WD車



279
280
281
# File 'lib/smalruby/character.rb', line 279

def two_wheel_drive_car(pin)
  Hardware.create_hardware(Hardware::TwoWheelDriveCar, pin)
end