image

  • フォト Amazonギフト券
    ※この時計の時刻は、閲覧しているパソコンのものであり、必ずしも正確な時間とは限りません

検索

最近のトラックバック

無料ブログはココログ

« ピックアップ:アップルが密かにシェアを上げている理由, 見えない仕事, etc... | トップページ | ピックアップ:DokuWikiを持ち歩く, mixi規約改定騒動まとめ, etc... »

2008-03-05

ruby + tk の練習

突然はなしが変わってRuby/Tkでアニメーションを作る話
   http://d.hatena.ne.jp/miura1729/20080302/1204443134

 

という記事のコードを基に、自分なりにすこし変形させてみた。
ビリヤードゲームでのボールの動きを真似してみた。
(下は動画ではありません、スイマセン)

20080305ball

ボールが 壁に反射した時/床を転がる時に だんだんと速度を落としていくようになっています。

$ cat ball2.rb

# See http://d.hatena.ne.jp/miura1729/20080302/1204443134

require 'rubygems'
require 'tk'
require 'singleton'

class Viewer < TkFrame
  include TkComposite

  WIDTH, HEIGHT = 512, 512

  def initialize_composite
    @frame.configure(:width=>WIDTH, :height=>HEIGHT)
    @frame.grid_propagate(false)

    @canvas = TkCanvas.new(@frame)
    @canvas.configure(:width=>WIDTH, :height=>HEIGHT)
    @canvas.grid('row'=>0, 'column'=>0, 'sticky'=>'news')
  end

  def draw_oval(x, y, r)
    TkcOval.new(@canvas, x - r, y - r, x + r, y + r, 'fill' => :red)
  end
end

class Field
  include Singleton

  def initialize
    @view = Viewer.new
    @view.pack(:expand=>true, :fill=>:both)
  end

  def draw_oval(x, y, r)
    @view.draw_oval(x, y, r)
  end
end

class Ball
  @@field = Field.instance

  def initialize(r, x, y, vx = 0, vy = 0, factorWall = 0.9, factorFloor= 0.99, minSpeed = 0.05)
    @r, @x, @y, = r, x, y
    @vx, @vy = vx, vy
    @shape = @@field.draw_oval(@x, @y, @r)
    @factorWall = factorWall
    @factorFloor = factorFloor
    @minSpeed = minSpeed
  end

  def resetV(v)
    @vx, @vy = v[0], v[1]
  end

  def redraw
    @shape.coords = [ @x - @r, @y - @r, @x + @r, @y + @r ]
  end

  def speeddownByWall
    @vx, @vy = @vx * @factorWall, @vy * @factorWall
  end

  def speeddownByFloor
    @vx, @vy = @vx * @factorFloor, @vy * @factorFloor
  end

  def compute_next_pos
    speeddownByFloor
    @x += @vx
    @y += @vy

    if (@y <= @r) || (Viewer::HEIGHT - @r <= @y) then
      @vy *= (-1)
      @y += @vy
      speeddownByWall
    end
    if (@x <= @r) || (Viewer::WIDTH - @r <= @x) then
      @vx *= (-1)
      @x += @vx
      speeddownByWall
    end

    if (@vx.abs + @vy.abs) < @minSpeed then
      return false    # delete Ball
    end

    redraw
    return true       # move Ball
  end
end

def newBall
  v = newV
  Ball.new(@r, @initX, @initY, v[0], v[1])
end

def newV
  th = rand * Math::PI * 2
  [@vx * Math.cos(th), @vy * Math.sin(th)]
end

@r = 10
@vx, @vy = 30, 30
@initX, @initY = 15 + @r , 15 + @r

balls = [ newBall ]

steps = 0
timer = TkAfter.start(10, -1, lambda {
  steps += 1

  balls.each do |ball|
    ball.resetV(newV)  if !ball.compute_next_pos
  end

  balls << newBall  if steps % 500 == 0
  # puts balls.size   if steps % 500 == 0
})

Tk.mainloop

ちょっと長くなってしまった。

同様のものを xfy/xvcd + SVG で書いたらどうなるだろう...

« ピックアップ:アップルが密かにシェアを上げている理由, 見えない仕事, etc... | トップページ | ピックアップ:DokuWikiを持ち歩く, mixi規約改定騒動まとめ, etc... »

コメント

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: ruby + tk の練習:

« ピックアップ:アップルが密かにシェアを上げている理由, 見えない仕事, etc... | トップページ | ピックアップ:DokuWikiを持ち歩く, mixi規約改定騒動まとめ, etc... »

mokuji

2013年12月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        

google

  • twitter
  • __
  • _
    Googleボットチェッカー

合わせて読む

  • 合わせて読む
    フィードメーター - katoy: cocolog あわせて読みたい

リンク