Bagaimana cara membuat efek World Healing Wave?

14

Saya ingin mengubah latar belakang saya yang gelap dan tertekan menjadi latar belakang yang menyenangkan , secara real-time, sehingga latar belakang yang bahagia ditampilkan dalam radius di sekitar karakter permainan.

Sebuah ForceField kebahagiaan , jika Anda mau.

Bagaimana ini bisa dilakukan dengan kinerja sebaik mungkin ketika merender ke kanvas dalam tampilan kustom?


PEMBARUAN: Inilah cara kerjanya di kepala saya:

    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

}

Saya menggunakan canvas.drawArc()untuk membuat lingkaran, tapi saya pasti kehilangan sesuatu.

Green_qaue
sumber
1
secara teknis itu disebut World Healing Wave
ratchet freak
Saya hanya menggunakan kanvas pada tampilan kustom yang dijalankan oleh game-loop saya sendiri pada 60fps
Green_qaue
Bisakah Anda membuat adegan dua kali? Satu kali untuk versi yang disembuhkan, satu kali untuk versi yang mati, dan kemudian gambar yang disembuhkan di atas orang mati dalam lingkaran yang terus meningkat sampai lingkaran menutupi seluruh layar.
Wolfgang Skyler
Itulah yang saya pikirkan. Hanya tidak tahu bagaimana cara melakukannya dengan bitmap. Dan saya rasa mungkin ada cara yang lebih baik karena merender 2 bgs sekaligus sangat mahal
Green_qaue
2
Saya rasa saya mengerti apa itu kebingungan - Android Canvasmelakukan sesuatu yang sedikit berbeda dari HTML <canvas>, yang saya pikir Anda maksud! Saya telah mengedit jawaban saya untuk menjelaskan cara kerja kliping secara umum, dengan beberapa tautan khusus Android dan kode contoh.
Anko

Jawaban:

20

Demo

GameDev Healing Wave

GameDev Meta : Henshin Main !! : D

Kode ini menggunakan canvas clipwilayah dan requestAnimationFrameuntuk kualitas dan efisiensi maksimum. (Lebih baik hidup .)

Saya berasumsi Anda maksud HTML canvas! Bahkan jika Anda tidak melakukannya, mesin rendering lain (seperti pipa rendering 2D Android, yang mungkin Anda maksudkan) juga mendukung daerah klip yang dipercepat perangkat keras . Kode kemungkinan akan terlihat serupa.

Meminta frame animasi dengan requestAnimationFrame(atau solusi platform lain yang disediakan) menghasilkan animasi berkualitas lebih tinggi dengan membiarkan mesin menentukan waktu render.

Ini menjadikannya lancar di netbook jarak-rendah dan di ponsel Android saya.

Penjelasan

Untuk menjadikan ini lebih bermanfaat secara umum, mari kita pahami kliping .

Katakanlah kita memiliki dua persegi panjang ini:

dua persegi panjang, satu tumpang tindih satu lainnya

Memotong juga berfungsi baik pada garis, titik, gambar atau apa pun yang Anda ingin render. Saya hanya berpegang pada persegi panjang untuk kesederhanaan.

Kami tidak ingin persegi panjang merah terlihat di sini (lingkaran hitam) sama sekali.

dua persegi panjang, area potong yang diinginkan persegi panjang berwarna hitam

Jadi kita bisa menginstruksikan penyaji untuk memotong persegi panjang merah dengan lingkaran itu.

dua persegi panjang;  yang merah telah terpotong

Dengan kata lain, ketika persegi panjang merah digambar, itu ditarik di mana-mana kecuali di mana lingkaran hitam itu berada.

Penyaji yang berbeda memiliki cara yang berbeda untuk menentukan wilayah mana yang akan dipotong. Dalam JavaScript, dengan HTML <canvas>, pada dasarnya saya lakukan

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

Sekarang, di Android Canvas, Anda ingin melakukan hal yang serupa, tetapi penyaji mengharapkan kode yang sedikit berbeda:

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

Dokumentasi Android tentang masalah ini mungkin berguna. Ada pertanyaan bagus seperti ini di StackOverflow tentang lebih banyak hal yang mungkin ingin Anda coba dengannya.

Anko
sumber
3

Implementasi kerja menggunakan metode 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();

Terima kasih kepada Anko untuk semua bantuannya!

Green_qaue
sumber