グラフィックライブラリで自作エフェクト

グラフィックライブラリでエフェクトはどのように作るのか?

私が知っているエフェクトの作り方は結構古い物になりますが、多くのエフェクトはPhotoshopの「フィルター」>「描画」>「雲模様」からできると思います。

こんな感じで描画されます。

これにフィルターをかけたり、コントラストを高めたり、重ねたりして

こんな画像を作りました。

勝手に誰かがアップした動画を使って紹介させていただくと・・・

この辺で後ろでキラキラしているのはこれを動的に沢山重ね合わせて大きさをグニャグニャさせながら動かして加算ブレンドしたものです。

youtu.beまたこれも誰かの動画を勝手に拝借すると・・・

パーティクルの大きさを変更せずにただ斜めに移動させながら加算ブレンドしただけでも川のエフェクトのようになります。

 youtu.be

AerobeatはBeatmaniaみたいなエフェクトを目指して作りました。

こんな小さなパーティクルを撒き散らしたり、下から上に浮上させたりするだけでもそれらを加算ブレンドするとそこそこキレイなエフェクトになります。

youtu.be

炎のエフェクトは?という話があったので、上のパーティクルを黄色と赤で塗って

 

 

こんな感じにし、中央から PI/2 ± PI/8 の角度にランダムに大量に放出して加算ブレンドしてみた。

パーティクル小さめだとこんな感じ

youtu.beパーティクル大きめだとこんな感じ。

youtu.beただしこれは1時間で作っただけなので、結構不自然。

複素数平面や線形代数使ってもっと縦横無尽に動かして変形すればもっと自然になるはず!

一応ソースコードもおいておく。


#include "DxLib.h"
#include 
#include 
#include 

#define PI 3.141592654f

using namespace std;

int imgHandle[8];

float rand(float val) {
    return GetRand(1000000) / 1000000.f * val;
}

float rand2(float val) {
    return (GetRand(1000000) / 500000.f - 1) * val;
}

class Particle {
    float x, y;
    float a;
    float aSub;
    float v, ang;
    float size, dispAng, dispAngSpd;
    float sizeSub;
    int img;
public:
    Particle() {
        img = imgHandle[(int)rand(8)];
        x = 640 + rand2(100);
        y = 680;
        v = 1+rand(3);
        ang = PI*3/2 + rand2(PI/8);
        dispAngSpd = rand2(PI / 100);
        a = 255;
        aSub = 1 + rand(3);
        size = 1.8 - rand(1.5);
        sizeSub = 0.002;
        dispAng = 0;
    }
    bool update() {
        a -= aSub;
        if (a < 0 || size < 0) {
            return false;
        }
        x += cos(ang) * v;
        y += sin(ang) * v;
        dispAng += dispAngSpd;
        size -= sizeSub;
        if (a < 170) {
            aSub += 0.1;
        }
        return true;
    }
    void draw() {
        SetDrawBlendMode(DX_BLENDMODE_ADD, (int)a);
        DrawRotaGraphF(x, y, size, dispAng, img, TRUE);
    }
};

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
    SetGraphMode(1280, 720, 32);
    ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK); //ウィンドウモード変更と初期化と裏画面設定

    int x = 0;
    int Handle;     // 画像格納用ハンドル
    Handle = LoadDivGraph("particle.png", 8, 8, 1, 100, 100, imgHandle); // 画像のロード

    list<shared_ptr> _list;

    while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
        for (int i = 0; i < 10; i++) {
            _list.push_back(make_shared());
        }
        for (list<shared_ptr>::iterator it = _list.begin(); it != _list.end();) {
            if ((*it)->update() == false) {
                it = _list.erase(it);
            }
            else {
                (*it)->draw();
                it++;
            }
        }
        printfDx("%d\n",_list.size());

    }

    DxLib_End(); // DXライブラリ終了処理
    return 0;
}