Java でタイル ベースのエンジンのライティングを行う最も効率的な方法は何ですか?
タイルの後ろに黒い背景を置いて、タイルのアルファを変更することでしょうか?
または、黒の前景を置き、そのアルファを変更しますか? それとも何か?
これは私が望む種類の照明の例です:
これを達成する方法はたくさんあります。最終決定を下す前に、少し時間をかけてください。使用することを選択できるいくつかのテクニックを簡単に要約し、最後にいくつかのコードを提供します。
ハードエッジの照明効果 (例の画像など) を作成したい場合は、いくつかのアプローチが思い浮かびます。
問題は、タイルを以前よりも明るくすることも (ハイライト)、ライトの色を変更することもできないことです。これらはどちらも、通常、ゲームの照明を美しく見せる側面です。
このアプローチには、最初のアプローチと同じ効果があり、オーバーレイ タイルを黒以外の色で着色できるという利点があります。これにより、色付きのライトとハイライトの両方が可能になります。
例:
簡単ですが、問題は、これが非常に非効率的な方法であることです。(タイルごとに 2 つのレンダリングされたタイル、一定の色変更、多くのレンダリング操作など)
あなたの例を見ると、光は常に特定のソース タイル (キャラクター、トーチなど) から来ると思います。
ソフト ライトは大した問題ではありません。タイルと比較して、ライト マスクの詳細を使用するだけです。通常は黒い領域で 15% のアルファのみを使用することで、タイルが照らされていないときにローサイト効果を追加できます。
マスク イメージを変更するだけで、より複雑な照明フォーム (コーンなど) を簡単に実現できます。
複数の光源を組み合わせる場合、この方法では問題が発生します。互いに交差する 2 つのマスクを描画すると、マスク自体が相殺される可能性があります。
私たちが望んでいるのは、ライトを差し引くのではなく、ライトを追加することです。問題の回避:
これにより、次のような結果になります。
最初にすべてのタイルをレンダリングすると仮定BufferedImage
して、最後に示した方法に似たガイダンス コードをいくつか提供します (グレースケール サポートのみ)。
たとえばトーチとプレーヤーの複数のライト マスクは、次のように組み合わせることができます。
public BufferedImage combineMasks(BufferedImage[] images)
{
// create the new image, canvas size is the max. of all image sizes
int w, h;
for (BufferedImage img : images)
{
w = img.getWidth() > w ? img.getWidth() : w;
h = img.getHeight() > h ? img.getHeight() : h;
}
BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
// paint all images, preserving the alpha channels
Graphics g = combined.getGraphics();
for (BufferedImage img : images)
g.drawImage(img, 0, 0, null);
return combined;
}
最終的なマスクは、次のメソッドで作成および適用されます。
public void applyGrayscaleMaskToAlpha(BufferedImage image, BufferedImage mask)
{
int width = image.getWidth();
int height = image.getHeight();
int[] imagePixels = image.getRGB(0, 0, width, height, null, 0, width);
int[] maskPixels = mask.getRGB(0, 0, width, height, null, 0, width);
for (int i = 0; i < imagePixels.length; i++)
{
int color = imagePixels[i] & 0x00ffffff; // Mask preexisting alpha
// get alpha from color int
// be careful, an alpha mask works the other way round, so we have to subtract this from 255
int alpha = (maskPixels[i] >> 24) & 0xff;
imagePixels[i] = color | alpha;
}
image.setRGB(0, 0, width, height, imagePixels, 0, width);
}
前述のとおり、これは基本的な例です。カラーブレンディングの実装は、もう少し手間がかかるかもしれません。