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!