Rev 2097 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
244 | jag | 1 | /* |
2 | * ball.cc |
||
2302 | jag | 3 | * DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath |
1713 | jag | 4 | * DIN Is Noise is released under GNU Public License 2.0 |
1822 | jag | 5 | * DIN Is Noise is released under GNU Public License 2.0 |
1479 | jag | 6 | * For more information, please visit https://dinisnoise.org/ |
244 | jag | 7 | */ |
8 | |||
81 | - | 9 | #include "mondrian.h" |
10 | #include "console.h" |
||
11 | #include "utils.h" |
||
12 | #include "vector2d.h" |
||
13 | #include <utility> |
||
395 | jag | 14 | |
127 | jag | 15 | using namespace std; |
81 | - | 16 | |
17 | extern mondrian mondrian0; |
||
1797 | jag | 18 | extern const float PI_BY_180; |
1822 | jag | 19 | extern const float TWO_PI; |
1756 | jag | 20 | extern int TRAILSIZE; |
81 | - | 21 | |
1756 | jag | 22 | ball::ball (int _type) : trail (TRAILSIZE) { |
478 | jag | 23 | init (_type); |
24 | } |
||
81 | - | 25 | |
26 | void ball::init (int _type) { |
||
1419 | jag | 27 | trig_what = NOTE; |
478 | jag | 28 | x = y = 0; |
29 | R = 0; |
||
81 | - | 30 | V = 0; |
31 | vx = vy = 0; |
||
478 | jag | 32 | vm = vm_1 = vm_inf = 0; |
81 | - | 33 | select = 0; |
34 | frozen = 1; |
||
35 | vol_mult = 1; |
||
36 | mod = 0; |
||
37 | attack_time = recent_attack_time; |
||
38 | decay_time = recent_decay_time; |
||
2001 | jag | 39 | pitch_mult = 1.0; // recent_pitch_mult; |
81 | - | 40 | num_notes = 0; |
41 | del = 0; |
||
42 | auto_rotate = 0; |
||
43 | dtheta = PI_BY_180; |
||
44 | set_type (_type); |
||
45 | ++ref; |
||
46 | } |
||
47 | |||
445 | jag | 48 | void ball::clone_this (ball* C) { |
437 | jag | 49 | |
50 | rnd<float> rd (0, TWO_PI); |
||
51 | float rad = rd (); |
||
445 | jag | 52 | C->x = x + op_clone.offset * cos (rad); |
53 | C->y = y + op_clone.offset * sin (rad); |
||
437 | jag | 54 | |
445 | jag | 55 | C->R = R; |
56 | C->R->balls.push_back (C); |
||
437 | jag | 57 | |
445 | jag | 58 | C->V = V; |
59 | C->vx = vx; |
||
60 | C->vy = vy; |
||
61 | C->vol_mult = vol_mult; |
||
62 | C->mod = mod; |
||
63 | C->attack_time = attack_time; |
||
64 | C->decay_time = decay_time; |
||
65 | C->pitch_mult = pitch_mult; |
||
66 | C->auto_rotate = auto_rotate; |
||
67 | C->dtheta = dtheta; |
||
68 | C->set_type (type); |
||
69 | C->op_turn = op_turn; |
||
70 | C->op_speed = op_speed; |
||
71 | C->op_teleport = op_teleport; |
||
72 | C->op_clone = op_clone; |
||
73 | C->op_clone.n = op_clone.max; |
||
441 | jag | 74 | if (op_clone.alarm.active) { |
459 | jag | 75 | if (op_clone.clone_can_clone) |
445 | jag | 76 | C->op_clone.alarm.start (); |
459 | jag | 77 | else |
445 | jag | 78 | C->op_clone.alarm.stop (); |
441 | jag | 79 | } |
490 | jag | 80 | C->op_transform = op_transform; |
445 | jag | 81 | C->frozen = frozen; |
474 | jag | 82 | C->trail = trail; |
1419 | jag | 83 | C->trig_what = trig_what; |
437 | jag | 84 | } |
85 | |||
81 | - | 86 | void ball::set_velocity (float dx, float dy) { |
87 | V = unit_vector (vx, vy, dx, dy); |
||
301 | jag | 88 | if (V == 0) V = unit_vector (vx, vy, 1.0f, 1.0f); |
1302 | jag | 89 | op_speed.max = max (op_speed.max, V); |
81 | - | 90 | calc_velocity_slope (); |
91 | } |
||
92 | |||
93 | void ball::rotate_velocity (int dir) { |
||
94 | rotate_vector (vx, vy, dir * dtheta); |
||
95 | calc_velocity_slope (); |
||
96 | } |
||
97 | |||
98 | void ball::calc_velocity_slope () { |
||
99 | if (vx != 0) { |
||
100 | vm = vy * 1.0f / vx; |
||
101 | vm_1 = 1.0f / vm; |
||
102 | vm_inf = 0; |
||
103 | } else { |
||
104 | vm = 0.0f; |
||
105 | vm_1 = 0.0f; |
||
106 | vm_inf = 1; |
||
107 | } |
||
108 | } |
||
109 | |||
127 | jag | 110 | void ball::on_edge_hit (int e1, int e2, int cl, float& v, float xry, float yrx, float elb, float ewh, pair<float, float>& invl, int& eh) { |
111 | eh = 1; |
||
112 | int walle [] = {e1, 0, e2}; |
||
113 | slit* S = 0; |
||
114 | rect* RO = get_other_rect_of_slit (R, walle[cl+1], xry, &S); |
||
115 | if (RO) { // ball in slit |
||
116 | eh = 0; // edge hit didnt happen |
||
117 | if (type == HEALER) mondrian0.remove_slit (S); // close slit |
||
118 | R->erase (this); |
||
119 | R = RO; // ball is now in other box |
||
120 | R->balls.push_back (this); |
||
121 | } else { // ball hit edge |
||
122 | if (type == WRECKER) { |
||
123 | if (mondrian0.slitting == mondrian::ANIMATE_SLIT) { |
||
124 | mondrian0.fdr.restart (); |
||
125 | mondrian0.add_remove_slit (x, y, &mondrian0.fdr); // make animated slit |
||
126 | } |
||
127 | else |
||
128 | mondrian0.add_remove_slit (x, y); // make slit |
||
129 | } |
||
130 | v = -v; // flip component of velocity to rebound |
||
1310 | jag | 131 | if (op_turn.alarm.active) op_turn.start (this); |
127 | jag | 132 | calc_velocity_slope (); |
133 | float xy, t0, dt; |
||
134 | xy = yrx; |
||
135 | t0 = elb; |
||
136 | dt = ewh; |
||
137 | mondrian0.launch_note (this, xy, t0, dt, invl); |
||
138 | } |
||
139 | } |
||
140 | |||
81 | - | 141 | void ball::update () { |
142 | |||
143 | int edge_hit = 0; |
||
144 | |||
243 | jag | 145 | trail.add (x, y); |
146 | |||
81 | - | 147 | if (!frozen) { |
148 | |||
313 | jag | 149 | float px = x, py = y; |
81 | - | 150 | |
151 | // move the ball by a constant speed we found when user made the ball |
||
152 | x += (V * vx); |
||
153 | y += (V * vy); |
||
313 | jag | 154 | |
81 | - | 155 | box<float>& e = R->extents; // get the box the ball is bouncing in |
156 | box<float>& eroot = mondrian0.root->extents; // get the root box |
||
127 | jag | 157 | |
81 | - | 158 | // check if the ball is still inside this box after move |
159 | if (inbox (e, x, y)) { |
||
160 | // ball is still inside the box so theres nothing to do |
||
161 | } else { // ball has hit a wall or ceiling of box |
||
313 | jag | 162 | check: |
81 | - | 163 | int clx = clamp<float> (e.left, x, e.right); |
164 | if (clx) { // hit wall |
||
165 | if (vm_inf == 0) y = py + vm * (x - px); else y = py; |
||
313 | jag | 166 | float yb4 = y; |
167 | if (clamp (e.bottom, y, e.top)) { // below floor or above ceiling |
||
168 | y = yb4; |
||
169 | goto check; |
||
301 | jag | 170 | } |
127 | jag | 171 | on_edge_hit (edge::LEFT, edge::RIGHT, clx, vx, y, x, eroot.left, eroot.width_1, R->vint, edge_hit); |
81 | - | 172 | } else { |
173 | int cly = clamp<float> (e.bottom, y, e.top); |
||
127 | jag | 174 | if (cly) { // hit floor or ceiling |
81 | - | 175 | if (vm_inf == 0) x = px + vm_1 * (y - py); else x = px; |
127 | jag | 176 | on_edge_hit (edge::BOTTOM, edge::TOP, cly, vy, x, y, eroot.bottom, eroot.height_1, R->hint, edge_hit); |
81 | - | 177 | } |
178 | } |
||
179 | } |
||
180 | } |
||
181 | if (auto_rotate && !edge_hit) rotate_velocity (auto_rotate); // auto_rotate = -1 is clockwise; auto_rotate = 1 is anti-clockwise |
||
182 | } |
||
183 | |||
184 | |||
185 | void ball::set_type (int T) { |
||
186 | type = T; |
||
187 | switch (type) { |
||
188 | case ball::BOUNCER: |
||
189 | color_using_modulation (); |
||
190 | break; |
||
191 | case ball::WRECKER: |
||
192 | r = 1.0f; g = 0.25f; b = 0.25f; |
||
193 | break; |
||
194 | case ball::HEALER: |
||
195 | r = 0.0f; g = 1.0f; b = 1.0f; |
||
196 | } |
||
197 | } |
||
198 | |||
199 | void ball::color_using_modulation () { |
||
200 | if (type != ball::BOUNCER) return; |
||
1546 | jag | 201 | if (mod < 1) { |
131 | jag | 202 | r = g = b = 0.15f; |
1546 | jag | 203 | } else if (mod > 1) { |
81 | - | 204 | r = g = b = 1.0f; |
205 | } else { |
||
131 | jag | 206 | r = g = b = 0.60f; |
81 | - | 207 | } |
208 | } |
||
335 | jag | 209 | |
210 | void ball::print () { |
||
211 | extern char BUFFER []; |
||
1994 | jag | 212 | sprintf (BUFFER, "type = %s > %s, attack = %0.3f s, decay = %0.3f s, modulation = %0.3f", types_str [type], trigstr [trig_what], attack_time, decay_time, pitch_mult); |
335 | jag | 213 | cons << BUFFER << eol; |
214 | } |
||
395 | jag | 215 | |
216 | void ball::eval_ops () { |
||
490 | jag | 217 | ball_op* ops [ball_op::NUM_OPS] = {&op_turn, &op_speed, &op_teleport, &op_clone, &op_transform}; |
489 | jag | 218 | for (int i = 0; i < ball_op::NUM_OPS; ++i) ops[i]->eval (this); |
395 | jag | 219 | } |