C语言实现气泡

来源:互联网 发布:java迭代什么意思 编辑:程序博客网 时间:2024/05/01 19:00

大家对WINDOWS的屏幕保护程序气泡一定不陌生,在此写一个简单的一个泡泡碰到四周会反弹的小程序,该程序所用到的所有函数,在上一遍日志C语言实现电子钟中都有提到,全部代码的话,在同名的资源中。在此只给出最关键的主函数。相信一目了然,注释也很丰富。

#include "clock_include.h"#include "LCD_function.h"      #include "pxy_function.h"#include "RTC_function.h"#include "UART.h"/******************************************************************************* 函数名:  main()***** 功能:    随机泡泡***** 参数:    无***** 返回值:***** 创建者:  潘星宇***** 创建时间: 2012-12-26***** 最后更新:2013-1-5****************************************************************************/int main(void){ int random_value;                            //随机数存储变量 volatile static float angle;             //角度值 float d;                              //画圆用1 U32 end_i; U32 end_j; volatile static U32 x0 = 250;             //圆心坐标 volatile static U32 y0 = 100; volatile static U32 x_register = 250;           //储存上一次的圆心坐标 volatile static U32 y_register = 100;                     static U32 radius = 30;                                //半径 int x;                               //画圆用2 int y;                               //画圆用3 volatile static U8 change_flag = 0;                     //碰到边框标志 volatile static U32 longth = 1;       //长度计数用 const U32 enge_left = 50;                               //定义左边界 const U32 enge_right = 450;                             //定义右边界 const U32 enge_up = 20;                                 //定义上边界 const U32 enge_down = 220;                               //定义下边界 LCD_Init();                     //LCD初始化 Brush_Background(0xffff);          //绘制背景 for (end_i=0; end_i<=400; end_i++)  //绘制边框 {  PutPixel(50+end_i,20,0x0);  PutPixel(50+end_i,220,0x0);  } for (end_j=0; end_j<=200; end_j++)  //绘制边框 {  PutPixel(50,20+end_j,0x0);  PutPixel(450,20+end_j,0x0);  }     random_value = rand(); if (random_value < 0) {  random_value = 0 - random_value;  }    random_value = random_value % 180; //对180求余 angle = (PI / 180)*random_value;  //得到一随机角度    while (1) {  while (1)  {     MidpointCircle (x_register, y_register, radius, 0xffff);    x=0;    y=radius;    d=5.0/4-radius;    while(x<=y)    {     PutPixel(x0+x,y0+y,0x0);     PutPixel(x0+x,y0-y,0x0);     PutPixel(x0-x,y0+y,0x0);     PutPixel(x0-x,y0-y,0x0);     PutPixel(x0+y,y0+x,0x0);     PutPixel(x0+y,y0-x,0x0);     PutPixel(x0-y,y0+x,0x0);     PutPixel(x0-y,y0-x,0x0);     if ((x0+x <= enge_left)||(x0-x <= enge_left)||(x0+y <= enge_left)||(x0-y <= enge_left))              //判断是否碰到了左边界                   {      change_flag = 1;                   }     else if ((x0+x >= enge_right)||(x0-x >= enge_right)||(x0+y >= enge_right)||(x0-y >= enge_right)||    //判断是否碰到了右边界              (y0+y >= enge_down) || (y0-y >= enge_down)||(y0+x >= enge_down)||(y0-x >= enge_down))  //判断是否碰到了下边界     {      change_flag = 2;              //右与下边界反弹规律一致     }     else if ((y0+y <= enge_up)||(y0-y <= enge_up)||(y0+x <= enge_up)||(y0-x <= enge_up))   //判断是否碰到了上边界        {      change_flag = 3;                    }     if(d<0)     {      d+=x*2.0+3;     }             else     {      d+=2.0*(x-y)+5;      y--;     }     x++;    }    for (end_i=0; end_i<=400; end_i++)  //绘制边框    {     PutPixel(50+end_i,20,0x0);     PutPixel(50+end_i,220,0x0);     }    for (end_j=0; end_j<=200; end_j++)  //绘制边框    {     PutPixel(50,20+end_j,0x0);     PutPixel(450,20+end_j,0x0);     }    delay (10000);     x_register = x0;         //储存上一次的值    y_register = y0;     if (change_flag == 1)                      //碰到边框了    {        change_flag = 0;     if (angle > PI / 2.0)     {      angle = PI - angle;     }     else     {      angle = 2*PI - angle;     }    }    else if (change_flag == 2)    {        change_flag = 0;     if (angle > PI / 2.0)     {      angle = 2*PI - angle;     }     else     {      angle = PI - angle;     }    }    else if (change_flag == 3)    {        change_flag = 0;     angle = 2*PI - angle;    }     x0 = (U32)(x0 + longth*cos(angle) + 0.5);  //圆心变化    y0 = (U32)(y0 - longth*sin(angle) + 0.5);  } }}           
在此补充两点:
(1)一开始的随机函数是想让每次小球出现的位置不一致,后来发现实际上每次上电的位置都是一样的,推测应该是随机函数每次运行第一次结果是一样的,欢迎拍砖;
(2)随机泡泡反弹关键在于角度的确定和判断是否触边。
   <1>角度不管反弹多少次,一定还是同一个角度(不过象限发生了变化),笔者没用这种方法
   <2>按照数学上x正半轴为起点,逆时针旋转判断角度,分为上,下左右四个边界的方法,通过入射角来求反射角,笔者采用的是这种方法
(3)判断是否触边,笔者在这个程序里,用的是第一种八点画圆的方法,再每次画完八个点后,即进行判断,当然可以简化判断条件
(4)如果将边界拓展到物理屏以外,也就是虚拟屏大于物理屏的效果,就跟WINDOWS的气泡效果差不多了,不过WINDOWS的更为复杂,不仅有多个气泡的
   碰撞效果,还有变色,阻尼效果等,感兴趣的朋友可以去搜别的文章,在此只是给大家提供个人的一个小小的思路,欢迎拍砖。
原创粉丝点击