Come faccio a creare una superficie curva con blocchi rettangolari?


12

Per un gioco simile a Peggle , voglio creare blocchi che seguono una curva, in questo modo:

blocchi lungo una curva

I blocchi scompaiono quindi quando la palla li colpisce.

Sono riuscito a disegnarne alcuni in orizzontale, ma ho problemi a farli seguire un percorso:

il mio tentativo di blocchi seguendo il percorso

Come faccio a fare questo? Devo creare oggetti Box2D con vertici personalizzati?


Vuoi semplicemente che le scatole non si sovrappongano o vuoi che non ci siano spazi vuoti da nessuna parte? (Non sono esattamente sicuro di cosa intendi per "offset dell'asse Y dell'oggetto secondo l'angolo dell'oggetto").
Roy T.

1
Non si può compilare una curva con i non-sovrapposti rettangoli , quindi si sta andando ad avere per creare un po 'geomety personalizzato se si desidera lacune.
Anko,

@RoyT. Le lacune non sono importanti. Il mio vero problema è calcolare la posizione del blocco che si susseguono con un'angolazione diversa.
Moerin,

Il modo in cui mi avvicinerei a questo è definire una serie di vertici che fungono da angoli comuni tra ogni riquadro. Anche usando un tracciato per definirli, sono comunque necessari parametri aggiuntivi per definire la distanza tra i vertici e la lunghezza di ogni riquadro.

4
Le "scatole" sulla prima immagine non sono scatole, sono coppie di triangoli: i.stack.imgur.com/Tzuql.png
egarcia,

Risposte:


14

Data una curva "radice", ecco come potresti generare vertici di blocco.

Bézier con blocchi

La curva della radice è al centro, in nero. I suoi punti di controllo sono indicati con una Xs rossa .

In breve : ho realizzato un Bézier e l'ho campionato (a una velocità configurabile). Ho quindi trovato il vettore perpendicolare del vettore da ciascun campione al successivo, l' ho normalizzato e l' ho ridimensionato su una mezza larghezza (configurabile), prima a sinistra, poi inversamente a destra. Quindi l'ha disegnato.

Cose che potresti aggiungere a questo:


Ecco il mio codice È scritto in Lua (per il framework di gioco LÖVE ), ma penso che sia leggibile da chiunque.

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

Se vuoi giocarci: prendi LÖVE e inserisci il codice sopra main.luanella sua directory. Metti vector.luadalla HUMPlibreria nella stessa directory. Eseguilo love <that-directory>da una riga di comando.

Muovi il mouse! Il punto di controllo centrale è impostato sulla posizione del mouse:

Impostazione del punto di controllo con il mouse


Anko hai provato LibGdx? in tal caso, preferisci Löve? Mi sto allontanando dall'utilizzo dell'API Android standard dopo il mio gioco attuale e sto cercando di decidere tra LibGdx e Löve. Interessante risposta sopra come sempre tra
Green_qaue,

@Anko Grazie mille, è più di quanto mi aspettassi. Inoltre, penso di poter capire facilmente il tuo codice poiché utilizzo MonkeyX per il mio gioco che è simile a LUA.
Moerin,

1
@iQ Non ho usato Libgdx, ma ne ho letto molto e conosco bene Java. Libgdx è grande . (Ha il supporto dell'accelerometro, generatori di curve integrati e tutto il resto), mentre Love2D è molto piccolo (non ha nessuno di questi, non c'è supporto shader, ecc.). Grazie alla sua semplicità, Love2D è stato ottimo per prototipi veloci e piccoli giochi, ma potrebbe essere troppo minimalista per alcuni progetti. Chissà. (Lo fai! Provalo e vedi.: D)
Anko,

Ottima risposta, e quella GIF è davvero un bel bonus!
Roy T.,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.