Recreating pokemon wavy sprite effect

psychic
Hey folks,
I'm trying to figure out how to recreate this wavy sprite/screen effect but I'm unsure where to start. Any pointers would be greatly appreciated.

I know this is more overkill but it really goes through all the effects you can do with sine waves.

You basically shift the image from left to right per line of pixels by certain amount. You can even see the vertical sine wave in your gif.

2 Likes

I did something like that for DuckBlur:
underwater2

Basically I move every line some pixel to the left/right based on a sinus function.
Here I am moving the content of the frame buffer but you could draw only one sprite using the same technique on a new bitmap.

EDIT: Here is the code (it is made in C but you should be able to do the same thing with Lua).

static const int kBytesInARow = 52;
static const int kBitsInAByte = 8;
static const int kEntriesInARow = kBytesInARow / sizeof(uint8_t);
static const float kDistortion = 3.0f;

static float water = 0;

void WaterEffectDraw(MELIntRectangle waterArea) {
    water += DELTA;

    uint8_t *frame = playdate->graphics->getFrame();
    for (int y = 0; y < LCD_ROWS; y++) {
        const int shift = (int)(cosf(water + y / 20.0f) * kDistortion);
        if (shift > 0) {
            const int maskShift = sizeof(uint8_t) * kBitsInAByte - shift;
            for (int x = 0; x < kEntriesInARow - 1; x++) {
                const uint8_t next = frame[x + y * kEntriesInARow + 1];
                frame[x + y * kEntriesInARow] = (frame[x + y * kEntriesInARow] << shift) | (next >> maskShift);
            }
            frame[kEntriesInARow + y * kEntriesInARow - 1] = frame[kEntriesInARow + y * kEntriesInARow - 1] << shift;
        } else if (shift < 0) {
            const int maskShift = sizeof(uint8_t) * kBitsInAByte + shift;
            uint8_t last = frame[y * kEntriesInARow];
            frame[y * kEntriesInARow] = last >> -shift;
            for (int x = 1; x < kEntriesInARow; x++) {
                const uint8_t current = frame[x + y * kEntriesInARow];
                frame[x + y * kEntriesInARow] = (frame[x + y * kEntriesInARow] >> -shift) | (last << maskShift);
                last = current;
            }
        }
    }
}
8 Likes