VisualFreeBasic游戏趣味编程_11.3_绘制樱花树

2026-1-22 / 0 评论 / 123 阅读

修改练习题11-1中的brunch()函数,当第10代树枝或树枝长度小于2时,绘制一个粉色填充圆,表示樱花:

   If childLength <= 2 Or childGeneration >= 9 Then
      gg.Pen 1, HSBtoRGB_Gdi(HSB(325, 50, 100, 255)) '设定线条颜色为粉色
      gg.Brush HSBtoRGB_Gdi(HSB(325, 50, 100, 255)) '设定填充颜色为粉色
      If childLength <= 4 Then
         gg.DrawEllipse x_end -2, y_end -2, 2 * 2, 2 * 2 '圆的半径为2(再小就看不清了)
      Else
         gg.DrawEllipse x_end - childLength / 2, y_end - childLength / 2, childLength, childLength '画一个圆,半径为子枝干长度的一半
      End If
   End If 


另外,为了使得生成的樱花树更加稠密,除了产生左右子枝干外,再生成一个中间的子枝干:

brunch(gg, x_end, y_end, childLength, angle , childThickness, childGeneration)


下面我们引入一些随机性,首先定义函数randBetween( )生成[min,max]之间的随机小数:

'生成[min,max]之间的随机小数
Function randBetween(xiao As Single, da As Single) As Single
   Randomize
   Dim t As Single = rnd() '生成[0,1]的随机小数
   '把值范围从[0,1]映射到[min,max]
   Dim r As Single = t * (da - xiao) + da
   Return r
End Function

左、右、中间3个子枝干的长度逐渐变短,并有一定随机性:

   Dim childLength       As Single = shortenRate *length
   Dim leftChildLength   As Single = childLength *randBetween(0.9, 1.1)
   Dim rightChildLength  As Single = childLength *randBetween(0.9, 1.1)
   Dim centerChildLength As Single = childLength *randBetween(0.8, 1.1)

有一定概率产生左、右、中间的子枝干,并且子枝干的旋转角度也有一定的随机性:

      If (randBetween(0, 1) < 0.95) Then ' 一定概率生成左边的子枝干
         brunch(gg, x_end, y_end, leftChildLength, angle - randBetween(15, 60), childThickness, childGeneration)
      End If
      If (randBetween(0, 1) < 0.95) Then ' 一定概率生成右边的子枝干
         brunch(gg, x_end, y_end, rightChildLength, angle + randBetween(15, 60), childThickness, childGeneration)
      End If
      If (randBetween(0, 1) < 0.85) Then '一定概率生成中间的子枝干
         brunch(gg, x_end, y_end, centerChildLength,angle+randBetween(-15, 15) , childThickness, childGeneration)
      End If

进一步,让树枝越向上、颜色越淡:

gg.Pen thickness, HSBtoRGB_Gdi(HSB(325, 100, 50 + generation * 5, 255)) '设定线条颜色为黑色

樱花颜色也加上一定的随机性:

gg.Pen thickness, HSBtoRGB_Gdi(HSB(randBetween(300, 350), 100, 50 + generation * 5, 255)) '

当点击鼠标后,重新画树

      Do 
         If IsKeyPress(VK_LBUTTON) Then Exit Do 
         Sleep 100  
      Loop 

完整代码

'全局变量定义
Dim Shared offsetAngle As Single = 30   ' 左右枝干和父枝干偏离的角度
Dim Shared shortenRate As Single = 0.65 ' 左右枝干长度与父枝干长度的比例
'枝干生成和绘制递归函数
'输入参数:枝干起始x,y坐标,枝干角度,第几代
Sub brunch(gg As yGDI, x_start As Single, y_start As Single, length As Single, angle As Single, thickness As Single, generation As Long)

   ' 利用三角函数求出当前枝干的终点x,y坐标
   Dim As Single x_end, y_end
   If angle > 360 Then angle -= 360
   If angle < 0   Then angle += 360

   x_end = x_start + length * Cos(angle * (3.1419265 / 180))
   y_end = y_start + length * Sin(angle * (3.1419265 / 180))
   gg.Brush
   gg.Pen thickness, HSBtoRGB_Gdi(HSB(randBetween(300, 350), 100, 50 + generation * 5, 255)) '
   gg.DrawLine(x_start, y_start, x_end, y_end) ' 画出当前枝干(画线)

   ' 求出子枝干的代数
   Dim childGeneration As Long = generation + 1
   '生成子枝干的长度,逐渐变短
   Dim childLength       As Single = shortenRate *length
   Dim leftChildLength   As Single = childLength *randBetween(0.9, 1.1)
   Dim rightChildLength  As Single = childLength *randBetween(0.9, 1.1)
   Dim centerChildLength As Single = childLength *randBetween(0.8, 1.1)

   If childLength <= 2 Or childGeneration >= 9 Then
      gg.Pen 1, HSBtoRGB_Gdi(HSB(325, 50, 100, 255)) '设定线条颜色为粉色
      gg.Brush HSBtoRGB_Gdi(HSB(325, 50, 100, 255)) '设定填充颜色为粉色
      If childLength <= 4 Then
         gg.DrawEllipse x_end -2, y_end -2, 2 * 2, 2 * 2 '圆的半径为2(再小就看不清了)
      Else
         gg.DrawEllipse x_end - childLength / 2, y_end - childLength / 2, childLength, childLength '画一个圆,半径为子枝干长度的一半
      End If
   End If
   ' 当子枝干长度大于2,并且代数小于或等于10,递归调用产生子枝干
   If childLength >= 2 And childGeneration <= 9 Then
      '生成子枝干的粗细,逐渐变细
      Dim childThickness As Single = thickness * 0.8
      If (childThickness < 1)       Then childThickness = 1 ' 枝干绘图最细的线宽为2
      If (randBetween(0, 1) < 0.95) Then ' 一定概率生成左边的子枝干
         brunch(gg, x_end, y_end, leftChildLength, angle - randBetween(15, 60), childThickness, childGeneration)
      End If
      If (randBetween(0, 1) < 0.95) Then ' 一定概率生成右边的子枝干
         brunch(gg, x_end, y_end, rightChildLength, angle + randBetween(15, 60), childThickness, childGeneration)
      End If
      If (randBetween(0, 1) < 0.85) Then '一定概率生成中间的子枝干
         brunch(gg, x_end, y_end, centerChildLength, angle + randBetween( -15, 15), childThickness, childGeneration)
      End If
   End If
End Sub
'生成[min,max]之间的随机小数
Function randBetween(xiao As Single, da As Single) As Single
   Randomize
   Dim t As Single = rnd() '生成[0,1]的随机小数
   '把值范围从[0,1]映射到[min,max]
   Dim r As Single = t * (da - xiao) + xiao
   Return r
End Function

Sub 游戏执行过程(hWndForm As hWnd)
   Dim gg As yGDI = hWndForm
   Do
      gg.Cls BGR(255, 255, 255) '白色背景
      brunch(gg, DpiUnScaleF(Me.ScaleWidth / 2), DpiUnScaleF(Me.ScaleHeight), 0.45 *DpiUnScaleF(Me.ScaleHeight) *shortenRate, 270, 15 *shortenRate, 1)
      gg.Redraw
      Sleep 500
      Do 
         If IsKeyPress(VK_LBUTTON) Then Exit Do 
         Sleep 100  
      Loop 
   Loop
End Sub

评论一下?

OωO
取消