游戏截图
开始游戏时显示的帮助 :
游戏的主要变量为小球、弹板、砖块,为此需要设计相应的对象(可以设计为类,本例设计为结构体了),地图(gamemap)设计为2维字节数组,其它变量有游戏关卡、得分、刷新时间等等。游戏地图用GDI绘制,因此引用Drawing2D组件。游戏界面绘制用mydraw()。
主要代码如下:
Imports System.Drawing.Drawing2D
Imports System.Drawing.Color
Imports System.Threading
Public Structure Qiu '定义小球
Dim q_center As Point
Dim q_radius As Integer
Dim q_type As Integer
Dim q_color As Color
Dim q_v_sudu As Integer
Dim q_v_fangxiang As Integer
End Structure
Public Structure Tanban '定义弹板
Dim t_length As Integer
Dim t_center As Point
Dim t_type As Integer '1-普通弹板
End Structure
Public Structure teshuFK '特殊方块
Dim tsfk_x As Integer 'x坐标
Dim tsfk_y As Integer 'y坐标
Dim tsfk_type As Integer '类型
Dim tsfk_show As Boolean '是否显示
End Structure
Public QiuL() As Qiu '弹球集合
Public qiuNum As Integer = 1 '弹球数量
Public Const W As Integer = 50 '方块长度
Public Const H As Integer = 20 '方块宽度
Public Const mapW As Integer = 1000 '游戏区宽度
Public Const mapH As Integer = 640 '游戏区高度
Public gameMap As Byte(,) '游戏地图
Public Const mapMX As Integer = 19
Public Const mapMY As Integer = 31
Public myTanban As Tanban '弹板
Public mydefen As Integer = 0 ' 得分
Public guanka As Integer = 1 '关卡
Public qiuJDxian As Boolean = False '小球运动方向线
Public shijianJge As Integer = 15 '刷新间隔,毫秒
Public fnyinStr As String = My.Application.Info.DirectoryPath '程序所在目录
Public tList As New List(Of Thread)
Public Sub newGame() '初始化游戏
With myTanban
.t_center = New Point(mapW / 2, mapH - H / 2)
.t_length = 160
.t_type = 1
End With
qiuNum = 1
ReDim QiuL(qiuNum - 1)
For i As Integer = 0 To qiuNum - 1
QiuL(i).q_center = New Point(myTanban.t_center.X, myTanban.t_center.Y - H)
QiuL(i).q_radius = 7
QiuL(i).q_type = 1
QiuL(i).q_color = Color.Red
QiuL(i).q_v_sudu = 0
QiuL(i).q_v_fangxiang = Int(Rnd() * 100 + 40)
Next
ReDim gameMap(mapMX, mapMY)
For i As Integer = 0 To mapMX
For j As Integer = 0 To mapMY
gameMap(i, j) = 0
Next
Next
mydefen = 0
guanka = 1
setGuanka()
End Sub
Public Sub setGuanka() '根据关卡设置数组
For i As Integer = 0 To 19
For j As Integer = 0 To 31
gameMap(i, j) = 0
Next
Next
If guanka > 19 Then guanka = 1
If guanka < 1 Then guanka = 19
Dim RANDOM As New Random(guanka)
For i As Integer = 1 To guanka * 17
Dim s As String = RANDOM.Next.ToString
gameMap(guanka * s.Substring(0, 1) Mod 20, guanka * s.Substring(1, 1) Mod 20) = Val(s.Substring(2, 1)) Mod 5
gameMap((guanka * s.Substring(3, 1) + 13) Mod 20, guanka * s.Substring(4, 1) Mod 20) = Val(s.Substring(5, 1)) Mod 5
Next
For j As Integer = 1 To guanka * 3
Dim s As String = RANDOM.Next.ToString
gameMap(guanka * s.Substring(0, 1) Mod 20, guanka * s.Substring(1, 1) Mod 20) = 9
Next
For k As Integer = 1 To 5 '设置特殊方块5个
gameMap(Int(mapMX * Rnd()), Int((mapMY - 15) * Rnd())) = Int(Rnd() * 8 + 91)
Next
If guanka Mod 2 = 0 Then '根据关卡设置弹板样式
myTanban.t_type = 2
Else
myTanban.t_type = 1
End If
End Sub
Public Function myDraw() As Bitmap '绘图
Dim bmp As Bitmap = New Bitmap(mapW, mapH)
Dim ea As Graphics = Graphics.FromImage(bmp)
ea.SmoothingMode = SmoothingMode.HighQuality
ea.Clear(Color.Black)
For i As Integer = 0 To mapMX
For j As Integer = 0 To mapMY
If gameMap(i, j) = 1 Then
ea.FillRectangle(Brushes.Brown, New Rectangle(i * W, j * H, W, H))
ElseIf gameMap(i, j) = 2 Then
ea.FillRectangle(Brushes.Teal, New Rectangle(i * W, j * H, W, H))
ElseIf gameMap(i, j) = 3 Then
ea.FillRectangle(Brushes.MediumBlue, New Rectangle(i * W, j * H, W, H))
ElseIf gameMap(i, j) = 4 Then
ea.FillRectangle(Brushes.LightBlue, New Rectangle(i * W, j * H, W, H))
ElseIf gameMap(i, j) = 9 Then
ea.FillRectangle(Brushes.Yellow, New Rectangle(i * W, j * H, W, H))
ElseIf gameMap(i, j) > 90 And gameMap(i, j) < 100 Then '画特殊方块
ea.FillRectangle(Brushes.Indigo, New Rectangle(i * W, j * H, W, H))
End If
Next
Next
If myTanban.t_type = 1 Then '画弹板
ea.FillRectangle(Brushes.Orange, New Rectangle(myTanban.t_center.X - myTanban.t_length / 2, myTanban.t_center.Y - H / 2, myTanban.t_length, H))
ElseIf myTanban.t_type = 2 Then
ea.FillRectangle(Brushes.Red, New Rectangle(myTanban.t_center.X - myTanban.t_length / 8, myTanban.t_center.Y - H / 2, myTanban.t_length / 4, H))
ea.FillRectangle(Brushes.Orange, New Rectangle(myTanban.t_center.X - myTanban.t_length / 2, myTanban.t_center.Y - H / 2, 3 * myTanban.t_length / 8, H))
ea.FillRectangle(Brushes.LawnGreen, New Rectangle(myTanban.t_center.X + myTanban.t_length / 8, myTanban.t_center.Y - H / 2, 3 * myTanban.t_length / 8, H))
End If
For i As Integer = 0 To qiuNum - 1 '画小球
If QiuL(i).q_v_sudu >= 0 Then
ea.FillPie(New SolidBrush(QiuL(i).q_color), New Rectangle(New Point(QiuL(i).q_center.X - QiuL(i).q_radius, QiuL(i).q_center.Y - QiuL(i).q_radius), New Size(2 * QiuL(i).q_radius, 2 * QiuL(i).q_radius)), 0, 360)
End If
Next
'绘制文件(块文本)
Dim denfenStr As String = "分数:" + mydefen.ToString
Dim textSize As SizeF
Dim myBackBrush As Brush = Brushes.Green
Dim myForeBrush As Brush = Brushes.GreenYellow
Dim myFont As New Font(SystemFonts.DefaultFont.Name, 15, FontStyle.Regular)
' 找出绘制示例文本所需要的大小
textSize = ea.MeasureString(denfenStr, myFont)
Dim xLocation, yLocation As Single ' 用于位置
' 获取一次位置以消除冗余计算
xLocation = mapW - textSize.Width - 10
yLocation = 10
Dim effectDepth As Integer = 2
For i = effectDepth To 0 Step -1
ea.DrawString(denfenStr, myFont, myBackBrush, xLocation + i, yLocation + i)
Next
' 在黑色文本之上绘制水绿色主文本
ea.DrawString(denfenStr, myFont, myForeBrush, xLocation, yLocation)
If qiuJDxian Then '画角度虚线
Dim mypen As Pen = New Pen(Color.GreenYellow, 2)
Dim pDash() As DashStyle = {DashStyle.Dot, DashStyle.DashDot, DashStyle.Dash}
mypen.DashStyle = pDash(2)
For i As Integer = 0 To qiuNum - 1
If QiuL(i).q_v_sudu > 0 Then
Else
ea.DrawLine(mypen, New Point(QiuL(i).q_center.X, QiuL(i).q_center.Y), New Point(QiuL(i).q_center.X + 140 * Math.Cos(QiuL(i).q_v_fangxiang / 180 * Math.PI), _
QiuL(i).q_center.Y - 140 * Math.Sin(QiuL(i).q_v_fangxiang / 180 * Math.PI)))
End If
Next
End If
Return bmp
ea.Dispose()
bmp.Dispose()
End Function
Public Function shifouguoguan() As Boolean '是否过关?,若数组全为0或9返回TRUE,过关
Dim sfgg As Boolean = False
Dim num As Integer = 0
For Each mapV As Integer In gameMap
If (mapV > 0 And mapV < 9) Or (mapV > 90 And mapV < 99) Then num += 1
Next
If num = 0 Then sfgg = True
Return sfgg
End Function
接下来就是小球运动时碰到方块反弹。主要是根据小球所处位置,判断是否碰撞。代码如下:
Public Function juliPP(ByVal P1 As Point, ByVal P2 As Point) As Single '求两点距离
Return Math.Sqrt((P1.X - P2.X) ^ 2 + (P1.Y - P2.Y) ^ 2)
End Function
Public Function YJpz(ByVal Yx As Integer, ByVal Yy As Integer, ByVal Jx As Integer, ByVal Jy As Integer) As Integer '检查圆与矩形碰撞
'Yx、Yy是小球在圆心;Jx,Jy是矩形在左上角在地图上在坐标
Dim v As Integer = 0
Dim r As Integer = QiuL(0).q_radius '小球的半径
Dim yc As Point = New Point(Yx, Yy) '小球的圆心
If Jx < 0 Or Jy < 0 Or Jx > mapMX Or Jy > mapMY Then '地图数组下标超范围,不碰撞
v = 0
Else
Dim Jc1 As Point = New Point(Jx * W, Jy * H) '矩形左上角
Dim Jc2 As Point = New Point(Jx * W + W, Jy * H) '矩形右上角
Dim Jc3 As Point = New Point(Jx * W + W, Jy * H + H) '矩形右下角
Dim Jc4 As Point = New Point(Jx * W + W, Jy * H + H) '矩形左下角
If gameMap(Jx, Jy) > 0 Then '地图数组不为0
If Yx - Jc1.X > 0 And Yx - Jc1.X < W And Yy - Jc1.Y > 0 And Yy - Jc1.Y < H Then '小球在矩形内部
v = 9
Else
If Yx < Jc1.X And Yy < Jc1.Y And juliPP(yc, Jc1) <= r Then
v = 1 '碰左上角
ElseIf Yx > Jc1.X + W And Yy < Jc1.Y And juliPP(yc, Jc2) <= r Then
v = 2 '碰右上角
ElseIf Yx > Jc1.X + W And Yy > Jc1.Y + H And juliPP(yc, Jc3) <= r Then
v = 3 '碰右下角
ElseIf Yx < Jc1.X And Yy > Jc1.Y + H And juliPP(yc, Jc4) <= r Then
v = 4 '碰左下角
ElseIf Yx >= Jc1.X And Yx <= Jc1.X + W And Yy < Jc1.Y And Jc1.Y - Yy <= r Then
v = 5 '碰上边
ElseIf Yx >= Jc1.X + W And Yy >= Jc1.Y And Yy <= Jc1.Y + H And Yx - Jc1.X - W <= r Then
v = 6 '碰右边
ElseIf Yx >= Jc1.X And Yx <= Jc1.X + W And Yy >= Jc1.Y + H And Yy - Jc1.Y - H <= r Then
v = 7 '碰下边
ElseIf Yx <= Jc1.X And Yy >= Jc1.Y And Yy <= Jc1.Y + H And Jc1.X - Yx <= r Then
v = 8 '碰左边
End If
End If
Else '地图数组为0,表示没砖块,不碰撞
v = 0
End If
End If
Return v
End Function
接下来在窗体上添加Timer控件,不断检查碰撞情况。
接下来在窗体KeyDown过程中进行按键控制。
打砖块游戏基本设计完成了。
--------------------------------------