PICO-8 Wiki
Register
Advertisement

PICO-8 can do mathematical operations on numbers, including arithmetic and trigonometric functions. All operations use PICO-8's number value type, a 16-bit fixed point type with a range of -32768.0 to 32767.9999847412109375 (0x8000.0000 to 0x7fff.ffff).

To assist with common game graphics tasks, PICO-8's trigonometric functions use an input range of 0.0 to 1.0, which is equivalent to a range of 0 to 2 PI radians, or 0 to 360 degrees.

Increasing angle values go clockwise around the circle. Another way of thinking about this is that the result of sin() is inverted to match the orientation of the y-axis, with increasing y values going down the display. See sin() and atan2() for further explanation.

For more information:

Approximating log[]

PICO-8 does not have a built-in logarithm function. You can create one based on a lookup table, adjusted for your desired level of accuracy. Here's a simple log-base-10 function:

log10_table =
{
  0, 0.3, 0.475,
  0.6, 0.7, 0.775,
  0.8375, 0.9, 0.95, 1
}

function log10(n)
  if (n < 1) return nil
  local t = 0
  while n > 10 do
    n /= 10
    t += 1
  end
  return log10_table[flr(n)] + t
end

for x=5,500,10 do
  printh('log10('..x..') = '..log10(x))
end

This function takes advantage of the facts that log10(a * b) = log10(a) + log10(b), and log10(10^t) = t. It divides the value by 10 repeatedly until the value is between 1 and 10, keeping track of the number of divisions (t). It uses a lookup table to approximate the log of the value in this range, then adds in the log of the 10's. You can change the base by replacing "10" with the new base wherever you see it, and changing the table with new approximations for the integers from 1 to 10.

For more accuracy, you can always use larger lookup tables, but at some point you're better off calculating the logarithm directly:

function log10(n)
  if (n <= 0) return nil
  local f, t = 0, 0
  while n < 0.5 do
    n *= 2.71828
    t -= 1
  end
  while n > 1.5 do
    n /= 2.71828
    t += 1
  end
	
  n -= 1
  for i = 9, 1, -1 do
    f = n*(1/i - f)
  end
  t += f
  -- to change base, change the
  -- divisor below to ln(base)
  return t / 2.30259
end

The above operates similarly to the lookup-table algorithm: first it finds a rough approximation by dividing n and incrementing t, then it adds a number to fine-tune the approximation. The difference is in how they do the fine-tuning: whereas the first algorithm uses a lookup table, the second algorithm uses a polynomial based on the natural logarithm's Taylor series. The result is still an approximation, but a much more accurate one: this function is correct to 3 decimal places, and often to 4. Changing the base only requires looking up ln(base) and replacing the single number at the end of the function.

Keep in mind that the PICO-8 number type has a positive max of 32767, so that's your effective domain. log10(32767) is 4.51543..., so that's your range. You may want more digits of accuracy if you're doing a lot of work within that domain.

Advertisement