好几天没更新了,有一些主观和客观原因,实在惭愧,不过从今日开始还是保证每周至少两篇
直到正式开始复刻.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. 还有可以用来连接物体创建组合体,用来碰撞检测下面的代码来自官方,略作修改.运行后你会发现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)endfunction 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) endendfunction 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