void Firework::draw(float elapsed) { for (unsigned i = 0; i < particles.size(); ++i) { CL_Pointf position = scale(particles[i].getPosition()); CL_Draw::fill(window.get_gc(), position, position - CL_Pointf(3, 3), CL_Colorf::white); } for (std::list<Line>::iterator it = lines.begin(); it != lines.end(); ++it) CL_Draw::line(window.get_gc(), CL_LineSegment2f(scale(it->line.p), scale(it->line.q)), CL_Colorf::white); CL_Draw::fill(window.get_gc(), scale(spring.position), scale(spring.position) - CL_Pointf(5, 5), CL_Colorf::red); }
std::pair<CL_Vec2f, const Line*> Firework::checkCollision(const CL_Vec2f& prevPosition, Particle& particle, const std::list<Line>& lines, bool& collision) const { bool intersects; for (std::list<Line>::const_iterator it = lines.begin(); it != lines.end(); ++it) { CL_Vec2f intersection = it->line.get_intersection(CL_LineSegment2f(prevPosition, particle.getPosition()), intersects); collision = intersects; if (collision) return std::pair<CL_Vec2f, const Line*>(intersection, &(*it)); } return std::pair<CL_Vec2f, const Line*>(); }
void Firework::update(float elapsed) { total += elapsed; const float startTime = 1.0f; const float explosionTime = 3.0f; if (total > startTime) { for (std::vector<Particle>::iterator it = particles.begin(); it != particles.end(); ++it) registry.unsubscribe(*it, engine); if (total > explosionTime && !hasExploded) { for (std::vector<Particle>::iterator it = particles.begin(); it != particles.end(); ++it) { registry.subscribe(*it, explosion); registry.subscribe(*it, springPair); //registry.subscribe(*it, spring); } for (unsigned i = 0; i < particles.size() / 2; ++i) registry.subscribe(particles[i], spring); hasExploded = true; } } for (std::vector<Particle>::iterator it = particles.begin(); it != particles.end(); ++it) { Particle& particle = *it; std::list<const ForceGenerator*> forceGenerators = registry.getForceGenerators(particle); CL_Vec2f force; for (std::list<const ForceGenerator*>::iterator it = forceGenerators.begin(); it != forceGenerators.end(); ++it) force += (*it)->calculate(particle); CL_Vec2f prevPosition = particle.getPosition(); integrator.integrate(particle, force, elapsed); // particle is not sliding if (slides.find(&particle) == slides.end()) { bool collision; std::pair<CL_Vec2f, const Line*> result = checkCollision(prevPosition, particle, lines, collision); if (collision) { CL_Vec2f intersection = result.first; const Line* line = result.second; CL_Vec2f direction = CL_Vec2f::rotate(line->line.normal(), 0, CL_Angle::from_degrees(90)); if (direction.y > 0) direction *= -1; float cos = CL_Vec2f::dot(CL_Vec2f::normalize(particle.velocity), direction); // bouncing if (line->line.normal().y == 0 || (cos < 0.95f && particle.velocity.length() > 1.0f)) { particle.position = intersection + reflect(intersection - particle.getPosition(), line->line.normal()); particle.velocity = reflect(-particle.velocity, line->line.normal()) * (1.0f - line->damping); } // sliding else { particle.position = intersection; particle.velocity = direction * particle.velocity.length() * cos; registry.subscribe(particle, line->friction); registry.unsubscribe(particle, gravity); slides[&particle] = line; } } } // particle is sliding else { const Line* line = slides[&particle]; CL_Vec2f p = particle.getPosition(); CL_Vec2f n = line->line.normal(); if (!line->line.intersects(CL_LineSegment2f(p - n, p + n), true)) { registry.subscribe(particle, gravity); registry.unsubscribe(particle, line->friction); slides.erase(&particle); } } } if (hasExploded) { for (std::vector<Particle>::iterator it = particles.begin(); it != particles.end(); ++it) registry.unsubscribe(*it, explosion); } }
void TestApp::test_line_segment2() { CL_Console::write_line(" Header: line_segment.h"); CL_Console::write_line(" Class: CL_LineSegment2"); CL_Console::write_line(" Function: get_midpoint()"); { CL_LineSegment2f line_a(CL_Vec2f(2.0f, 8.0f), CL_Vec2f(4.0f, 20.0f)); if (line_a.get_midpoint() != CL_Vec2f(3.0f, 14.0f) ) fail(); } CL_Console::write_line(" Function: point_right_of_line()"); { CL_LineSegment2f line_a(CL_Vec2f(2.0f, 8.0f), CL_Vec2f(16.0f, 15.0f)); float value = line_a.point_right_of_line(CL_Vec2f(11.0, 7.0f)); if (value >= 0.0f) fail(); value = line_a.point_right_of_line(CL_Vec2f(3.0, 16.0f)); if (value <= 0.0f) fail(); value = line_a.point_right_of_line(CL_Vec2f(21.0, 17.5f)); if (value != 0.0f) fail(); value = line_a.point_right_of_line(CL_Vec2f(7.0, 10.0f)); if (value >= 0.0f) fail(); value = line_a.point_right_of_line(CL_Vec2f(7.0, 11.0f)); if (value <= 0.0f) fail(); } CL_Console::write_line(" Function: normal()"); { CL_LineSegment2f line_a(CL_Vec2f(0.0f, 10.0f), CL_Vec2f(0.0f, 20.0f)); CL_Vec2f normal = line_a.normal(); if (normal != CL_Vec2f(-1.0f, 0.0f)) fail(); line_a = CL_LineSegment2f(CL_Vec2f(0.0f, 20.0f), CL_Vec2f(0.0f, 10.0f)); normal = line_a.normal(); if (normal != CL_Vec2f(1.0f, 0.0f)) fail(); line_a = CL_LineSegment2f(CL_Vec2f(10.0f, 0.0f), CL_Vec2f(20.0f, 0.0f)); normal = line_a.normal(); if (normal != CL_Vec2f(0.0f, 1.0f)) fail(); line_a = CL_LineSegment2f(CL_Vec2f(20.0f, 0.0f), CL_Vec2f(10.0f, 0.0f)); normal = line_a.normal(); if (normal != CL_Vec2f(0.0f, -1.0f)) fail(); line_a = CL_LineSegment2f(CL_Vec2f(10.0f, 10.0f), CL_Vec2f(20.0f, 20.0f)); normal = line_a.normal(); if ( ! ( (normal.x >= -0.8f) && (normal.x <= -0.7f) ) ) fail(); if ( ! ( (normal.y >= 0.7f) && (normal.y <= 0.8f) ) ) fail(); } CL_Console::write_line(" Function: collinear()"); { CL_LineSegment2f line_a(CL_Vec2f(2.0f, 8.0f), CL_Vec2f(4.0f, 12.0f)); CL_LineSegment2f line_b(CL_Vec2f(4.0f, 12.0f), CL_Vec2f(6.0f, 16.0f)); if (!line_a.collinear(line_b) ) fail(); line_b = CL_LineSegment2f(CL_Vec2f(5.0f, 12.0f), CL_Vec2f(6.0f, 16.0f)); if (line_a.collinear(line_b) ) fail(); line_b = CL_LineSegment2f(CL_Vec2f(5.0f, 14.0f), CL_Vec2f(6.0f, 16.0f)); if (!line_a.collinear(line_b) ) fail(); line_b = CL_LineSegment2f(CL_Vec2f(2.0f, 8.0f), CL_Vec2f(4.0f, 12.0f)); if (!line_a.collinear(line_b) ) fail(); } CL_Console::write_line(" Function: intersects()"); { CL_LineSegment2f line_a(CL_Vec2f(2.0f, 8.0f), CL_Vec2f(16.0f, 15.0f)); CL_LineSegment2f line_b(CL_Vec2f(3.0f, 16.0f), CL_Vec2f(11.0f, 7.0f)); if (!line_a.intersects(line_b, false) ) fail(); line_b = CL_LineSegment2f(CL_Vec2f(-3.0f, 9.0f), CL_Vec2f(2.0f, 4.0f)); if (line_a.intersects(line_b, false) ) fail(); line_b = CL_LineSegment2f(CL_Vec2f(16.0f, 18.0f), CL_Vec2f(18.0f, 13.0f)); if (line_a.intersects(line_b, false) ) fail(); line_b = CL_LineSegment2f(CL_Vec2f(-2.0f, -8.0f), CL_Vec2f(-16.0f, -15.0f)); if (line_a.intersects(line_b, false) ) fail(); line_b = CL_LineSegment2f(CL_Vec2f(16.0f, 15.0f), CL_Vec2f(18.0f, 20.0f)); if (!line_a.intersects(line_b, false) ) fail(); line_b = CL_LineSegment2f(CL_Vec2f(2.0f, 6.0f), CL_Vec2f(16.0f, 13.0f)); if (line_a.intersects(line_b, false) ) fail(); line_b = CL_LineSegment2f(CL_Vec2f(2.0f, 8.0f), CL_Vec2f(16.0f + 14.0f, 15.0f + 7.0f)); if (line_a.intersects(line_b, false) ) fail(); line_b = CL_LineSegment2f(CL_Vec2f(2.0f, 8.0f), CL_Vec2f(16.0f + 14.0f, 15.0f + 7.0f)); if (!line_a.intersects(line_b, true) ) fail(); line_a = CL_LineSegment2f(CL_Vec2f(50.0f,75.0f),CL_Vec2f(75.0f,50.0f)); line_b = CL_LineSegment2f(CL_Vec2f(73.4f,98.0f),CL_Vec2f(73.4f,73.4f)); if (line_a.intersects(line_b, false)) fail(); } CL_Console::write_line(" Function: get_intersection()"); { bool did_intersect; CL_LineSegment2f line_a(CL_Vec2f(2.0f, 8.0f), CL_Vec2f(16.0f, 15.0f)); CL_LineSegment2f line_b(CL_Vec2f(3.0f, 16.0f), CL_Vec2f(11.0f, 7.0f)); CL_Vec2f dest_intercept = line_a.get_intersection(line_b, did_intersect); if (!did_intersect) fail(); if ((dest_intercept.x <= 7.0f ) || (dest_intercept.x >= 8.0f )) fail(); if ((dest_intercept.y <= 10.0f ) || (dest_intercept.y >= 11.0f )) fail(); line_b = CL_LineSegment2f(CL_Vec2f(-3.0f, 9.0f), CL_Vec2f(2.0f, 4.0f)); line_a.get_intersection(line_b, did_intersect); if (did_intersect) fail(); line_b = CL_LineSegment2f(CL_Vec2f(16.0f, 20.0f), CL_Vec2f(26.0f, 15.0f)); line_a.get_intersection(line_b, did_intersect); if (did_intersect) fail(); // Parallel line_b = CL_LineSegment2f(CL_Vec2f(-2.0f, -8.0f), CL_Vec2f(-16.0f, -15.0f)); line_a.get_intersection(line_b, did_intersect); if (did_intersect) fail(); line_b = CL_LineSegment2f(CL_Vec2f(16.0f, 15.0f), CL_Vec2f(18.0f, 20.0f)); dest_intercept = line_a.get_intersection(line_b, did_intersect); if (!did_intersect ) fail(); if (dest_intercept != line_b.p) fail(); line_b = CL_LineSegment2f(CL_Vec2f(2.0f, 8.0f), CL_Vec2f(18.0f, 20.0f)); dest_intercept = line_a.get_intersection(line_b, did_intersect); if (!did_intersect) fail(); if (dest_intercept != line_b.p) fail(); // Parallel line_b = CL_LineSegment2f(CL_Vec2f(2.0f, 6.0f), CL_Vec2f(16.0f, 13.0f)); line_a.get_intersection(line_b, did_intersect); if (did_intersect) fail(); // Parallel line_b = CL_LineSegment2f(CL_Vec2f(2.0f, 8.0f), CL_Vec2f(16.0f + 14.0f, 15.0f + 7.0f)); line_a.get_intersection(line_b, did_intersect); if (did_intersect) fail(); } CL_Console::write_line(" Function: point_distance()"); { CL_LineSegment2f line_a(CL_Vec2f(1.0f, 0.0f), CL_Vec2f(9.0f, 0.0f)); CL_Vec2f point; float distance; point = CL_Vec2f(-1.0f, 0.0f); distance = line_a.point_distance(point); if (distance != 2.0f ) fail(); point = CL_Vec2f(6.0f, 0.0f); distance = line_a.point_distance(point); if (distance != 0.0f ) fail(); point = CL_Vec2f(11.0f, 0.0f); distance = line_a.point_distance(point); if (distance != 2.0f ) fail(); line_a = CL_LineSegment2f(CL_Vec2f(0.0f, 1.0f), CL_Vec2f(0.0f, 9.0f)); point = CL_Vec2f(0.0f, -1.0f); distance = line_a.point_distance(point); if (distance != 2.0f ) fail(); point = CL_Vec2f(0.0f, 6.0f); distance = line_a.point_distance(point); if (distance != 0.0f ) fail(); point = CL_Vec2f(0.0f, 11.0f); distance = line_a.point_distance(point); if (distance != 2.0f ) fail(); line_a = CL_LineSegment2f(CL_Vec2f(0.0f, 1.0f), CL_Vec2f(0.0f, 9.0f)); point = CL_Vec2f(25.0f, 5.0f); distance = line_a.point_distance(point); if (distance != 25.0f ) fail(); } }