SFML.netで画像の色違いを表現するプログラム


#最初に

少し前に、SDL2で色変化プログラムを書いたのですが、
SFMLでも同じことできたらいいなと思って、
画像の色違いを表現するコードを考えてました

相変わらず説明下手ですがどうか

↓関連記事
【C# + SDL2】色調を用いて、画像の色違いを表現してみるサンプル
https://qiita.com/minion_cs_user/items/43147d3c6ff28cbbdf62

SFML.netを使ってみた
https://qiita.com/minion_cs_user/items/7ffe3b9042dc72152caf

#コード全文

``` csharp
/*

レトロゲームでよくある、画像の色違いを表現する
プログラムです

コードはそんなに長くないけど、
一からこれ書くのは結構大変だね

このアルゴリズム、
SFMLの標準機能でついたりしないかな？

*/

using System;
using SFML.Graphics;
using System.IO;
using SFML.Window;
using System.Collections.Generic;

namespace TestProgram {
	sealed class Program {
		const string errorFilePath = "error.txt";

		public static Program Obj { get; } = new Program();

		static Random Random { get; } = new Random();

		static void Main() {
			try { Obj.Start(); }
			catch (Exception e) {
				File.WriteAllText(errorFilePath, e.Message);
				Console.WriteLine(e.Message);
			}
		}
		
		void Start() {
			var window = new RenderWindow(new VideoMode(300, 300), "", Styles.Close);
			window.Closed += (sender, e) => window.Close();
			window.SetFramerateLimit(60);

			//テクスチャ表示用スプライトを作成
			var normal = new Sprite(LoadTextureNormal());
			normal.Position = new SFML.System.Vector2f(20, 20);

			//色違いテクスチャ表示用スプライトを作成
			var custom = new Sprite(LoadTextureCustom());
			custom.Position = new SFML.System.Vector2f(120, 20);

			var group = new List<Sprite>();
			//分割されたテクスチャのグループを作成
			var group_textures = LoadTextureSplit();
			//分割されたテクスチャのグループを表示する際の色配列を作成
			var group_color_ary = new Color[group_textures.Length];
			for (var i = 0; i < group_color_ary.Length; i++) group_color_ary[i] = GetColorRandom();

			foreach (var i in group_textures) {
				var sprite = new Sprite(i);

				sprite.Position = new SFML.System.Vector2f(220, 20);

				group.Add(sprite);
			}

			while (window.IsOpen) { 
				window.DispatchEvents();
				window.Clear();

				//テクスチャを表示
				window.Draw(normal);
				//テクスチャの色違いを表示
				window.Draw(custom);

				for(var i = 0; i < group.Count; i++) {
					//表示テスト用として、毎フレーム色を変える
					group_color_ary[i].R++;

					//分割されたテクスチャの表示色を指定
					group[i].Color = group_color_ary[i];
					//分割されたテクスチャを１つずつ表示
					window.Draw(group[i]);
				}

				window.Display();
			}
		}

		static Color GetColorRandom() {
			var r = (byte)Random.Next(byte.MaxValue);
			var g = (byte)Random.Next(byte.MaxValue);
			var b = (byte)Random.Next(byte.MaxValue);
			
			return new Color(r, g, b);
		}
		
		//テクスチャを作成
		static Texture LoadTextureNormal() {
			return new Texture("test.png");
		}
		//テクスチャの色違いを作成
		static Texture LoadTextureCustom() {
			var image = new Image("test.png");

			var color_ary2d = new Color[image.Size.X, image.Size.Y];

			var old_colors = new List<Color>();
			var new_colors = new List<Color>();

			for (var i = 0; i < image.Size.X; i++) {
				for (var n = 0; n < image.Size.Y; n++) {
					var color = image.GetPixel((uint)i, (uint)n);

					if (!old_colors.Contains(color)) {
						old_colors.Add(color);
						new_colors.Add(GetColorRandom());
					}

					//テクスチャ作成用配列に色を指定
					color_ary2d[i, n] = new_colors[old_colors.IndexOf(color)];
				}
			}

			//テクスチャ作成用配列からテクスチャを作成
			return new Texture(new Image(color_ary2d));
		}
		//テクスチャのパーツを分割
		static Texture[] LoadTextureSplit() {
			var image = new Image("test.png");

			var color_ary2d_list = new List<Color[,]>();

			var old_colors = new List<Color>();

			for (var i = 0; i < image.Size.X; i++) {
				for (var n = 0; n < image.Size.Y; n++) {
					var color = image.GetPixel((uint)i, (uint)n);

					if (!old_colors.Contains(color)) {
						old_colors.Add(color);

						color_ary2d_list.Add(new Color[image.Size.X, image.Size.Y]);
					}

					//テクスチャの表示部分は全て白にする
					//（色調による色変化ができるため）
					color_ary2d_list[old_colors.IndexOf(color)][i, n] = Color.White;
				}
			}

			var ary = new Texture[color_ary2d_list.Count];

			for(var i = 0; i < color_ary2d_list.Count; i++) {
				////テクスチャ作成用配列からテクスチャを作成
				ary[i] = new Texture(new Image(color_ary2d_list[i]));
			}
			
			return ary;
		}
	}
}


``` 

#最後に

これを一から書くなら
SFMLで書くよりSDL2で書くほうが楽なのかな？