如何用矩形块制作曲面?


12

对于类似Peggle的游戏,我要制作遵循曲线的块,如下所示:

沿着曲线的方块

然后,当球击中障碍物时,障碍物将消失。

我设法水平绘制了一些,但是在使它们遵循一条路径时遇到了麻烦:

我对路径跟踪块的尝试

我该怎么做呢?是否需要使用自定义顶点创建Box2D对象?


您是否希望这些框完全不重叠,还是希望任何地方都没有缝隙?(我不确定“根据对象角度偏移对象Y轴”的意思)。
罗伊·T。

1
您不能使用非重叠矩形填充曲线,因此如果您不希望有间隙,则必须创建一些自定义几何。
Anko 2014年

@RoyT。差距并不重要。我真正的问题是计算以不同角度彼此跟随的块的位置。
Moerin 2014年

我要采用的方法是定义一系列顶点,这些顶点充当每个框之间的公共角。即使使用路径来定义它们,您仍然需要其他参数来定义顶点之间的距离以及每个框的长度。

4
第一张图片上的“盒子”不是盒子,它们是三角形对:i.stack.imgur.com/Tzuql.png
egarcia 2014年

Answers:


14

给定一条“根”曲线,这是生成块顶点的方法。

贝塞尔积木

根曲线在中间,为黑色。其控制点以红色Xs表示。

简而言之:我制作了贝塞尔曲线并对其进行了采样(以可配置的速率)。然后,我找到了从每个样本到下一个样本的向量的垂直向量,对其进行了归一化,然后缩放为(可配置)半角,首先是左侧,然后是右侧。然后画出来。

您可以添加的内容:


这是我的代码。它是用Lua(针对LÖVE游戏框架)编写的,但我认为任何人都可以阅读。

local v = require "vector"

-- A function that makes bezier functions
-- Beziers have start point     p0
--              control point   p1
--              end point       p2
local function makeBezierFunction(p0,p1,p2)
    return function (t)
        local pow = math.pow
        return pow( (1-t),2 ) * p0
               + 2 * (1-t) * t * p1
               + pow(t,2) * p2
    end
end

love.graphics.setBackgroundColor(255, 255, 255)
function love.draw()
    local line = love.graphics.line
    local colour = love.graphics.setColor

    -- Bezier sampling parameters
    local nSegments = 10
    local segIncr = 1/nSegments

    -- Bezier definition: Start (`p0`), control (`p1`) and end `p2`) point
    local p0 = v(100,100)
    local p1 = v( love.mouse.getX(), love.mouse.getY() )
    local p2 = v(500,100)
    local controlPoints = {p0,p1,p2}
    local bez = makeBezierFunction(p0,p1,p2)

    -- Sample the bezier
    for i=0,1-segIncr,segIncr do
        colour(0, 0, 0)
        local x1,y1 = bez(i        ):unpack()
        local x2,y2 = bez(i+segIncr):unpack()
        line(x1,y1,x2,y2)

        -- Find left and right points.
        local center = v(x1, y1)
        local forward = v(x2, y2) - center
        local left = center + forward:perpendicular():normalize_inplace() * 10
        local right = center - forward:perpendicular():normalize_inplace() * 10

        -- Draw a line between them.
        line(left.x, left.y, right.x, right.y)

        -- Find *next* left and right points, if we're not beyond the end of
        -- the curve.
        if i + segIncr <= 1 then
            local x3, y3 = bez(i+segIncr*2):unpack()
            local center2 = v(x2, y2)
            local forward2 = v(x3, y3) - center2
            local left2 = center2 + forward2:perpendicular():normalize_inplace() * 10
            local right2 = center2 - forward2:perpendicular():normalize_inplace() * 10

            -- Connect the left and right of the current to the next point,
            -- forming the top and bottom surface of the blocks.
            colour(0, 0xff, 0)
            line(left.x, left.y, left2.x, left2.y)
            colour(0, 0, 0xff)
            line(right.x, right.y, right2.x, right2.y)
        end
    end

    -- Draw an X at the control points
    for _,p in ipairs(controlPoints) do
        local x,y = p:unpack()
        colour(0xff,0x00,0x00)
        line(x-5,y-5, x+5,y+5)
        line(x-5,y+5, x+5,y-5)
    end
    -- Draw lines between control points
    for i=1,#controlPoints do
        colour(0xff,0x00,0x00, 100)
        local cp1 = controlPoints[i]
        local cp2 = controlPoints[i+1]
        if cp1 and cp2 then
            line(cp1.x, cp1.y
                ,cp2.x, cp2.y)
        end
    end
end

如果您想使用它,请执行以下操作:获取LÖVE并将上面的代码放入main.lua其自己的目录中。vector.luaHUMP库中放入同一目录。love <that-directory>从命令行运行它。

左右移动鼠标!中间控制点设置为鼠标位置:

用鼠标设置控制点


Anko您尝试过LibGdx吗?如果是这样,您更喜欢洛夫吗?在我当前的游戏之后,我不再使用标准的android API,而我正试图在LibGdx和Löve之间做出选择。顺便说一句,有趣的回答是顺便说一句
Green_qaue 2014年

@Anko非常感谢,它超出了我的预期。我想我可以轻松理解您的代码,因为我在游戏中使用MonkeyX类似于LUA。
Moerin

1
@iQ我还没有使用过Libgdx,但是我已经阅读了很多有关Libgdx的文章,而且我非常了解Java。Libgdx 很大。(它具有加速度计支持,内置的曲线生成器以及其他所有功能),而Love2D 很小(它不包含其中任何一个,不支持着色器等)。由于其简单性,Love2D非常适合用于快速原型制作和小型游戏,但对于某些项目而言可能过于简约。谁知道。(您愿意!尝试一下:D)
Anko 2014年

很好的答案,而且GIF确实是一个不错的奖励!
罗伊(Roy T.)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.