Beispiel #1
0
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);
}
Beispiel #2
0
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*>();
}
Beispiel #3
0
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();

	}
}