1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
#ifndef pmask_H
#define pmask_H
/*
This is the Pixel MASK library, which does pixel-perfect collisions using
bit masks.
There are several configuration options here, hope they aren't too
confusing.
*/
#define PMASK_VERSION 5
#define USE_ALLEGRO
//#define USE_SDL
#ifdef USE_ALLEGRO
struct BITMAP;
#endif
#ifdef USE_SDL
struct SDL_Surface;
#endif
#ifdef __cplusplus
# define pmask_USE_INLINE
extern "C" {
#endif
//MASK_WORD_TYPE and MASK_WORD_BITBITS can be changed for your platform
//MASK_WORD_TYPE should be the largest fast integer type available
#define MASK_WORD_TYPE unsigned long int
//MASK_WORD_BITBITS should be the log base 2
//of the number of bits in MASK_WORD_TYPE
//e.g. 4 for 16-bit ints, 5 for 32-bit ints, 6 for 64-bit ints
//don't worry about setting it incorrectly
//you'll get a compile error if you do, not a run-time error
#if defined(__alpha__) || defined(__ia64__) || defined(__x86_64__) || defined(__s390x__) || (defined(__sparc__) && defined(__arch64__))
#define MASK_WORD_BITBITS 6
#else
#define MASK_WORD_BITBITS 5
#endif
//if SINGLE_MEMORY_BLOCK is defined
//then each mask will be allocated as
//only a single memory block.
//this means that masks will (in theory)
//be ever-so-slightly faster and more memory efficient
//however, if in single memory block mode
//then the masks are variable-sized
//so you can not use an array of them
//#define MASK_SINGLE_MEMORY_BLOCK
//trying to make portable const-ness easier:
#ifndef CONST
# define CONST const
#endif
//This is the bounding box collision detection macro.
//It is a general purpose macro. Pass it the coordinates of one rectangle and the width and
//height of it, then pass the coordinates of a second rectangle and the width and height of
//it. It will return 0 if theres not collision or 1 if there is a collision between the
//rectangles (the ectangles overlap).
//This macro works looking for out of range values, if some value is out of
//range it returns 0, if all the values are in range it returns true.
#define check_bb_collision_general(x1,y1,w1,h1,x2,y2,w2,h2) (!( ((x1)>=(x2)+(w2)) || ((x2)>=(x1)+(w1)) || ((y1)>=(y2)+(h2)) || ((y2)>=(y1)+(h1)) ))
#define check_bb_collision(mask1,mask2,x1,y1,x2,y2) check_bb_collision_general(x1,y1,mask1->w,mask1->h,x2,y2,mask2->w,mask2->h)
typedef struct PMASK //8 bytes in a 32-bit environment
{
short int w;//width
short int h;//height
# ifdef MASK_SINGLE_MEMORY_BLOCK
MASK_WORD_TYPE mask[1];//mask data (single memory block)
# else
MASK_WORD_TYPE *mask;//mask data (pointer at second memory block)
# endif
} PMASK;
void install_pmask(); //sets up library
int _check_pmask_collision(CONST struct PMASK *mask1, CONST struct PMASK *mask2, int dx, int dy); //checks for collision (0 = no collision, 1 = collision)
int check_pmask_collision(CONST struct PMASK *mask1, CONST struct PMASK *mask2, int x1, int y1, int x2, int y2); //checks for collision (0 = no collision, 1 = collision)
//note: result[0] is set to the X coordinate of the collision, result[1] to the Y coordinate
int _check_pmask_collision_position(CONST struct PMASK *mask1, CONST struct PMASK *mask2, int dx, int dy, int *result);
int check_pmask_collision_position(CONST struct PMASK *mask1, CONST struct PMASK *mask2, int x1, int y1, int x2, int y2, int *result);
int get_pmask_pixel(CONST struct PMASK *mask, int x, int y) ; //returns 0 if mask is clear at those coordinates, 1 if not clear
void set_pmask_pixel(struct PMASK *mask, int x, int y, int value) ;//makes mask clear at those coordinates if value is zero, others makes mask not-clear at those coordinates
void init_pmask (struct PMASK *mask, int w, int h); //initializes a PMASK
void pmask_load_pixels (struct PMASK *mask, void *pixels, int pitch, int bytes_per_pixel, int trans_color);//loads a pmask with pixel data from memory
void pmask_load_func (struct PMASK *mask, int x, int y, void *surface, int trans_color, int (*func)(void*,int,int));//loads a pmask with pixel data from a function
void deinit_pmask(PMASK *mask);//de-initializes a pmask
PMASK *create_pmask (int w, int h);//creates a new pmask and initializes it
void destroy_pmask(struct PMASK *mask);//destroys a pmask created by create_pmask
#if defined USE_ALLEGRO
void init_allegro_pmask(struct PMASK *mask, struct BITMAP *sprite);
PMASK *create_allegro_pmask(struct BITMAP *sprite);
void draw_allegro_pmask(CONST struct PMASK *mask, struct BITMAP *destination, int x, int y, int color) ;
void draw_allegro_pmask_stretch(CONST struct PMASK *mask, struct BITMAP *destination, int x, int y, int w, int h, int color) ;
#endif
#if defined USE_SDL
void init_sdl_pmask(struct PMASK *mask, struct SDL_Surface *sprite, int trans_color);
PMASK *create_sdl_pmask(struct SDL_Surface *sprite, int trans_color);
#endif
int serialize_pmask(void *destination, int maxsize, CONST PMASK *source);
//serialize_pmask is a helper for sending a PMASK to a file or over a network
//it accepts a buffer to write to, and a maxime number of bytes to write
//it returns the number of bytes written, or -1 if an error occured
int init_deserialize_pmask(void *source, int maxsize, PMASK *destination);
//init_deserialize_pmask is a helper for reading a PMASK from a file or over a network
//it accepts a buffer to read from, and a maximum number of bytes to read
//it also accepts a pointer at the PMASK to initialize
//it returns the number of bytes read
PMASK *create_deserialize_pmask(void *source, int maxsize, int *size);
//create_deserialize_pmask is a helper for reading a PMASK from a file or over a network
//it accepts a buffer to read from, and a maximum number of bytes to read
//it accepts a pointer at an integer to put the # of bytes read
//it returns a newly allocated PMASK structure, or NULL if an error occured
int get_serialized_pmask_size ( int w, int h );
//simple helper to determine the serialized size of a PMASK
#ifdef __cplusplus
}
#endif
#define MASK_WORD_SIZE sizeof(MASK_WORD_TYPE)
#define MASK_WORD_BITS (MASK_WORD_SIZE*8)
#if defined pmask_USE_INLINED
inline int _get_pmask_pixel(struct PMASK *mask, int x, int y) {
//no bounds checking
return 1 & (mask->mask[(mask->h * (x >> MASK_WORD_BITBITS)) + y] >> (x & (MASK_WORD_BITS-1)));
}
inline void _set_pmask_pixel(struct PMASK *mask, int x, int y, int value) {
//no bounds checking
if (value) {
mask->mask[(mask->h * (x >> MASK_WORD_BITBITS)) + y] |= 1 << (x & (MASK_WORD_BITS-1));
} else {
mask->mask[(mask->h * (x >> MASK_WORD_BITBITS)) + y] &=~(1 << (x & (MASK_WORD_BITS-1)));
}
}
#else
# define _get_pmask_pixel get_pmask_pixel
# define _set_pmask_pixel set_pmask_pixel
#endif
#endif /* ifndef pmask_H */
|