#include <xtd/threading/thread>
#include <xtd/console>
#include <xtd/is>
#include <xtd/random>
#include <xtd/startup>
#include <memory>
 
 
namespace console_firework_example {
  public:
    firework(
int x, 
int y, 
console_color color, 
int delay_) : x_(x), y_(y), color_(color), delay_(delay_) {}
 
    firework(const firework& firework) : x_(firework.x_), y_(firework.y_), color_(firework.color_), delay_(firework.delay_) {}
    
    int delay() {return delay_;}
    
    virtual void paint() const = 0;
    
  protected:
    static void write(int x, int y, const string& str) {
      console::set_cursor_position(x, y);
      console::write(str);
    }
    
    int x_ = 0;
    int y_ = 0;
    int delay_ = 0;
  };
  
  class firework_start : public firework {
  public:
    firework_start(
int x, 
int y, 
console_color color, 
int speed) : console_firework_example::firework(x, y, color, speed) {}
 
    explicit firework_start(const firework& firework) : console_firework_example::firework(firework) {}
    
    void paint() const override {
      console::foreground_color(color_);
      write(x_, y_, "+");
    }
  };
  
  class firework_exploded : public firework {
  public:
    firework_exploded(
int x, 
int y, 
console_color color, 
int speed) : console_firework_example::firework(x, y, color, speed) {}
 
    explicit firework_exploded(const firework& firework) : console_firework_example::firework(firework) {}
    
    void paint() const override {
      console::foreground_color(color_);
      write(x_ - 1, y_ - 1, " - ");
      write(x_ - 1, y_, "-+-");
      write(x_ - 1, y_ + 1, " - ");
    }
  };
  
  class firework_start_expanded1 : public firework {
  public:
    firework_start_expanded1(
int x, 
int y, 
console_color color, 
int speed) : console_firework_example::firework(x, y, color, speed) {}
 
    explicit firework_start_expanded1(const firework& firework) : console_firework_example::firework(firework) {}
    
    void paint() const override {
      console::foreground_color(color_);
      write(x_ - 2, y_ - 2, " --- ");
      write(x_ - 2, y_ - 1, "-+++-");
      write(x_ - 2, y_, "-+#+-");
      write(x_ - 2, y_ + 1, "-+++-");
      write(x_ - 2, y_ + 2, " --- ");
    }
  };
  
  class firework_start_expanded2 : public firework {
  public:
    firework_start_expanded2(
int x, 
int y, 
console_color color, 
int speed) : console_firework_example::firework(x, y, color, speed) {}
 
    explicit firework_start_expanded2(const firework& firework) : console_firework_example::firework(firework) {}
    
    void paint() const override {
      console::foreground_color(color_);
      write(x_ - 2, y_ - 2, " +++ ");
      write(x_ - 2, y_ - 1, "++#++");
      write(x_ - 2, y_, "-# #-");
      write(x_ - 2, y_ + 1, "++#++");
      write(x_ - 2, y_ + 2, " +++ ");
    }
  };
  
  class firework_start_expanded3 : public firework {
  public:
    firework_start_expanded3(
int x, 
int y, 
console_color color, 
int speed) : console_firework_example::firework(x, y, color, speed) {}
 
    explicit firework_start_expanded3(const firework& firework) : console_firework_example::firework(firework) {}
    
    void paint() const override {
      console::foreground_color(color_);
      write(x_ - 2, y_ - 2, "  #  ");
      write(x_ - 2, y_ - 1, "## ##");
      write(x_ - 2, y_, "#   #");
      write(x_ - 2, y_ + 1, "## ##");
      write(x_ - 2, y_ + 2, "  #  ");
    }
  };
  
  class firework_start_expanded4 : public firework {
  public:
    firework_start_expanded4(
int x, 
int y, 
console_color color, 
int speed) : console_firework_example::firework(x, y, color, speed) {}
 
    explicit firework_start_expanded4(const firework& firework) : console_firework_example::firework(firework) {}
    
    void paint() const override {
      console::foreground_color(color_);
      write(x_ - 2, y_ - 2, " # # ");
      write(x_ - 2, y_ - 1, "#   #");
      write(x_ - 2, y_, "     ");
      write(x_ - 2, y_ + 1, "#   #");
      write(x_ - 2, y_ + 2, " # # ");
    }
  };
  
  class firework_end : public firework {
  public:
    firework_end(
int x, 
int y, 
console_color color, 
int speed) : console_firework_example::firework(x, y, color, speed) {}
 
    explicit firework_end(const firework& firework) : console_firework_example::firework(firework) {}
    
    void paint() const override {
      console::foreground_color(color_);
      write(x_ - 2, y_ - 2, "     ");
      write(x_ - 2, y_ - 1, "     ");
      write(x_ - 2, y_, "     ");
      write(x_ - 2, y_ + 1, "     ");
      write(x_ - 2, y_ + 2, "     ");
    }
  };
  
  public:
    static void main() {
      console::write_line("Adjuste window size and pres any key when ready to start...");
      auto console_height = console::window_height();
      auto console_width = console::window_width();
      console::read_key(false);
      console::cursor_visible(false);
      console::clear();
      
      auto fireworks = std::list<ptr<firework>> {};
      auto colors = 
list {console_color::blue, console_color::green, console_color::cyan, console_color::red, console_color::magenta, console_color::yellow, console_color::white};
 
      
      while (!console::key_available()) {
        fireworks.
push_back(new_ptr<firework_start>(rand.next(2, console_width - 2), rand.next(2, console_height - 2), colors[rand.next(colors.size())], rand.next(1, 5)));
 
        
        for (auto& firework : fireworks) {
          if (is<firework_end>(firework)) fireworks_to_removed.
push_back(firework);
 
          explode(firework);
        }
        
        for (auto& firework : fireworks_to_removed)
          fireworks.remove(firework);
        
        threading::thread::sleep(100_ms);
      }
      
      console::reset_color();
      console::clear();
      console::cursor_visible(true);
    }
 
  private:
      firework->paint();
      if (is<firework_start_expanded4>(firework)) firework = new_ptr<firework_end>(*firework);
      if (is<firework_start_expanded3>(firework)) firework = new_ptr<firework_start_expanded4>(*firework);
      if (is<firework_start_expanded2>(firework)) firework = new_ptr<firework_start_expanded3>(*firework);
      if (is<firework_start_expanded1>(firework)) firework = new_ptr<firework_start_expanded2>(*firework);
      if (is<firework_exploded>(firework)) firework = new_ptr<firework_start_expanded1>(*firework);
      if (date_time::now().
ticks() % firework->delay() == 0 && is<firework_start>(firework)) firework = new_ptr<firework_exploded>(*firework);
 
    }
  };
}
 
startup_(console_firework_example::program::main);
 
 
Represents a strongly typed list of objects that can be accessed by index. Provides methods to search...
Definition list.hpp:71
 
virtual void push_back(const type_t &value)
Appends the given element value to the end of the container.
Definition list.hpp:778
 
Represents a pseudo-random number generator, a device that produces a sequence of numbers that meet c...
Definition random.hpp:40
 
#define static_
This keyword is use to represent a static object. A static object can't be instantiated (constructors...
Definition static.hpp:37
 
#define startup_(main_method)
Defines the entry point to be called when the application loads. Generally this is set either to the ...
Definition startup.hpp:175
 
#define abstract_
This keyword is used to represents an abstract class.
Definition abstract.hpp:25
 
xtd::sptr< type_t > ptr
The xtd::ptr object is a shared pointer.
Definition ptr.hpp:27
 
std::chrono::duration< int64, tick > ticks
Represents a tick duration.
Definition ticks.hpp:21
 
console_color
Specifies constants that define foreground and background colors for the console.
Definition console_color.hpp:20
 
The xtd::collections::generic namespace contains interfaces and classes that define generic collectio...
Definition comparer.hpp:15
 
The xtd namespace contains all fundamental classes to access Hardware, Os, System,...
Definition xtd_about_box.hpp:10