Edited at

DXLibで画像の透明部分を判定する

More than 1 year has passed since last update.

DXライブラリにはLoadGraphDrawGraph,DrawExtendGraphといった便利な関数が充実しています。

画像の表示、変形表示などを行うにはこれで十分ですが、これらの関数はピクセル単位でアクセスしたい場面で力を発揮できません。

具体的には、キャラクターの一枚絵をクリックしてリアクションを引き出したいときなどでしょうか。「艦○れ」みたいな。

背景の透過部分では判定させずに、キャラクターの身体をクリックしたときだけ反応させたいようなケースでは、マウスの座標を取得し、画像のそのピクセルのアルファ値(透過度)を調べないといけません。

今回はそんな感じのサンプルコードを作ってみました。

#include<Dxlib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
ChangeWindowMode(TRUE);
if(DxLib_Init() < 0)return -1;

int sHandle = LoadSoftImage("img.png");
int gHandle = LoadGraph("img.png");

while (!ProcessMessage() && !ScreenFlip() && !ClearDrawScreen()){
//DrawSoftImageは負荷が非常に高いので、DrawGraphで描画する
DrawGraph(0, 0, gHandle, TRUE);

int mouseX = 0, mouseY = 0;
GetMousePoint(&mouseX, &mouseY);
int r = 0, g = 0, b = 0, a = 0;
GetPixelSoftImage(sHandle, mouseX, mouseY, &r, &g, &b, &a);
//アルファ値は0(透明)~255(不透明)
if (a > 0){
DrawFormatString(20, 20, 0xffffff, "ON BODY");
}
}

DxLib_End();
return 0;
}

「img.png」には適当な透過PNG画像を用意してください。

LoadSoftImageで読み込んだ画像にはピクセル単位でアクセスすることができます。

GetPixelSoftImageの引数にハンドルと座標とRGB値、そしてアルファ値を保存するアドレスを指定します。

取得できるアルファ値は0~255の整数となり、完全に透明な座標では0になります。

気をつけるべき点として、LoadSoftImageで読み込んだ画像をそのまま描画するDrawSoftImage使うべきではないということです。理由はマシンへの負荷が非常に高いからとされています。

著者の環境で検証したところ、描画する画像が40枚を超えた辺りで露骨に処理落ちし始めました。これでは実際のゲーム作りに耐えられませんね。

今回は使い慣れているLoadGraphで再度画像を読み込みましたが、CreateGraphFromSoftImageという関数を使うと、サンプルコード中の「sHandle」からDrawGraphで使えるハンドルを作成することができます。ゲームのロード時間を節約したいときなどは、こちらの方が効果的かもしれません。

他にもLoadSoftImageは一枚の画像から色違い(2Pカラー)を作成したり、面白い使い方ができそうです。