/*
 * This Game is distributed under the GNU GENERAL PUBLIC LICENSE
 * version 2. See COPYING for details.
 *
 * Copyright (C) 1999, 2000, 2001 Harry Storbacka <harrysto@nic.fi> 
 * 
 * Race homepage: http://race.sourceforge.net
*/

#include <ClanLib/core.h>
#include <ClanLib/display.h>
#include "rect.h"
#include "collision.h"

/* Pixel based collision detection that works ONLY on 32 bit surfaces. 
 * Returns true if there are overlapping opaque pixels in the union rect. */

bool RaceCollision::alpha_based( CL_Surface *obj_1, CL_Surface *obj_2,
	                             int obj_1_x, int obj_1_y, 
	                             int obj_2_x, int obj_2_y,
								 int frame_1, int frame_2,
								 RaceRect union_rect )
{
	CL_SurfaceProvider *provider_1 = obj_1->get_provider();
	CL_SurfaceProvider *provider_2 = obj_2->get_provider();

	int height_1 = provider_1->get_height();
	int height_2 = provider_2->get_height();

	int pitch_1 = provider_1->get_pitch();
	int pitch_2 = provider_2->get_pitch();

	provider_1->lock();
	provider_2->lock();

	unsigned char *data_1 = (unsigned char *)provider_1->get_data();
	unsigned char *data_2 = (unsigned char *)provider_2->get_data();

	/*
	 *  ________
	 * |        |
	 * |        |<-- obj_1
	 * |     ___|___
	 * |    |XXX|   |
	 * |____|XXX|   |
     *      |       |<-- obj_2
	 *      |_______|
	 * 
	 *       ________
	 *      |        |
	 *      |        |
	 *  ____|___     | <-- obj_1
	 * |    |XXX|    |
	 * |    |XXX|____|
     * |        |
	 * |________|<-- obj_2
	 * 
	 * (the positions are changed so that obj_2 is ALWAYS under.)
	 */


	data_1 += ( frame_1 * height_1 * pitch_1 ) // move to right frame
  			  + ((union_rect.y1 - obj_1_y) * pitch_1) // move to y start
              + ( 4 * abs(obj_1_x - union_rect.x1)); // move to x start

	data_2 += ( frame_2 * height_2 * pitch_2) // move to right frame
  	          + 4 * abs(obj_2_x - union_rect.x1); // move to x start


	for( int y = 0; y < union_rect.get_height(); y++ )
	{
		unsigned char *obj_1_data = data_1 + y*pitch_1;
		unsigned char *obj_2_data = data_2 + y*pitch_2;
	
		for( int x = 0; x < union_rect.get_width(); x++ )
		{
			if( obj_2_data[0] > 205 && obj_1_data[0] > 205 )
		  		return true;
		
			obj_1_data+=4;
			obj_2_data+=4;
		}
	}

	//provider_1->unlock();
	//provider_2->unlock();

	return false;
}







bool RaceCollision::check( CL_Surface *obj_1, CL_Surface *obj_2,
	                             int obj_1_x, int obj_1_y,
	                             int obj_2_x, int obj_2_y,
                                 int frame_1=0, int frame_2=0 )
{
	int width_1 = obj_1->get_width();
	int height_1 = obj_1->get_height();

	int width_2 = obj_2->get_width();
	int height_2 = obj_2->get_height();

	RaceRect obj_1_rect( obj_1_x, obj_1_y, obj_1_x + width_1, obj_1_y + height_1 );
	RaceRect obj_2_rect( obj_2_x, obj_2_y, obj_2_x + width_2, obj_2_y + height_2 );

	if( obj_1_rect.overlapping( obj_2_rect ) )
	{
		RaceRect union_rect = obj_1_rect.clip(obj_2_rect);
	
		if( obj_1_y < obj_2_y )
		{
			if( alpha_based( obj_1, obj_2, obj_1_x, obj_1_y, obj_2_x, obj_2_y, frame_1, frame_2, union_rect ))
				return true;
		}
		else	  	
		{
			if( alpha_based( obj_2, obj_1,  obj_2_x, obj_2_y, obj_1_x, obj_1_y, frame_2, frame_1, union_rect ))
				return true;
		}
	}
	return false;
}









bool RaceCollision::check( CL_Surface *obj, CL_Surface *car,
                           RaceRect obj_rect,
                           int car_x, int car_y,
						   int o_frame=0, int c_frame=0 )
{
	RaceRect car_rect( car_x, car_y, car_x + car->get_width(), car_y + car->get_height() );

	if( obj_rect.overlapping( car_rect ) )
	{
		RaceRect union_rect = obj_rect.clip(car_rect);
	
		if( obj_rect.y1 < car_y )
		{
			if( alpha_based( obj, car, obj_rect.x1, obj_rect.y1, car_x, car_y, o_frame, c_frame, union_rect ))
				return true;
		}
		else
		{
			if( alpha_based( car, obj, car_x, car_y, obj_rect.x1, obj_rect.y1, c_frame, o_frame, union_rect ))
				return true;
		}
	}
	return false;
}



