Come posso creare un effetto World Healing Wave?


14

Voglio cambiare il mio sfondo scuro e deprimente in uno sfondo erboso felice , in tempo reale, in modo tale che lo sfondo felice sia mostrato in un raggio attorno a un personaggio del gioco.

Un campo di forza di felicità , se vuoi.

Come è possibile farlo nel modo più efficiente possibile quando si esegue il rendering su una tela in una vista personalizzata?


AGGIORNAMENTO: Ecco come funziona nella mia testa:

    private int hModeX, hModeY;
    private float hModeRadius = 0.1f;
    private float hModeStart = 0;
    happyModeBg = Bitmap.createScaledBitmap(happyModeBg, getWidth(),getHeight(), true);
    hModeX = getWidth()/2;
    hModeY = getHeight()/2;

private void initHappyMode(Canvas canvas){
    hModeRadius = 75 * thread.getDelta();

    if(hModeRadius > 500) {
        hModeStart = timestep; //What is timestep?
    }

    //context.arc(x, y, radius, 0, 2 * Math.PI, false); <- your version
    canvas.save();
    canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint) // <- my version
    //context.clip(); <- dont know what this does or if there is an equivilant
    canvas.drawBitmap(happyModeBg, 0, 0, null);
    canvas.restore();
    //requestAnimationFrame(step); <- dont know what this does since I cant seem to find it for android

}

Sto usando canvas.drawArc()per fare un cerchio, ma sicuramente mi manca qualcosa.


1
tecnicamente si chiama World Healing Wave
maniaco del cricchetto

Uso semplicemente la tela in una vista personalizzata gestita dal mio loop di gioco a 60 fps
Green_qaue,

Potresti renderizzare la scena due volte? Una volta per la versione guarita, una volta per la versione morta, quindi disegna i guariti sui morti in un cerchio sempre crescente fino a quando il cerchio non copre l'intero schermo.
Wolfgang Skyler,

Questo è un po 'quello che ho pensato. Non so come procedere con una bitmap. E poi forse c'è un modo migliore poiché rendere 2 bgs in una volta è molto costoso
Green_qaue,

2
Penso di vedere di cosa si trattasse la confusione: Android Canvasfa le cose un po 'diversamente dall'HTML <canvas>, che pensavo intendessi! Ho modificato la mia risposta per spiegare come funziona il clipping in generale, con alcuni link specifici di Android e un codice di esempio.
Anko,

Risposte:


20

dimostrazione

GameDev Healing Wave

GameDev Meta : Henshin Main !! : D

Il codice utilizza una canvas clipregione e requestAnimationFrameper la massima qualità ed efficienza. (È meglio dal vivo .)

Pensavo intendessi HTML canvas! Anche se non lo hai fatto, anche altri motori di rendering (come la pipeline di rendering 2D di Android, che potresti aver inteso) supportano anche le aree di clip con accelerazione hardware . Il codice probabilmente avrà un aspetto simile.

La richiesta di frame di animazione con requestAnimationFrame(o la soluzione fornita da un'altra piattaforma) produce animazioni di qualità superiore consentendo al motore di determinare i tempi di rendering.

Questo rende senza problemi su un netbook a basso raggio e sul mio telefono Android.

Spiegazione

Per renderlo più generalmente utile, capiamo davvero il ritaglio .

Diciamo che abbiamo questi due rettangoli:

due rettangoli, uno sovrapposto all'altro

Il ritaglio funziona anche su linee, punti, immagini o qualsiasi altra cosa tu possa voler renderizzare. Sto solo attaccando ai rettangoli per semplicità.

Non vogliamo affatto che il rettangolo rosso sia visibile qui (cerchio nero).

due rettangoli, l'area di taglio desiderata del rettangolo rosso in nero

Quindi possiamo dare istruzioni al renderer di tagliare il rettangolo rosso con quel cerchio.

due rettangoli;  quello rosso è stato tagliato

In altre parole, quando viene disegnato il rettangolo rosso, viene disegnato ovunque tranne dove sarebbe stato quel cerchio nero.

Diversi renderer hanno modi diversi di specificare la regione da tagliare. In JavaScript, con l'HTML <canvas>, l'ho fatto essenzialmente

// Draw the blue rectangle

context.save(); // Save the current state of the graphics context,
                // so we can go back to it.

// Draw the black circle
context.clip(); // Tell the renderer that was our clip region,
                // since the last `context.save()`.

// Draw the red rectangle.
// It will appear clipped by the black circle.

context.restore(); // Tell the renderer we should restore all
                   // the clipping settings back to what they were
                   // `context.save`d as.

// From here on, nothing is clipped anymore.

Ora, in un Android Canvas, ti consigliamo di fare una cosa simile, ma il renderer prevede un codice leggermente diverso:

// Draw the blue rectangle

canvas.save(); // Same idea as above -- just setting a point we can
               // restore to later.

// Now, `canvas.clipPath` expects a `Path` object.
// Let's create one that contains a circle.
Path path = new Path();
path.addCircle(100, 100, 100, Direction.CW); 
canvas.clipPath(path);

// Draw the red rectangle
// It will be clipped by the circle defined in the `path` that we
// used as the `clipPath`.

canvas.restore(); // Aaaand restore the state.

// Things drawn here won't be clipped anymore.

La documentazione Android sull'argomento potrebbe essere utile. Ci sono buone domande come questa su StackOverflow su più cose che potresti voler provare.


3

Implementazione funzionante usando il metodo Ankos:

canvas.drawBitmap(depressingBg, 0, 0, null);
canvas.save();
radius += 400*thread.getDelta(); // expansion speed
Path path = new Path();
// draw around player position
path.addCircle(player.x, player.y, radius, Direction.CW);
canvas.clipPath(path);
canvas.drawBitmap(happyBg, 0, 0, null);
canvas.restore();

Grazie ad Anko per tutto l'aiuto!

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.