Shmup/src/utilities/utilities.cpp

214 lines
6.7 KiB
C++

#include "../config.h"
#include <azur/azur.h>
#include <azur/gint/render.h>
#include "utilities.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fxlibc/printf.h>
#include <sys/types.h>
extern font_t milifont_prop;
void Azur_draw_text(int x, int y, char const *fmt, ...)
{
char str[128];
va_list args;
va_start(args, fmt);
vsnprintf(str, 128, fmt, args);
va_end(args);
dfont( &milifont_prop );
azrp_text( x, y, C_WHITE, str );
}
bool AABB_Collision( SpriteLocator image1, SpriteLocator image2 )
{
if( (image2.x >= image1.x + image1.image->width)
|| (image2.x + image2.image->width <= image1.x)
|| (image2.y >= image1.y + image1.image->height)
|| (image2.y + image2.image->height <= image1.y) )
return false;
// no need to do pixel perfect detection
return true;
}
bool Pixel_Perfect_Collision( SpriteLocator image1, SpriteLocator image2 )
{
if( !AABB_Collision( image1, image2 ) )
return false; // bounding boxes not overlapping, impossible to have collision
/* if we reach that point, this means that we need to perform pixel perfect collsion detection */
/* First we will calculate the corners of the zone to be tested for collision */
/* as it is not usefull to check for all the surface of the image, only the */
/* overlapping area will be verified */
/* WARNING !! */
/* P4 format is not supported yet has it is currently focused on use with Azur */
/* that is mostly P8/RGB565 oriented for ultra fast performances */
if ( IMAGE_IS_P4(image1.image->format) || IMAGE_IS_P4(image2.image->format) )
return false;
int astartx, aendx;
int astarty, aendy;
int adeltax, adeltay;
int bstartx, bendx;
int bstarty, bendy;
int bdeltax, bdeltay;
int rows, columns;
if (image1.x <= image2.x)
{
adeltax = image2.x - image1.x;
columns = MIN(image1.image->width - adeltax, image2.image->width);
bdeltax = 0;
}
else
{
bdeltax = image1.x - image2.x;
columns = MIN(image2.image->width - bdeltax, image1.image->width);
adeltax = 0;
}
if (image1.y <= image2.y)
{
adeltay = image2.y - image1.y;
rows = MIN(image1.image->height - adeltay, image2.image->height);
bdeltay = 0;
}
else
{
bdeltay = image1.y - image2.y;
rows = MIN(image2.image->height - bdeltay, image1.image->height);
adeltay = 0;
}
/* if BOTH images are in a 16bits color format, we will not use masks and will quicken the process */
if ( IMAGE_IS_RGB16(image1.image->format) && IMAGE_IS_RGB16(image2.image->format) )
{
void *data1 = image1.image->data + adeltay * image1.image->stride;
void *data2 = image2.image->data + bdeltay * image2.image->stride;
uint16_t *data_u16_1 = (uint16_t *) data1;
uint16_t *data_u16_2 = (uint16_t *) data2;
int transp1 = image_alpha(image1.image->format);
int transp2 = image_alpha(image2.image->format);
for( int j=0; j<rows; j++)
{
for (int i=0; i<columns; i++)
{
if( (data_u16_1[ adeltax + i ] != transp1 )
&& (data_u16_2[ bdeltax + i ] != transp2 ) )
return true;
}
data1 += image1.image->stride;
data_u16_1 = (uint16_t *) data1;
data2 += image2.image->stride;
data_u16_2 = (uint16_t *) data2;
}
return false;
}
/* if BOTH images are in a 8bits color format, we will not use masks and will quicken the process */
if ( IMAGE_IS_P8(image1.image->format) && IMAGE_IS_P8(image2.image->format) )
{
void *data1 = image1.image->data + adeltay * image1.image->stride;
void *data2 = image2.image->data + bdeltay * image2.image->stride;
int8_t *data_u8_1 = (int8_t *) data1;
int8_t *data_u8_2 = (int8_t *) data2;
int transp1 = image_alpha(image1.image->format);
int transp2 = image_alpha(image2.image->format);
for( int j=0; j<rows; j++)
{
for (int i=0; i<columns; i++)
{
if( (data_u8_1[ adeltax + i ] != transp1 )
&& (data_u8_2[ bdeltax + i ] != transp2 ) )
return true;
}
data1 += image1.image->stride;
data_u8_1 = (int8_t *) data1;
data2 += image2.image->stride;
data_u8_2 = (int8_t *) data2;
}
return false;
}
/* if we reach that point, this means that images have differnt format and we need to manage this */
uint8_t d1;
uint8_t d2;
void *data1 = image1.image->data + adeltay * image1.image->stride;
void *data2 = image2.image->data + bdeltay * image2.image->stride;
int8_t *data_u8_1 = (int8_t *) data1;
uint16_t *data_u16_1 = (uint16_t *) data1;
int8_t *data_u8_2 = (int8_t *) data2;
uint16_t *data_u16_2 = (uint16_t *) data2;
int transp1 = image_alpha(image1.image->format);
int transp2 = image_alpha(image2.image->format);
bool im1_P16 = IMAGE_IS_RGB16(image1.image->format);
bool im1_P8 = IMAGE_IS_P8(image1.image->format);
bool im2_P16 = IMAGE_IS_RGB16(image2.image->format);
bool im2_P8 = IMAGE_IS_P8(image2.image->format);
for( int j=0; j<rows; j++)
{
for (int i=0; i<columns; i++)
{
/* d1 is set to 1 if pixel of image1 is not transparent and to 0 if transparent */
/* need to be format dependant here so quite time consumming test at each loop :( )*/
if (im1_P16)
d1 = data_u16_1[ adeltax + i ] == transp1 ? 0 : 1;
else if (im1_P8)
d1 = data_u8_1[ adeltax + i ] == transp1 ? 0 : 1;
/* d2 is set to 1 if pixel of image2 is not transparent and to 0 if transparent */
/* need to be format dependant here so quite time consumming test at each loop :( )*/
if (im2_P16)
d2 = data_u16_2[ bdeltax + i ] == transp2 ? 0 : 1;
else if (im2_P8)
d2 = data_u8_2[ bdeltax + i ] == transp2 ? 0 : 1;
/* if d1 + d2 = 2 means that both coincident pixels are not transparent and then we have collision*/
if (d1 + d2 == 2) return true;
}
/* we move the pointer to the next line of both images */
data1 += image1.image->stride;
data2 += image2.image->stride;
data_u8_1 = (int8_t *) data1;
data_u8_2 = (int8_t *) data2;
data_u16_1 = (uint16_t *) data1;
data_u16_2 = (uint16_t *) data2;
}
return false;
}