remicalsoft’s blog (original) (raw)
グラフィックライブラリでエフェクトはどのように作るのか?
私が知っているエフェクトの作り方は結構古い物になりますが、多くのエフェクトはPhotoshopの「フィルター」>「描画」>「雲模様」からできると思います。
こんな感じで描画されます。
これにフィルターをかけたり、コントラストを高めたり、重ねたりして
こんな画像を作りました。
勝手に誰かがアップした動画を使って紹介させていただくと・・・
この辺で後ろでキラキラしているのはこれを動的に沢山重ね合わせて大きさをグニャグニャさせながら動かして加算ブレンドしたものです。
youtu.beまたこれも誰かの動画を勝手に拝借すると・・・
パーティクルの大きさを変更せずにただ斜めに移動させながら加算ブレンドしただけでも川のエフェクトのようになります。
AerobeatはBeatmaniaみたいなエフェクトを目指して作りました。
こんな小さなパーティクルを撒き散らしたり、下から上に浮上させたりするだけでもそれらを加算ブレンドするとそこそこキレイなエフェクトになります。
炎のエフェクトは?という話があったので、上のパーティクルを黄色と赤で塗って
こんな感じにし、中央から 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;
}
Flutterの後続としてGoogleがアピールしているクロスプラットフォーム開発環境であるComposeMultiplatform。
まだα版やβ版が含まれるもののFlutter並に色んなプラットフォームに対応している。
GoogleはGoogleの主要アプリをこのComposeMultiplatformに書き換えていくと宣言している。
ただ、FlutterはGoogleが開発元であるのに対し、ComposeMultiplatformはJetbrainが開発元であり開発元が異なる。
しかしGoogleの製品はベースがJetbrainの製品であることがよくあり、AndroidStudioのベースはJetbrainのIntelliJ IDEAだし、Androidの開発言語のKotlin自体開発元がJetbrainだ。
なので、Jetbrainが開発しているComposeMultiplatformは今後のGoogleの主要開発プラットフォームになっていく可能性は大いにある。
そこで今回このComposeMultiplatformを勉強してみた。
ComposeMultiplatformの開発環境を整える
まだComposeMultiplatformはAndroidStudioに標準では備わっていないのでプラグインをいれる形となる。
Pluginの検索画面で該当プラグインをインストールする。
そうすると「New Project」の画面にKotlin Multiplatform Appが表示されるので選ぶ。
そうすると基本的な構成が全て出来上がる。
Activityにはこのように書くと、MainScreen以降は全て共有部に記載できる。
MainScreen以降の画面遷移は自作する。
シーンIDを定義し、remenberとしておくと、このIDが変わると自動的に画面が再構成されるようになっている。
そのsceneIDに変化した時どうするかは以下のように実装する。
MenuScreenは以下のように実装した。Contextが必要なくAndroidのAPIが必要ない。
これを実行するとこうなる。
まだActivityが最初に出てきたように、完全にワンコードでAndroid/iOSに出力されるわけではなさそう。ある程度のOS依存コードはある。特に最初の呼び出し口。
また、Activityを遷移させたい時はその部分を各ネイティブで実装するそうだ。
ただ逆に言えばネイティブコードが同じパッケージ内にあるかのように非常に簡単に呼び出せるのでネイティブ実装と合わせて実装するのがやり易い。
これで一つアプリを作ってみた。