1 | // SuperTux |
2 | // Copyright (C) 2006 Matthias Braun <matze@braunis.de> |
3 | // |
4 | // This program is free software: you can redistribute it and/or modify |
5 | // it under the terms of the GNU General Public License as published by |
6 | // the Free Software Foundation, either version 3 of the License, or |
7 | // (at your option) any later version. |
8 | // |
9 | // This program is distributed in the hope that it will be useful, |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | // GNU General Public License for more details. |
13 | // |
14 | // You should have received a copy of the GNU General Public License |
15 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | |
17 | #include "object/particles.hpp" |
18 | |
19 | #include <math.h> |
20 | |
21 | #include "math/random.hpp" |
22 | #include "math/util.hpp" |
23 | #include "object/camera.hpp" |
24 | #include "supertux/sector.hpp" |
25 | #include "video/drawing_context.hpp" |
26 | #include "video/video_system.hpp" |
27 | #include "video/viewport.hpp" |
28 | |
29 | //TODO: remove this function in favor of the one below |
30 | Particles::Particles(const Vector& epicenter, int min_angle, int max_angle, |
31 | const Vector& initial_velocity, const Vector& acceleration, int number, |
32 | Color color_, int size_, float life_time, int drawing_layer_) : |
33 | accel(acceleration), |
34 | timer(), |
35 | live_forever(), |
36 | color(color_), |
37 | size(static_cast<float>(size_)), |
38 | drawing_layer(drawing_layer_), |
39 | particles() |
40 | { |
41 | if (life_time == 0) { |
42 | live_forever = true; |
43 | } else { |
44 | live_forever = false; |
45 | timer.start(life_time); |
46 | } |
47 | |
48 | // create particles |
49 | for (int p = 0; p < number; p++) |
50 | { |
51 | auto particle = std::make_unique<Particle>(); |
52 | particle->pos = epicenter; |
53 | |
54 | float angle = math::radians(graphicsRandom.randf(static_cast<float>(min_angle), static_cast<float>(max_angle))); |
55 | particle->vel.x = /*fabs*/(sinf(angle)) * initial_velocity.x; |
56 | // if(angle >= math::PI && angle < math::TAU) |
57 | // particle->vel.x *= -1; // work around to fix signal |
58 | particle->vel.y = /*fabs*/(cosf(angle)) * initial_velocity.y; |
59 | // if(angle >= math::PI_2 && angle < 3*math::PI_2) |
60 | // particle->vel.y *= -1; |
61 | |
62 | particles.push_back(std::move(particle)); |
63 | } |
64 | } |
65 | |
66 | Particles::Particles(const Vector& epicenter, int min_angle, int max_angle, |
67 | const float min_initial_velocity, const float max_initial_velocity, |
68 | const Vector& acceleration, int number, Color color_, |
69 | int size_, float life_time, int drawing_layer_) : |
70 | |
71 | accel(acceleration), |
72 | timer(), |
73 | live_forever(), |
74 | color(color_), |
75 | size(static_cast<float>(size_)), |
76 | drawing_layer(drawing_layer_), |
77 | particles() |
78 | { |
79 | if (life_time == 0) { |
80 | live_forever = true; |
81 | } else { |
82 | live_forever = false; |
83 | timer.start(life_time); |
84 | } |
85 | |
86 | // create particles |
87 | for (int p = 0; p < number; p++) |
88 | { |
89 | auto particle = std::make_unique<Particle>(); |
90 | particle->pos = epicenter; |
91 | |
92 | float velocity = (min_initial_velocity == max_initial_velocity) ? min_initial_velocity : |
93 | graphicsRandom.randf(min_initial_velocity, max_initial_velocity); |
94 | float angle = (min_angle == max_angle) ? |
95 | math::radians(static_cast<float>(min_angle)) : |
96 | math::radians(graphicsRandom.randf(static_cast<float>(min_angle), static_cast<float>(max_angle))); |
97 | // Note that angle defined as clockwise from vertical (up is zero degrees, right is 90 degrees) |
98 | particle->vel.x = (sinf(angle)) * velocity; |
99 | particle->vel.y = (-cosf(angle)) * velocity; |
100 | |
101 | particles.push_back(std::move(particle)); |
102 | } |
103 | } |
104 | |
105 | void |
106 | Particles::update(float dt_sec) |
107 | { |
108 | Vector camera = Sector::get().get_camera().get_translation(); |
109 | |
110 | // update particles |
111 | for (auto i = particles.begin(); i != particles.end(); ) { |
112 | (*i)->pos.x += (*i)->vel.x * dt_sec; |
113 | (*i)->pos.y += (*i)->vel.y * dt_sec; |
114 | |
115 | (*i)->vel.x += accel.x * dt_sec; |
116 | (*i)->vel.y += accel.y * dt_sec; |
117 | |
118 | if ((*i)->pos.x < camera.x || (*i)->pos.x > static_cast<float>(SCREEN_WIDTH) + camera.x || |
119 | (*i)->pos.y < camera.y || (*i)->pos.y > static_cast<float>(SCREEN_HEIGHT) + camera.y) { |
120 | i = particles.erase(i); |
121 | } else { |
122 | ++i; |
123 | } |
124 | } |
125 | |
126 | if ((timer.check() && !live_forever) || particles.size() == 0) |
127 | remove_me(); |
128 | } |
129 | |
130 | void |
131 | Particles::draw(DrawingContext& context) |
132 | { |
133 | // draw particles |
134 | for (auto& particle : particles) { |
135 | context.color().draw_filled_rect(Rectf(particle->pos, Sizef(size,size)), color, drawing_layer); |
136 | } |
137 | } |
138 | |
139 | /* EOF */ |
140 | |