C语言实现气泡

大家对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的更为复杂,不仅有多个气泡的
   碰撞效果,还有变色,阻尼效果等,感兴趣的朋友可以去搜别的文章,在此只是给大家提供个人的一个小小的思路,欢迎拍砖。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值