love2d教程24--碰撞跳跃

只要做一些可以运动的游戏,碰撞检测会成为家常便饭,简单的只要判断一下两个物体

的坐标关系就可以了;复杂的则需要比较高级的算法。box2d里自带碰撞检测,它采用

的是连续碰撞检测(在文档上看的,我也不知具体为何),可是我们并不想对整个游戏

里角色都使用物理引擎。虽然可以只用它的碰撞检测,但是也挺麻烦的(不用box2d管

理坐标,而是我们自己设置,之后把坐标传给box2d,再从box2d里获取)。而且我想

做一个通用的碰撞管理类,我用box2d试了一下,可是它的坐标系是在物体中心,而

love2d的坐标系是左顶点,而且我又比较懒,看到love2d的wiki上有做好的碰撞检测

(叫hardoncollider),便直接拿来用了。

从hardoncollider的介绍来看,功能还是很强大的,可以检测多边形,圆形甚至凹形。

至于碰撞检测算法,我估计它采用的是网格法,即把屏幕当做网,如下图

image

注意网格的宽度要与检测的物体宽度相当,否则会出现检测不准。我猜想可能可能是判

断网格里出现的物体个数来判断是否相碰,若哪位读者知道,请不吝赐教。

 

下面介绍如何使用。

 

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的方便,可惜不好集成)。

下面是我做的一个效果:

23

由于我使用的是矩形,所以在碰撞是有点问题。代码写的有点乱,看看可以不必深究。

我把碰撞分到了两个类里了,role和gmwold,role类管理运动,创建时要指定形状(

使用hardoncollider里的shape),gmworld管理碰撞并处理碰撞的效果。我把role分

为了"dynamic、wall、ladder",表示角色、墙、梯子,这样方便在gmwold里管理角色

,当然可能还有更具体的要做如子弹等。

还有很多没完成,先放出测试代码,点击下载。如果你有更好的想法,请不吝告知。

posted @ 2013-04-05 20:21  半山th  阅读(1620)  评论(4编辑  收藏  举报