Once I wrote a series of blog posts about game programming in Small Basic. Today, I'd like to add one more post about game math.
In this article, I'll talk about following Math operations.
- Random Number
- Remainder
- Trigonometric Functions
- Math for Kinetics (Dynamics)
- Math for Collision
Random Number
Random number is sometimes used to such as random action of enemy or AI (artificial intelligence). A simple sample is in a blog post Small Basic Game Programming - Let's start with RPS game. And you can learn more about random number in another post Small Basic - Random Numbers.
Remainder
Remainder is a useful function for such as following case:
- to check a number is odd or even
- to convert large angle (>= 360 decree) to small (< 360)
- to do another operation once every N times
- to get column from a 2-D board that implemented as 1-D array
Following code is a sample of the last one in the list above. This code is from my 2048 game (CLZ771-0).
Sub
Board_CellToIndex
' param col, row - cell position
' return i - index of board array
i
=
(
row
-
1
)
*
4
+
col
EndSub
Sub
Board_IndexToCell
' param i - index of board array
' return col, row - cell position
col
=
Math
.
Remainder
(
i
-
1
,
4
)
+
1
row
=
Math
.
Floor
(
(
i
-
1
)
/
4
)
+
1
EndSub
Trigonometric Functions
Trigonometric functions will be used in following situations:
- to rotate Shapes not from their centers (using sin and cos)
- to convert a polar coordinate to a rectangular coordinate (using sin and cos)
- to convert a rectangular coordinate to a polar coordinate (using arctan)
Following subroutine converts a rectangular (Cartesian) coordinate (x, y) to a polar coordinate (r, a). This subroutine uses tan-1 (arctan) function. For example, this subroutine is used in my game Dragon vs Turtle (HMP803-5) to get an angle for moving the Turtle from a mouse position.
Sub
Math_CartesianToPolar
' Math | convert Cartesian coordinate to polar coordinate
' param x, y - Cartesian coordinate
' return r, a - polar coordinate (0<=a<360)
r
=
Math
.
SquareRoot
(
x
*
x
+
y
*
y
)
If
x
=
0
And
y
>
0
Then
a
=
90
' [degree]
ElseIf
x
=
0
And
y
<
0
Then
a
=
-
90
Else
a
=
Math
.
ArcTan
(
y
/
x
)
*
180
/
Math
.
Pi
EndIf
If
x
<
0
Then
a
=
a
+
180
ElseIf
x
>
=
0
And
y
<
0
Then
a
=
a
+
360
EndIf
EndSub
Math for Kinetics (Dynamics)
Motion of a point is calculated from it's acceleration (a [m/s2]), velocity (v [m/s]), displacement (d [m]) and time (t [s]). Delta velocity is calculated from following equation.
Delta displacement is calculated from following equation.
Following graph shows Δd as a dark gray trapezoid. And the slope of the graph shows acceleration. This t-v graph is drawn by a program JLF545-1.
My game Lunar Module (DTF312-2) uses this kind of calculation.
Math for Collision
Today I'd like to introduce two easy way to calculate collision. The first one is a circle and walls of the graphics window. Following code is from a program LDH017. And this code is checking the circle position with walls (x<=0, x>=the graphic window width, y<=0 and y>=the graphics window height).
' collision detect with walls
If
(
_x
-
_s
[
id
]
[
"w"
]
/
2
)
<
=
0
Then
_x
=
_x
-
2
*
(
_x
-
_s
[
id
]
[
"w"
]
/
2
)
_s
[
_id
]
[
"vx"
]
=
-
_s
[
_id
]
[
"vx"
]
*
_s
[
_id
]
[
"r"
]
ElseIf
gw
<
=
(
_x
+
_s
[
id
]
[
"w"
]
/
2
)
Then
_x
=
_x
-
2
*
(
_x
+
_s
[
id
]
[
"w"
]
/
2
-
gw
)
_s
[
_id
]
[
"vx"
]
=
-
_s
[
_id
]
[
"vx"
]
*
_s
[
_id
]
[
"r"
]
EndIf
If
(
_y
-
_s
[
id
]
[
"h"
]
/
2
)
<
=
0
Then
_y
=
_y
-
2
*
(
_y
-
_s
[
id
]
[
"h"
]
/
2
)
_s
[
_id
]
[
"vy"
]
=
-
_s
[
_id
]
[
"vy"
]
*
_s
[
_id
]
[
"r"
]
ElseIf
gh
<
=
(
_y
+
_s
[
id
]
[
"h"
]
/
2
)
Then
_y
=
_y
-
2
*
(
_y
+
_s
[
id
]
[
"h"
]
/
2
-
gh
)
_s
[
_id
]
[
"vy"
]
=
-
_s
[
_id
]
[
"vy"
]
*
_s
[
_id
]
[
"r"
]
EndIf
The second one is between circles. To detect collision between two circles, calculate the distance of two centers. This method can be used when the shape is not circle. Following games use this method.
Following code is from DONKEY KONG. The d means the distance between Mario and a barrel.
nb
=
barrel
[
"num"
]
For
ib
=
1
To
nb
xb
=
barrel
[
ib
]
[
"x"
]
+
16
yb
=
barrel
[
ib
]
[
"y"
]
+
16
d
=
Math
.
SquareRoot
(
Math
.
Power
(
(
xb
-
xm
)
,
2
)
+
Math
.
Power
(
(
yb
-
ym
)
,
2
)
)
If
d
<
20
Then
mario
[
"hit"
]
=
"True"
mario
[
"vx"
]
=
0
ym
=
ym
-
24
mario
[
"vr"
]
=
720
EndIf
EndFor
See Also
- Small Basic: How to Use Trigonometric Functions
- Small Basic: Dynamic Graphics for more details about dynamics and collision