|
// ring.c, a rotating ring |
|
// Written by Yu-Jie Lin |
|
// |
|
// This is free and unencumbered software released into the public domain. |
|
// |
|
// Anyone is free to copy, modify, publish, use, compile, sell, or |
|
// distribute this software, either in source code form or as a compiled |
|
// binary, for any purpose, commercial or non-commercial, and by any |
|
// means. |
|
// |
|
// In jurisdictions that recognize copyright laws, the author or authors |
|
// of this software dedicate any and all copyright interest in the |
|
// software to the public domain. We make this dedication for the benefit |
|
// of the public at large and to the detriment of our heirs and |
|
// successors. We intend this dedication to be an overt act of |
|
// relinquishment in perpetuity of all present and future rights to this |
|
// software under copyright law. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
|
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|
// OTHER DEALINGS IN THE SOFTWARE. |
|
// |
|
// For more information, please refer to <http://unlicense.org/> |
|
|
|
#include <curses.h> |
|
#include <math.h> |
|
#include <signal.h> |
|
#include <stdlib.h> |
|
#include <time.h> |
|
|
|
|
|
#define M_2PI (2 * M_PI) |
|
#define SCALE_X (2) |
|
|
|
|
|
double R, STEP_A; |
|
int SCREEN_H, SCREEN_W; |
|
int CENTER_X, CENTER_Y; |
|
|
|
|
|
void signal_handler(int sig); |
|
void cleanup(void); |
|
void resize(void); |
|
|
|
|
|
int |
|
main(void) |
|
{ |
|
signal(SIGINT, signal_handler); |
|
|
|
initscr(); |
|
keypad(stdscr, TRUE); |
|
nonl(); |
|
cbreak(); |
|
noecho(); |
|
timeout(0); |
|
curs_set(0); |
|
|
|
if (has_colors()) |
|
{ |
|
start_color(); |
|
|
|
for (int i = 0; i < 24; i++) |
|
{ |
|
init_pair(i + 1, 232 + i, COLOR_BLACK); |
|
} |
|
} |
|
|
|
resize(); |
|
|
|
bool do_clear = TRUE; |
|
bool do_sweep = TRUE; |
|
bool inward = TRUE; |
|
double r = 0.5; |
|
double a = 0; |
|
|
|
struct timespec req = { |
|
.tv_sec = 0, |
|
.tv_nsec = 50000000 |
|
}; |
|
|
|
while (TRUE) |
|
{ |
|
int c = getch(); |
|
switch (c) |
|
{ |
|
case KEY_RESIZE: |
|
resize(); |
|
break; |
|
case 'c': |
|
do_clear = !do_clear; |
|
break; |
|
case 's': |
|
do_sweep = !do_sweep; |
|
break; |
|
case 'a': |
|
case 'z': |
|
if (!do_sweep) |
|
{ |
|
r += ((c == 'a') ? 1 : -1) / R / SCALE_X; |
|
} |
|
break; |
|
case 'q': |
|
case 'Q': |
|
cleanup(); |
|
return EXIT_SUCCESS; |
|
} |
|
|
|
if (do_clear) |
|
{ |
|
erase(); |
|
} |
|
|
|
for (double i = 0; i < M_2PI; i += STEP_A) |
|
{ |
|
double y, x; |
|
|
|
y = r * sin(a + i) * R; |
|
x = r * cos(a + i) * R; |
|
|
|
y = CENTER_Y - y; |
|
x = CENTER_X + x * SCALE_X; |
|
|
|
attrset(COLOR_PAIR(1 + (int) (i / M_2PI * 360) % 24)); |
|
mvaddch(y, x, '*'); |
|
} |
|
|
|
a += STEP_A; |
|
if (do_sweep) |
|
{ |
|
r += (inward ? -1 : 1) / R / SCALE_X; |
|
if (r <= 0) |
|
{ |
|
r = 0; |
|
inward = !inward; |
|
} |
|
else if (r >= 0.5) |
|
{ |
|
r = 0.5; |
|
inward = !inward; |
|
} |
|
} |
|
|
|
nanosleep(&req, NULL); |
|
} |
|
} |
|
|
|
|
|
void |
|
signal_handler(int sig) |
|
{ |
|
cleanup(); |
|
|
|
signal(sig, SIG_DFL); |
|
raise(sig); |
|
} |
|
|
|
|
|
void |
|
cleanup(void) |
|
{ |
|
endwin(); |
|
} |
|
|
|
|
|
void |
|
resize(void) |
|
{ |
|
getmaxyx(stdscr, SCREEN_H, SCREEN_W); |
|
R = sqrt(pow(SCREEN_H / 2, 2) + pow(SCREEN_W / 2 / SCALE_X, 2)); |
|
CENTER_X = SCREEN_W / 2; |
|
CENTER_Y = SCREEN_H / 2; |
|
STEP_A = tan((double) 1 / (CENTER_X / SCALE_X)); |
|
|
|
clear(); |
|
} |