Làm thế nào để tôi tạo một bề mặt cong ra khỏi các khối hình chữ nhật?


12

Đối với một trò chơi giống như Peggle , tôi muốn tạo các khối theo một đường cong, như thế này:

khối dọc theo một đường cong

Các khối sau đó sẽ biến mất khi quả bóng chạm vào chúng.

Tôi đã xoay sở để vẽ một số theo chiều ngang, nhưng tôi gặp khó khăn khi khiến chúng đi theo một con đường:

nỗ lực của tôi tại các khối theo đường dẫn

Làm thế nào để tôi làm điều này? Tôi có cần tạo các đối tượng Box2D với các đỉnh tùy chỉnh không?


Bạn có muốn các hộp chỉ đơn giản là không chồng chéo hoặc bạn muốn không có khoảng trống ở bất cứ đâu? (Tôi không chắc chính xác ý bạn là gì khi "bù đắp trục Y của đối tượng theo góc đối tượng").
Roy T.

1
Bạn không thể lấp đầy một đường cong bằng các hình chữ nhật không chồng chéo , vì vậy bạn sẽ phải tạo một số hình học tùy chỉnh nếu bạn không muốn có khoảng trống.
Anko

@RoyT. Những khoảng trống không quan trọng. Vấn đề thực sự của tôi là tính toán vị trí của khối theo nhau với các góc khác nhau.
Moerin

Cách tôi sẽ tiếp cận điều này là xác định một loạt các đỉnh đóng vai trò là các góc chung giữa mỗi hộp. Ngay cả khi sử dụng đường dẫn để xác định chúng, bạn vẫn cần các tham số bổ sung để xác định khoảng cách giữa các đỉnh và thời gian mỗi hộp là bao lâu.

4
Các "hộp" trên hình ảnh đầu tiên không phải là các hộp, chúng là các cặp hình tam giác: i.stack.imgur.com/Tzuql.png
egarcia

Câu trả lời:


14

Đưa ra một đường cong "gốc", đây là cách bạn có thể tạo các đỉnh khối.

Bézier với các khối

Đường cong gốc nằm ở giữa, màu đen. Điểm kiểm soát của nó được hiển thị với Xs màu đỏ .

Tóm lại : Tôi đã tạo ra một Bézier và lấy mẫu nó (với tốc độ cấu hình). Sau đó, tôi tìm thấy vectơ vuông góc của vectơ từ mỗi mẫu sang mẫu tiếp theo, chuẩn hóa nó và thu nhỏ nó thành một nửa chiều rộng (có thể định cấu hình), đầu tiên ở bên trái, sau đó ngược lại bên phải. Sau đó vẽ nó.

Những thứ bạn có thể thêm vào đây:


Đây là mã của tôi. Nó được viết bằng Lua (dành cho khung trò chơi LÖVE ), nhưng tôi nghĩ nó có thể đọc được cho bất kỳ ai.

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

Nếu bạn muốn chơi với nó: Nhận LÖVE và đặt đoạn mã trên vào main.luathư mục riêng của nó. Đặt vector.luatừ HUMPthư viện trong cùng thư mục. Chạy nó như love <that-directory>từ một dòng lệnh.

Di chuyển chuột xung quanh! Điểm kiểm soát giữa được đặt thành vị trí chuột:

Đặt điểm kiểm soát bằng chuột


Anko bạn đã thử LibGdx chưa? Nếu vậy, bạn có thích Löve? Tôi đang chuyển sang sử dụng API Android tiêu chuẩn sau trò chơi hiện tại của mình và tôi đang cố gắng quyết định giữa LibGdx và Löve. Câu trả lời thú vị ở trên như mọi khi btw
Green_qaue

@Anko Cảm ơn rất nhiều, nó nhiều hơn tôi mong đợi. Nhiều hơn tôi nghĩ rằng tôi có thể dễ dàng hiểu mã của bạn vì tôi sử dụng MonkeyX cho trò chơi của mình tương tự như LUA.
Moerin

1
@iQ Tôi chưa sử dụng Libgdx, nhưng tôi đã đọc rất nhiều về nó và tôi biết rõ về Java. Libgdx là lớn . (Nó có gia tốc hỗ trợ, xây dựng trong máy phát điện cong và tất cả mọi thứ), trong khi Love2D là rất nhỏ (nó không có bất kỳ của những người, theres' không hỗ trợ shader, vv). Nhờ sự đơn giản của nó, Love2D đã rất tuyệt vời cho các nguyên mẫu nhanh và các trò chơi nhỏ, nhưng nó có thể quá tối giản cho một số dự án. Ai biết. (Bạn làm! Hãy thử và xem .: D)
Anko

Câu trả lời tuyệt vời, và GIF đó thực sự là một phần thưởng tuyệt vời!
Roy T.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.