用VB设计一个蝴蝶飞动的程序
因为这里只能上传一张图片,所以写了一个单张图片的。装载系列图片的我也写了,只是窗体初始化会很麻烦。以下代码是实现单张图片的随意飞舞程序,能做到:
1、碰到窗体边缘时,图片会自动改变飞舞的方向(题意中要求的“返回”,只能是在一条线上来回移动,本程序实现蝴蝶出发位置随意,能在窗体内四处飞舞),而且头部也会跟着改变方向
2、窗体改变大小时,蝴蝶不会消失不见,会立即在新的窗体内继续飞舞
'建一个Picture1控件,在它的属性对话框内设置Appearance=0?AutoRedraw=True?AutoSize=True?BorderStyle=0,然后在它的Picture中加载蝴蝶图片
'再建一个Picture2控件,在它的属性对话框内设置Appearance=0?AutoRedraw=False?AutoSize=False?BorderStyle=0,其他默认属性都不得改变
'Form的BackColor设为与蝴蝶图片的背景色一致,本程序中,即&H80000009&
'再加一个Timer1控件
Private?Const?Pi?=?3.1415926535
Private?Declare?Function?SetPixel?Lib?"gdi32"?(ByVal?hdc?As?Long,?ByVal?x?As?Long,?ByVal?y?As?Long,?ByVal?crColor?As?Long)?As?Long
Private?Declare?Function?GetPixel?Lib?"gdi32"?(ByVal?hdc?As?Long,?ByVal?x?As?Long,?ByVal?y?As?Long)?As?Long
Dim?x0!,?y0!,?x1!,?x2!,?y1!,?y2!,?foot!,?zt%?'x0和y0是图片框长高,(x1,y1)-(x2,y2)是窗体坐标系,foot是蝴蝶移动步长,zt是蝴蝶飞舞的线路标记
Dim?k!?'k或1/k是飞行轨迹的斜率
Dim?flag?As?Boolean?'flag判断是顺时针还是逆时针飞舞
Private?Sub?bmp_rotate(pic1?As?PictureBox,?pic2?As?PictureBox,?ByVal?theta?As?Single)?'自定义角度旋转图片
Dim?c1x?As?Integer,?c1y?As?Integer
Dim?c2x?As?Integer,?c2y?As?Integer
Dim?a?As?Single
Dim?p1x?As?Integer,?p1y?As?Integer
Dim?p2x?As?Integer,?p2y?As?Integer
Dim?n?As?Integer,?r?As?Integer
c1x?=?pic1.ScaleWidth?/?2
c1y?=?pic1.ScaleHeight?/?2
c2x?=?pic2.ScaleWidth?/?2
c2y?=?pic2.ScaleHeight?/?2
If?c2x?<?c2y?Then?n?=?c2y?Else?n?=?c2x
n?=?n?-?1
pic1hDC&?=?pic1.hdc
pic2hDC&?=?pic2.hdc
For?p2x?=?0?To?n
For?p2y?=?0?To?n
If?p2x?=?0?Then?a?=?Pi?/?2?Else?a?=?Atn(p2y?/?p2x)
r?=?Sqr(1&?*?p2x?*?p2x?+?1&?*?p2y?*?p2y)
p1x?=?r?*?Cos(a?+?theta)
p1y?=?r?*?Sin(a?+?theta)
c0&?=?GetPixel(pic1hDC,?c1x?+?p1x,?c1y?+?p1y)
c1&?=?GetPixel(pic1hDC,?c1x?-?p1x,?c1y?-?p1y)
c2&?=?GetPixel(pic1hDC,?c1x?+?p1y,?c1y?-?p1x)
c3&?=?GetPixel(pic1hDC,?c1x?-?p1y,?c1y?+?p1x)
If?c0&?<>?-1?Then?xret&?=?SetPixel(pic2hDC,?c2x?+?p2x,?c2y?+?p2y,?c0&)
If?c1&?<>?-1?Then?xret&?=?SetPixel(pic2hDC,?c2x?-?p2x,?c2y?-?p2y,?c1&)
If?c2&?<>?-1?Then?xret&?=?SetPixel(pic2hDC,?c2x?+?p2y,?c2y?-?p2x,?c2&)
If?c3&?<>?-1?Then?xret&?=?SetPixel(pic2hDC,?c2x?-?p2y,?c2y?+?p2x,?c3&)
Next
t%?=?DoEvents()
Next
End?Sub
Private?Sub?Place(ByVal?picnum?As?Integer,?ByVal?x?As?Single,?ByVal?y?As?Single)?'控制两个图片框的位置
If?picnum?=?1?Then
Picture1.Left?=?x
Picture1.Top?=?y
Else
Picture2.Left?=?x
Picture2.Top?=?y
End?If
End?Sub
Private?Sub?Direct(ByVal?angle?As?Integer)?'按指定角度旋转图片,angle是角度
angle?=?angle?Mod?360
hudu?=?(Pi?*?angle?*?1#)?/?(180?*?1#)?'弧度
bmp_rotate?Picture1,?Picture2,?hudu
End?Sub
Private?Sub?Form_Activate()
x1?=?0!
x2?=?10000!
y1?=?0!
y2?=?10000!
Me.Scale?(x1,?y1)-(x2,?y2)
Randomize
Picture1.ScaleMode?=?3
Picture2.ScaleMode?=?3
x0?=?Picture1.Width
Picture2.Width?=?x0
y0?=?Picture1.Height
Picture2.Height?=?y0
Picture1.Visible?=?True
Picture2.Visible?=?False
x?=?Int(1000?+?(x2?-?x1?-?x0?-?1000)?*?Rnd)?'蝴蝶出发处的横坐标
y?=?Int(1000?+?(y2?-?y1?-?y0?-?1000)?*?Rnd)?'蝴蝶出发处的纵坐标
k?=?y?/?x?'k为撞向水平边框或离开竖直边框的斜率,1/k则为撞向竖直边框或离开水平边框的斜率
Place?1,?-x2,?y2?-?y0?'将图片框的复制源移出窗体的可见范围,但Visible属性又必须是True,否则复制图片会失败
Place?2,?x,?y?'初始化蝴蝶的出发位置
Timer1.Enabled?=?True
Timer1.Interval?=?100?'定义移动周期
zt?=?0
End?Sub
Private?Sub?Form_Click()
Timer1.Enabled?=?Not?Timer1.Enabled
End?Sub
Private?Sub?Form_Resize()?'窗体改变大小时,坐标系需要重新定义
x1?=?0!
x2?=?10000!
y1?=?0!
y2?=?10000!
Me.Scale?(x1,?y1)-(x2,?y2)
Cls
x0?=?Picture1.Width
Picture2.Width?=?x0
y0?=?Picture1.Height
Picture2.Height?=?y0
'如果蝴蝶在窗体外,则立即召回
If?Picture2.Left?<?x1?Then?Place?2,?x1,?Picture2.Top
If?Picture2.Top?<?y1?Then?Place?2,?Picture2.Left,?y1
If?Picture2.Left?>?x2?-?x1?-?x0?Then?Place?2,?x2?-?x1?-?x0,?Picture2.Top
If?Picture2.Top?>?y2?-?y1?-?y0?Then?Place?2,?Picture2.Left,?y2?-?y1?-?y0
End?Sub
Private?Sub?Form_Unload(Cancel?As?Integer)
End
End?Sub
'zt=0,1,2,3时,分别表示顺时针向右上(简称顺右上)或逆左下,顺右下或逆左上,顺左下或逆右上,顺左上或逆右下
Private?Sub?Timer1_Timer()
foot?=?100
x?=?Picture2.Left:?y?=?Picture2.Top
Select?Case?True
Case?(flag?=?True?And?zt?=?0)?Or?(flag?=?False?And?zt?=?2)
Place?2,?x?+?foot,?y?-?k?*?foot
'Line?(x,?y)-(x?+?foot,?y?-?k?*?foot)
Direct?360
If?Picture2.Left?>?x2?-?x1?-?x0?-?foot?Then?zt?=?1:?flag?=?False?'撞到垂直边框,将逆左上
If?Picture2.Top?<?foot?Then?zt?=?1:?flag?=?True?'撞到水平边框,将顺右下
Case?(flag?=?True?And?zt?=?1)?Or?(flag?=?False?And?zt?=?3)
Place?2,?x?+?foot,?y?+?foot?/?k
'Line?(x,?y)-(x?+?foot,?y?+?foot?/?k)
Direct?270
If?Picture2.Left?>?x2?-?x1?-?x0?-?foot?Then?zt?=?2:?flag?=?True?'撞到垂直边框,将顺左下
If?Picture2.Top?>?y2?-?y1?-?y0?-?foot?Then?zt?=?2:?flag?=?False?'撞到水平边框,将逆右上
Case?(flag?=?True?And?zt?=?2)?Or?(flag?=?False?And?zt?=?0)
Place?2,?x?-?foot,?y?+?k?*?foot
'Line?(x,?y)-(x?-?foot,?y?+?k?*?foot)
Direct?180
If?Picture2.Left?<?foot?Then?zt?=?3:?flag?=?False?'撞到垂直边框,将逆右下
If?Picture2.Top?>?y2?-?y1?-?y0?-?foot?Then?zt?=?3:?flag?=?True?'撞到水平边框,将顺左上
Case?(flag?=?True?And?zt?=?3)?Or?(flag?=?False?And?zt?=?1)
Place?2,?x?-?foot,?y?-?foot?/?k
'Line?(x,?y)-(x?-?foot,?y?-?foot?/?k)
Direct?90
If?Picture2.Left?<?foot?Then?zt?=?0:?flag?=?True?'撞到垂直边框,将顺右上
If?Picture2.Top?<?foot?Then?zt?=?0:?flag?=?False?'撞到水平边框,将逆左下
End?Select
Picture2.Visible?=?True
End?Sub