MonoGameでSkiaSharpを使う

提供: MonoBook
ナビゲーションに移動 検索に移動

MonoGameSkiaSharpを使えれば、MonoGame標準では微妙に抜け落ちてる線を引いたり、丸を描いたり、塗りつぶしたりといった描画処理を簡単に行える。また、MonoGameが不得意な文字列の描画をTrue Type Fontを使って組版ばりの品質で行える。日本語文字列の描画も大丈夫。ほぼOSにも依存しない。これ重要。

環境構築

基本的にMonoGameプロジェクトにNuGetでSkiaSharpを突っ込むだけで利用できる。

ただしMonoGameプロジェクトのターゲットフレームワークは初期状態で「Mono / .NET 4.5」となっているが、 このままだとSkiaSharpがWindowsと勘違いしてDLLを開こうとして落ちる。 このためターゲットフレームワークを「Xamarin.* Mobile Framework」に変更するか、 packages.configを書き換える必要がある。この点には注意する必要がある。

あとはSkiaSharpのSKBitmapをMonoGameのTexture2Dに変換できれば楽勝だ。

    using System;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    using SkiaSharp;

	public static class MonoGameExtensions
	{
		public static Texture2D ToTexture2D(this SKBitmap skbitmap, GraphicsDevice graphicsDevice)
		{
			var texture = new Texture2D(graphicsDevice, skbitmap.Width, skbitmap.Height, mipmap: false, format:SurfaceFormat.Color);
			texture.SetData(skbitmap.Bytes);
			return texture;
		}
	}

試しに虹色グラデーションな円を描いてみる。

using System;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

using SkiaSharp;

namespace MonoGameSkia
{
	public class Game1 : Game
	{
		GraphicsDeviceManager graphics;
		SpriteBatch spriteBatch;
		Texture2D texture;

		public Game1()
		{
			graphics = new GraphicsDeviceManager(this);
			Content.RootDirectory = "Content";
		}

		protected override void Initialize()
		{
			base.Initialize();
		}

		protected override void LoadContent()
		{
			// Create a new SpriteBatch, which can be used to draw textures.
			spriteBatch = new SpriteBatch(GraphicsDevice);

			//TODO: use this.Content to load your game content here 

			var w = 500;
			var h = 500;

			using (var bitmap = new SKBitmap(w, h))
			using (var canvas = new SKCanvas(bitmap))
			{
				// 透明色で塗りつぶす
				canvas.Clear(SKColors.Transparent);

				// 虹色グラデーションシェーダー
				var shader = SKShader.CreateSweepGradient(
					new SKPoint(w/2, h/2),
					new[] {
						new SKColor(0x00,0x00,0xff),
						new SKColor(0x00,0xdb,0xff),
						new SKColor(0x00,0xff,0x49),
						new SKColor(0x91,0xff,0x00),
						new SKColor(0xff,0x93,0x00),
						new SKColor(0xff,0x00,0x47),
						new SKColor(0xdd,0x00,0xff),
					}, null);

				var paint = new SKPaint
				{
					Shader = shader,
					StrokeWidth = 50,
					IsStroke = true,
				};

				// 円を描く
				canvas.DrawCircle(w/2, h/2, w/4, paint);

				// 描画コマンド実行
				canvas.Flush();

				// SKBitmapをTexture2Dに変換
				texture = bitmap.ToTexture2D(graphics.GraphicsDevice);
			}
		}

		protected override void Update(GameTime gameTime)
		{
#if !__IOS__ && !__TVOS__
			if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
				Exit();
#endif
			base.Update(gameTime);
		}

		protected override void Draw(GameTime gameTime)
		{
			graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

			spriteBatch.Begin();
			spriteBatch.Draw(texture, new Vector2(0, 0), Color.White);
			spriteBatch.End();

			base.Draw(gameTime);
		}
	}
}

関連項目