-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
90 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
// Circles | ||
// | ||
// How to draw circles without ever using a multiplication? | ||
// | ||
// Copyright (c) 2024, Olaf "brolf" Pichler <[email protected]> | ||
// | ||
// Permission to use, copy, modify, and/or distribute this software for any | ||
|
@@ -28,7 +30,7 @@ | |
|
||
#define FPS 60 | ||
#define FRAMETIME (T_SECOND / FPS) | ||
#define FRAMES (TIME_LONG * FPS) | ||
#define FRAMES (TIME_MEDIUM * FPS) | ||
|
||
static int modno; | ||
static unsigned int frame; | ||
|
@@ -37,16 +39,23 @@ static oscore_time nexttick; | |
static u_int16_t xmax; | ||
static u_int16_t ymax; | ||
|
||
#define P_MAX 25 | ||
// random seeds for color selection | ||
static u_int16_t rs1; | ||
static u_int16_t rs2; | ||
|
||
typedef struct { | ||
u_int16_t x; | ||
u_int16_t y; | ||
u_int16_t r; | ||
u_int16_t x; // x coordinate of center | ||
u_int16_t y; // y coordinate of center | ||
u_int16_t r; // r curent radius of circle | ||
u_int16_t lt; // livetime (rmax) after which the circle should die | ||
} Circle; | ||
static Circle points[P_MAX]; | ||
|
||
static const RGB black = RGB(0,0,0); | ||
// Number of circles to draw | ||
#define P_MAX 25 | ||
static Circle circles[P_MAX]; | ||
|
||
// Color palette and stuff | ||
static const RGB black = RGB(0,0,0); | ||
static const RGB palette[] = { | ||
RGB(255, 0, 0), RGB(204, 0, 0), RGB(153, 0, 0), RGB(255, 85, 85), | ||
RGB(204, 68, 68), RGB(153, 51, 51), RGB(255, 127, 0), RGB(204, 102, 0), | ||
|
@@ -67,49 +76,62 @@ static const RGB palette[] = { | |
RGB(204, 68, 204), RGB(153, 51, 153), RGB(255, 0, 127), RGB(204, 0, 102), | ||
RGB(153, 0, 76), RGB(255, 85, 170), RGB(204, 68, 136), RGB(153, 51, 102) | ||
}; | ||
static const u_int16_t palette_size = sizeof(palette)/sizeof(RGB); | ||
static const u_int16_t palette_size = sizeof(palette) / sizeof(RGB); | ||
|
||
|
||
// xor the color value at the given position with `color` | ||
static void matrix_xor( u_int16_t x, u_int16_t y, RGB color ){ | ||
|
||
RGB tmp = matrix_get(x, y); | ||
tmp.red = tmp.red ^ color.red; | ||
tmp.green = tmp.green ^ color.green; | ||
tmp.blue = tmp.blue ^ color.blue; | ||
tmp.alpha = color.alpha; | ||
|
||
matrix_set(x, y, tmp); | ||
|
||
|
||
// printf("%i, %i, %i, %i\n", tmp.red, tmp.green, tmp.blue, tmp.alpha); | ||
|
||
} | ||
|
||
static void reinit_circle(Circle *c){ | ||
c->x = rand()%(xmax/2) + xmax/4; | ||
c->y = rand()%(ymax/2) + ymax/4; | ||
static void check_or_reinit(Circle *c); | ||
// reinitializes a circle given by the pointer `c` | ||
static void reinit_circle( Circle *c ){ | ||
|
||
c->x = rand()%(xmax); | ||
c->y = rand()%(ymax); | ||
c->lt = rand() % (( xmax > ymax ? xmax : ymax ) / 4) + 2; | ||
c->r = 1; | ||
// check if the coosen circle is valid | ||
check_or_reinit(c); | ||
} | ||
|
||
// checks if th circle given by pointer `c` fits inside matrix else it calls `reinit_circle` | ||
static void check_or_reinit(Circle *c){ | ||
|
||
if( !(xmax > c->x + c->r) || | ||
!(c->x >= c->r) || | ||
!(ymax > c->y + c->r) || | ||
!(c->y >= c->r) | ||
!(c->y >= c->r) || | ||
!(c->lt > c->r) | ||
) | ||
{ | ||
reinit_circle(c); | ||
check_or_reinit(c); | ||
} | ||
} | ||
|
||
static void xor_circle(Circle *c, u_int16_t color_id) { | ||
|
||
// draws the circle `c` by using xor and a given `color_id` | ||
// `color_id` maps to the `palette` | ||
static void xor_circle(Circle *c, u_int16_t color_id){ | ||
|
||
// randomly but consistently choose a color | ||
RGB color = palette[(color_id * rs1 + rs2) % palette_size]; | ||
|
||
// asserts so we do not over or underflow | ||
assert(xmax > c->x + c->r); | ||
assert(c->x >= c->r); | ||
|
||
assert(ymax > c->y + c->r); | ||
assert(c->y >= c->r); | ||
|
||
// here comes the magic | ||
const u_int16_t cr2 = c->r+c->r; | ||
|
||
int16_t x = c->r; | ||
|
@@ -118,18 +140,16 @@ static void xor_circle(Circle *c, u_int16_t color_id) { | |
int16_t dx = cr2+cr2 - 4; | ||
int16_t d = cr2 - 1; | ||
|
||
while(y <= x){ | ||
matrix_xor( (c->y - y), (c->x - x), color); | ||
matrix_xor( (c->y - y), (c->x + x), color); | ||
matrix_xor( (c->y + y), (c->x - x), color); | ||
matrix_xor( (c->y + y), (c->x + x), color); | ||
|
||
while(y <= x) | ||
{ | ||
matrix_xor( (c->y - y), (c->x- x), palette[color_id%palette_size]); | ||
matrix_xor( (c->y - y), (c->x + x), palette[color_id%palette_size]); | ||
matrix_xor( (c->y + y), (c->x - x), palette[color_id%palette_size]); | ||
matrix_xor( (c->y + y), (c->x + x), palette[color_id%palette_size]); | ||
|
||
matrix_xor( (c->y - x), (c->x - y), palette[color_id%palette_size]); | ||
matrix_xor( (c->y - x), (c->x + y), palette[color_id%palette_size]); | ||
matrix_xor( (c->y + x), (c->x - y), palette[color_id%palette_size]); | ||
matrix_xor( (c->y + x), (c->x + y), palette[color_id%palette_size]); | ||
matrix_xor( (c->y - x), (c->x - y), color); | ||
matrix_xor( (c->y - x), (c->x + y), color); | ||
matrix_xor( (c->y + x), (c->x - y), color); | ||
matrix_xor( (c->y + x), (c->x + y), color); | ||
|
||
d += dy; | ||
dy -= 4; | ||
|
@@ -141,7 +161,7 @@ static void xor_circle(Circle *c, u_int16_t color_id) { | |
dx -= 4; | ||
--x; | ||
} | ||
#else | ||
#else // why not make it branchless | ||
int Mask = (d >> 31); | ||
d += dx & Mask; | ||
dx -= -4 & Mask; | ||
|
@@ -150,59 +170,68 @@ static void xor_circle(Circle *c, u_int16_t color_id) { | |
} | ||
} | ||
|
||
int init(int moduleno, char* argstr) | ||
{ | ||
xmax = matrix_getx(); | ||
ymax = matrix_gety(); | ||
|
||
for( u_int16_t x = 0; x < xmax; x++){ | ||
// effect reset and initialisation | ||
static void my_init(){ | ||
|
||
for( u_int16_t y = 0; y < ymax; y++){ | ||
matrix_set(x,y, black); | ||
rs1 = rand() % 65536; | ||
rs2 = rand() % 65536; | ||
|
||
// sometimes draw the circles on top of old effect | ||
if( rand() % 3 ) matrix_clear(); | ||
else { | ||
static RGB tmp; | ||
for(u_int16_t x = 0; x < xmax; x++){ | ||
for(u_int16_t y = 0; y < ymax; y++){ | ||
tmp = matrix_get(x, y); | ||
matrix_set(x, y, RGB(tmp.red/2, tmp.green/2, tmp.blue/2)); | ||
} | ||
} | ||
} | ||
|
||
for( u_int16_t i = 0; i < P_MAX; i++ ){ | ||
reinit_circle(&points[i]); | ||
xor_circle(&points[i], i); | ||
// initialize the circles | ||
reinit_circle(&circles[i]); | ||
// darw the first circles | ||
xor_circle(&circles[i], i); | ||
} | ||
} | ||
|
||
int init(int moduleno, char* argstr){ | ||
|
||
xmax = matrix_getx(); | ||
ymax = matrix_gety(); | ||
|
||
my_init(); | ||
|
||
modno = moduleno; | ||
frame = 0; | ||
|
||
return 0; | ||
} | ||
|
||
void reset(int _modno) | ||
{ | ||
|
||
for( u_int16_t x = 0; x < xmax; x++){ | ||
|
||
for( u_int16_t y = 0; y < ymax; y++){ | ||
matrix_set(x,y, black); | ||
} | ||
} | ||
|
||
for( u_int16_t i = 0; i < P_MAX; i++ ){ | ||
reinit_circle(&points[i]); | ||
xor_circle(&points[i], i); | ||
} | ||
void reset(int _modno) { | ||
|
||
my_init(); | ||
|
||
nexttick = udate(); | ||
frame = 0; | ||
} | ||
|
||
int draw(int _modno, int argc, char* argv[]) | ||
{ | ||
int draw(int _modno, int argc, char* argv[]){ | ||
|
||
// slow the effect down a bit | ||
if (frame % 2 == 0){ | ||
|
||
for (u_int16_t i = 0; i < P_MAX; ++i) { | ||
xor_circle(&points[i], i); | ||
points[i].r += 1; | ||
check_or_reinit(&points[i]); | ||
xor_circle(&points[i], i); | ||
for (u_int16_t i = 0; i < P_MAX; ++i){ | ||
// delete old trace | ||
xor_circle(&circles[i], i); | ||
// increase the radius of current circle | ||
circles[i].r += 1; | ||
// check if circle still valid | ||
check_or_reinit(&circles[i]); | ||
// paint new circle | ||
xor_circle(&circles[i], i); | ||
} | ||
} | ||
|
||
|