• 又到中秋节,通过C语言利用SimpleCG制作电子贺卡


            感觉现在时间过的真是飞快,很多人都觉得现在的时间比以前缩短了好多,眨眼间又到了中秋了。通过前面对SimpeCG的了解,现在用C语言绘制一张中秋电子贺卡应该不难了,我们在本篇文章就来试试吧。

            不过在这里我们尝试使用SimpleCG的另外一个绘图功能--PencilTurtle,就是小朋友很喜欢的海龟作图方式。这个功能后面再详细介绍,不过很多朋友可能都接触过了,因为早期有很多学习机会附带。

            先看看效果图:

    运行程序可以在这里下载

    http://simplecg.qqpet.com/AnimateMidAutumn2.zip 

    代码可以在这里查看

    中秋贺卡代码

    全部主体代码如下:

     

    1. // AnimateMidAutumn.cpp : 定义控制台应用程序的入口点。
    2. //
    3. #include "../import/include/CGBoard.h"
    4. #include "math.h"
    5. extern "C"
    6. {
    7. #include "PencileTurtle.h"
    8. #include "Midi.h"
    9. }
    10. #ifdef _DEBUG
    11. #pragma comment(lib,"../import/lib/SimpleCG_MDd.lib")
    12. #else
    13. #pragma comment(lib,"../import/lib/SimpleCG_MT.lib")
    14. #endif
    15. int g_nWidth = 640; //画面宽度
    16. int g_nHeight= 480; //画面高度
    17. int g_nMusic = 0;
    18. HMIDIOUT g_hMidi = 0;
    19. #define ADDCOLOR(x,y) ((x+y)>255?255:(x+y))
    20. void StartMusic()
    21. {
    22. g_hMidi = SMidOpenMidi();
    23. SetTimbre( g_hMidi, 0, 10 );
    24. g_nMusic = PlaySimpleSongBack( g_hMidi, 0, 90, -1, _T("***1/1-6*5/6+1|*1===|1/1-6*5/6+2|*2===|3/1-6*+3/1-6|+*2/=1*-6=|+44/-6*+1/=|*2===|1/1-6*5/6+1|*1===|1/1-6*5/6+2|*2===|//2**3/1-6/+2**3/1-6|*+2/=1*-6=|+44/-6+*1/=|/2**2===|2-5/7*6/7|/7**+1===|/3232*31|4//4*5432*1|2=/=565|*2===|/3232*31|4//4*5432*1|2=/=565|*2===|2==/22|31*2==|2===|1/1-6*5/6+1|*1===|1/1-6*5/6+2*2===|//2**3/1-6/+2**3/1-6|+*2/=1*-6=|+44/-6+*1/=|/1**2===|2-5/7*6/7|/7**+1===|"));
    25. }
    26. void StopPlayMusic()
    27. {
    28. if( g_nMusic>0 )
    29. {
    30. StopMusic(g_nMusic);
    31. }
    32. SMidCloseMidi( g_hMidi );
    33. }
    34. void DrawMoon()
    35. {
    36. PTSetAngle(0);
    37. setfillcolor(RGB(254,231,122));
    38. PTMoveTo( 500,150 );
    39. PTBeginFill();
    40. PTCircle( 50 );
    41. PTEndFill();
    42. }
    43. void DrawMoonCake( int nX, int nY )
    44. {
    45. int i=0;
    46. int nCount = 18;
    47. setlinecolor(RGB(0xF2,0x90,0x0));
    48. setfillcolor(RGB(0xF8,0x80,0x20));
    49. for(i=0;i
    50. {
    51. PTMoveTo( nX,nY );
    52. PTTurnLeft(360 / nCount);
    53. PTMove(100);
    54. PTBeginFill();
    55. PTCircle( 20 );
    56. PTEndFill();
    57. }
    58. setlinewidth(5);
    59. for(i=0;i
    60. {
    61. PTMoveTo( nX,nY );
    62. PTTurnLeft(360 / nCount);
    63. PTMove(92);
    64. PTCircle( 20 );
    65. }
    66. setlinewidth(10);
    67. setfillcolor(RGB(0xFF,0x90,0x30));
    68. PTHome();
    69. PTMoveTo( nX,nY+95 );
    70. PTBeginFill();
    71. PTCircle( 95 );
    72. PTEndFill();
    73. //setlinecolor(RGB(162,84,13));
    74. setlinecolor(RGB(248,128,32));
    75. setlinewidth(5);
    76. int j=0;
    77. for(j=0;j<4;++j)
    78. {
    79. PTMoveTo( nX + 90*cos(C_PI/2*j),nY - 90*sin(C_PI/2*j) );
    80. //PTMoveTo( 200,330 );
    81. PTSetAngle(90*j+90);
    82. for(i=0;i<1080;++i)
    83. {
    84. PTTurnLeft(1*((float)i/1080));
    85. PTForward(.15);
    86. }
    87. }
    88. for(j=0;j<4;++j)
    89. {
    90. PTMoveTo( nX + 90*cos(C_PI/2*j),nY - 90*sin(C_PI/2*j) );
    91. PTSetAngle(90*j-90);
    92. for(i=0;i<270;++i)
    93. {
    94. PTTurnRight(1);
    95. PTForward(.6*((float)(270-i)/180));
    96. }
    97. }
    98. }
    99. void DrawWord(int nX,int nY,int nDelay)
    100. {
    101. settextcolor(RGB(228,108,12));
    102. setbackmode(enumBKM_TRANSPARENT);
    103. settextfontWeight(FW_BOLD);
    104. settextfontPointSize(30);
    105. outtextXY( nX-20, nY-80, _T("中"));
    106. if( nDelay>0 )
    107. {
    108. Sleep(nDelay);
    109. ReflushWindow();
    110. }
    111. outtextXY( nX-80, nY-20, _T("秋"));
    112. if( nDelay>0 )
    113. {
    114. Sleep(nDelay);
    115. ReflushWindow();
    116. }
    117. outtextXY( nX-20, nY+40, _T("快"));
    118. if( nDelay>0 )
    119. {
    120. Sleep(nDelay);
    121. ReflushWindow();
    122. }
    123. outtextXY( nX+40, nY-20, _T("乐"));
    124. if( nDelay>0 )
    125. {
    126. Sleep(nDelay);
    127. ReflushWindow();
    128. }
    129. }
    130. void DrawFiveStar(int nX,int nY,int nLen)
    131. {
    132. int i=0;
    133. PTMoveTo( nX,nY );
    134. setlinestyle(PS_NULL);
    135. setfillcolor(RGB(255,255,0));
    136. PTTurnRight(rand()%360);
    137. PTBeginFill();
    138. for(i=0;i<5;++i)
    139. {
    140. PTForward(nLen);
    141. PTTurnRight(144);
    142. }
    143. PTEndFill();
    144. setlinestyle(PS_SOLID);
    145. }
    146. void DrawStar()
    147. {
    148. int i=0;
    149. for(i=0;i<20;++i)
    150. {
    151. int nX = rand()%640;
    152. int nY = rand()%480;
    153. setfillcolor(RGB(245+rand()%10,245+rand()%10,245+rand()%10));
    154. PTMoveTo( nX,nY );
    155. PTBeginFill();
    156. PTCircle( rand()%5 );
    157. PTEndFill();
    158. }
    159. for(i=0;i<8;++i)
    160. {
    161. int nX = rand()%640;
    162. int nY = rand()%480;
    163. DrawFiveStar( nX, nY, 6+rand()%6);
    164. }
    165. }
    166. void DrawLeaves(int nX,int nY, int nSize)
    167. {
    168. setlinecolor(RGB(29,49,84));
    169. setfillcolor(RGB(29,49,84));
    170. PTMoveTo( nX,nY );
    171. PTSetAngle(rand()%80);
    172. int nWidhth = rand()%30+65;
    173. PTBeginFill();
    174. PTArc( nSize, nWidhth );
    175. PTTurnLeft(10);
    176. PTArc( nSize, -nWidhth );
    177. PTEndFill();
    178. }
    179. void DrawBack()
    180. {
    181. int i=0;
    182. setbackcolor(RGB(45,76,130));
    183. ClearDevice();
    184. DrawStar();
    185. setlinecolor(RGB(43,67,115));
    186. setfillcolor(RGB(43,67,115));
    187. PTMoveTo( 0,400 );
    188. PTSetAngle(0);
    189. PTBeginFill();
    190. for(i=0;i<90;++i)
    191. {
    192. PTTurnRight(1);
    193. PTForward(10*((float)(90-i)/90));
    194. }
    195. PTSetAngle(180);
    196. PTForward(380);
    197. PTEndFill();
    198. PTMoveTo( 250,480 );
    199. PTSetAngle(45);
    200. PTBeginFill();
    201. for(i=0;i<90;++i)
    202. {
    203. PTTurnRight(1);
    204. PTForward(20*((float)(90-i)/90));
    205. }
    206. PTSetAngle(-90);
    207. PTForward(380);
    208. PTEndFill();
    209. for(i=0;i<30;++i)
    210. {
    211. DrawLeaves(rand()%600,480, 10+rand()%40);
    212. }
    213. }
    214. void DrawRabbit(int nX, int nY, float fSize )
    215. {
    216. int i=0;
    217. setlinewidth(1);
    218. setlinecolor(RGB(0,0,0));
    219. setfillcolor(RGB(255,255,255));
    220. PTMoveTo( nX,nY );
    221. PTBeginFill();
    222. PTSetAngle(80);
    223. PTArc( -20*fSize, 60 );
    224. PTArc( -10*fSize, 20 );
    225. PTTurnRight(85);
    226. PTArc( -20*fSize, 65 );
    227. PTSetAngle(-40);
    228. PTArc(-16*fSize, 40);
    229. PTTurnLeft(20);
    230. PTArc(-10*fSize, 90);
    231. PTSetAngle(-40);
    232. PTArc(-20*fSize, 69);
    233. PTSetAngle(240);
    234. PTArc(-20, 100);
    235. /*PTForward(34);*/
    236. PTSetAngle(110);
    237. PTArc(-20*fSize, 69);
    238. PTTurnLeft(115);
    239. PTArc(-10*fSize, 90);
    240. PTSetAngle(85);
    241. PTArc(-16*fSize, 40);
    242. PTSetAngle(140);
    243. PTArc( -20*fSize, 55 );
    244. PTArc( -10*fSize, 20 );
    245. PTTurnRight(85);
    246. PTArc( -20*fSize, 65 );
    247. PTEndFill();
    248. }
    249. void DrawRabbit2(int nX, int nY, float fSize )
    250. {
    251. int i=0;
    252. setlinewidth(1);
    253. setlinecolor(RGB(0,0,0));
    254. setfillcolor(RGB(200,200,200));
    255. PTMoveTo( nX+10,nY-25 );
    256. PTBeginFill();
    257. PTSetAngle(30);
    258. PTArc( 35*fSize, -60 );
    259. PTSetAngle(30);
    260. PTArc( -35*fSize, 60 );
    261. PTEndFill();
    262. PTSetAngle(30);
    263. PTArc( 35*fSize, -60 );
    264. setfillcolor(RGB(255,255,255));
    265. PTBeginFill();
    266. PTSetAngle(230);
    267. PTArc( 35*fSize, -60 );
    268. PTSetAngle(230);
    269. PTArc( -35*fSize, 60 );
    270. PTEndFill();
    271. PTMoveTo( nX-60,nY );
    272. PTBeginFill();
    273. PTSetAngle(140);
    274. PTArc( -25*fSize, 80 );
    275. PTSetAngle(-140);
    276. PTArc( 35*fSize, -100 );
    277. PTEndFill();
    278. PTMoveTo( nX-20,nY-20 );
    279. PTBeginFill();
    280. PTSetAngle(180);
    281. PTArc( 50*fSize, -90 );
    282. PTCircle( -6 );
    283. PTTurnRight(50);
    284. PTArc( 80*fSize, -50 );
    285. PTTurnRight(130);
    286. PTArc( 80*fSize, -10 );
    287. PTTurnRight(200);
    288. PTArc( 30*fSize, -130 );
    289. PTEndFill();
    290. setlinestyle(PS_NULL);
    291. setfillcolor(RGB(255,225,200));
    292. PTBeginFill();
    293. PTMoveTo( nX-40,nY-15 );
    294. PTCircle( -7 );
    295. PTEndFill();
    296. setfillcolor(RGB(255,191,191));
    297. PTMoveTo( nX-40,nY-28 );
    298. PTBeginFill();
    299. PTCircle( -3 );
    300. PTEndFill();
    301. setlinestyle(PS_SOLID);
    302. }
    303. void DrawLight(int nX, int nY,float fSize)
    304. {
    305. {
    306. POINT pt[]={{nX,nY},{nX-1.8*fSize,nY-2.3*fSize},{nX+0.5*fSize,nY-4*fSize},{nX+2.6*fSize,nY-4*fSize},{nX+3.6*fSize,nY-fSize},{nX+2*fSize,nY-fSize}};
    307. setfillcolor(RGB(233,145,66));
    308. _fillpolygon(pt,sizeof(pt)/sizeof(pt[0]));
    309. _line(nX+0.5*fSize,nY-4*fSize,nX+2*fSize,nY-fSize);
    310. }
    311. {
    312. POINT pt[]={{nX,nY},{nX+2*fSize,nY-fSize},{nX+3.6*fSize,nY-fSize},{nX+1.6*fSize,nY}};
    313. setfillcolor(RGB(253,202,59));
    314. _fillpolygon(pt,sizeof(pt)/sizeof(pt[0]));
    315. }
    316. setfillcolor(RGB(253,239,120));
    317. _solidcircle(nX+2*fSize,nY-0.5*fSize,0.3*fSize);
    318. }
    319. void DrawProcess()
    320. {
    321. POINT ptLight[10]={0};
    322. int nSize[10]={0};
    323. int i=0;
    324. for(i=0;i<10;++i)
    325. {
    326. ptLight[i].x=rand()%200+400;
    327. ptLight[i].y=rand()%200+200;
    328. nSize[i] = ((float)ptLight[i].y) / 400 *20;
    329. }
    330. bool bIsRunning = true;
    331. StartMusic();
    332. DrawBack();
    333. DrawMoon();
    334. DrawMoonCake(150,150);
    335. DrawWord( 150,150, 500 );
    336. DrawRabbit( 80, 360, 1 );
    337. DrawRabbit( 450, 330, 0.5 );
    338. DrawRabbit2( 550, 300, 1 );
    339. while(bIsRunning&&IsShowingWindow())
    340. {
    341. PTSpeed(0);
    342. DrawBack();
    343. DrawMoon();
    344. DrawMoonCake(150,150);
    345. DrawWord( 150,150, 0 );
    346. DrawRabbit( 80, 360, 1 );
    347. DrawRabbit( 450, 330, 0.5 );
    348. DrawRabbit2( 550, 300, 1 );
    349. for(i=0;i<5;++i)
    350. {
    351. DrawLight(ptLight[i].x,ptLight[i].y, nSize[i]);
    352. if(ptLight[i].y>0)
    353. ptLight[i].y -= 2;
    354. else
    355. ptLight[i].y = rand()%200+200;
    356. nSize[i] = ((float)ptLight[i].y) / 400 *20;
    357. }
    358. ReflushWindow();
    359. Sleep(100);
    360. }
    361. StopPlayMusic();
    362. }
    363. int _tmain(int argc, _TCHAR* argv[])
    364. {
    365. //初始化
    366. if( !ShowingBoard(g_nWidth,g_nHeight, DrawProcess))
    367. return 1;
    368. //关闭图库
    369. CloseBoard();
    370. return 0;
    371. }

    其中有很多功能在之前的教程都还没教到,会在后续的文章中介绍,例如文字的输出,海龟作图的方式,以及乐曲的播放等。

            在这里顺带说一说乐曲的播放,该播放函数可以播放一般的C大调简谱乐曲,如果有同学想现在尝试该功能的话,我这里大概说一说如何转换任意简谱,通过简单学习,你就能将任意简谱转换成MIDI播放。MIDI播放函数如下:

    g_nMusic = PlaySimpleSongBack( g_hMidi, 0, 90, -1, _T("***1/1-6*5/6+1|*1===|1/1-6*5/6+2|*2===|3/1-6*+3/1-6|+*2/=1*-6=|+44/-6*+1/=|*2===|1/1-6*5/6+1|*1===|1/1-6*5/6+2|*2===|//2**3/1-6/+2**3/1-6|*+2/=1*-6=|+44/-6+*1/=|/2**2===|2-5/7*6/7|/7**+1===|/3232*31|4//4*5432*1|2=/=565|*2===|/3232*31|4//4*5432*1|2=/=565|*2===|2==/22|31*2==|2===|1/1-6*5/6+1|*1===|1/1-6*5/6+2*2===|//2**3/1-6/+2**3/1-6|+*2/=1*-6=|+44/-6+*1/=|/1**2===|2-5/7*6/7|/7**+1===|"));
    	

            首先我们从网上看一下《明月几时有》(网络引用,版权原作者所有)的简谱如下:

    这是四四拍的,这首歌简谱是如何转成我们播放的格式的呢?非常简单! 我们的简谱文本主要有六个特殊字符,分别是+、-、*、/、=、|。就是加减乘除等号,其余就是1、2、3、4、5、6 、7音符,还有一个0休止符。下面介绍详细的转换过程。

            首先默认起始状态是C大调、音符是32分音符,此时1、2、3演奏出来的是C大调,就是音符底下和上面都没有点,然后+号升8度,-号降8度,而且输入+、-后影响后面所有的音符,除非再次使用+、-进行调节,乘号*和除号/是改变音符长短,默认是32分音符,输入一个*变成16分音符,再输入*变成8分音符,再一个*就成4分音符,看代码中“ ***1/1-6*5/6+1|*1===|1/1-6*5/6+2|*2===”,开始的三个*就是改变状态为4分音符。然后输出一个1(dou)、紧跟一个/,改变音符为8分音符,然后输出简谱中第二个1(dou),注意第二个1下面的下划线,表示8分音符,接着一个减号-,就把后面降8度,输出的6(啦)就是底下有点的,而且依据前面的音长还是8分音符,到了5(嗦)没有下划线是4分音符,所以要提高音长,我们输入乘号*后再输出5,然后后面的6(啦)又有下划线,音长又变成8分音符,我们输出除号/缩短音长为8分音符后再输出6。接着加号+升8度输出底下没有点的1,|是分段符,跟简谱一样。接着提高音符为4分音符再输出1,就是没有下划线的1(dou)。三个=号对应简谱的-,延长同样的拍。后面类似就不赘述了。对这个演奏有兴趣又没看明白的可以评论告诉我,我后面详细发些例子讲解。理解后还是很简单的。并且可以很方便转换网上的简谱歌曲,例如《罗刹海市》(版权归原作者所有)的简谱片断转换后及播放代码如下,有兴趣的同学可以尝试转换完全。

    1. int _tmain(int argc, _TCHAR* argv[])
    2. {
    3. HMIDIOUT hMidi = SMidOpenMidi();
    4. PlaySimpleSong( hMidi, 0, 60,1,_T("**333|-5/566+116|*06533/53*32|0313|/23*3-6+1011-5665303+11|-3/=5+*11|122-7|6/=76*53|0+*3/3/3532*-6+1-63/+2-7*6653|+/5665*6|6+/1/=1*-6+1*-5| -635|6/65*6/+11*0-115|/3235**3|/0+*3/3|/3532*-6+1|0-*3//+2-7|*6//67*6*53|"));
    5. SMidCloseMidi( hMidi );
    6. return 0;
    7. }

            海龟作图方式和文字也在后续文章详细介绍相关函数。请耐心等待。

            今天的文章就到这里了,想下载SimpleCG库的同学可以在下面下载。

    https://gitcode.net/b2b160/simplecg_demo

    安装方法如下

    SimpleCG库安装使用_b2b160的博客-CSDN博客

  • 相关阅读:
    git在linux情况下设置git 命令高亮
    是时候开始构建适用于 Android Automotive OS 的应用了
    HTTP/3核心概念之QUIC
    上周热点回顾(6.3-6.9)
    【绘图案例-绘图的步骤 Objective-C语言】
    【Linux】userdel 命令使用
    Python:为何成为当下最热门的编程语言?
    关于生命周期的面试题vue
    Python爬虫技术系列-06requests完成yz网数据采集V01
    网络安全之命令执行漏洞复现
  • 原文地址:https://blog.csdn.net/b2b160/article/details/133313696