さらにBox2D

まあ、画像をアップしてもよくわからないが。

マウスで物を掴んで動かせるようになった。
これでようやくよくあるサンプルレベルになってきたわけだ。

require 'rubygems'
require 'dxruby'
require 'box2d'

include Box2d

b = B2AABB.new
b.minVertex.set(0.0, 0.0) # 世界の左上
b.maxVertex.set(640.0, 480.0) # 世界の右下
gravity = B2Vec2.new(0, 200.0) # 重力
$world = B2World.new(b, gravity, true) # 世界作成


def getBodyAtMouse
  mousePVec = B2Vec2.new
  mouseX, mouseY = Input.mousePosX, Input.mousePosY
  mousePVec.set(mouseX, mouseY)
  aabb = B2AABB.new
  aabb.minVertex.set(mouseX - 0.001, mouseY - 0.001)
  aabb.maxVertex.set(mouseX + 0.001, mouseY + 0.001)
  # Query the world for overlapping shapes.
  k_maxCount = 10
  shapes = Array.new(10)
  count = $world.query(aabb, shapes, k_maxCount)
  body = nil
  for i in 0...count do
    if shapes[i].m_body.is_static == false
      inside = shapes[i].test_point(mousePVec)
      if inside
        body = shapes[i].m_body
        break
      end
    end
  end
  return body
end

# 四角
class Box
  attr_reader :body
  def initialize(x, y, width, height, density = 1.0, friction = 0.3, restitution = 0.5)
    @width = width
    @height = height
    boxDef = B2BoxDef.new
    boxDef.extents.set(width/2, height/2)
    boxDef.density = density # 密度・・??とりあえず0にすると落ちない
    boxDef.friction = friction # 摩擦
    boxDef.restitution = restitution # 反発係数。これらは0.0〜1.0で設定する
    bodyDef = B2BodyDef.new
    bodyDef.position.set(x + width/2, y + height/2)
    bodyDef.add_shape(boxDef)
    @body = $world.create_body(bodyDef)
    @image = Image.new(width, height).box(0, 0, width-1, height-1, [255,255,255])
  end

  def draw
    pos = @body.get_origin_position()
    rot = @body.get_rotation()
    Window.drawRot(pos.x-@width/2, pos.y-@height/2, @image, rot / Math::PI * 180)
  end
end

# 丸
class Circle
  def initialize(x, y, r, density = 1.0, friction = 0.0, restitution = 0.5)
    @r = r
    circleDef = B2CircleDef.new
    circleDef.radius = r
    circleDef.density = density # 密度・・??とりあえず0にすると落ちない
    circleDef.friction = friction # 摩擦
    circleDef.restitution = restitution # 反発係数。これらは0.0〜1.0で設定する
    bodyDef = B2BodyDef.new
    bodyDef.position.set(x + r, y + r)
    bodyDef.add_shape(circleDef)
    @body = $world.create_body(bodyDef)
    @image = Image.new(r*2-1, r*2-1).circle(r-1, r-1, r-1, [255,255,255])
  end

  def draw
    pos = @body.get_origin_position()
    rot = @body.get_rotation()
    Window.draw(pos.x-@r+1, pos.y-@r+1, @image)
  end
end

# 四角作成
body = Array.new(20) do
  Box.new(rand(520)+40,rand(300), 30, 60)
end

# 丸追加
body += Array.new(20) do
  Circle.new(rand(480)+40,rand(300), 30)
end

# 枠作成
body.push Box.new(0, 440, 640, 40, 0)
body.push Box.new(0, 0, 40, 440, 0)
body.push Box.new(600, 0, 40, 440, 0)

timeStep = 1.0 / 60.0
iterations = 10

m_mouseJoint = nil

Window.loop do
  if Input.mousePush?(M_LBUTTON)
    temp_body = getBodyAtMouse
    if temp_body
      md = B2MouseJointDef.new
      md.body1 = $world.m_groundBody
      md.body2 = temp_body
      md.target.set(Input.mousePosX, Input.mousePosY)
      md.maxForce = 30000.0 * temp_body.m_mass
      md.timeStep = timeStep
      m_mouseJoint = $world.create_joint(md).get_as_mouse_joint
      temp_body.wake_up
    end
  end
  if m_mouseJoint
    if Input.mouseDown?(M_LBUTTON)
      p2 = B2Vec2.new(Input.mousePosX, Input.mousePosY)
      m_mouseJoint.set_target(p2)
    else
      $world.destroy_joint(m_mouseJoint)
      m_mouseJoint = nil
    end
  end

  # 世界を動かす
  $world.step(timeStep, iterations)

  # 描画
  body.each do |b|
    b.draw
  end

  break if Input.keyPush?(K_ESCAPE)
end