Small Basic Game Programming - Game Math


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

Comments (6)

  1. Great article. Thanks Nonki.

  2. This is a fantastic summary of the different types of Game Math!

  3. Sean Liming says:

    Nice summary. Like the tie in examples.

  4. Following condition is needed for Small Basic 1.2 before Else in Math_CartesianToPolar subroutine.

     ElseIf x = 0 Then ' this condition is needed for SB 1.2

       a = 0

Skip to main content