nsnake
Classic snake game for the terminal
AnimationFire.cpp
1 #include <Display/Animations/AnimationFire.hpp>
2 #include <Engine/Graphics/Colors.hpp>
3 #include <Engine/Helpers/Utils.hpp>
4 
5 static ColorPair red = Colors::pair("red", "default");
6 static ColorPair redBold = Colors::pair("red", "default", true);
7 static ColorPair white;
8 static ColorPair yellow = Colors::pair("yellow", "default");
9 static ColorPair yellowBold = Colors::pair("yellow", "default", true);
10 
11 // An ASCII gray scale :)
12 // Characters will be accessed proportionally to the intensity
13 // int gray_scale_size = 70;
14 // char gray_scale[71] = ".\'`^\",:;Il!i><~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$ ";
15 
16 static int gray_scale_size = 12;
17 static char gray_scale[13] = " .':-=+*#%@#";
18 
19 AnimationFire::AnimationFire(Window* window):
20  Animation(window),
21  particle(NULL)
22 { }
23 AnimationFire::~AnimationFire()
24 {
25  SAFE_DELETE(particle);
26 }
27 void AnimationFire::load()
28 {
29  unsigned int width = window->getW();
30  unsigned int height = window->getH();
31 
32  particle = new Array2D<ParticleFire>(width, height);
33 
34  // Creating the cooling map
35  coolingMap = new Array2D<int>(width, height);
36 
37  for (unsigned int i = 0; i < width; i++)
38  for (unsigned int j = 0; j < height; j++)
39  coolingMap->set(i, j, Utils::Random::between(INTENSITY_MIN,
40  INTENSITY_PERCENT(13)));
41 
42  // Will smooth the cooling map a number of times
43  for (int n = 0; n < 10; n++)
44  for (unsigned int i = 1; i < width-1; i++)
45  for (unsigned int j = 1; j < height-1; j++)
46  coolingMap->set(i, j, (coolingMap->at(i-1, j) +
47  coolingMap->at(i+1, j) +
48  coolingMap->at(i, j+1) +
49  coolingMap->at(i, j-1)) / 4);
50 
51  timer.start();
52 }
53 void AnimationFire::update()
54 {
55  // Updating only at the right time!
56  if (timer.delta_ms() < 100)
57  return;
58 
59  // How fast the fire cools down each frame
60  int cooling_ratio = Utils::Random::between(INTENSITY_PERCENT(3),
61  INTENSITY_PERCENT(12));
62 
63  // Slim chance of a sudden burst or dim of the fire
64  bool burst = Utils::Random::booleanWithChance(0.10);
65  bool dim = Utils::Random::booleanWithChance(0.12);
66  if (burst) cooling_ratio = INTENSITY_PERCENT(1);
67  if (dim) cooling_ratio = INTENSITY_PERCENT(30);
68 
69  // Spawning high-intensity flames on the bottom particles
70  for (unsigned int i = 0; i < (particle->width()); i++)
71  particle->set(i, particle->height() - 1, ParticleFire(Utils::Random::between(INTENSITY_PERCENT(90), INTENSITY_MAX)));
72 
73  // Randomly adding Sparks - high-intensity flames little higher
74  for (unsigned int i = 0; i < (particle->width()); i++)
75  {
76  if (Utils::Random::booleanWithChance(2.31))
77  {
78  int height = particle->height() - Utils::Random::between(3, 6);
79 
80  particle->set(i, height, ParticleFire(Utils::Random::between(INTENSITY_PERCENT(90), INTENSITY_MAX)));
81  }
82  }
83 
84  // Making all particles climb up
85  for (unsigned int i = 0; i < (particle->width()); i++)
86  {
87  for (unsigned int j = 0; j < (particle->height()-1); j++)
88  {
89  // Cooling all particles based on the ones below
90  particle->set(i, j, ParticleFire(particle->at(i, j + 1).intensity - cooling_ratio));
91 
92  // Cooling based on the cooling map
93  particle->set(i, j, ParticleFire(particle->at(i, j).intensity - coolingMap->at(i, j)));
94  }
95  }
96 
97  timer.start();
98 }
99 void AnimationFire::draw()
100 {
101  for (unsigned int i = 0; i < (particle->width()); i++)
102  {
103  for (unsigned int j = 0; j < (particle->height()); j++)
104  {
105  int c = ' ';
106  ColorPair p = white;
107  int s = particle->at(i, j).intensity;
108 
109  if (s > INTENSITY_PERCENT(90))
110  p = white;
111 
112  else if (s > INTENSITY_PERCENT(80))
113  p = yellowBold;
114 
115  else if (s > INTENSITY_PERCENT(70))
116  p = yellowBold;
117 
118  else if (s > INTENSITY_PERCENT(60))
119  p = yellow;
120 
121  else if (s > INTENSITY_PERCENT(50))
122  p = redBold;
123 
124  else if (s > INTENSITY_PERCENT(40))
125  p = redBold;
126 
127  else if (s > INTENSITY_PERCENT(30))
128  p = red;
129 
130  else if (s > INTENSITY_PERCENT(20))
131  p = red;
132 
133  else
134  continue; // Too low intensity
135 
136 
137  if ((s > INTENSITY_MAX) || (s < INTENSITY_MIN))
138  continue;
139 
140  else
141  c = gray_scale[(s - INTENSITY_MIN) * (gray_scale_size-1)/INTENSITY_MAX];
142 
143  window->printChar(c, i, j, p);
144  }
145  }
146 }
147 
A single particle inside the whole fire.