Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / image / ImageCanvas.cs
@lijincheng lijincheng on 19 Jun 2023 4 KB 队列渲染
  1.  
  2. using Godot;
  3.  
  4. public partial class ImageCanvas : Sprite2D, IDestroy
  5. {
  6. /// <summary>
  7. /// 画布大小
  8. /// </summary>
  9. public int Width { get; }
  10. /// <summary>
  11. /// 画布高度
  12. /// </summary>
  13. public int Height { get; }
  14.  
  15. public bool IsDestroyed { get; private set; }
  16.  
  17. private Image _canvas;
  18. private ImageTexture _texture;
  19.  
  20. public ImageCanvas(int width, int height)
  21. {
  22. Width = width;
  23. Height = height;
  24.  
  25. _canvas = Image.Create(width, height, false, Image.Format.Rgba8);
  26. _texture = ImageTexture.CreateFromImage(_canvas);
  27. var w = _canvas.GetWidth();
  28. var h = _canvas.GetHeight();
  29. for (int i = 0; i < w; i++)
  30. {
  31. _canvas.SetPixel(i, h / 2, Colors.Green);
  32. }
  33. for (int j = 0; j < h; j++)
  34. {
  35. _canvas.SetPixel(w / 2, j, Colors.Green);
  36. }
  37. }
  38.  
  39. public override void _Ready()
  40. {
  41. Centered = false;
  42. Texture = _texture;
  43. }
  44.  
  45. /// <summary>
  46. /// 添加到预渲染队列中
  47. /// </summary>
  48. /// <param name="texture">需要渲染的纹理</param>
  49. /// <param name="x">离画布左上角x坐标</param>
  50. /// <param name="y">离画布左上角y坐标</param>
  51. /// <param name="angle">旋转角度, 角度制</param>
  52. /// <param name="centerX">旋转中心点x</param>
  53. /// <param name="centerY">旋转中心点y</param>
  54. /// <param name="flipY">是否翻转y轴</param>
  55. public void DrawImageInCanvas(Texture2D texture, int x, int y, float angle, int centerX, int centerY, bool flipY)
  56. {
  57. var item = new ImageRenderData();
  58. item.ImageCanvas = this;
  59. item.SrcImage = texture.GetImage();
  60. item.X = x;
  61. item.Y = y;
  62. item.Rotation = Mathf.DegToRad(Mathf.RoundToInt(Utils.ConvertAngle(angle)));
  63. item.CenterX = centerX;
  64. item.CenterY = centerY;
  65. item.FlipY = flipY;
  66. var cosAngle = Mathf.Cos(item.Rotation);
  67. var sinAngle = Mathf.Sin(item.Rotation);
  68. if (cosAngle == 0)
  69. {
  70. cosAngle = 1e-6f;
  71. }
  72.  
  73. if (sinAngle == 0)
  74. {
  75. sinAngle = 1e-6f;
  76. }
  77.  
  78. var width = item.SrcImage.GetWidth();
  79. var height = item.SrcImage.GetHeight();
  80. if (width > 128)
  81. {
  82. GD.PrintErr("警告: 图像宽度大于 128, 旋转后像素点可能绘制到画布外导致像素丢失!");
  83. }
  84. if (height > 128)
  85. {
  86. GD.PrintErr("警告: 图像高度大于 128, 旋转后像素点可能绘制到画布外导致像素丢失!");
  87. }
  88. //旋转后的图片宽高
  89. item.RenderWidth = Mathf.CeilToInt(width * Mathf.Abs(cosAngle) + height * sinAngle) + 2;
  90. item.RenderHeight = Mathf.CeilToInt(width * sinAngle + height * Mathf.Abs(cosAngle)) + 2;
  91.  
  92. if (item.RenderWidth >= RenderViewportSize.X)
  93. {
  94. GD.PrintErr($"图像旋转后的宽度大于{RenderViewportSize.X}, 不支持绘制到 ImageCanvas 下!");
  95. return;
  96. }
  97. //旋转后的图像中心点偏移
  98. item.RenderOffsetX =
  99. (int)((item.CenterX / sinAngle +
  100. (0.5f * item.RenderWidth * sinAngle - 0.5f * item.RenderHeight * cosAngle +
  101. 0.5f * height) /
  102. cosAngle -
  103. (-0.5f * item.RenderWidth * cosAngle - 0.5f * item.RenderHeight * sinAngle +
  104. 0.5f * width) /
  105. sinAngle - item.CenterY / cosAngle) /
  106. (cosAngle / sinAngle + sinAngle / cosAngle)) + 1;
  107. item.RenderOffsetY =
  108. (int)((item.CenterX / cosAngle -
  109. (-0.5f * item.RenderWidth * cosAngle - 0.5f * item.RenderHeight * sinAngle + 0.5f * width) /
  110. cosAngle -
  111. (0.5f * item.RenderWidth * sinAngle - 0.5f * item.RenderHeight * cosAngle + 0.5f * height) /
  112. sinAngle + item.CenterY / sinAngle) /
  113. (sinAngle / cosAngle + cosAngle / sinAngle)) + 1;
  114.  
  115. _queueItems.Enqueue(item);
  116. }
  117.  
  118. public void Destroy()
  119. {
  120. if (IsDestroyed)
  121. {
  122. return;
  123. }
  124.  
  125. IsDestroyed = true;
  126. QueueFree();
  127. _canvas.Dispose();
  128. _texture.Dispose();
  129. }
  130.  
  131. private void Redraw()
  132. {
  133. _texture.Update(_canvas);
  134. }
  135. }