Small Basic Game Programming - Air Hockey Game

Both in Challenge of the Month - July 2013 and Challenge of the Month - July 2014, the challenges of air hockey game was presented.  Through this challenges, I wrote KLB414-4 for an year.  [W] key and [S] key are for the player 1 (left side) to move the mallet, [O] key and [L] key are for the player 2 (right side).  A winner is the first to win 7 points.

Main

Main loop repeats games.  In this program, the value of the variable continue is always "True".

1.``' Air Hockey 0.5b

2.``' Copyright (c) 2013-2014 Nonki Takahashi. MIT License.

3.``'

4.``' History:

5.``' 0.5b 2014-07-09 Determined a winner is the first to win 7 points. (KLB414-4)

6.``' 0.4b 2014-07-09 Supported collision between puck and mallet. (KLB414-3)

7.``' 0.3a 2014-07-03 Added mallet control. (KLB414-2)

8.``' 0.2a 2013-07-30 Changed field design. (KLB414-1)

9.``' 0.11a 2013-07-29 Modified for Silverlight. (KLB414-0)

10.``' 0.1a 2013-07-29 Created as alpha version. (KLB414)

11.``'

12.``' Reference:

13.``' LitDev, Small Basic: Dynamic Graphics, TechNet Wiki, 2013-2014.

14.``'

15.``GraphicsWindow``.`` Title `` = ``"Air Hockey 0.5b - W,S for P1; O,L for P2"

16.`` gw `` = ``598

17.`` gh `` = ``428

18.``GraphicsWindow``.`` Width `` = ``gw

19.``GraphicsWindow``.`` Height `` = ``gh

20.``GraphicsWindow``.`` BackgroundColor `` = ``"DimGray"

21.``Field_Init``(``)

22.`` continue `` = ``"True"

23.`` While ``continue

24.``  ``Game_Init``(``)

25.``  ``Game_Start``(``)

26.``  ``Game_End``(``)

27.``EndWhile

Field Initialization

This subroutine draws an air hockey field.  And adds a puck and mallets for both players as Shapes.

28.`` Sub ``Field_Init

29.``  `` fh `` = `` 30 ``' font height

30.``  ``GraphicsWindow``.`` FontName `` = ``"Trebuchet MS"

31.``  ``GraphicsWindow``.`` BrushColor `` = ``"White"

32.``  ``GraphicsWindow``.`` FontSize `` = ``fh

33.``  ``score``[``1``]``[``"obj"`` ] `` = ``Shapes``.``AddText``(``0``)

34.``  ``Shapes``.``Move``(``score``[``1``]``[``"obj"``]`` , `` gw `` / `` 2 `` - ``100`` , ``10``)

35.``  ``score``[``2``]``[``"obj"`` ] `` = ``Shapes``.``AddText``(``0``)

36.``  ``Shapes``.``Move``(``score``[``2``]``[``"obj"``]`` , `` gw `` / `` 2 `` + ``100`` , ``10``)

37.``  ``field``[``"width"`` ] `` = ``580

38.``  ``field``[``"height"`` ] `` = ``360

39.``  ``field``[``"x"`` ] `` = ``(`` gw `` - ``field``[``"width"``]`` ) `` / ``2

40.``  ``field``[``"y"`` ] `` = ``(`` gh `` - ``field``[``"height"`` ] `` + ``fh`` ) `` / ``2

41.``  ``field``[``"x2"`` ] `` = ``field``[``"x"`` ] `` + ``field``[``"width"``]

42.``  ``field``[``"y2"`` ] `` = ``field``[``"y"`` ] `` + ``field``[``"height"``]

43.``  ``param``[``"x"`` ] `` = ``field``[``"x"`` ] `` - ``10

44.``  ``param``[``"y"`` ] `` = ``(``field``[``"y"`` ] `` + ``field``[``"y2"``]`` ) `` / `` 2 `` - ``70

45.``  ``param``[``"width"`` ] `` = ``20

46.``  ``param``[``"height"`` ] `` = ``140

47.``  ``param``[``"border-radius"`` ] `` = ``10

48.``  ``goal``[``"y"`` ] `` = ``param``[``"y"``]

49.``  ``goal``[``"y2"`` ] `` = ``param``[``"y"`` ] `` + ``param``[``"height"``]

50.``  ``GraphicsWindow``.`` BrushColor `` = ``"Black"

51.``  ``FillRoundRectangle``(``)

52.``  ``param``[``"x"`` ] `` = ``field``[``"x2"`` ] `` - ``10

53.``  ``FillRoundRectangle``(``)

54.``  ``GraphicsWindow``.`` BrushColor `` = ``"Blue"

55.``  ``GraphicsWindow``.``FillRectangle``(``field``[``"x"``]`` , ``field``[``"y"``]`` , ``field``[``"width"``]`` , ``field``[``"height"``]``)

56.``  ``GraphicsWindow``.`` PenWidth `` = ``5

57.``  ``GraphicsWindow``.`` PenColor `` = ``"LightGray"

58.``  ``param``[``"x"`` ] `` = ``field``[``"x"`` ] `` + ``20

59.``  ``param``[``"y"`` ] `` = ``field``[``"y"`` ] `` + ``20

60.``  ``param``[``"width"`` ] `` = ``field``[``"width"`` ] `` - ``40

61.``  ``param``[``"height"`` ] `` = ``field``[``"height"`` ] `` - ``40

62.``  ``param``[``"border-radius"`` ] `` = ``100

63.``  ``DrawRoundRectangle``(``)

64.``  `` x `` = ``param``[``"x"`` ] `` + ``param``[``"width"`` ] `` / ``2

65.``  ``GraphicsWindow``.``DrawLine``(``x`` , ``param``[``"y"``]`` , ``x`` , ``param``[``"y"`` ] `` + ``param``[``"height"``]``)

66.``  ``GraphicsWindow``.`` BrushColor `` = ``"Black"

67.``  ``GraphicsWindow``.`` PenWidth `` = ``0

68.``  `` For `` y `` = ``field``[``"y"`` ] `` + `` 20 `` To ``field``[``"y"`` ] `` + ``field``[``"height"`` ] `` - `` 20 `` Step ``20

69.``    `` For `` x `` = ``field``[``"x"`` ] `` + `` 20 `` To ``field``[``"x"`` ] `` + ``field``[``"width"`` ] `` - `` 20 `` Step ``20

70.``      ``GraphicsWindow``.``FillEllipse``(`` x `` - ``1`` , `` y `` - ``1`` , ``2`` , ``2``)

71.``    ``EndFor

72.``  `` EndFor

73.``  ``GraphicsWindow``.`` BrushColor `` = ``"Yellow"

74.``  ``puck``[``"size"`` ] `` = ``34

75.``  ``puck``[``"r"`` ] `` = ``puck``[``"size"`` ] `` / ``2

76.``  ``puck``[``"obj"`` ] `` = ``Shapes``.``AddEllipse``(``puck``[``"size"``]`` , ``puck``[``"size"``]``)

77.``  ``GraphicsWindow``.`` BrushColor `` = ``"White"

78.``  ``mallet``[``1``]``[``"size"`` ] `` = ``34

79.``  ``mallet``[``1``]``[``"r"`` ] `` = ``mallet``[``1``]``[``"size"`` ] `` / ``2

80.``  ``mallet``[``1``]``[``"obj"`` ] `` = ``Shapes``.``AddEllipse``(``mallet``[``1``]``[``"size"``]`` , ``mallet``[``1``]``[``"size"``]``)

81.``  ``mallet``[``2``]``[``"size"`` ] `` = ``34

82.``  ``mallet``[``2``]``[``"r"`` ] `` = ``mallet``[``2``]``[``"size"`` ] `` / ``2

83.``  ``mallet``[``2``]``[``"obj"`` ] `` = ``Shapes``.``AddEllipse``(``mallet``[``2``]``[``"size"``]`` , ``mallet``[``2``]``[``"size"``]``)

84.``  ``GraphicsWindow``.`` BrushColor `` = ``"DimGray"

85.``  `` screen `` = ``Shapes``.``AddRectangle``(``gw`` , ``gh``)

86.``  ``Shapes``.``SetOpacity``(``screen`` , ``0``)

87.``EndSub

Game Initialization

This subroutine initializes the position and the velocity of the puck and the positions of the mallets.

88.`` Sub ``Game_Init

89.``  `` x `` = ``field``[``"x"``]

90.``  `` y `` = ``field``[``"y"`` ] `` + ``field``[``"height"`` ] `` / ``2

91.``  ``mallet``[``1``]``[``"cx"`` ] `` = `` x `` + `` 20

92.``  ``mallet``[``1``]``[``"cy"`` ] `` = ``y

93.``  ``Shapes``.``Move``(``mallet``[``1``]``[``"obj"``]`` , ``mallet``[``1``]``[``"cx"`` ] `` - ``mallet``[``1``]``[``"r"``]`` , ``mallet``[``1``]``[``"cy"`` ] `` - ``mallet``[``1``]``[``"r"``]``)

94.``  ``mallet``[``2``]``[``"cx"`` ] `` = `` x `` + ``field``[``"width"`` ] `` - ``20

95.``  ``mallet``[``2``]``[``"cy"`` ] `` = ``y

96.``  ``Shapes``.``Move``(``mallet``[``2``]``[``"obj"``]`` , ``mallet``[``2``]``[``"cx"`` ] `` - ``mallet``[``2``]``[``"r"``]`` , ``mallet``[``2``]``[``"cy"`` ] `` - ``mallet``[``2``]``[``"r"``]``)

97.``  ``puck``[``"cx"`` ] `` = `` x `` + ``(``field``[``"width"`` ] `` / ``2``)

98.``  ``puck``[``"cy"`` ] `` = ``y

99.``  ``Shapes``.``Move``(``puck``[``"obj"``]`` , ``puck``[``"cx"`` ] `` - ``puck``[``"r"``]`` , ``puck``[``"cy"`` ] `` - ``puck``[``"r"``]``)

100.``  `` v0 `` = ``400

101.``  ``puck``[``"vx"`` ] `` = ``100

102.``  ``puck``[``"vy"`` ] `` = ``80

103.``  ``AdjustV0``(``)

104.``  ``score``[``1``]``[``"value"`` ] `` = ``0

105.``  ``Shapes``.``SetText``(``score``[``1``]``[``"obj"``]`` , ``score``[``1``]``[``"value"``]``)

106.``  ``score``[``2``]``[``"value"`` ] `` = ``0

107.``  ``Shapes``.``SetText``(``score``[``2``]``[``"obj"``]`` , ``score``[``2``]``[``"value"``]``)

108.``  `` deltaY `` = ``puck``[``"size"``]

109.``  ``GraphicsWindow``.`` KeyDown `` = ``OnKeyDown

110.``EndSub

Playing the Game

This subroutine continues the game until one player wins 7 points.  In this loop, the position and the velocity of the puck is updated 24 times per one second. 

111.`` Sub ``Game_Start

112.``  `` inGame `` = ``"True"

113.``  `` dt `` = `` 1 `` / `` 24 ``' [second]

114.``  `` While ``inGame

115.``    `` start `` = ``Clock``.``ElapsedMilliseconds

116.``    ``UpdatePuck``(``)

117.``    `` delay `` = `` dt `` * `` 1000 `` - ``(``Clock``.`` ElapsedMilliseconds `` - ``start``)

118.``    `` If `` 0 `` < `` delay ``Then

119.``      ``Program``.``Delay``(``delay``)

120.``    ``EndIf

121.``  ``EndWhile

122.``EndSub

Game End

This subroutine shows the winner.

123.`` Sub ``Game_End

124.``  ``Shapes``.``SetOpacity``(``screen`` , ``40``)

125.``  ``GraphicsWindow``.`` FontSize `` = ``40

126.``  ``GraphicsWindow``.`` BrushColor `` = ``"White"

127.``  `` result `` = ``Shapes``.``AddText``(`` "PLAYER " `` + `` winner ``+  ``" WON"``)

128.``  `` x `` = ``(`` gw `` - ``283`` ) `` / ``2

129.``  `` y `` = ``(`` gh `` - ``40`` ) `` / ``2

130.``  ``Shapes``.``Move``(``result`` , ``x`` , ``y``)

131.``  ``Sound``.``PlayBellRingAndWait``(``)

132.``  ``Program``.``Delay``(``5000``)

133.``  ``Shapes``.``SetOpacity``(``screen`` , ``0``)

134.``  ``Shapes``.``Remove``(``result``)

135.``EndSub

Adjusting the Velocity of the Puck

This subroutine adjusts the scalar value of the velocity for the puck - puck["vx"] and puck["vy"] to be the same value of the variable v0.

136.`` Sub ``AdjustV0

137.``  `` v `` = ``Math``.``SquareRoot``(``Math``.``Power``(``puck``[``"vx"``]`` , ``2`` ) `` + ``Math``.``Power``(``puck``[``"vy"``]`` , ``2``)``)

138.``  ``puck``[``"vx"`` ] `` = ``puck``[``"vx"`` ] `` * `` v0 `` / ``v

139.``  ``puck``[``"vy"`` ] `` = ``puck``[``"vy"`` ] `` * `` v0 `` / ``v

140.``EndSub

Collision Detection

This subroutine detects collision between the puck and the mallets, and updates the velocity of the puck if the collision is detected.  The origin of this subroutine is the same named subroutine written in a TechNet Wiki article Dynamic Graphics by LitDev.  The original is for collision between balls, but this subroutine is changed that only the puck is reflected because the mallets are held by the players.

141.`` Sub ``CollisionCheck

142.``  `` For `` i `` = `` 1 `` To ``2

143.``    `` dx `` = ``mallet``[``i``]``[``"cx"`` ] `` - ``puck``[``"cx"``]

144.``    `` dy `` = ``mallet``[``i``]``[``"cy"`` ] `` - ``puck``[``"cy"``]

145.``    `` distance `` = ``Math``.``SquareRoot``(`` dx `` * `` dx `` + `` dy `` * ``dy``)

146.``    `` If `` distance `` < ``puck``[``"size"`` ] ``Then

147.``      ``Sound``.``PlayClick``(``)

148.``      `` relativeVx `` = ``puck``[``"vx"``]

149.``      `` relativeVy `` = ``puck``[``"vy"``]

150.``      `` nx `` = `` dx `` / ``distance

151.``      `` ny `` = `` dy `` / ``distance

152.``      `` l `` = `` nx `` * `` relativeVx `` + `` ny `` * ``relativeVy

153.``      `` relativeVx `` = `` relativeVx `` - ``(`` 2 `` * `` l `` * ``nx``)

154.``      `` relativeVy `` = `` relativeVy `` - ``(`` 2 `` * `` l `` * ``ny``)

155.``      ``puck``[``"vx"`` ] `` = ``relativeVx

156.``      ``puck``[``"vy"`` ] `` = ``relativeVy

157.``      ``puck``[``"cx"`` ] `` = ``puck``[``"cx"`` ] `` - `` nx `` * ``(``puck``[``"size"`` ] `` - ``distance``)

158.``      ``puck``[``"cy"`` ] `` = ``puck``[``"cy"`` ] `` - `` ny `` * ``(``puck``[``"size"`` ] `` - ``distance``)

159.``    ``EndIf

160.``  ``EndFor

161.``EndSub

Key Input Event Handler

This subroutine moves the mallets when the keys are input. 

162.`` Sub ``OnKeyDown

163.``  `` key `` = ``GraphicsWindow``.``LastKey

164.``  `` If `` key `` = `` "W" `` Then ``' player 1 up

165.``    `` If ``goal``[``"y"`` ] ``<`` = ``mallet``[``1``]``[``"cy"`` ] `` - `` deltaY ``Then

166.``      ``mallet``[``1``]``[``"cy"`` ] `` = ``mallet``[``1``]``[``"cy"`` ] `` - ``deltaY

167.``      ``Shapes``.``Move``(``mallet``[``1``]``[``"obj"``]`` , ``mallet``[``1``]``[``"cx"`` ] `` - ``mallet``[``1``]``[``"r"``]`` , ``mallet``[``1``]``[``"cy"`` ] `` - ``mallet``[``1``]``[``"r"``]``)

168.``    ``EndIf

169.``  `` ElseIf `` key `` = `` "S" `` Then ``' player 1 down

170.``    `` If ``mallet``[``1``]``[``"cy"`` ] `` + `` deltaY ``<`` = ``goal``[``"y2"`` ] ``Then

171.``      ``mallet``[``1``]``[``"cy"`` ] `` = ``mallet``[``1``]``[``"cy"`` ] `` + ``deltaY

172.``      ``Shapes``.``Move``(``mallet``[``1``]``[``"obj"``]`` , ``mallet``[``1``]``[``"cx"`` ] `` - ``mallet``[``1``]``[``"r"``]`` , ``mallet``[``1``]``[``"cy"`` ] `` - ``mallet``[``1``]``[``"r"``]``)

173.``    ``EndIf

174.``  `` ElseIf `` key `` = `` "O" `` Then ``' player 2 up

175.``    `` If ``goal``[``"y"`` ] ``<`` = ``mallet``[``2``]``[``"cy"`` ] `` - `` deltaY ``Then

176.``      ``mallet``[``2``]``[``"cy"`` ] `` = ``mallet``[``2``]``[``"cy"`` ] `` - ``deltaY

177.``      ``Shapes``.``Move``(``mallet``[``2``]``[``"obj"``]`` , ``mallet``[``2``]``[``"cx"`` ] `` - ``mallet``[``2``]``[``"r"``]`` , ``mallet``[``2``]``[``"cy"`` ] `` - ``mallet``[``2``]``[``"r"``]``)

178.``    ``EndIf

179.``  `` ElseIf `` key `` = `` "L" `` Then ``' player 2 down

180.``    `` If ``mallet``[``2``]``[``"cy"`` ] `` + `` deltaY ``<`` = ``goal``[``"y2"`` ] ``Then

181.``      ``mallet``[``2``]``[``"cy"`` ] `` = ``mallet``[``2``]``[``"cy"`` ] `` + ``deltaY

182.``      ``Shapes``.``Move``(``mallet``[``2``]``[``"obj"``]`` , ``mallet``[``2``]``[``"cx"`` ] `` - ``mallet``[``2``]``[``"r"``]`` , ``mallet``[``2``]``[``"cy"`` ] `` - ``mallet``[``2``]``[``"r"``]``)

183.``    ``EndIf

184.``  ``EndIf

185.``EndSub

Update of the Velocity and the Position for the Puck

This subroutine simulates the movement of the puck which moves with the constant velocity along with Newton's law of inertia. And it also checks goal or collision with the frame of the field. If a player get a goal, the position of the puck is set back to the center. At the last, it also checks collision with mullets by calling CallingCheck(). If a player get 7 points, inGame flag is set as "False" to terminate the loop in Game_Start().

186.`` Sub ``UpdatePuck

187.``  `` isGoal `` = ``"False"

188.``  `` x `` = ``puck``[``"cx"`` ] `` + `` dt `` * ``puck``[``"vx"``]

189.``  `` If `` x `` < ``field``[``"x"`` ] `` + ``puck``[``"r"`` ] ``Then

190.``    `` y `` = ``puck``[``"cy"`` ] `` + `` dt `` * ``(``field``[``"x"`` ] `` - ``puck``[``"cx"``]`` ) `` * ``puck``[``"vy"`` ] `` / ``puck``[``"vx"``]

191.``    `` If ``(``goal``[``"y"`` ] `` < ``y`` ) `` And ``(`` y `` < ``goal``[``"y2"``]`` ) ``Then

192.``      ``score``[``2``]``[``"value"`` ] `` = ``score``[``2``]``[``"value"`` ] `` + ``1

193.``      ``Shapes``.``SetText``(``score``[``2``]``[``"obj"``]`` , ``score``[``2``]``[``"value"``]``)

194.``      `` isGoal `` = ``"True"

195.``      `` If ``score``[``2``]``[``"value"`` ] `` = `` 7 ``Then

196.``        `` inGame `` = ``"False"

197.``        `` winner `` = ``2

198.``      ``EndIf

199.``    ``Else

200.``      ``puck``[``"cx"`` ] `` = ``field``[``"x"`` ] `` + ``puck``[``"r"`` ] `` + ``(``field``[``"x"`` ] `` + ``puck``[``"r"`` ] `` - ``x``)

201.``      ``puck``[``"vx"`` ] `` = ``-``puck``[``"vx"``]

202.``      ``Sound``.``PlayClick``(``)

203.``    ``EndIf

204.``  `` ElseIf ``field``[``"x2"`` ] `` - ``puck``[``"r"`` ] `` < `` x ``Then

205.``    `` y `` = ``puck``[``"cy"`` ] `` + `` dt `` * ``(``field``[``"x2"`` ] `` - ``puck``[``"cx"``]`` ) `` * ``puck``[``"vy"`` ] `` / ``puck``[``"vx"``]

206.``    `` If ``(``goal``[``"y"`` ] `` < ``y`` ) `` And ``(`` y `` < ``goal``[``"y2"``]`` ) ``Then

207.``      ``score``[``1``]``[``"value"`` ] `` = ``score``[``1``]``[``"value"`` ] `` + ``1

208.``      ``Shapes``.``SetText``(``score``[``1``]``[``"obj"``]`` , ``score``[``1``]``[``"value"``]``)

209.``      `` isGoal `` = ``"True"

210.``      `` If ``score``[``1``]``[``"value"`` ] `` = `` 7 ``Then

211.``        `` inGame `` = ``"False"

212.``        `` winner `` = ``1

213.``      ``EndIf

214.``    ``Else

215.``      ``puck``[``"cx"`` ] `` = ``field``[``"x2"`` ] `` - ``puck``[``"r"`` ] `` - ``(`` x `` - ``(``field``[``"x2"`` ] `` - ``puck``[``"r"``]``)``)

216.``      ``puck``[``"vx"`` ] `` = ``-``puck``[``"vx"``]

217.``      ``Sound``.``PlayClick``(``)

218.``    ``EndIf

219.``  ``Else

220.``    ``puck``[``"cx"`` ] `` = ``x

221.``  ``EndIf

222.``  `` If `` isGoal ``Then

223.``    `` If `` y `` < `` goal ``[``"y"`` ] `` + ``puck``[``"r"`` ] ``Then

224.``      `` y `` = ``goal``[``"y"`` ] `` + ``puck``[``"r"``]

225.``    `` ElseIf ``goal``[``"y2"`` ] `` - ``puck``[``"r"`` ] `` < `` y ``Then

226.``      `` y `` = ``goal``[``"y2"`` ] `` - ``puck``[``"r"``]

227.``    ``EndIf

228.``    ``Shapes``.``Move``(``puck``[``"obj"``]`` , `` x `` - ``puck``[``"r"``]`` , `` y `` - ``puck``[``"r"``]``)

229.``    ``Sound``.``PlayChimeAndWait``(``)

230.``    ``puck``[``"cx"`` ] `` = `` gw `` / ``2

231.``    ``puck``[``"cy"`` ] `` = ``(``field``[``"y"`` ] `` + ``field``[``"y2"``]`` ) `` / ``2

232.``    ``AdjustV0``(``)

233.``  ``Else

234.``    `` y `` = ``puck``[``"cy"`` ] `` + `` dt `` * ``puck``[``"vy"``]

235.``    `` If `` y `` < ``field``[``"y"`` ] `` + ``puck``[``"r"`` ] ``Then

236.``      ``puck``[``"cy"`` ] `` = ``field``[``"y"`` ] `` + ``puck``[``"r"`` ] `` + ``(``field``[``"y"`` ] `` + ``puck``[``"r"`` ] `` - ``y``)

237.``      ``puck``[``"vy"`` ] `` = ``-``puck``[``"vy"``]

238.``      ``Sound``.``PlayClick``(``)

239.``    `` ElseIf ``field``[``"y2"`` ] `` - ``puck``[``"r"`` ] `` < `` y ``Then

240.``      ``puck``[``"cy"`` ] `` = ``field``[``"y2"`` ] `` - ``puck``[``"r"`` ] `` - ``(`` y `` - ``(``field``[``"y2"`` ] `` - ``puck``[``"r"``]``)``)

241.``      ``puck``[``"vy"`` ] `` = ``-``puck``[``"vy"``]

242.``      ``Sound``.``PlayClick``(``)

243.``    ``Else

244.``      ``puck``[``"cy"`` ] `` = ``y

245.``    ``EndIf

246.``    ``CollisionCheck``(``)

247.``    ``Shapes``.``Move``(``puck``[``"obj"``]`` , ``puck``[``"cx"`` ] `` - ``puck``[``"r"``]`` , ``puck``[``"cy"`` ] `` - ``puck``[``"r"``]``)

248.``  ``EndIf

249.``EndSub

Drawing Rounded Rectangle

This subroutine draws a rounded rectangle - a rectangle with rounded corners.

250.`` Sub ``DrawRoundRectangle

251.``  ``Stack``.``PushValue``(``"local"`` , ``param``)

252.``  ``Stack``.``PushValue``(``"local"`` , ``local``)

253.``  `` local `` = ``param

254.``  `` param `` = ``""

255.``  ``param``[``"r"`` ] `` = ``local``[``"border-radius"``]

256.``  `` If ``(``local``[``"width"`` ] `` / `` 2 `` < ``param``[``"r"``]`` ) `` Or ``(``local``[``"height"`` ] `` / `` 2 `` < ``param``[``"r"``]`` ) ``Then

257.``    ``param``[``"r"`` ] `` = ``Math``.``Min``(``local``[``"width"`` ] `` / ``2`` , ``local``[``"height"`` ] `` / ``2``)

258.``  ``EndIf

259.``  ``param``[``"da"`` ] `` = ``5

260.``  ``param``[``"x"`` ] `` = ``local``[``"x"`` ] `` + ``param``[``"r"``]

261.``  ``param``[``"y"`` ] `` = ``local``[``"y"`` ] `` + ``param``[``"r"``]

262.``  ``param``[``"a1"`` ] `` = ``180

263.``  ``param``[``"a2"`` ] `` = ``270

264.``  ``DrawArc``(``)

265.``  ``GraphicsWindow``.``DrawLine``(``local``[``"x"`` ] `` + ``param``[``"r"``]`` , ``local``[``"y"``]`` , ``local``[``"x"`` ] `` + ``local``[``"width"`` ] `` - ``param``[``"r"``]`` , ``local``[``"y"``]``)

266.``  ``param``[``"x"`` ] `` = ``local``[``"x"`` ] `` + ``local``[``"width"`` ] `` - ``param``[``"r"``]

267.``  ``param``[``"y"`` ] `` = ``local``[``"y"`` ] `` + ``param``[``"r"``]

268.``  ``param``[``"a1"`` ] `` = ``270

269.``  ``param``[``"a2"`` ] `` = ``360

270.``  ``DrawArc``(``)

271.``  ``GraphicsWindow``.``DrawLine``(``local``[``"x"`` ] `` + ``local``[``"width"``]`` , ``local``[``"y"`` ] `` + ``param``[``"r"``]`` , ``local``[``"x"`` ] `` + ``local``[``"width"``]`` , ``local``[``"y"`` ] `` + ``local``[``"height"`` ] `` - ``param``[``"r"``]``)

272.``  ``param``[``"x"`` ] `` = ``local``[``"x"`` ] `` + ``local``[``"width"`` ] `` - ``param``[``"r"``]

273.``  ``param``[``"y"`` ] `` = ``local``[``"y"`` ] `` + ``local``[``"height"`` ] `` - ``param``[``"r"``]

274.``  ``param``[``"a1"`` ] `` = ``0

275.``  ``param``[``"a2"`` ] `` = ``90

276.``  ``DrawArc``(``)

277.``  ``GraphicsWindow``.``DrawLine``(``local``[``"x"`` ] `` + ``param``[``"r"``]`` , ``local``[``"y"`` ] `` + ``local``[``"height"``]`` , ``local``[``"x"`` ] `` + ``local``[``"width"`` ] `` - ``param``[``"r"``]`` , ``local``[``"y"`` ] `` + ``local``[``"height"``]``)

278.``  ``param``[``"x"`` ] `` = ``local``[``"x"`` ] `` + ``param``[``"r"``]

279.``  ``param``[``"y"`` ] `` = ``local``[``"y"`` ] `` + ``local``[``"height"`` ] `` - ``param``[``"r"``]

280.``  ``param``[``"a1"`` ] `` = ``90

281.``  ``param``[``"a2"`` ] `` = ``180

282.``  ``DrawArc``(``)

283.``  ``GraphicsWindow``.``DrawLine``(``local``[``"x"``]`` , ``local``[``"y"`` ] `` + ``param``[``"r"``]`` , ``local``[``"x"``]`` , ``local``[``"y"`` ] `` + ``local``[``"height"`` ] `` - ``param``[``"r"``]``)

284.``  `` local `` = ``Stack``.``PopValue``(``"local"``)

285.``  `` param `` = ``Stack``.``PopValue``(``"local"``)

286.``EndSub

Filling Rounded Rectangle

This subroutine fills a rounded rectangle with a color.

287.`` Sub ``FillRoundRectangle

288.``  ``Stack``.``PushValue``(``"local"`` , ``param``)

289.``  `` If ``(``param``[``"width"`` ] `` / `` 2 `` < ``param``[``"border-radius"``]`` ) `` Or ``(``param``[``"height"`` ] `` / `` 2 `` < ``param``[``"border-radius"``]`` ) ``Then

290.``    ``param``[``"border-radius"`` ] `` = ``Math``.``Min``(``param``[``"width"`` ] `` / ``2`` , ``param``[``"height"`` ] `` / ``2``)

291.``  ``EndIf

292.``  ``GraphicsWindow``.``FillEllipse``(``param``[``"x"``]`` , ``param``[``"y"``]`` , ``param``[``"border-radius"`` ] `` * ``2`` , ``param``[``"border-radius"`` ] `` * ``2``)

293.``  ``GraphicsWindow``.``FillRectangle``(``param``[``"x"`` ] `` + ``param``[``"border-radius"``]`` , ``param``[``"y"``]`` , ``param``[``"width"`` ] `` - ``param``[``"border-radius"`` ] `` * ``2`` , ``param``[``"height"``]``)

294.``  ``GraphicsWindow``.``FillEllipse``(``param``[``"x"`` ] `` + ``param``[``"width"`` ] `` - ``param``[``"border-radius"`` ] `` * ``2`` , ``param``[``"y"``]`` , ``param``[``"border-radius"`` ] `` * ``2`` , ``param``[``"border-radius"`` ] `` * ``2``)

295.``  ``GraphicsWindow``.``FillRectangle``(``param``[``"x"``]`` , ``param``[``"y"`` ] `` + ``param``[``"border-radius"``]`` , ``param``[``"width"``]`` , ``param``[``"height"`` ] `` - ``param``[``"border-radius"`` ] `` * ``2``)

296.``  ``GraphicsWindow``.``FillEllipse``(``param``[``"x"``]`` , ``param``[``"y"`` ] `` + ``param``[``"height"`` ] `` - ``param``[``"border-radius"`` ] `` * ``2`` , ``param``[``"border-radius"`` ] `` * ``2`` , ``param``[``"border-radius"`` ] `` * ``2``)

297.``  ``GraphicsWindow``.``FillEllipse``(``param``[``"x"`` ] `` + ``param``[``"width"`` ] `` - ``param``[``"border-radius"`` ] `` * ``2`` , ``param``[``"y"`` ] `` + ``param``[``"height"`` ] `` - ``param``[``"border-radius"`` ] `` * ``2`` , ``param``[``"border-radius"`` ] `` * ``2`` , ``param``[``"border-radius"`` ] `` * ``2``)

298.``  `` param `` = ``Stack``.``PopValue``(``"local"``)

299.``EndSub

Drawing Arc

This subroutine draws an arc.

300.`` Sub ``DrawArc

301.``  ``Stack``.``PushValue``(``"local"`` , ``param``)

302.``  ``Stack``.``PushValue``(``"local"`` , ``local``)

303.``  ``Stack``.``PushValue``(``"local"`` , ``a``)

304.``  `` local `` = ``param

305.``  `` param `` = ``""

306.``  ``local``[``"pw"`` ] `` = ``GraphicsWindow``.``PenWidth

307.``  ``local``[``"pc"`` ] `` = ``GraphicsWindow``.``PenColor

308.``  ``local``[``"bc"`` ] `` = ``GraphicsWindow``.``BrushColor

309.``  ``GraphicsWindow``.`` BrushColor `` = ``local``[``"pc"``]

310.``  ``local``[``"r1"`` ] `` = ``local``[``"r"`` ] `` - ``local``[``"pw"`` ] `` / ``2

311.``  ``local``[``"r2"`` ] `` = ``local``[``"r"`` ] `` + ``local``[``"pw"`` ] `` / ``2

312.``  `` For `` a `` = ``local``[``"a1"`` ] `` To ``local``[``"a2"`` ] `` Step ``local``[``"da"``]

313.``    ``local``[``"rad"`` ] `` = ``Math``.``GetRadians``(``a``)

314.``    ``param``[``"x1"`` ] `` = ``local``[``"x"`` ] `` + ``local``[``"r1"`` ] `` * ``Math``.``Cos``(``local``[``"rad"``]``)

315.``    ``param``[``"y1"`` ] `` = ``local``[``"y"`` ] `` + ``local``[``"r1"`` ] `` * ``Math``.``Sin``(``local``[``"rad"``]``)

316.``    ``param``[``"x2"`` ] `` = ``local``[``"x"`` ] `` + ``local``[``"r2"`` ] `` * ``Math``.``Cos``(``local``[``"rad"``]``)

317.``    ``param``[``"y2"`` ] `` = ``local``[``"y"`` ] `` + ``local``[``"r2"`` ] `` * ``Math``.``Sin``(``local``[``"rad"``]``)

318.``    `` If ``local``[``"a1"`` ] `` < `` a ``Then

319.``      ``FillQuadrangle``(``)

320.``    ``EndIf

321.``    ``param``[``"x4"`` ] `` = ``param``[``"x1"``]

322.``    ``param``[``"y4"`` ] `` = ``param``[``"y1"``]

323.``    ``param``[``"x3"`` ] `` = ``param``[``"x2"``]

324.``    ``param``[``"y3"`` ] `` = ``param``[``"y2"``]

325.``  ``EndFor

326.``  ``GraphicsWindow``.`` BrushColor `` = ``local``[``"bc"``]

327.``  `` a `` = ``Stack``.``PopValue``(``"local"``)

328.``  `` local `` = ``Stack``.``PopValue``(``"local"``)

329.``  `` param `` = ``Stack``.``PopValue``(``"local"``)

330.``EndSub

Filling Quadrangle

This subroutines fills a quadrangle with a color.

331.`` Sub ``FillQuadrangle

332.``  ``GraphicsWindow``.``FillTriangle``(``param``[``"x1"``]`` , ``param``[``"y1"``]`` , ``param``[``"x2"``]`` , ``param``[``"y2"``]`` , ``param``[``"x3"``]`` , ``param``[``"y3"``]``)

333.``  ``GraphicsWindow``.``FillTriangle``(``param``[``"x3"``]`` , ``param``[``"y3"``]`` , ``param``[``"x4"``]`` , ``param``[``"y4"``]`` , ``param``[``"x1"``]`` , ``param``[``"y1"``]``)

334.``EndSub

As this game, creating game with physical phenomena needs to use knowledge of physics.  This air hockey game doesn't affected by friction or gravity, but some games need to simulate them.

I'd like to end this game programming series for now.  Most of the games introduced here are born within the Small Basic MSDN Forum.  Especially, we can get a game challenge every month in Challenge of the Month.  I recommend you to challenge them.

Have a fun game programming!