Minimal abstract interface for simple games
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

133 lines
2.7 KiB

/**
Simple SAF program for exploring the Mandelbrot set, arrows to move, A/B to
zoom.
by drummyfish, released under CC0 1.0, public domain
*/
#define SAF_PROGRAM_NAME "Mandelbrot"
#define SAF_SETTING_ENABLE_SOUND 0
#include "../saf.h"
/*
Checks whether the point is in the mandelbrot set, returns number of
iterations, up until 255, to which the point did not diverge to infinity, i.e.
255 means probably inside the set.
*/
uint8_t iteratePoint(double x, double y)
{
// writing this without floats is left as an excercise for the reader
double current[2];
current[0] = x;
current[1] = y;
uint8_t iterations = 0;
while (1)
{
double
newX = current[0] * current[0] - current[1] * current[1] + x,
newY = 2 * current[0] * current[1] + y;
current[0] = newX;
current[1] = newY;
#define INF 999999999999
if (iterations == 255 ||
current[0] > INF || current[0] < -INF ||
current[1] > INF || current[1] < -INF)
break;
#undef INF
iterations++;
}
return iterations;
}
double
cx = -1,
cy = -1,
step = 2.0 / SAF_SCREEN_WIDTH;
void draw(void)
{
double dx, dy = cy, halfStep = step / 2;
for (int y = 0; y < SAF_SCREEN_HEIGHT; ++y)
{
dx = cx;
for (int x = 0; x < SAF_SCREEN_WIDTH; ++x)
{
// antialias (sample at 4 points):
uint8_t r = 0,g = 0,b = 0;
uint16_t rr = 0, gg = 0, bb = 0;
SAF_colorToRGB(iteratePoint(dx,dy), &r, &g, &b);
rr = r; gg = g; bb = b;
SAF_colorToRGB(iteratePoint(dx + halfStep,dy), &r, &g, &b);
rr += r; gg += g; bb += b;
SAF_colorToRGB(iteratePoint(dx,dy + halfStep), &r, &g, &b);
rr += r; gg += g; bb += b;
SAF_colorToRGB(iteratePoint(dx + halfStep,dy + halfStep), &r, &g, &b);
rr += r; gg += g; bb += b;
SAF_drawPixel(x,y,SAF_colorFromRGB(rr / 4, gg / 4, bb / 4));
dx += step;
}
dy += step;
}
}
void SAF_init(void)
{
draw();
}
uint8_t SAF_loop(void)
{
uint8_t redraw = 1;
#define STEP 10
if (SAF_buttonJustPressed(SAF_BUTTON_LEFT))
cx -= step * STEP;
else if (SAF_buttonJustPressed(SAF_BUTTON_RIGHT))
cx += step * STEP;
else if (SAF_buttonJustPressed(SAF_BUTTON_UP))
cy -= step * STEP;
else if (SAF_buttonJustPressed(SAF_BUTTON_DOWN))
cy += step * STEP;
else if (SAF_buttonJustPressed(SAF_BUTTON_A))
{
// zoom and shift
step /= 2;
cx += step / 2 * SAF_SCREEN_WIDTH;
cy += step / 2 * SAF_SCREEN_HEIGHT;
}
else if (SAF_buttonJustPressed(SAF_BUTTON_B))
{
step *= 2;
cx -= step / 4 * SAF_SCREEN_WIDTH;
cy -= step / 4 * SAF_SCREEN_HEIGHT;
}
else
redraw = 0;
#undef STEP
if (redraw) // only redraw when needed, it's expensive
draw();
return 1;
}