123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- #include "starfield.h"
- #include "utils.h"
- Starfield::Starfield(door::Door &Door, std::mt19937 &Rng)
- : door{Door}, rng{Rng}, uni_x{1, Door.width}, uni_y{1, Door.height},
- white{door::COLOR::WHITE}, dark{door::COLOR::BLACK, door::ATTR::BRIGHT} {
-
-
- regenerate();
- }
- star_pos Starfield::make_pos(void) {
- star_pos pos;
- do {
- pos.x = uni_x(rng);
- pos.y = uni_y(rng);
- } while (sky.find(pos) != sky.end());
- return pos;
- }
- void Starfield::regenerate(void) {
- int mx = door.width;
- int my = door.height;
-
- sky.clear();
-
- int MAX_STARS = ((mx * my) / 40);
-
-
- for (int i = 0; i < MAX_STARS; i++) {
- star_pos pos = make_pos();
-
-
-
- pos.symbol = i % 2;
- pos.color = i % 5 < 2;
- sky.insert(pos);
- }
- }
- void Starfield::display(void) {
- door << door::reset << door::cls;
- stars[0] = ".";
- if (door::unicode) {
- stars[1] = "\u2219";
- } else {
- stars[1] = "\xf9";
- };
- int i = 0;
-
- star_pos last_pos;
- for (auto &pos : sky) {
- bool use_goto = true;
- if (i != 0) {
-
- if (pos.y == last_pos.y) {
-
- int dx = pos.x - last_pos.x;
- if (dx == 0) {
- use_goto = false;
- } else {
- if (dx < 5) {
- door << std::string(dx, ' ');
- use_goto = false;
- } else {
-
- door << "\x1b[" << dx << "C";
- use_goto = false;
- }
- }
- }
- }
- if (use_goto) {
- door::Goto star_at(pos.x, pos.y);
- door << star_at;
- }
- if (pos.color)
- door << dark;
- else
- door << white;
- if (pos.symbol)
- door << stars[0];
- else
- door << stars[1];
- ++i;
- last_pos = pos;
- last_pos.x++;
- }
- }
- AnimatedStarfield::AnimatedStarfield(door::Door &Door, std::mt19937 &Rng)
- : door{Door}, rng{Rng}, uni_x{1, Door.width}, uni_y{1, Door.height},
- white{door::COLOR::WHITE}, dark{door::COLOR::BLACK, door::ATTR::BRIGHT} {
- mx = door.width;
- my = door.height;
- cx = mx / 2.0;
- cy = my / 2.0;
- max_d = distance(0, 0);
-
-
- regenerate();
- }
- moving_star AnimatedStarfield::make_pos(bool centered) {
- moving_star pos;
- do {
- pos.x = uni_x(rng);
- pos.y = uni_y(rng);
- pos.visible = true;
- if (centered) {
- pos.x /= 4;
- pos.x += cx - (cx / 4);
- pos.y /= 4;
- pos.y += cy - (cy / 4);
- }
- pos.xpos = pos.x;
- pos.ypos = pos.y;
- pos.movex = pos.xpos - cx;
- pos.movey = pos.ypos - cy;
- double bigd = max(abs(pos.movex), abs(pos.movey));
- pos.movex /= bigd;
- pos.movey /= bigd;
- if (visible) {
- pos.visible = visible(pos.x, pos.y);
- }
- } while (centered and (pos.y == cy));
-
- return pos;
- }
- void AnimatedStarfield::regenerate(void) {
-
- sky.clear();
-
- int MAX_STARS = ((mx * my) / 40);
-
-
- for (int i = 0; i < MAX_STARS; i++) {
- moving_star pos = make_pos();
- pos.symbol = i % 2;
- pos.color = i % 5 < 2;
- sky.push_back(pos);
- }
- }
- void AnimatedStarfield::display(void) {
- door << door::reset << door::cls;
- stars[0] = ".";
- if (door::unicode) {
- stars[1] = "\u2219";
- } else {
- stars[1] = "\xf9";
- };
- for (auto &pos : sky) {
- if (pos.visible) {
- door::Goto star_at(pos.x, pos.y);
- door << star_at;
- if (pos.color)
- door << dark;
- else
- door << white;
- if (pos.symbol)
- door << stars[0];
- else
- door << stars[1];
- }
- }
- }
- void AnimatedStarfield::animate(void) {
- for (auto &star : sky) {
-
-
- double speed = max_d / distance(star.movex, star.movey);
- star.xpos += star.movex / (speed * (mx / my));
- star.ypos += star.movey / speed;
- int nx = int(star.xpos + 0.5);
- int ny = int(star.ypos + 0.5);
-
-
- while ((star.xpos < 1) or (star.xpos >= mx - 1) or (star.ypos < 1) or
- (star.ypos >= my - 1)) {
-
- moving_star new_pos = make_pos(true);
- nx = new_pos.x;
- ny = new_pos.y;
- star.xpos = new_pos.x;
- star.ypos = new_pos.y;
- star.movex = new_pos.movex;
- star.movey = new_pos.movey;
-
-
- }
-
- if ((star.x != nx) or (star.y != ny)) {
-
- if (star.visible) {
- door << door::Goto(star.x, star.y) << " ";
- };
- star.x = nx;
- star.y = ny;
- if (visible) {
- star.visible = visible(star.x, star.y);
- }
-
- if (star.visible) {
- door << door::Goto(star.x, star.y);
- if (star.color)
- door << dark;
- else
- door << white;
- if (star.symbol)
- door << stars[0];
- else
- door << stars[1];
- }
- }
- }
- }
- double AnimatedStarfield::distance(double x, double y) {
- return sqrt(((cx - x) * (cx - x)) + ((cy - y) * (cy - y)));
- }
- void AnimatedStarfield::setVisible(checkVisibleFunction cvf) { visible = cvf; }
|