love2d教程24--碰撞跳跃
只要做一些可以运动的游戏,碰撞检测会成为家常便饭,简单的只要判断一下两个物体
的坐标关系就可以了;复杂的则需要比较高级的算法。box2d里自带碰撞检测,它采用
的是连续碰撞检测(在文档上看的,我也不知具体为何),可是我们并不想对整个游戏
里角色都使用物理引擎。虽然可以只用它的碰撞检测,但是也挺麻烦的(不用box2d管
理坐标,而是我们自己设置,之后把坐标传给box2d,再从box2d里获取)。而且我想
做一个通用的碰撞管理类,我用box2d试了一下,可是它的坐标系是在物体中心,而
love2d的坐标系是左顶点,而且我又比较懒,看到love2d的wiki上有做好的碰撞检测
(叫hardoncollider),便直接拿来用了。
从hardoncollider的介绍来看,功能还是很强大的,可以检测多边形,圆形甚至凹形。
至于碰撞检测算法,我估计它采用的是网格法,即把屏幕当做网,如下图
注意网格的宽度要与检测的物体宽度相当,否则会出现检测不准。我猜想可能可能是判
断网格里出现的物体个数来判断是否相碰,若哪位读者知道,请不吝赐教。
下面介绍如何使用。
1、首先加载,hardoncollider已经帮我们生成了一个对象,直接在require时接收,即
HC = require 'hardoncollider'
2、在love.load里使用HC(cell_size, callback_collide, callback_stop)创建一个检测
器Collider,其中的参数都可省略,分别表示网格大小、碰撞发生时的回调、碰撞完成
后的回调。
3、向检测器里添加要检测的形状,如Collider:add****,这个函数会返回一个形状
4、更新
注意还有回调函数,on_collide(dt, shape_a, shape_b),函数名和参数名任意,
参数分别表示 时间间隔、相碰的形状a、相碰的形状b,我们要在这个函数里处理这些
形状的运动、形变、旋转等。以及运动move(dx,dy)、moveTo(x,y),分别表示每帧
运动距离、一次运动到坐标。
那么如何得到坐标呢,我找了半天居然是center(),它返回形状的中心坐标x、y。
下面是官网的一个例子。
HC = require 'hardoncollider' function on_collide(dt, shape_a, shape_b) -- 判断shape_a,shape_b是哪个形状 local other if shape_a == ball then other = shape_b elseif shape_b == ball then other = shape_a else -- 都不是退出 return end -- 重置目的地 if other == goalLeft then ball.velocity = {x = 100, y = 0} ball:moveTo(400,300) elseif other == goalRight then ball.velocity = {x = -100, y = 0} ball:moveTo(400,300) elseif other == borderTop or other == borderBottom then -- 碰到底部或顶部反弹 ball.velocity.y = -ball.velocity.y else -- 碰到挡板后反弹 local px,py = other:center() local bx,by = ball:center() local dy = by - py ball.velocity.x = -ball.velocity.x ball.velocity.y = dy -- 保持速度 local len = math.sqrt(ball.velocity.x^2 + ball.velocity.y^2) ball.velocity.x = ball.velocity.x / len * 100 ball.velocity.y = ball.velocity.y / len * 100 end end function love.load() --创建一个检测器 Collider = HC(5, on_collide) --创建一个圆形 ball = Collider:addCircle(400,300, 10) ball.velocity = {x = -100, y = 0} --挡板 paddleLeft = Collider:addRectangle(10,250, 20,100) paddleRight = Collider:addRectangle(770,250, 20,100) --顶部、底部 borderTop = Collider:addRectangle(0,-100, 800,100) borderBottom = Collider:addRectangle(0,600, 800,100) goalLeft = Collider:addRectangle(-100,0, 100,600) goalRight = Collider:addRectangle(800,0, 100,600) end function love.update(dt) ball:move(ball.velocity.x * dt, ball.velocity.y * dt) Collider:update(dt) end function love.draw() --绘图 ball:draw('fill',16) paddleLeft:draw('fill') paddleRight:draw('fill') end
hardoncollider还有其它的类,可以分开使用,具体的看官网的例子,或者我的附件。
接下来说一下跳跃,跳跃时要注意起跳和落下的情况的处理,多设置几个变量就可以
解决,还是有点麻烦的(这时便想起了box2d的方便,可惜不好集成)。
下面是我做的一个效果:
由于我使用的是矩形,所以在碰撞是有点问题。代码写的有点乱,看看可以不必深究。
我把碰撞分到了两个类里了,role和gmwold,role类管理运动,创建时要指定形状(
使用hardoncollider里的shape),gmworld管理碰撞并处理碰撞的效果。我把role分
为了"dynamic、wall、ladder",表示角色、墙、梯子,这样方便在gmwold里管理角色
,当然可能还有更具体的要做如子弹等。
还有很多没完成,先放出测试代码,点击下载。如果你有更好的想法,请不吝告知。
作者:半山
出处:http://www.cnblogs.com/xdao/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。