Wie erstelle ich einen World Healing Wave-Effekt?

14

Ich möchte meinen dunklen und deprimierenden Hintergrund in einen ändern in Echtzeit fröhlichen grasbewachsenen Hintergrund , sodass der fröhliche Hintergrund in einem Radius um eine Spielfigur angezeigt wird.

EIN Kraftfeld des Glücks , wenn Sie so wollen.

Wie kann dies beim Rendern auf einer Leinwand in einer benutzerdefinierten Ansicht so performant wie möglich durchgeführt werden?


UPDATE: So funktioniert es in meinem Kopf:

    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

}

Ich benutze canvas.drawArc(), um einen Kreis zu machen, aber mir fehlt definitiv etwas.

Green_qaue
quelle
1
technisch heißt es world healing wave
ratschenfreak
Ich benutze nur Canvas in einer benutzerdefinierten Ansicht, die von meiner eigenen Spieleschleife mit
60
Könnten Sie die Szene zweimal rendern? Einmal für die geheilte Version, einmal für die tote Version, und dann ziehen Sie die geheilten über die Toten in einem immer größer werdenden Kreis, bis der Kreis den gesamten Bildschirm bedeckt.
Wolfgang Skyler
Das ist was ich gedacht habe. Ich weiß nur nicht, wie ich das mit einer Bitmap machen soll. Und ich denke, vielleicht gibt es einen besseren Weg, da das Rendern von 2 Bgs auf einmal sehr kostspielig ist
Green_qaue
2
Ich denke, ich verstehe, worum es bei der Verwirrung ging - Android Canvasmacht die Dinge ein bisschen anders als HTML <canvas>, was Sie gemeint haben! Ich habe meine Antwort bearbeitet, um zu erklären, wie das Ausschneiden im Allgemeinen funktioniert, und zwar mit einigen Android-spezifischen Links und Beispielcode.
Anko

Antworten:

20

Demo

GameDev Heilwelle

GameDev Meta : Henshin Main !!: D

Der Code verwendet eine canvas clipRegion und requestAnimationFramefür maximale Qualität und Effizienz. (Es ist besser zu leben .)

Ich nahm an, Sie meinten HTML canvas ! Selbst wenn Sie dies nicht getan haben, unterstützen andere Rendering-Engines (wie die 2D-Rendering-Pipeline von Android, die Sie möglicherweise gemeint haben) auch hardwarebeschleunigte Clip- Regionen. Der Code wird wahrscheinlich ähnlich aussehen.

Das Anfordern von Animationsframes mit requestAnimationFrame(oder der von einer anderen Plattform bereitgestellten Lösung) führt zu einer Animation mit höherer Qualität, indem die Engine das Render-Timing bestimmen kann.

Dies funktioniert problemlos auf einem Netbook mit geringer Reichweite und auf meinem Android-Handy.

Erläuterung

Um dies allgemein nützlicher zu machen, sollten wir das Beschneiden wirklich verstehen .

Nehmen wir an, wir haben diese beiden Rechtecke:

zwei Rechtecke, von denen eines das andere überlappt

Das Ausschneiden funktioniert genauso gut für Linien, Punkte, Bilder oder alles andere, was Sie rendern möchten. Ich halte mich der Einfachheit halber nur an Rechtecke.

Das rote Rechteck soll hier (schwarzer Kreis) überhaupt nicht sichtbar sein.

zwei Rechtecke, der gewünschte Ausschnittbereich des roten Rechtecks ​​in Schwarz

So können wir den Renderer anweisen, das rote Rechteck an diesem Kreis zu beschneiden .

zwei Rechtecke;  Der rote wurde abgeschnitten

Mit anderen Worten, wenn das rote Rechteck gezeichnet wird, wird es überall gezeichnet, außer dort, wo dieser schwarze Kreis gewesen wäre.

Verschiedene Renderer legen auf unterschiedliche Weise fest, nach welchem ​​Bereich geschnitten werden soll. In JavaScript habe <canvas>ich mit dem HTML im Wesentlichen getan

// 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.

In einem Android- CanvasGerät möchten Sie jetzt eine ähnliche Aktion ausführen, der Renderer erwartet jedoch einen etwas anderen Code:

// 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.

Android- Dokumentation zu diesem Thema könnte nützlich sein. Es gibt gute Fragen wie diese zu StackOverflow über weitere Dinge, die Sie vielleicht ausprobieren möchten.

Anko
quelle
3

Arbeitsumsetzung mit Ankos-Methode:

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();

Vielen Dank an Anko für die Hilfe!

Green_qaue
quelle