Як створити ефект Всесвітньої цілющої хвилі?


14

Я хочу змінити свій темний і пригнічуючий фон на щасливий трав'янистий фон у реальному часі таким чином, щоб щасливий фон відображався в радіусі навколо ігрового персонажа.

ForceField щастя , якщо ви будете.

Як це можна зробити якомога ефективніше, коли рендерінг полотна в користувацькому вигляді?


ОНОВЛЕННЯ: Ось як це працює в моїй голові:

    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

}

Я використовую canvas.drawArc()для створення кола, але мені точно щось не вистачає.


1
Технічно це називається Всесвітньою цілющою хвилею
щурячий вирод

Я просто використовую полотно на власному перегляді, керованому моїм власним ігровим циклом зі швидкістю 60 кадрів в секунду
Green_qaue

Не могли б ви два рази зобразити сцену? Один раз для зціленої версії, один раз для мертвої версії, а потім намалюйте зцілених над мертвими постійно зростаючим колом, поки коло не охопить весь екран.
Вольфганг Скайлер

Ось таке, про що я думав. Тільки не знаю, як це зробити з растровою картою. І я, можливо, є кращий спосіб, оскільки надання 2 одиниць одночасно дуже дороге
Green_qaue

2
Я думаю, я бачу, в чому полягає плутанина - Android Canvasробить щось трохи інакше, ніж HTML <canvas>, який я вважав, що ти мав на увазі! Я відредагував свою відповідь, щоб пояснити, як відсікання працює взагалі, за допомогою деяких посилань на Android та коду прикладу.
Анко

Відповіді:


20

Демо

GameDev Цілюща хвиля

GameDev Meta : Henshin Main !! : D

Код використовує canvas clipрегіон та requestAnimationFrameзабезпечує максимальну якість та ефективність. (Краще жити .)

Я припускав, що ти маєш на увазі HTML canvas! Навіть якщо ви цього не зробили, інші двигуни візуалізації (наприклад, 2D конвеєр Android-рендерінга, який ви могли б мати на увазі) також підтримують областях кліпів, прискорених апаратним забезпеченням . Код, ймовірно, буде схожим.

Запит кадрів анімації з requestAnimationFrame(або запропонованим рішенням іншої платформи) призводить до анімації більш високої якості, дозволяючи двигуну визначати терміни візуалізації.

Це плавно відображається на нетбуку з низьким діапазоном та на моєму телефоні Android.

Пояснення

Щоб зробити це загалом корисніше, давайте по-справжньому розберемося із відсіканням .

Скажімо, у нас є ці два прямокутники:

два прямокутники, один перекриває інший

Відсікання працює так само добре, як на лініях, точках, зображеннях або будь-якому іншому, що ви можете зробити. Я просто дотримуюся прямокутників для простоти.

Ми взагалі не хочемо, щоб червоний прямокутник був видно тут (чорне коло).

два прямокутники, бажана зона висічення червоного прямокутника в чорному кольорі

Таким чином, ми можемо доручити рендеріру обрізати червоний прямокутник за цим колом.

два прямокутники;  червоний вирізали

Іншими словами, коли намальовано червоний прямокутник, він малюється скрізь, за винятком того місця, де було б це чорне коло.

Різні рендері по-різному визначають, в якому регіоні відсікати. У JavaScript, з HTML <canvas>, я по суті

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

Тепер в Android Canvasви хочете робити подібну річ, але рендерінг очікує трохи іншого коду:

// 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 щодо цього питання може бути корисною. Є хороші питання , як цей на StackOverflow про більше кількості речей ви можете захотіти спробувати з нею.


3

Робоча реалізація за методом 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();

Дякую Анко за всю допомогу!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.