SDXFrameWork  0.12
SDXFrameWork
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
Drawing.h
1 //Copyright © 2014 SDXFramework
2 //[License]GNU Affero General Public License, version 3
3 //[Contact]http://sourceforge.jp/projects/dxframework/
4 #pragma once
5 #include <Multimedia/SDX.h>
6 #include <Multimedia/Color.h>
7 #include <Multimedia/Image.h>
8 #include <Multimedia/Font.h>
9 #include <Utility/VariadicStream.h>
10 #include <Framework/Shape.h>
11 #include <Framework/Camera.h>
12 
13 namespace SDX
14 {
17  class Drawing
18  {
19  private:
20  //生成、削除、コピー等を禁止
21  Drawing() = default;
22  ~Drawing() = default;
23  void operator =(const Drawing& src){}
24  Drawing(const Drawing& src){}
25 
27  static void RGBACulculate(int 赤, int 緑, int 青)
28  {
29  SDL_SetRenderDrawBlendMode(Screen::GetHandle(), (SDL_BlendMode)Screen::GetRenderer()->blendMode);
30  SDL_SetRenderDrawColor
31  (
33  Screen::GetRenderer()->rgba.GetRed() * 赤 / 255,
34  Screen::GetRenderer()->rgba.GetGreen() * 緑 / 255,
35  Screen::GetRenderer()->rgba.GetBlue() * 青 / 255,
37  );
38  }
39 
41  static void MakeCircle(SDL_Renderer* renderer,int x1, int y1,int x2, int y2)
42  {
43  //実装参考[http://hp.vector.co.jp/authors/VA028002/sdl/]
44  //パブリックドメインなのでわりとコピペしてます
45  int r;
46  int dx, dy;
47  int xa, ya, xb, yb;
48  int f;
49 
50  SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
51  SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
52  SDL_RenderClear(renderer);
53  SDL_SetRenderDrawColor(renderer,255,255,255,255);
54 
55  dx = x2 - x1 < 0 ? x1 - x2 : x2 - x1;
56  dy = y2 - y1 < 0 ? y1 - y2 : y2 - y1;
57 
58  r = dx / 2;
59  xa = r;
60  ya = 0;
61  f = 3 - 2 * r;
62  x1 += dx / 2;
63  y1 += dy / 2;
64  x2 = x1 + dx % 2;
65  y2 = y1 + dy % 2;
66  while (xa >= ya){
67  xb = (xa * dy) / dx;
68  yb = (ya * dy) / dx;
69 
70  SDL_RenderDrawLine(renderer, xa + x2, -yb + y1,xa + x2, yb + y2); /*A*/
71  SDL_RenderDrawLine(renderer, ya + x2, -xb + y1, ya + x2, xb + y2); /*B*/
72  SDL_RenderDrawLine(renderer, -ya + x1, -xb + y1, -ya + x1, xb + y2); /*C*/
73  SDL_RenderDrawLine(renderer, -xa + x1, -yb + y1, -xa + x1, yb + y2); /*D*/
74 
75  if (f >= 0){
76  xa--;
77  f -= 4 * xa;
78  }
79  ya++;
80  f += 4 * ya + 2;
81  }
82  }
83 
85  static Image& GetCircle(const Color &描画色, const Rect &矩形 = {0,0,0,0}, int 太さ = 0)
86  {
87  static Image circleA;
88  static Image circleB;
89  static Image circleC;
90  const int CIRCLE_SIZE = 512;
91 
92  if (circleA.GetHandle() == nullptr)
93  {
94  circleA.Make(CIRCLE_SIZE, CIRCLE_SIZE);
95  circleB.Make(CIRCLE_SIZE, CIRCLE_SIZE);
96  circleC.Make(CIRCLE_SIZE, CIRCLE_SIZE);
97 
98  auto mode = Screen::GetRenderer()->blendMode;
99  auto col = Screen::GetRenderer()->rgba;
100  int alpha = Screen::GetRenderer()->rgba.GetAlpha();//Alpha値の場合ここの減算率が変化する
101  auto cam = Camera::Get();
102 
103  Camera::Set();
105  auto prev = Screen::GetTarget();
106 
107  Screen::SetTarget(&circleA);
108  MakeCircle(Screen::GetHandle(), 0, 0, CIRCLE_SIZE, CIRCLE_SIZE);
109  Screen::SetTarget(&circleB);
110  SDL_SetRenderDrawColor(Screen::GetHandle(), 0, 0, 0, 0);
111  SDL_RenderClear(Screen::GetHandle());
112  Screen::SetTarget(&circleC);
113  Drawing::Rect({ 0, 0, CIRCLE_SIZE, CIRCLE_SIZE }, Color::White, true);
114  Screen::SetTarget(prev);
115 
116  Screen::SetDrawMode(col,mode);
117  Camera::Set(cam);
118  }
119 
120  if (太さ <= 0)
121  {
122  circleA.SetColor(描画色);
123  return circleA;
124  }
125  else
126  {
127  太さ = std::max(太さ * CIRCLE_SIZE * 2 / int(矩形.GetW() + 矩形.GetH()), 2);//最低2
128 
129  auto prev = Screen::GetTarget();
130  auto mode = Screen::GetRenderer()->blendMode;
131  auto col = Screen::GetRenderer()->rgba;
132  int alpha = Screen::GetRenderer()->rgba.GetAlpha();//Alpha値の場合ここの減算率が変化する
133  auto cam = Camera::Get();
134 
135  Camera::Set();
137 
138  Screen::SetTarget(&circleB);
139  circleA.SetColor(Color::White);
140  circleA.Draw({ 0, 0 });
141  circleA.SetColor(Color::Black);
142  circleA.DrawExtend({ 太さ, 太さ , CIRCLE_SIZE - 太さ*2 , CIRCLE_SIZE - 太さ*2 });
143  Screen::SetTarget(&circleC);
144  circleA.SetColor({255-alpha,255-alpha,255-alpha});
145  circleA.Draw({ 0, 0 });
146  circleA.SetColor(Color::White);
147  circleA.DrawExtend({ 太さ, 太さ , CIRCLE_SIZE - 太さ*2, CIRCLE_SIZE - 太さ*2 });
148  Screen::SetTarget(prev);
149  Camera::Set(cam);
150 
151 
152  if (mode == BlendMode::Mula)
153  {
154  Screen::SetDrawMode({255,255,255,alpha},BlendMode::Mula);
155  circleB.DrawExtend(矩形);
156  }
157  else
158  {
159  if (mode != BlendMode::Add)
160  {
161  Screen::SetDrawMode({ 255, 255, 255, alpha }, BlendMode::Mula);
162  circleC.DrawExtend(矩形);
163  }
164  Screen::SetDrawMode({ 描画色.GetRed(), 描画色.GetGreen(), 描画色.GetBlue(), alpha }, BlendMode::Add);
165  circleB.DrawExtend(矩形);
166  }
167 
168  Screen::SetDrawMode(col, mode);
169 
170  return circleB;
171  }
172  }
173 
175  static void GetTriangle(const Color &描画色, const Point &中心座標 = {0,0}, int 辺の長さ = 0, double 角度 = 0, int 太さ = 0)
176  {
177  static Image imageA;
178  static Image imageB;
179  static Image imageC;
180 
181  const int WSIZE = 173*2;
182  const int HSIZE = 200*2;
183 
184  if (imageA.GetHandle() == nullptr)
185  {
186  imageA.Make(WSIZE, HSIZE);//高さ=√3の近似
187  imageB.Make(WSIZE, HSIZE);
188  imageC.Make(WSIZE, HSIZE);
189 
190  auto prev = Screen::GetTarget();
191  auto mode = Screen::GetRenderer()->blendMode;
192  auto col = Screen::GetRenderer()->rgba;
193  auto cam = Camera::Get();
194 
195  Camera::Set();
197 
198  Screen::SetTarget(&imageA);
199  //横向きの三角形を描画
200  SDL_SetRenderDrawColor(Screen::GetHandle(), 0, 0, 0, 0);
201  SDL_RenderClear(Screen::GetHandle());
202  SDL_SetRenderDrawBlendMode(Screen::GetHandle(), SDL_BLENDMODE_BLEND);
203  SDL_SetRenderDrawColor(Screen::GetHandle(), 255, 255, 255, 255);
204  for (int y = 0; y < HSIZE/2; ++y)
205  {
206  int x = WSIZE * y * 2 / HSIZE;
207  SDL_RenderDrawLine(Screen::GetHandle(), 0, y, x, y);
208  SDL_RenderDrawLine(Screen::GetHandle(), 0, HSIZE-y-1, x, HSIZE-y-1);
209  }
210  Screen::SetTarget(&imageB);
211  SDL_SetRenderDrawColor(Screen::GetHandle(), 0, 0, 0, 0);
212  SDL_RenderClear(Screen::GetHandle());
213  Screen::SetTarget(&imageC);
214  Drawing::Rect({ 0, 0, WSIZE, HSIZE }, Color::White, true);
215  Screen::SetTarget(prev);
216 
217  Screen::SetDrawMode(col, mode);
218  Camera::Set(cam);
219  }
220 
221  const double 拡大率 = double(辺の長さ) / HSIZE;
222 
223  if (太さ <= 0)
224  {
225  imageA.SetColor(描画色);
226  imageA.DrawRotateAxis({ 中心座標.x ,中心座標.y}, { WSIZE/3, HSIZE/2 }, 拡大率, 角度);
227  }
228  else
229  {
230  太さ = std::max(太さ * WSIZE* 2 / (辺の長さ), 2);//最低2
231 
232  auto prev = Screen::GetTarget();
233  int alpha = Screen::GetRenderer()->rgba.GetAlpha();//Alpha値によりここの減算率が変化する
234  auto mode = Screen::GetRenderer()->blendMode;
235  auto col = Screen::GetRenderer()->rgba;
236  auto cam = Camera::Get();
237 
238  Camera::Set();
240 
241  Screen::SetTarget(&imageB);
242  imageA.SetColor(Color::White);
243  imageA.Draw({ 0, 0 });
244  imageA.SetColor(Color::Black);
245  imageA.DrawExtend({ 太さ/2, 太さ , WSIZE - 太さ*3/2, HSIZE - 太さ*2 });
246  Screen::SetTarget(&imageC);
247  imageA.SetColor({ 255 - alpha, 255 - alpha, 255 - alpha });
248  imageA.Draw({ 0, 0 });
249  imageA.SetColor(Color::White);
250  imageA.DrawExtend({ 太さ/2, 太さ , WSIZE - 太さ*3/2, HSIZE - 太さ*2 });
251  Screen::SetTarget(prev);
252  Camera::Set(cam);
253 
254  if (mode == BlendMode::Mula)
255  {
256  Screen::SetDrawMode({ 255, 255, 255, alpha }, BlendMode::Mula);
257  imageB.DrawRotateAxis({ 中心座標.x, 中心座標.y }, { WSIZE / 3, HSIZE / 2 }, 拡大率, 角度);
258  }
259  else
260  {
261  if ( mode != BlendMode::Add)
262  {
263  Screen::SetDrawMode({ 255, 255, 255, alpha }, BlendMode::Mula);
264  imageC.DrawRotateAxis({ 中心座標.x, 中心座標.y }, { WSIZE / 3, HSIZE / 2 }, 拡大率, 角度);
265  }
266 
267  Screen::SetDrawMode({ 描画色.GetRed(), 描画色.GetGreen(), 描画色.GetBlue(), alpha }, BlendMode::Add);
268  imageB.DrawRotateAxis({ 中心座標.x, 中心座標.y }, { WSIZE / 3, HSIZE / 2 }, 拡大率, 角度);
269  }
270 
271  Screen::SetDrawMode(col, mode);
272  }
273  }
274 public:
276  static Font& GetFont()
277  {
278  static Font defaultFont;
279  return defaultFont;
280  }
281 
283  static void SetDefaultFont(const char* フォント名, int 大きさ,int 行間 = 0 , bool 高品質レンダリング = true)
284  {
285  GetFont().Load(フォント名, 大きさ, 行間, 高品質レンダリング);
286  }
287 
289  static void Line(const Point &始点, const Point &終点, const Color &色, int 太さ = 1)
290  {
291  if (太さ <= 1)
292  {
293  int xA,xB,yA,yB;
294  RGBACulculate(色.GetRed(), 色.GetGreen(), 色.GetBlue());
295  if (Camera::Get())
296  {
297  xA = (int)Camera::Get()->TransX(始点.x);
298  xB = (int)Camera::Get()->TransX(終点.x);
299  yA = (int)Camera::Get()->TransY(始点.y);
300  yB = (int)Camera::Get()->TransY(終点.y);
301  }
302  else
303  {
304  xA = (int)始点.x;
305  xB = (int)終点.x;
306  yA = (int)始点.y;
307  yB = (int)終点.y;
308  }
309 
310  SDL_RenderDrawLine(Screen::GetHandle(), xA, yA, xB, yB);
311  }
312  else
313  {
314  static Image image;
315  if (image.GetHandle() == nullptr)
316  {
317  auto prev = Screen::GetRenderer()->target;
318  auto mode = Screen::GetRenderer()->blendMode;
319  auto col = Screen::GetRenderer()->rgba;
320  auto cam = Camera::Get();
321 
322  image.Make(256, 256);
323  Camera::Set();
325  Screen::SetTarget(&image);
326  Drawing::Rect({ 0, 0, 256, 256 }, Color::White, true);
327  Screen::SetTarget(prev);
328  Screen::SetDrawMode(col,mode);
329  Camera::Set(cam);
330  }
331 
332  double rateX = std::sqrt((終点.x - 始点.x)*(終点.x - 始点.x) + (終点.y - 始点.y) * (終点.y - 始点.y));//太さ
333  double rateY = 太さ;//長さ
334  double angle = std::atan2( 終点.y - 始点.y , 終点.x - 始点.x);
335 
336  image.SetColor(色);
337  image.DrawRotateAxis({ (始点.x + 終点.x)/2, (始点.y + 終点.y)/2 }, { 128, 128 }, rateX/256, rateY/256, angle);
338  }
339  }
340 
342  static void Rect(const Rect &領域, const Color &色, bool 塗りつぶしフラグ = true)
343  {
344  SDL_Rect buf = { (int)領域.GetLeft(), (int)領域.GetTop(), (int)領域.GetW(), (int)領域.GetH() };
345 
346  if (Camera::Get())
347  {
348  buf = Camera::Get()->TransRect(buf);
349  }
350 
351  RGBACulculate(色.GetRed(), 色.GetGreen(), 色.GetBlue());
352  if (塗りつぶしフラグ)
353  {
354  SDL_RenderFillRect(Screen::GetHandle(), &buf);
355  }
356  else
357  {
358  SDL_RenderDrawRect(Screen::GetHandle(), &buf);
359  }
360  }
361 
365  static void Circle(const Circle &円形, const Color& 色, int 太さ = 0)
366  {
367  if (円形.radius <= 0){ return; }
368 
369  if (太さ <= 0)
370  {
371  GetCircle(色).DrawExtend({ 円形.x - 円形.radius, 円形.y - 円形.radius , 円形.radius*2, 円形.radius*2 });
372  }
373  else
374  {
375  GetCircle(色, { 円形.x - 円形.radius, 円形.y - 円形.radius, 円形.radius * 2, 円形.radius * 2 }, 太さ);
376  }
377  }
378 
382  static void Oval(const Point &中心, int 幅, int 高さ, const Color& 色, int 太さ = 0)
383  {
384  if (太さ <= 0)
385  {
386  GetCircle(色).DrawExtend({ 中心.x - 幅 / 2, 中心.y - 高さ / 2, (double)幅, (double)高さ });
387  }
388  else
389  {
390  GetCircle(色, { 中心.x - 幅 / 2, 中心.y - 高さ / 2, 幅, 高さ }, 太さ);
391  }
392  }
393 
395  static void Polygon(std::vector<Point> 頂点, const Color &色 ,int 太さ = 1)
396  {
397  for (unsigned int a = 0; a < 頂点.size() ; ++a)
398  {
399  if (a == 頂点.size() - 1)
400  {
401  //最後の辺
402  Drawing::Line(頂点[a],頂点[0],色,太さ);
403  }
404  else
405  {
406  Drawing::Line(頂点[a], 頂点[a+1], 色, 太さ);
407  }
408 
409  }
410  }
411 
415  static void Triangle(const Point &中心座標,int 辺の長さ , double 角度 , const Color &描画色 , int 太さ = 0)
416  {
417  if (太さ <= 0)
418  {
419  GetTriangle(描画色, 中心座標, 辺の長さ, 角度);
420  }
421  else
422  {
423  GetTriangle(描画色, 中心座標, 辺の長さ, 角度, 太さ);
424  }
425  }
426 
428  static void Pixel(const Point &座標, const Color &色)
429  {
430  RGBACulculate(色.GetRed(), 色.GetGreen(), 色.GetBlue());
431 
432  double x = 座標.x;
433  double y = 座標.y;
434 
435  if (Camera::Get())
436  {
437  x = Camera::Get()->TransX(x);
438  y = Camera::Get()->TransY(y);
439  }
440 
441  SDL_RenderDrawPoint(Screen::GetHandle(), (int)x, (int)y);
442  }
443 
446  static void ImageFile(const Point &座標, const char *ファイル名, bool 透過フラグ = true)
447  {
448  Image buf(ファイル名);
449  buf.Draw(座標, false);
450  buf.Release();
451  }
452 
455  static void String(const Point &座標, const Color &色, const VariadicStream &描画する文字列)
456  {
457  GetFont().Draw(座標, 色, 描画する文字列);
458  }
459  };
460 }
bool Draw(const Point &座標, const Color &描画色, const VariadicStream &描画する文字列, bool 反転フラグ=false) const override
文字を描画.
Definition: Font.h:569
SDL_Texture * Make(int 幅, int 高さ)
空のイメージを作成.
Definition: Image.h:120
int GetGreen() const
緑の要素を取得.
Definition: Color.h:36
矩形を表す図形クラス.
Definition: Rect.h:22
static Image * GetTarget()
描画先Imageを取得.
Definition: Screen.h:55
double y
座標
Definition: Point.h:26
static void Pixel(const Point &座標, const Color &色)
指定座標に点を描画.
Definition: Drawing.h:428
bool DrawRotateAxis(const Point &座標, const Point &回転軸座標, double 拡大率, double 角度, bool 反転フラグ=false) const override
回転軸、角度、拡大率を指定して描画.
Definition: Image.h:244
Color rgba
描画輝度とα値
Definition: Renderer.h:53
bool DrawExtend(const Rect &描画領域, bool 反転フラグ=false) const override
指定矩形内に描画.
Definition: Image.h:201
double GetTop() const
上端のY座標を取得.
Definition: Rect.h:124
int GetBlue() const
青の要素を取得.
Definition: Color.h:42
リソースを読み込まずに描画を行う関数群.
Definition: Drawing.h:17
double GetLeft() const
左端のX座標を取得.
Definition: Rect.h:118
static void Circle(const Circle &円形, const Color &色, int 太さ=0)
中心と半径を指定して円を描画.
Definition: Drawing.h:365
SDL_Rect TransRect(const SDL_Rect &変換前矩形) const
領域を画面上のどこに相当するか変換.
Definition: Camera.h:102
double x
座標
Definition: Circle.h:23
static void Line(const Point &始点, const Point &終点, const Color &色, int 太さ=1)
始点と終点を結ぶ直線を描画.
Definition: Drawing.h:289
点を表す図形クラス.
Definition: Point.h:22
BlendMode blendMode
描画モード
Definition: Renderer.h:51
static void String(const Point &座標, const Color &色, const VariadicStream &描画する文字列)
文字を描画.
Definition: Drawing.h:455
TrueTypeFontとBMPFontをまとめて扱うクラス.
Definition: Font.h:24
double TransX(double X座標変換前) const
カメラの位置と拡大率に応じてX座標を変換.
Definition: Camera.h:84
static Renderer * GetRenderer()
アクティブなRendererを取得.
Definition: Screen.h:33
double y
座標
Definition: Circle.h:24
double TransY(double Y座標変換前) const
カメラの位置と拡大率に応じてY座標を変換.
Definition: Camera.h:90
static bool SetTarget(Image *描画対象=nullptr)
描画先を変更.
Definition: Screen.h:48
static void Triangle(const Point &中心座標, int 辺の長さ, double 角度, const Color &描画色, int 太さ=0)
正三角形を描画.
Definition: Drawing.h:415
static const Color White
白 [RGB]255,255,255
Definition: Color.h:81
画像データを表すクラス.
Definition: Image.h:17
色を表すクラス.
Definition: Color.h:11
bool Load(const char *フォント名, int 大きさ, int 行間=0, bool 高品質レンダリングフラグ=true)
フォントを作成する.
Definition: Font.h:182
積算ブレンド
SDL_Texture * GetHandle() const
ハンドルを取得.
Definition: Image.h:175
static const Color Black
黒 [RGB]0,0,0
Definition: Color.h:78
bool Release()
イメージをメモリから開放.
Definition: Image.h:109
static SDL_Renderer * GetHandle()
スクリーンハンドルを取得.
Definition: Screen.h:26
static Camera * Get()
現在アクティブなカメラを取得.
Definition: Camera.h:57
static void SetDrawMode(const Color &輝度+α値=Color::White, BlendMode ブレンドモード=BlendMode::Alpha)
描画輝度と描画モードをまとめて設定
Definition: Screen.h:100
int GetRed() const
赤の要素を取得.
Definition: Color.h:30
可変数引数な文字列を処理するクラス.
Definition: VariadicStream.h:25
加算ブレンド
static void ImageFile(const Point &座標, const char *ファイル名, bool 透過フラグ=true)
画像を一時的にメモリに読み込んで描画.
Definition: Drawing.h:446
double x
座標
Definition: Point.h:25
static void Set(Camera *アクティブにするCamera=nullptr)
現在アクティブなカメラを設定.
Definition: Camera.h:63
static void Polygon(std::vector< Point > 頂点, const Color &色, int 太さ=1)
頂点を指定して多角形を描画.
Definition: Drawing.h:395
void SetColor(const Color &描画色)
描画色を指定.
Definition: Image.h:316
int GetAlpha() const
透明度を取得.
Definition: Color.h:48
static Font & GetFont()
デフォルトのフォントを取得する.
Definition: Drawing.h:276
円を表す図形クラス.
Definition: Circle.h:20
bool Draw(const Point &座標, bool 反転フラグ=false) const override
指定座標に描画.
Definition: Image.h:181
static void SetDefaultFont(const char *フォント名, int 大きさ, int 行間=0, bool 高品質レンダリング=true)
デフォルトのフォントを設定する.
Definition: Drawing.h:283
double GetW() const override
幅を取得.
Definition: Rect.h:107
static void Rect(const Rect &領域, const Color &色, bool 塗りつぶしフラグ=true)
左上の座標と大きさを指定して矩形を描画.
Definition: Drawing.h:342
double GetH() const override
高さを取得.
Definition: Rect.h:112
double radius
半径
Definition: Circle.h:25
static void Oval(const Point &中心, int 幅, int 高さ, const Color &色, int 太さ=0)
中心と外接する四角形の大きさを指定して楕円を描画.
Definition: Drawing.h:382