love2d教程17--物理引擎1

好几天没更新了,有一些主观和客观原因,实在惭愧,不过从今日开始还是保证每周至少两篇
直到正式开始复刻.
love的物理引擎基于box2d(著名的2d物理引擎,愤怒的小鸟就使用此引擎),可见
love在物理上的强大,而且api和box2d也是对应的,方便了移植和学习.

(网上流行的box2d大多是2.0.x版,love2d的box2d我想至少是2.1.x,请注意区别)
首先摘录一段box2d中文手册(我已放到doc目录下)的核心概念
"Box2D中有一些基本对象, 这里我们先做一个简要的定义, 随后的文档会有更详细的描述。
形状(shape)
2D几何对象, 比如圆形(circle)或多边形(polygon)。
刚体(rigid body)
十分坚硬的物质, 坚硬得像钻石,它上面任意两点之间的距离都保持不变。在后面的讨论中,我们用
物体(body)来代替刚体。
夹具(fixture)
fixture将形状绑定到物体之上, 并有一定的材质属性, 比如密度(density), 摩擦(friction)和恢复
(restitution)。
(译注:一个物体和另一物体碰撞, 碰撞后速度和碰撞前速度的比值会保持不变,这比值就叫恢复系数
。)
约束(constraint)
约束是个物理连接, 用于消除物体的自由度。在2D中, 物体有3个自由度(水平,垂直,旋转)。如果我
们把一个物体钉在墙上(像钟摆那样), 那就把它约束到了墙上。这个时候,此物体就只能绕着钉子旋转
, 所以这个约束消除了它2个自由度。
(译注:简单的说, 需要用几个参数来确定物体的空间状态, 这个物体就有几个自由度。在二维中,完全
没有约束的条件下, 我们要确定物体的状态, 要有x坐标, y坐标, 旋转角这三个参数, 所以自由度为3。
如果物体被钉在墙上, 只要有旋转角,就可以完全确定物体的状态,有了钉子这个约束,物体自由度
就变成了1。)
接触约束(contact constraint)
一种特殊的约束, 设计的目的是为了防止刚体被穿透, 也用于模拟摩擦和恢复。接触约束不用你来创
建, 它们会自动被Box2D生成。
关节(joint)
关节就是种约束, 用于将两个或多个body固定到一起。Box2D支持不同的关节类型:转动(revolute),棱
柱(prismatic),距离(distance)等。一些关节可以有限制(limits)和马达(motors)。
关节限制(joint limit)
关节限制限定了一个关节的运动范围。例如人类的胳膊肘只能在某一角度范围内运动。
关节马达(joint motor)
根据关节的自由度, 关节马达可以驱动关节所连接的物体。例如, 你可以使用一个马达来驱动一个
肘的旋转。
世界(world)
一个物理世界就是各种, 刚体(bodies), 夹具(fixtures), 约束(constraints)相互作用的集合。 Box2D支持创
建多个世界, 但这通常没有必要。"

box2d对物理世界的模拟很逼真,采用的是mks单位(即国际单位),内部使用高精度的物理公式来模拟,
它只负责计算.因此我们使用上先要设置像素和长度的转换系数,把需要模拟的参数传给box2d,再从box2d
里得到计算后的结果,从而显示结果.

在love2d里使用物理引擎,基本步骤如下
1.创建一个世界,在love2d 0.8里有如下两个方法
--水平加速度,竖直加速度,是否休眠(即物体停止运动时,不再模拟,这样可以减少开销)
world=love.physics.newWorld( xg, yg, sleep )
--最小的点坐标,最大的点坐标,后面同上
worldlove.physics.newWorld( x1, y1, x2, y2, xg, yg, sleep )
2.创建物体
--物体所在的世界,物体在世界里的坐标,物体的类型("static"静止,"dynamic"运动)
body=love.physics.newBody( world, x, y, type )
3.创建形状
shape=love.physics.new具体形状
4.创建夹具(可以看看百科)
fixture=love.physics.newFixture(body,shape,密度)
5.更新
在love.update(dt)里
world:update(dt)
6. 显示
使用如下的方法得到计算的结果
body:getWorldPoints(shape:getPoints())
我们就可以在love.draw()里绘制我们的图形了.
7.当然每种类型都有自己的函数,可以根据需要来设置
8. 还有Joint可以用来连接物体创建组合体,Contact用来碰撞检测

下面的代码来自官方教程,略作修改.运行后你会发现box2d很强大.
我们并没有处理碰撞,但它已经帮我们处理好了.
这是关于box2d的一些文章,可以看看.

main.lua

function love.load()
  love.graphics.setBackgroundColor(104, 136, 248) --设置背景为蓝色
  love.graphics.setMode(650, 650, false, true, 0) --设置窗口650*650,不全屏,开启垂直同步,全屏抗锯齿缓存0

  --下面是物理引擎的使用
  love.physics.setMeter(64) --设置64px(像素)为1米,box2d使用实际的物理体系单位
  world = love.physics.newWorld(0, 9.81*64, true) --创建一个世界,其水平加速度为0,竖直9.81m/s(即地球)

  objects = {} -- 物理对象table

  --创建地面
  objects.ground = {}
  objects.ground.body = love.physics.newBody(world, 650/2, 650-50/2)  --创建一个静态物体, 在世界world中的位置是(650/2, 650-50/2)
  objects.ground.shape = love.physics.newRectangleShape(650, 50)   --创建一个矩形
  objects.ground.fixture = love.physics.newFixture(objects.ground.body, objects.ground.shape)  --把矩形附加到物体

  --创建一个球
  objects.ball = {}
  objects.ball.body = love.physics.newBody(world, 650/2, 650/2, "dynamic") --创建一个动态物体
  objects.ball.shape = love.physics.newCircleShape(20) --创建一个圆形
  objects.ball.fixture = love.physics.newFixture(objects.ball.body, objects.ball.shape, 1) --把圆形附加到物体上,密度为1
  objects.ball.fixture:setRestitution(0.7) --反弹系数,即碰撞反弹后速度为原来的0.7倍

  --创建一些方块
  objects.block1 = {}
  objects.block1.body = love.physics.newBody(world, 200, 550, "dynamic")
  objects.block1.shape = love.physics.newRectangleShape(0, 0, 50, 100)  --竖直的方块
  objects.block1.fixture = love.physics.newFixture(objects.block1.body, objects.block1.shape, 5) --密度比球大,质量更大

  objects.block2 = {}
  objects.block2.body = love.physics.newBody(world, 200, 650/2, "dynamic")
  objects.block2.shape = love.physics.newRectangleShape(0, 0, 100, 50)  --水平的方块
  objects.block2.fixture = love.physics.newFixture(objects.block2.body, objects.block2.shape, 2)


end


function love.update(dt)
  world:update(dt)


  if love.keyboard.isDown("right") then
    objects.ball.body:applyForce(400, 0) --给球(400,0)牛的力,力是矢量,即沿x轴正方向400,y轴正方向0
  elseif love.keyboard.isDown("left") then
    objects.ball.body:applyForce(-400, 0) --给球(-400,0)牛的力
  elseif love.keyboard.isDown("up") then
    objects.ball.body:applyForce(0,-400)
  end
end

function love.draw()
  love.graphics.setColor(72, 160, 14) -- 绿色,用来画地面
  love.graphics.polygon("fill", objects.ground.body:getWorldPoints(objects.ground.shape:getPoints()))--使用地面坐标画多边形

  love.graphics.setColor(193, 47, 14) --红色,用来画球
  love.graphics.circle("fill", objects.ball.body:getX(), objects.ball.body:getY(), objects.ball.shape:getRadius())

  love.graphics.setColor(50, 50, 50) --灰色,用来画方块
  love.graphics.polygon("fill", objects.block1.body:getWorldPoints(objects.block1.shape:getPoints()))
  love.graphics.polygon("fill", objects.block2.body:getWorldPoints(objects.block2.shape:getPoints()))
end

 

代码下载(已clone的直接git pull)
git clone git://gitcafe.com/dwdcth/love2d-tutor.git
或git clone https://github.com/dwdcth/mylove2d-tutor-in-chinese.git

posted @ 2013-01-26 11:36  半山无极  阅读(...)  评论(...编辑  收藏