赞
踩
2023年马上就要过去,希望2024年会越来越好,根据自己学的内容来实现一些我的idea。
最开始的构思是这样的,“2024”用数码管来输出然后中文的“新年快乐”用点阵来实现,但是点阵是动态的截图不好看,就想干脆用LCD1602输出英文的新年快乐算了,这样就只需要一个AT89C51就行了,还剩下五根引脚,想起来过年我印象中听过最多的歌是“好运来”就想增加一个蜂鸣器来播放好运来歌曲,大致的构思出的原理图如下,实验所需器件在代码后面。
首先是对2024的输出,这个就是输出他的BCD码。这个网络标号最开始就是C0在上面,输出的时候发现不对,然后就反过来标记,算是蒙对的。
- #include<reg51.h>
-
- void main(void){
- while(1){
- //2024 0010 0000 0010 0100
- P1=0x20;
- P3=0x24;
- }
- }
用LCD 1602输出我们没必要重新书写代码,只需要修改之后的代码即可。顺便对输出“2024”部分封装成函数。字符型液晶显示器LCD 1602的显示控制(Keil+Proteus)_1602液晶显示电路在keli中名称-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/134224776
- #include<reg51.h>
- #include<intrins.h> //包含_nop_()空函数指令的头文件
- #define uchar unsigned char
- #define uint unsigned int
- #define out P0
- sbit RS=P2^0;//位变量
- sbit RW=P2^1;//位变量
- sbit E=P2^2;//位变量
- //函数声明部分
- void lcd_initial(void);//LCD初始化函数
- void check_busy(void);//检查忙标志位函数
- void write_command(uchar com);//写命令函数
- void write_data(uchar dat);//写数据函数
- void string(uchar ad,uchar *s);//显示字符串
- void delay(uint);//延时
- void print_LED();//输出“2024”的数码管
-
- void main(void){
- lcd_initial();//对LCD初始化
- while(1){
- print_LED();
- string(0x81,"Happy New Year");//显示第一行的字符
- string(0xC1,"peace happiness");//显示第二行的字符
- delay(100);//延时
- write_command(0x01);//清屏
- delay(100);//延时
- }
- }
-
- //延时
- void delay(uint j){
- uchar i=250;
- for(;j>0;j--){
- while(--i);
- i=249;
- while(--i);
- i=250;
- }
- }
-
- //检查忙标志
- void check_busy(void){
- uchar dt;
- do{
- dt=0xff;//dt为变量单元,初值为0xff
- //RS=0,E=1时才可以读忙标志位
- E=0;
- RS=0;
- RW=1;
- E=1;
- dt=out;//out为P0口,P0口的状态送入dt中
- }while(dt&0x80);//如果忙标志位BF=1,继续循环检测,等待BF=0
- E=0;//BF=0,LCD 1602不忙,结束检测
- }
-
- //写命令
- void write_command(uchar com){
- check_busy();
- //按规定RS和E同时为0时,才可以写命令
- E=0;
- RS=0;
- RW=0;
- out=com;//将命令com写入P0口
- E=1;//写命令时,E应为正脉冲,即正跳变,所以前面先置E=0
- _nop_();//空操作1个机器周期,等待硬件反应
- E=0;//E由高电平变为低电平,LCD 1602开始执行命令
- delay(1);//延时,等待硬件反应
- }
-
- //写数据
- void write_data(uchar dat){
- check_busy();//检测忙标志位BF=1则等待,若BF=0,则可对LCD 1602写入命令
- E=0;//按规定写数据时,E应为正脉冲,所以先置E=0
- //按规定RS=1和RW=0时,才可以写入数据
- RS=1;
- RW=0;
- out=dat;//将数据”dat“从P0口输出,即写入LCD 1602
- E=1;//E产生正跳变
- _nop_();//空操作1个机器周期,等待硬件反应
- E=0;//E由高电平变为低电平,写数据操作结束
- delay(1);
- }
-
- //液晶显示器初始化函数
- void lcd_initial(void){
- write_command(0x38);//8位两行显示,5*7点阵字符
- _nop_();//空操作1个机器周期,等待硬件反应
- write_command(0x0C);//开整体显示,光标关,无闪烁
- _nop_();//空操作1个机器周期,等待硬件反应
- //write_command(0x05);//光标右移
- _nop_();//空操作1个机器周期,等待硬件反应
- write_command(0x01);//清屏
- delay(1);
- }
- //输出显示字符串
- void string(uchar ad,uchar *s){
- write_command(ad);
- while(*s>0){
- write_data(*s++);//输出字符串,且指针增1
- delay(100);
- }
- }
-
- void print_LED(){//输出“2024”的数码管
- //2024 0010 0000 0010 0100
- P1=0x20;
- P3=0x24;
- }
先找到“好运来”的音乐简谱,然后带入之前的代码中。
单片机实验(三)-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/134624276
- #include<reg51.h>
- #include<intrins.h> //包含_nop_()空函数指令的头文件
- #define uchar unsigned char
- #define uint unsigned int
- #define out P0
-
- #define L1 1
- #define L1_ 2
- #define L2 3
- #define L2_ 4
- #define L3 5
- #define L4 6
- #define L4_ 7
- #define L5 8
- #define L5_ 9
- #define L6 10
- #define L6_ 11
- #define L7 12
- #define M1 13
- #define M1_ 14
- #define M2 15
- #define M2_ 16
- #define M3 17
- #define M4 18
- #define M4_ 19
- #define M5 20
- #define M5_ 21
- #define M6 22
- #define M6_ 23
- #define M7 24
- #define H1 25
- #define H1_ 26
- #define H2 27
- #define H2_ 28
- #define H3 29
- #define H4 30
- #define H4_ 31
- #define H5 32
- #define H5_ 33
- #define H6 34
- #define H6_ 35
- #define H7 36
-
- #define ClockSpeed 12000000 //时钟频率,Hz
- #define SongSpeed 240 //ms,八分音符
- sbit beepIO = P2^7; //定义蜂鸣器IO口
-
- uchar freq_select;
-
- //音阶频率表
- unsigned int code freq_table[]={0,61714 ,61928 ,62131 ,62322 ,62502 ,62673 ,62833 ,62985 ,63128 ,63263 ,63391 ,63511, //低音
- 63628 ,63731 ,63835 ,63928 ,64021 ,64103 ,64185 ,64260 ,64331 ,64400 ,64463 ,64524, //中音
- 64580 ,64633 ,64684 ,64732 ,64777 ,64820 ,64860 ,64898 ,64934 ,64968 ,65000 ,65030 //高音
- };
-
-
- //好运来
- uchar code song[]={
- //叠个千纸鹤 再系个红腰带
- M6,3, M6,1, H1,1, H1,1, M6,3, M6,1, M5,1, M3,1, M5,1, H1,1, M6,2, 0,2,
- //愿善良的人们 天天好运来.你
- M6,1, H1,1, H1,1, H1,1, H1,2, M5,2, M6,1, M5,1, M2,1, M5,1, M3,3, M2,1,
- //勤劳生活美,你健康春常在
- M3,1, M2,1, M1,1, M3,1, M2,3, M3,1, M6,1, M5,1, M3,1, M6,1, M6,1, M5,3,
- //你一生的忙碌为了笑逐颜开。
- M6,1, H1,1, H1,3, M6,1, H2,1, H2,1, H2,1, H1,1, M6,2, M5,1, H1,1, M6,4, M6,3,
- //好运来,祝你好运来,好运
- M6,2, H3,3, H2,1, H2,2, H1,1, M6,1, M5,2, H1,2, M6,4, M6,2, H2,2,
- //带来了喜和爱。好运
- H1,2, M6,1, M5,1, M2,2, M5,1, M6,1, M5,1, M3,3, M3,2, M6,3, M5,1,
- //来,我们好运来,迎着好运来
- M6,2, M6,1, M5,1, M6,2, H2,3, H1,1, H2,4, H1,3, H1,1, H1,1, H2,1,
- //兴旺发达通四海。
- H3,1, H3,1, H2,1, H1,1, M5,2, H1,3, M6,1, M6,2,
- 40
- };
- sbit RS=P2^0;//位变量
- sbit RW=P2^1;//位变量
- sbit E=P2^2;//位变量
- //函数声明部分
- void lcd_initial(void);//LCD初始化函数
- void check_busy(void);//检查忙标志位函数
- void write_command(uchar com);//写命令函数
- void write_data(uchar dat);//写数据函数
- void string(uchar ad,uchar *s);//显示字符串
- void delay(uint);//延时
- void print_2024();//输出“2024”的数码管
- void print_HappyNewYear();//输出“新年快乐”的LCD 1602
- void timer0_initial();//初始化定时器0的状态
- void delay_ms(unsigned int x); //音乐延时函数
-
- void main(void){
- uchar select;
- timer0_initial();//对定时器T0进行初始化
- lcd_initial();//对LCD初始化
- print_2024();
- print_HappyNewYear();
- while(song[select]!= 40) //判断歌曲是否结束
- {
- freq_select=song[select];
- if(freq_select) //判断是否是休止符0
- {
- select++;
- delay_ms(song[select]*SongSpeed);
- TR0 = 0; //关闭蜂鸣器一段时间再打开,模拟按键抬手动作。
- delay_ms(10);
- TR0 = 1;
- select++;
- }else{
- TR0 = 0;
- select++;
- delay_ms(song[select]*SongSpeed);
- TR0 = 1;
- select++;
- }
- }
- }
-
- //延时
- void delay(uint j){
- uchar i=250;
- for(;j>0;j--){
- while(--i);
- i=249;
- while(--i);
- i=250;
- }
- }
-
- //检查忙标志
- void check_busy(void){
- uchar dt;
- do{
- dt=0xff;//dt为变量单元,初值为0xff
- //RS=0,E=1时才可以读忙标志位
- E=0;
- RS=0;
- RW=1;
- E=1;
- dt=out;//out为P0口,P0口的状态送入dt中
- }while(dt&0x80);//如果忙标志位BF=1,继续循环检测,等待BF=0
- E=0;//BF=0,LCD 1602不忙,结束检测
- }
-
- //写命令
- void write_command(uchar com){
- check_busy();
- //按规定RS和E同时为0时,才可以写命令
- E=0;
- RS=0;
- RW=0;
- out=com;//将命令com写入P0口
- E=1;//写命令时,E应为正脉冲,即正跳变,所以前面先置E=0
- _nop_();//空操作1个机器周期,等待硬件反应
- E=0;//E由高电平变为低电平,LCD 1602开始执行命令
- delay(1);//延时,等待硬件反应
- }
-
- //写数据
- void write_data(uchar dat){
- check_busy();//检测忙标志位BF=1则等待,若BF=0,则可对LCD 1602写入命令
- E=0;//按规定写数据时,E应为正脉冲,所以先置E=0
- //按规定RS=1和RW=0时,才可以写入数据
- RS=1;
- RW=0;
- out=dat;//将数据”dat“从P0口输出,即写入LCD 1602
- E=1;//E产生正跳变
- _nop_();//空操作1个机器周期,等待硬件反应
- E=0;//E由高电平变为低电平,写数据操作结束
- delay(1);
- }
-
- //液晶显示器初始化函数
- void lcd_initial(void){
- write_command(0x38);//8位两行显示,5*7点阵字符
- _nop_();//空操作1个机器周期,等待硬件反应
- write_command(0x0C);//开整体显示,光标关,无闪烁
- _nop_();//空操作1个机器周期,等待硬件反应
- //write_command(0x05);//光标右移
- _nop_();//空操作1个机器周期,等待硬件反应
- write_command(0x01);//清屏
- delay(1);
- }
- //输出显示字符串
- void string(uchar ad,uchar *s){
- write_command(ad);
- while(*s>0){
- write_data(*s++);//输出字符串,且指针增1
- delay(100);
- }
- }
-
- void print_2024(){//输出“2024”的数码管
- //2024 0010 0000 0010 0100
- P1=0x20;
- P3=0x24;
- }
-
- void print_HappyNewYear(){//输出“新年快乐”的LCD 1602
- string(0x81,"Happy New Year");//显示第一行的字符
- string(0xC1,"peace happiness");//显示第二行的字符
- delay(50);//延时
- //write_command(0x01);//清屏
- }
-
- void timer0_initial()//初始化定时器0的状态
- {
- beepIO = 0;
- TH0 = 0xFD;
- TL0 = 0x09;
- TMOD = 0x01; //选择定时器0,工作方式1
- ET0 = 1; //允许定时器0中断
- EA = 1; //CPU开放中断
- TF0 = 0; //溢出标志位清0
- TR0 = 1; //开启定时器0
- }
-
- void BeepTimer0() interrupt 1 //中断函数
- {
- beepIO = !beepIO; //蜂鸣器IO口高低电平转换
- TH0 = freq_table[freq_select]/256 ;
- TL0 = freq_table[freq_select]%256 ;
- }
-
- void delay_ms(unsigned int x) //音乐延时函数
- {
- uchar t;
- while(x--) for(t=0;t<120;t++);
- }
本来觉得影响不大的,但是忽略了音乐的播放是需要延迟来表示每一个音的节拍,所以就把lcd清屏取消了,让他就一直显示这个,目前的话就是一轮之后会重新从主函数开始,而且LCD输出的时候他会发出其他的声音。
所以又继续完善了一下
- #include<reg51.h>
- #include<intrins.h> //包含_nop_()空函数指令的头文件
- #define uchar unsigned char
- #define uint unsigned int
- #define out P0
-
- #define L1 1
- #define L1_ 2
- #define L2 3
- #define L2_ 4
- #define L3 5
- #define L4 6
- #define L4_ 7
- #define L5 8
- #define L5_ 9
- #define L6 10
- #define L6_ 11
- #define L7 12
- #define M1 13
- #define M1_ 14
- #define M2 15
- #define M2_ 16
- #define M3 17
- #define M4 18
- #define M4_ 19
- #define M5 20
- #define M5_ 21
- #define M6 22
- #define M6_ 23
- #define M7 24
- #define H1 25
- #define H1_ 26
- #define H2 27
- #define H2_ 28
- #define H3 29
- #define H4 30
- #define H4_ 31
- #define H5 32
- #define H5_ 33
- #define H6 34
- #define H6_ 35
- #define H7 36
-
- #define ClockSpeed 12000000 //时钟频率,Hz
- #define SongSpeed 240 //ms,八分音符
- sbit beepIO = P2^7; //定义蜂鸣器IO口
-
- uchar freq_select;
-
- //音阶频率表
- unsigned int code freq_table[]={0,61714 ,61928 ,62131 ,62322 ,62502 ,62673 ,62833 ,62985 ,63128 ,63263 ,63391 ,63511, //低音
- 63628 ,63731 ,63835 ,63928 ,64021 ,64103 ,64185 ,64260 ,64331 ,64400 ,64463 ,64524, //中音
- 64580 ,64633 ,64684 ,64732 ,64777 ,64820 ,64860 ,64898 ,64934 ,64968 ,65000 ,65030 //高音
- };
-
-
- //好运来
- uchar code song[]={
- //叠个千纸鹤 再系个红腰带
- M6,3, M6,1, H1,1, H1,1, M6,3, M6,1, M5,1, M3,1, M5,1, H1,1, M6,2, 0,2,
- //愿善良的人们 天天好运来.你
- M6,1, H1,1, H1,1, H1,1, H1,2, M5,2, M6,1, M5,1, M2,1, M5,1, M3,3, M2,1,
- //勤劳生活美,你健康春常在
- M3,1, M2,1, M1,1, M3,1, M2,3, M3,1, M6,1, M5,1, M3,1, M6,1, M6,1, M5,3,
- //你一生的忙碌为了笑逐颜开。
- M6,1, H1,1, H1,3, M6,1, H2,1, H2,1, H2,1, H1,1, M6,2, M5,1, H1,1, M6,4, M6,3,
- //好运来,祝你好运来,好运
- M6,2, H3,3, H2,1, H2,2, H1,1, M6,1, M5,2, H1,2, M6,4, M6,2, H2,2,
- //带来了喜和爱。好运
- H1,2, M6,1, M5,1, M2,2, M5,1, M6,1, M5,1, M3,3, M3,2, M6,3, M5,1,
- //来,我们好运来,迎着好运来
- M6,2, M6,1, M5,1, M6,2, H2,3, H1,1, H2,4, H1,3, H1,1, H1,1, H2,1,
- //兴旺发达通四海。
- H3,1, H3,1, H2,1, H1,1, M5,2, H1,3, M6,1, M6,2,
- 40
- };
- sbit RS=P2^0;//位变量
- sbit RW=P2^1;//位变量
- sbit E=P2^2;//位变量
- //函数声明部分
- void lcd_initial(void);//LCD初始化函数
- void check_busy(void);//检查忙标志位函数
- void write_command(uchar com);//写命令函数
- void write_data(uchar dat);//写数据函数
- void string(uchar ad,uchar *s);//显示字符串
- void delay(uint);//延时
- void timer0_initial();//初始化定时器0的状态
- void delay_ms(unsigned int x); //音乐延时函数
- void print_2024();//输出“2024”的数码管
- void print_HappyNewYear();//输出“新年快乐”的LCD 1602
-
- void main(void){
-
- print_2024();//输出“2024”的数码管
- print_HappyNewYear();//输出“新年快乐”的LCD 1602
- //其他的都静态输出即可
- while(1){
- uchar select=0;//每次重新初始化
- timer0_initial();//对定时器T0进行初始化
- while(song[select]!= 40) //判断歌曲是否结束
- {
- freq_select=song[select];
- if(freq_select) //判断是否是休止符0
- {
- select++;
- delay_ms(song[select]*SongSpeed);
- TR0 = 0; //关闭蜂鸣器一段时间再打开,模拟按键抬手动作。
- delay_ms(10);
- TR0 = 1;
- select++;
- }else{
- TR0 = 0;
- select++;
- delay_ms(song[select]*SongSpeed);
- TR0 = 1;
- select++;
- }
- }
- }
- }
-
- //延时
- void delay(uint j){
- uchar i=250;
- for(;j>0;j--){
- while(--i);
- i=249;
- while(--i);
- i=250;
- }
- }
-
- //检查忙标志
- void check_busy(void){
- uchar dt;
- do{
- dt=0xff;//dt为变量单元,初值为0xff
- //RS=0,E=1时才可以读忙标志位
- E=0;
- RS=0;
- RW=1;
- E=1;
- dt=out;//out为P0口,P0口的状态送入dt中
- }while(dt&0x80);//如果忙标志位BF=1,继续循环检测,等待BF=0
- E=0;//BF=0,LCD 1602不忙,结束检测
- }
-
- //写命令
- void write_command(uchar com){
- check_busy();
- //按规定RS和E同时为0时,才可以写命令
- E=0;
- RS=0;
- RW=0;
- out=com;//将命令com写入P0口
- E=1;//写命令时,E应为正脉冲,即正跳变,所以前面先置E=0
- _nop_();//空操作1个机器周期,等待硬件反应
- E=0;//E由高电平变为低电平,LCD 1602开始执行命令
- delay(1);//延时,等待硬件反应
- }
-
- //写数据
- void write_data(uchar dat){
- check_busy();//检测忙标志位BF=1则等待,若BF=0,则可对LCD 1602写入命令
- E=0;//按规定写数据时,E应为正脉冲,所以先置E=0
- //按规定RS=1和RW=0时,才可以写入数据
- RS=1;
- RW=0;
- out=dat;//将数据”dat“从P0口输出,即写入LCD 1602
- E=1;//E产生正跳变
- _nop_();//空操作1个机器周期,等待硬件反应
- E=0;//E由高电平变为低电平,写数据操作结束
- delay(1);
- }
-
- //液晶显示器初始化函数
- void lcd_initial(void){
- write_command(0x38);//8位两行显示,5*7点阵字符
- _nop_();//空操作1个机器周期,等待硬件反应
- write_command(0x0C);//开整体显示,光标关,无闪烁
- _nop_();//空操作1个机器周期,等待硬件反应
- //write_command(0x05);//光标右移
- _nop_();//空操作1个机器周期,等待硬件反应
- write_command(0x01);//清屏
- delay(1);
- }
- //输出显示字符串
- void string(uchar ad,uchar *s){
- write_command(ad);
- while(*s>0){
- write_data(*s++);//输出字符串,且指针增1
- delay(100);
- }
- }
-
- void timer0_initial()//初始化定时器0的状态
- {
- beepIO = 0;
- TH0 = 0xFD;
- TL0 = 0x09;
- TMOD = 0x01; //选择定时器0,工作方式1
- ET0 = 1; //允许定时器0中断
- EA = 1; //CPU开放中断
- TF0 = 0; //溢出标志位清0
- TR0 = 1; //开启定时器0
- }
-
- void BeepTimer0() interrupt 1 //中断函数
- {
- beepIO = !beepIO; //蜂鸣器IO口高低电平转换
- TH0 = freq_table[freq_select]/256 ;
- TL0 = freq_table[freq_select]%256 ;
- }
-
- void delay_ms(unsigned int x) //音乐延时函数
- {
- uchar t;
- while(x--) for(t=0;t<120;t++);
- }
-
- void print_2024(){//输出“2024”的数码管
- //2024 0010 0000 0010 0100
- P1=0x20;
- P3=0x24;
- }
-
- void print_HappyNewYear(){//输出“新年快乐”的LCD 1602
- lcd_initial();//对LCD初始化
- string(0x81,"Happy New Year");//显示第一行的字符
- string(0xC1,"peace happiness");//显示第二行的字符
- delay(50);//延时
- //write_command(0x01);//清屏
- }
-
-
-
器件名称 | Proteus关键字 |
红色共阴极数码管 | 7SEG-BCD |
蓝色共阴极数码管 | 7SEG-BCD-BLUE |
绿色共阴极数码管 | 7SEG-BCD-GRN |
51单片机 | AT89C51 |
复位按钮 | BUTTON |
电容 | CAP |
电解电容 | CAP-ELEC |
晶体振荡器 | CRYSTAL |
字符型LCD 1602显示器 | LM016L |
滑动变阻器 | POT-HG |
电阻 | RES |
排阻 | RESPACK-8 |
蜂鸣器 | SPEAKER |
好运来
在B站上面看到了一个视频,打算就是实现这个烟花效果,当然光靠命令行是实现不了的。
首先需要用到EasyX库,我用的编译器是Dev-C++。
EasyX Graphics Library for C++https://easyx.cn/15天学会EasyX 第1天:EasyX的下载与配置安装_easyx下载-CSDN博客https://blog.csdn.net/LCR2025/article/details/131019284
链接“-leasyx -lgdi32 -lole32”
- #include<stdio.h>
- #include<easyx.h>//图形界面库
-
- int main(){
- initgraph(1200,800);//创建窗口 宽1200 高度800
- settextcolor(YELLOW);//设置字体的颜色
- settextstyle(25,0,"楷体");//设置字体的风格 字号
-
- outtextxy(300,300,"2024新年之际,祝福你健康、快乐、平安、幸福");
- outtextxy(300,350,"愿你每天都笑容满面");
- outtextxy(300,400,"所求皆如愿,所行皆坦途,多喜乐,长安宁");
- outtextxy(300,450,"平安喜乐,万事胜意");
- outtextxy(300,500,"期末考试顺利");
- outtextxy(600,550,"——封奚泽优");
- getchar();//按回车键继续
-
- while(1);
- return 0;
- }
dev c++播放音乐MP3(win环境)亲测有效_怎么在devc++里面用#pragma comment (lib,“winmm.lib”)-CSDN博客https://blog.csdn.net/weixin_47170063/article/details/110310633解决用mciSendString()函数不能播放音乐的问题_mcisendstring播放不出音乐-CSDN博客https://blog.csdn.net/m0_46436640/article/details/106591562
链接“-lwinmm”
直接放弃这个环节了,我的一直播放不了,目前不知道是什么情况,看到有的说是不能用网易云下载的音乐要用QQ音乐下载的,也有用TEXT又不用TEXT的我这里都播放不了,直接进入下一个部分了。
有知道的大佬可以帮我分析分析
- //烟花弹
- struct yhd{
- //属性
- int x,y;//当前坐标
- int hx,hy;//最高点的坐标
- unsigned long t1,t2,dt;//时间来控制速度
- IMAGE img;//保存烟花弹的图片
- bool isshoot;//烟花是否属于正在上升的状态
- }yhd;
这个也一直输出不了,重新安装了一下编译器,出现了一个错误,一个是中文注释不现实,一个是输出中文乱码。
DEVC++运行中文乱码的解决方法 - 哔哩哔哩 (bilibili.com)https://www.bilibili.com/read/cv26335420/
打算换一个编译器尝试一下,暂时先这样。
- #include<stdio.h>
- #include<easyx.h>//图形界面库
- #include<stdlib.h>
- #include<time.h>
- #define _CRT_SECURE_NO_WARNINGS
- #include<windows.h>
- #pragma comment(lib,"winmm.lib")//媒体库文件
- #include <mmsystem.h>//媒体头文件
-
- //烟花弹
- struct yhd{
- //属性
- int x,y;//当前坐标
- int hx,hy;//最高点的坐标
- unsigned long t1,t2,dt;//时间来控制速度
- IMAGE img;//保存烟花弹的图片
- bool isshoot;//烟花是否属于正在上升的状态
- }yhd;
-
-
- int main(){
- srand((unsigned)time(NULL));//选取种子文件
- initgraph(1200,800);//创建窗口 宽1200 高度800
- //打开音乐文件
- mciSendString(TEXT("open music.mp3 alias song"),NULL,0,NULL);//mci 媒体控制接口
- mciSendString(TEXT("play song repeat"),NULL,0,NULL);//mci 媒体控制接口
-
- settextcolor(YELLOW);//设置字体的颜色
- settextstyle(25,0,"楷体");//设置字体的风格 字号
-
- outtextxy(300,300,"2024新年之际,祝福你健康、快乐、平安、幸福");
- outtextxy(300,350,"愿你每天都笑容满面");
- outtextxy(300,400,"所求皆如愿,所行皆坦途,多喜乐,长安宁");
- outtextxy(300,450,"平安喜乐,万事胜意");
- outtextxy(300,500,"期末考试顺利");
- outtextxy(600,550,"——封奚泽优");
- //getchar();//按回车键继续
-
- //初始化烟花弹(烟花弹需要上升,y坐标变化,x不变)
- yhd.x=rand()%(1200-20);
- yhd.y=750;//最开始烟花弹的位置
- yhd.hx=yhd.x;
- yhd.hy=rand()%400;//爆炸高度
- yhd.t1=GetTickCount();//获取当前系统的时间
- yhd.dt=10;//dt 10ms
- yhd.isshoot=true;//最开始是上升状态
- loadimage(&yhd.img,"yhd.png",20,50);//加载图片
- putimage(yhd.x,yhd.y,&yhd.img,SRCINVERT);
-
- while(1);
- return 0;
- }
下载了Visual Studio 2022,先粘贴之前的代码,发现没有easyx图形库
我们重新安装一下
Visual Studio 2022手动安装EasyX_easyx下手动载-CSDN博客https://blog.csdn.net/zeandon/article/details/130771808
然后就链接成功了,接着就是显示
只是播放音乐看到后面。
VS中如何导入并且播放音乐_vs2022装bgm-CSDN博客https://blog.csdn.net/weixin_43701019/article/details/100027495
然后终于有声音了,结果是因为换了一首歌,都是mp3格式的,但是有的就是不行,很奇怪,避免在网易云上面下载
我这里用的是相对路径
- #include<stdio.h>
- #include<easyx.h>//图形界面库
- #include<stdlib.h>
- #include<time.h>
- #define _CRT_SECURE_NO_WARNINGS
- #include<windows.h>
- #pragma comment(lib,"winmm.lib")//媒体库文件
- #include <mmsystem.h>//媒体头文件
-
- //烟花弹
- struct yhd {
- //属性
- int x, y;//当前坐标
- int hx, hy;//最高点的坐标
- unsigned long t1, t2, dt;//时间来控制速度
- IMAGE img;//保存烟花弹的图片
- bool isshoot;//烟花是否属于正在上升的状态
- }yhd;
-
-
- int main() {
- srand((unsigned)time(NULL));//选取种子文件
- initgraph(1200, 800);//创建窗口 宽1200 高度800
- //打开音乐文件
- mciSendString(L"open music.mp3 alias bgm", 0, 0, 0);//mci 媒体控制接口
- mciSendString(L"play bgm repeat", 0, 0, 0);//mci 媒体控制接口
-
- settextcolor(YELLOW);//设置字体的颜色
- settextstyle(25, 0, _T("楷体"));//设置字体的风格 字号
-
-
- outtextxy(300, 300, _T("2024新年之际,祝福你健康、快乐、平安、幸福"));
- outtextxy(300, 350, _T("愿你每天都笑容满面"));
- outtextxy(300, 400, _T("所求皆如愿,所行皆坦途,多喜乐,长安宁"));
- outtextxy(300, 450, _T("平安喜乐,万事胜意"));
- outtextxy(300, 500, _T("期末考试顺利"));
- outtextxy(600, 550, _T("——封奚泽优"));
-
-
- while (1);//防止直接退出程序
- return 0;
- }
音乐
果然就是音乐本身的问题,带回原来的Dev-C++还是可以运行。
-
-
- //烟花弹
- struct yhd {
- //属性
- int x, y;//当前坐标
- int hx, hy;//最高点的坐标
- unsigned long t1, t2, dt;//时间来控制速度
- IMAGE img;//保存烟花弹的图片
- bool isshoot;//烟花是否属于正在上升的状态
- }yhd;
-
-
-
- //初始化烟花弹(烟花弹需要上升,y坐标变化,x不变)
- yhd.x = rand() % (1200 - 20);
- yhd.y = 750;//最开始烟花弹的位置
- yhd.hx = yhd.x;
- yhd.hy = rand() % 400;//爆炸高度
- yhd.t1 = GetTickCount();//获取当前系统的时间
- yhd.dt = 10;//dt 10ms
- yhd.isshoot = true;//最开始是上升状态
- loadimage(&yhd.img, _T("yhd.jpg"), 20, 50);//加载图片
- putimage(yhd.x, yhd.y, &yhd.img, SRCINVERT);
-
- //获取当前时间
- yhd.t2 = GetTickCount();//t2
- //速度 处于发射状态
- if (yhd.t2 - yhd.t1 > yhd.dt && yhd.isshoot == true) {
- //会覆盖之前的
- putimage(yhd.x, yhd.y, &yhd.img, SRCINVERT);
- if (yhd.y > yhd.hy) {//有一个上界
- yhd.y -= 5;//上升
- }
- putimage(yhd.x, yhd.y, &yhd.img, SRCINVERT);
- if(yhd.y<=yhd.hy){
- //已经到达最高点
- //1.擦除烟花弹
- putimage(yhd.x, yhd.y, &yhd.img, SRCINVERT);
- //停止上升
- yhd.isshoot = false;
- }
- if (yhd.isshoot == false) {
- //初始化烟花弹(烟花弹需要上升,y坐标变化,x不变)
- yhd.x = rand() % (1200 - 20);
- yhd.y = 750;//最开始烟花弹的位置
- yhd.hx = yhd.x;
- yhd.hy = rand() % 400;//爆炸高度
- yhd.t1 = GetTickCount();//获取当前系统的时间
- yhd.dt = 10;//dt 10ms
- yhd.isshoot = true;//最开始是上升状态
- loadimage(&yhd.img, _T("yhd.jpg"), 20, 50);//加载图片
- putimage(yhd.x, yhd.y, &yhd.img, SRCINVERT);
- }
- yhd.t1 = yhd.t2;
- }
中间还发现命令行界面总是需要单独关闭,弄的太烦了,然后就用了下面的方法来关闭。
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
视频中的代码不完整,简直了。
定义烟花类
- //烟花
- struct yh{
- int r;//当前半径
- int maxr;//最大半径
- int x, y;//中心点的坐标(窗口)
- int cx, cy;//中心点的坐标(图片)
- int xy[240][240];//图片的宽高,保存图片中的每一个像素点
- bool isboom;//是否开始爆炸(图片的显示)
- bool isdraw;//是否开始显示(用户看到的)
- unsigned long t1, t2, dt;//爆炸的速度
- } yh;
初始化烟花
- yh.r=0;//当前半径
- yh.maxr = 120;//最大半径
- yh.cx = 120;
- yh.cy = 120;//中心点的坐标(图片)
- yh.xy[240][240];//图片的宽高,保存图片中的每一个像素点
- yh.isboom=false;//是否开始爆炸(图片的显示)
- yh.isdraw=false;//是否开始显示(用户看到的)
- yh.t1 = GetTickCount();
- yh.dt = 5;//爆炸的速度5ms
- IMAGE yhimg;
- loadimage(&yhimg, _T("yh.jpg"), 240, 240);//加载图片
-
- SetWorkingImage(&yhimg);//指定待获取的图片(默认是从窗口获取)
- //获取图片的像素点放到数组当中
- for (int a = 0; a < 240; a++) {
- for (int b = 0; b < 240; b++) {
- yh.xy[a][b]=getpixel(a, b);
- }
- }
- SetWorkingImage();//将烟花图片释放
烟花的绽放
- //dt的数组
- int drt[] = { 5,5,5,15,15,15,25,25,25,55,60,65 };//烟花绽放的速度越来越慢ms
- yh.t2 = GetTickCount();
- //烟花已经爆炸
- if (yh.t2 - yh.t1 > yh.dt && yh.isboom == true) {
- if (yh.r < yh.maxr) {
- yh.r++;//半径不断变大,但是不能超过最大的范围
- yh.dt = drt[yh.r / 10];//dt不断变大
- yh.isdraw = true;//开始绘制
- }
- //爆炸结束(重置)
- if (yh.r >= yh.maxr - 1) {
- //停止绘制,停止爆炸
- yh.isdraw = false;
- yh.isboom = false;
- yh.t1 = GetTickCount();
- yh.dt = 5;
- yh.r = 0;
- }
- yh.t1 = yh.t2;
- }
- if (yh.isdraw == true) {
- //628次 2π
- for (double a = 0; a <= 6.28; a += 0.01) {
- //圆的轨迹方程
- int x1 = yh.cx + yh.r * cos(a);
- int y1 = yh.cy - yh.r * sin(a);
- //x1,y1 628个来自图片的像素点坐标
- yh.xy[x1][y1];
- }
- }
他是到这里结束了,然后无法实现烟花图片的输出,因为他并没有相关的代码,需要输出像素点。我最开始写的是putpixel(x1,y1,yh.xy[x1][y1]);发现每次输出的位置都是那一个地方,想着要和最高点的高度有关,改成了putpixel(hy.x,yh.y,yh.xy[x1][y1]);发现结果都不输出了,我想了很久发现如果坐标固定不变,那不就是一个点在一直输出,人眼无法发现这个变化,所以想应该在图片画圆的时候同步对窗口中以最高点为圆心画圆,所以最终变成了putpixel(x2,y2,yh.xy[x1][y1]);
- //开始绘制图像
- if (yh.isdraw == true) {
- //628次 2π
- for (double a = 0; a <= 6.28; a += 0.01) {
- //圆的轨迹方程(图片)
- int x1 = yh.cx + yh.r * cos(a);
- int y1 = yh.cy - yh.r * sin(a);
- //圆的轨迹方程(窗口)
- int x2 = yh.x + yh.r * cos(a);
- int y2 = yh.y - yh.r * sin(a);
- //x1,y1 628个来自图片的像素点坐标
- putpixel(x2,y2,yh.xy[x1][y1]);
- }
- }
- }
这样就实现了单个烟花的绽放
首先判断变成了这个,需要等爆炸完之后发下一个,其次是位置不能在if (yhd.t2 - yhd.t1 > yhd.dt && yhd.isshoot == true) 里面,此时的已经不再上升了,放里面就实现不了发送多个。
- if (yhd.isshoot == false && yh.isboom == false) {
- //初始化烟花弹
- initYHD();
- }
接着就是这最后一个问题了,如何让绽放的烟花自己消失。
最开始我的想法是输出一个黑色的像素点然后去覆盖他,但是考虑到有文字出现所以需要的不是覆盖而是恢复之前的,所以我的想法是用一个结构体来保存之前窗口将会被覆盖的像素,在之后的几轮中一边绽放新的一边恢复之前的,想法很好,但是现实很骨感,如果两个烟花绽放重合,你现在保存的像素之后还是有烟花绽放的影子,所以之后就像用黑色覆盖就覆盖吧,把字体重新输出不就行了。结果和现实还是有点差距。如果是重合的话,黑色还是会把之前的给覆盖了,这个目前还没解决,有大佬会的话,希望能够提供一下思路。
- //用于保存之前被覆盖的像素
- struct tmp{
- int x, y;//中心点的坐标(窗口)
- int ishuifu;//是否恢复
- }tmp;
-
- //当已经发送第二个的时候恢复第一个的
- if (tmp.ishuifu) {
- //圆的轨迹方程(窗口)
- int x3 = tmp.x + yh.r * cos(a);
- int y3 = tmp.y - yh.r * sin(a);
- //重新弄成黑色
- putpixel(x3, y3,0x000000);
- }
和老师讲的还是有点差距的,我的有点小丑。
- #include<stdio.h>
- #include<easyx.h>//图形界面库
- #include<stdlib.h>
- #include<graphics.h>
- #include<conio.h>
- #include<time.h>
- #define _CRT_SECURE_NO_WARNINGS
- #include<windows.h>
- #pragma comment(lib,"winmm.lib")//媒体库文件
- #include <mmsystem.h>//媒体头文件
- #pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
- #include<math.h>
-
- //烟花弹
- struct yhd {
- //属性
- int x, y;//当前坐标
- int hx, hy;//最高点的坐标
- unsigned long t1, t2, dt;//时间来控制速度
- IMAGE img;//保存烟花弹的图片
- bool isshoot;//烟花是否属于正在上升的状态
- }yhd;
-
- //烟花
- struct yh{
- int r;//当前半径
- int maxr;//最大半径
- int x, y;//中心点的坐标(窗口)
- int cx, cy;//中心点的坐标(图片)
- int xy[240][240];//图片的宽高,保存图片中的每一个像素点
- bool isboom;//是否开始爆炸(图片的显示)
- bool isdraw;//是否开始显示(用户看到的)
- unsigned long t1, t2, dt;//爆炸的速度
- } yh;
-
- //用于保存之前被覆盖的像素
- struct tmp{
- int x, y;//中心点的坐标(窗口)
- int ishuifu;//是否恢复
- }tmp;
-
- void initYHD();//初始化烟花弹
- void initYH();//初始化烟花
- void printText();//输出文字
-
- //主函数
- int main() {
- srand((unsigned)time(NULL));//选取种子文件
- initgraph(1200, 800);//创建窗口 宽1200 高度800
- //打开音乐文件
- mciSendString(L"open music.mp3 alias bgm", 0, 0, 0);//mci 媒体控制接口
- mciSendString(L"play bgm repeat", 0, 0, 0);//mci 媒体控制接口
-
- //getchar();//按回车键继续
-
- //初始化烟花弹(烟花弹需要上升,y坐标变化,x不变)
- initYHD();
- //初始化烟花
- initYH();
-
- //不恢复
- tmp.ishuifu = false;
-
- while (1) {
- //打印文字
- printText();
- //获取当前时间
- yhd.t2 = GetTickCount();//t2
- //速度 处于发射状态
- if (yhd.t2 - yhd.t1 > yhd.dt && yhd.isshoot == true) {
- //会覆盖之前的
- putimage(yhd.x, yhd.y, &yhd.img, SRCINVERT);
- if (yhd.y > yhd.hy) {//有一个上界
- yhd.y -= 5;//上升
- }
- //覆盖之前的
- putimage(yhd.x, yhd.y, &yhd.img, SRCINVERT);
-
- if(yhd.y<=yhd.hy){
- //已经到达最高点
- //1.擦除烟花弹
- putimage(yhd.x, yhd.y, &yhd.img, SRCINVERT);
- //停止上升
- yhd.isshoot = false;
- //开始爆炸
- yh.isboom = true;
- //上升最高点的坐标就是爆炸的中心
- yh.x = yhd.x;
- yh.y = yhd.y;
- }
- yhd.t1 = yhd.t2;
- }
-
- //2.重新初始化烟花弹烟花爆炸完毕(这个要移出来,如果放在前面那个if里面就不能实现了,新的一轮要isshoot==true才能进去,这判断又是不能为true)
- if (yhd.isshoot == false && yh.isboom == false) {
- //保存原点坐标
- tmp.x = yh.x;
- tmp.y = yh.y;
- //恢复
- tmp.ishuifu = true;
-
- //初始化烟花弹
- initYHD();
- }
-
- //dt的数组
- int drt[] = { 5,5,5,15,15,15,25,25,25,55,60,65 };//烟花绽放的速度越来越慢ms
- yh.t2 = GetTickCount();
- //烟花已经爆炸
- if (yh.t2 - yh.t1 > yh.dt && yh.isboom == true) {
- if (yh.r < yh.maxr) {
- yh.r++;//半径不断变大,但是不能超过最大的范围
- yh.dt = drt[yh.r / 10];//dt不断变大
- yh.isdraw = true;//开始绘制
- }
- //爆炸结束(重置)
- if (yh.r >= yh.maxr - 1) {
- //停止绘制,停止爆炸
- yh.isdraw = false;
- yh.isboom = false;
- yh.t1 = GetTickCount();
- yh.dt = 5;
- yh.r = 0;
- }
- yh.t1 = yh.t2;
- }
- //开始绘制图像
- if (yh.isdraw == true) {
- //628次 2π
- int i = 0, j = 0;
- for (double a = 0; a <= 6.28; a += 0.01) {
- //当已经发送第二个的时候恢复第一个的
- if (tmp.ishuifu) {
- //圆的轨迹方程(窗口)
- int x3 = tmp.x + yh.r * cos(a);
- int y3 = tmp.y - yh.r * sin(a);
- //重新弄成黑色
- putpixel(x3, y3,0x000000);
- }
-
- //圆的轨迹方程(图片)
- int x1 = yh.cx + yh.r * cos(a);
- int y1 = yh.cy - yh.r * sin(a);
- //圆的轨迹方程(窗口)
- int x2 = yh.x + yh.r * cos(a);
- int y2 = yh.y - yh.r * sin(a);
- //x1,y1 628个来自图片的像素点坐标
- putpixel(x2,y2,yh.xy[x1][y1]);
- }
- }
- }
-
- while (1);//防止直接退出程序
- return 0;
- }
-
- //初始化烟花弹
- void initYHD() {
- //初始化烟花弹(烟花弹需要上升,y坐标变化,x不变)
- yhd.x = rand() % (1200 - 20);
- yhd.y = 750;//最开始烟花弹的位置
- yhd.hx = yhd.x;
- yhd.hy = rand() % 400;//爆炸高度
- yhd.t1 = GetTickCount();//获取当前系统的时间
- yhd.dt = 5;//dt 10ms
- yhd.isshoot = true;//最开始是上升状态
- loadimage(&yhd.img, _T("yhd.jpg"), 20, 50);//加载图片
- putimage(yhd.x, yhd.y, &yhd.img, SRCINVERT);
- }
-
- //初始化烟花
- void initYH() {
- yh.r=0;//当前半径
- yh.maxr = 120;//最大半径
- yh.cx = 120;
- yh.cy = 120;//中心点的坐标(图片)
- yh.xy[240][240];//图片的宽高,保存图片中的每一个像素点
- yh.isboom=false;//是否开始爆炸(图片的显示)
- yh.isdraw=false;//是否开始显示(用户看到的)
- yh.t1 = GetTickCount();
- yh.dt = 5;//爆炸的速度5ms
- IMAGE yhimg;
- loadimage(&yhimg, _T("yh.jpg"), 240, 240);//加载图片
-
- SetWorkingImage(&yhimg);//指定待获取的图片(默认是从窗口获取)
- //获取图片的像素点放到数组当中
- for (int a = 0; a < 240; a++) {
- for (int b = 0; b < 240; b++) {
- yh.xy[a][b]=getpixel(a, b);
- }
- }
- SetWorkingImage();//将烟花图片释放
- }
-
- void printText() {//输出文字
- settextcolor(YELLOW);//设置字体的颜色
- settextstyle(25, 0, _T("楷体"));//设置字体的风格 字号
-
-
- outtextxy(300, 300, _T("2024新年之际,祝福你健康、快乐、平安、幸福"));
- outtextxy(300, 350, _T("愿你每天都笑容满面"));
- outtextxy(300, 400, _T("所求皆如愿,所行皆坦途,多喜乐,长安宁"));
- outtextxy(300, 450, _T("平安喜乐,万事胜意"));
- outtextxy(300, 500, _T("期末考试顺利"));
- outtextxy(600, 550, _T("——封奚泽优"));
- }
本来构思的是看自己学的都可以如何祝大家新年快乐,目前只用到了单片机的知识,C语言部分一直实现不了,之后会持续更新,争取早日输出。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。