Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
51 KB
Referenced Files
None
Subscribers
None
diff --git a/util/allegro5/bitmap.cpp b/util/allegro5/bitmap.cpp
index de67852d..7cd11346 100644
--- a/util/allegro5/bitmap.cpp
+++ b/util/allegro5/bitmap.cpp
@@ -1,1067 +1,1082 @@
#include <sstream>
#include <allegro5/allegro5.h>
#include <allegro5/allegro_memfile.h>
#include <allegro5/allegro_primitives.h>
#include "util/debug.h"
#include "util/thread.h"
namespace Graphics{
/* it doesnt look like we need to pack colors into 16-bit values */
#if 0
static const int rgb_r_shift_16 = 0;
static const int rgb_g_shift_16 = 5;
static const int rgb_b_shift_16 = 11;
static inline int pack565(unsigned char red, unsigned char green, unsigned char blue){
return (((red >> 3) << rgb_r_shift_16) |
((green >> 2) << rgb_g_shift_16) |
((blue >> 3) << rgb_b_shift_16));
}
/* from allegro4 */
static inline void unpack565(int color, unsigned char * red, unsigned char * green, unsigned char * blue){
static int _rgb_scale_5[32] = {
0, 8, 16, 24, 33, 41, 49, 57,
66, 74, 82, 90, 99, 107, 115, 123,
132, 140, 148, 156, 165, 173, 181, 189,
198, 206, 214, 222, 231, 239, 247, 255
};
static int _rgb_scale_6[64] = {
0, 4, 8, 12, 16, 20, 24, 28,
32, 36, 40, 44, 48, 52, 56, 60,
65, 69, 73, 77, 81, 85, 89, 93,
97, 101, 105, 109, 113, 117, 121, 125,
130, 134, 138, 142, 146, 150, 154, 158,
162, 166, 170, 174, 178, 182, 186, 190,
195, 199, 203, 207, 211, 215, 219, 223,
227, 231, 235, 239, 243, 247, 251, 255
};
*red = _rgb_scale_5[(color >> rgb_r_shift_16) & 0x1F];
*green = _rgb_scale_6[(color >> rgb_g_shift_16) & 0x3F];
*blue = _rgb_scale_5[(color >> rgb_b_shift_16) & 0x1F];
}
#endif
enum BlendingType{
Translucent,
Add,
Difference,
Multiply
};
struct BlendingData{
BlendingData():
red(0), green(0), blue(0), alpha(0), type(Translucent){
}
int red, green, blue, alpha;
BlendingType type;
};
static BlendingData globalBlend;
/* must be a pointer so it can be created dynamically after allegro init */
// Util::Thread::LockObject * allegroLock;
Color makeColorAlpha(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha){
return al_map_rgba(red, blue, green, alpha);
}
Color MaskColor(){
static Color mask = makeColorAlpha(0, 0, 0, 0);
return mask;
}
Color getBlendColor(){
return makeColorAlpha(255, 255, 255, globalBlend.alpha);
}
Color doTransBlend(const Color & color, int alpha){
unsigned char red, green, blue;
al_unmap_rgb(color, &red, &green, &blue);
return makeColorAlpha(red, green, blue, alpha);
/*
red *= alpha_f;
green *= alpha_f;
blue *= alpha_f;
return al_map_rgb_f(red, green, blue);
*/
}
Color transBlendColor(const Color & color){
return doTransBlend(color, globalBlend.alpha);
}
class Blender{
public:
Blender(){
}
virtual ~Blender(){
/* default is to draw the source and ignore the destination */
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
}
};
class MaskedBlender: public Blender {
public:
MaskedBlender(){
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
}
};
class TransBlender: public Blender {
public:
TransBlender(){
switch (globalBlend.type){
case Translucent: al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA); break;
case Add: al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE); break;
case Multiply: al_set_blender(ALLEGRO_DEST_MINUS_SRC, ALLEGRO_ONE, ALLEGRO_ONE); break;
case Difference: al_set_blender(ALLEGRO_DEST_MINUS_SRC, ALLEGRO_ONE, ALLEGRO_ONE); break;
}
}
};
static const int WINDOWED = 0;
static const int FULLSCREEN = 1;
static Bitmap * Scaler = NULL;
Bitmap::Bitmap():
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
/* TODO */
}
Bitmap::Bitmap( const char * load_file ):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
internalLoadFile(load_file);
}
Bitmap::Bitmap( const std::string & load_file ):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
internalLoadFile(load_file.c_str());
}
Bitmap::Bitmap(ALLEGRO_BITMAP * who, bool deep_copy):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
if (deep_copy){
ALLEGRO_BITMAP * clone = al_clone_bitmap(who);
setData(new BitmapData(clone));
} else {
setData(new BitmapData(who));
}
}
Bitmap::Bitmap(int width, int height):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
ALLEGRO_BITMAP * bitmap = al_create_bitmap(width, height);
if (bitmap == NULL){
std::ostringstream out;
out << "Could not create bitmap with dimensions " << width << ", " << height;
throw BitmapException(__FILE__, __LINE__, out.str());
}
setData(new BitmapData(bitmap));
}
Bitmap::Bitmap( const Bitmap & copy, bool deep_copy):
mustResize(false),
bit8MaskColor(copy.bit8MaskColor){
if (deep_copy){
ALLEGRO_BITMAP * clone = al_clone_bitmap(copy.getData()->getBitmap());
setData(new BitmapData(clone));
} else {
setData(copy.getData());
}
}
void Bitmap::convertToVideo(){
ALLEGRO_BITMAP * original = getData()->getBitmap();
ALLEGRO_BITMAP * copy = al_clone_bitmap(original);
if (copy == NULL){
throw BitmapException(__FILE__, __LINE__, "Could not create video bitmap");
}
al_destroy_bitmap(getData()->getBitmap());
getData()->setBitmap(copy);
}
void changeTarget(const Bitmap & from, const Bitmap & who){
al_set_target_bitmap(who.getData()->getBitmap());
if ((al_get_bitmap_flags(who.getData()->getBitmap()) & ALLEGRO_VIDEO_BITMAP) &&
(al_get_bitmap_flags(from.getData()->getBitmap()) & ALLEGRO_MEMORY_BITMAP)){
((Bitmap&) from).convertToVideo();
if (&from == &who){
al_set_target_bitmap(who.getData()->getBitmap());
}
}
}
void changeTarget(const Bitmap * from, const Bitmap & who){
changeTarget(*from, who);
}
void changeTarget(const Bitmap & from, const Bitmap * who){
changeTarget(from, *who);
}
void changeTarget(const Bitmap * from, const Bitmap * who){
changeTarget(*from, *who);
}
enum Format{
PNG,
GIF,
};
void dumpColor(const Color & color){
unsigned char red, green, blue, alpha;
al_unmap_rgba(color, &red, &green, &blue, &alpha);
Global::debug(0) << "red " << (int) red << " green " << (int) green << " blue " << (int) blue << " alpha " << (int) alpha << std::endl;
}
Bitmap Bitmap::memoryPCX(unsigned char * const data, const int length, const bool mask){
ALLEGRO_FILE * memory = al_open_memfile((void *) data, length, "r");
ALLEGRO_BITMAP * pcx = al_load_bitmap_f(memory, ".pcx");
al_fclose(memory);
// dumpColor(al_get_pixel(pcx, 0, 0));
Bitmap out(pcx);
out.set8BitMaskColor(makeColorAlpha(255, 255, 255, 255));
return out;
}
static bool isVideoBitmap(ALLEGRO_BITMAP * bitmap){
return (al_get_bitmap_flags(bitmap) & ALLEGRO_VIDEO_BITMAP) &&
!(al_get_bitmap_flags(bitmap) & ALLEGRO_MEMORY_BITMAP);
}
void Bitmap::replaceColor(Color original, Color replaced){
changeTarget(this, this);
if (isVideoBitmap(getData()->getBitmap())){
al_lock_bitmap(getData()->getBitmap(), ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);
}
for (int x = 0; x < getWidth(); x++){
for (int y = 0; y < getHeight(); y++){
Color pixel = getPixel(x, y);
if (pixel == original){
al_put_pixel(x, y, replaced);
}
}
}
if (isVideoBitmap(getData()->getBitmap())){
al_unlock_bitmap(getData()->getBitmap());
}
}
static ALLEGRO_BITMAP * memoryGIF(const char * data, int length){
ALLEGRO_FILE * memory = al_open_memfile((void *) data, length, "r");
al_fclose(memory);
/* FIXME: get gif addon for a5 */
#if 0
RGB * palette = NULL;
/* algif will close the packfile for us in both error and success cases */
BITMAP * gif = load_gif_packfile(pack, palette);
if (!gif){
al_fclose(memory);
// pack_fclose(pack);
ostringstream out;
out <<"Could not load gif from memory: " << (void*) data << " length " << length;
throw LoadException(__FILE__, __LINE__, out.str());
}
BITMAP * out = create_bitmap(gif->w, gif->h);
blit(gif, out, 0, 0, 0, 0, gif->w, gif->h);
destroy_bitmap(gif);
// pack_fclose(pack);
#endif
ALLEGRO_BITMAP * out = NULL;
return out;
}
void Bitmap::internalLoadFile(const char * path){
this->path = path;
ALLEGRO_BITMAP * loaded = al_load_bitmap(path);
if (loaded == NULL){
std::ostringstream out;
out << "Could not load file '" << path << "'";
throw BitmapException(__FILE__, __LINE__, out.str());
}
al_convert_mask_to_alpha(loaded, al_map_rgb(255, 0, 255));
setData(new BitmapData(loaded));
}
static ALLEGRO_BITMAP * load_bitmap_from_memory(const char * data, int length, Format type){
switch (type){
case PNG : {
break;
}
case GIF : {
return memoryGIF(data, length);
break;
}
}
throw Exception::Base(__FILE__, __LINE__);
}
Bitmap::Bitmap(const char * data, int length):
mustResize(false),
bit8MaskColor(makeColor(0, 0, 0)){
Format type = GIF;
setData(new BitmapData(load_bitmap_from_memory(data, length, type)));
if (getData()->getBitmap() == NULL){
std::ostringstream out;
out << "Could not create bitmap from memory";
throw BitmapException(__FILE__, __LINE__, out.str());
}
}
Bitmap::Bitmap( const Bitmap & copy, int x, int y, int width, int height ):
mustResize(false),
bit8MaskColor(copy.bit8MaskColor){
path = copy.getPath();
ALLEGRO_BITMAP * his = copy.getData()->getBitmap();
if (x < 0)
x = 0;
if (y < 0)
y = 0;
if (width + x > al_get_bitmap_width(his)){
width = al_get_bitmap_width(his) - x;
}
if (height + y > al_get_bitmap_height(his)){
height = al_get_bitmap_height(his) - y;
}
ALLEGRO_BITMAP * sub = al_create_sub_bitmap(his, x, y, width, height);
setData(new BitmapData(sub));
}
int Bitmap::getWidth() const {
if (getData()->getBitmap() != NULL){
return al_get_bitmap_width(getData()->getBitmap());
}
return 0;
}
int getRed(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color, &red, &green, &blue);
return red;
}
int getGreen(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color, &red, &green, &blue);
return green;
}
int getBlue(Color color){
unsigned char red, green, blue;
al_unmap_rgb(color, &red, &green, &blue);
return blue;
}
Color makeColor(int red, int blue, int green){
return al_map_rgb(red, blue, green);
}
int Bitmap::getHeight() const {
if (getData()->getBitmap() != NULL){
return al_get_bitmap_height(getData()->getBitmap());
}
return 0;
}
void initializeExtraStuff(){
// al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_RGB_565);
// allegroLock = new Util::Thread::LockObject();
}
int setGraphicsMode(int mode, int width, int height){
initializeExtraStuff();
switch (mode){
case FULLSCREEN: {
al_set_new_display_flags(ALLEGRO_FULLSCREEN);
break;
}
case WINDOWED: {
al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE);
break;
}
default: break;
}
ALLEGRO_DISPLAY * display = al_create_display(width, height);
if (display == NULL){
std::ostringstream out;
out << "Could not create display with dimensions " << width << ", " << height;
throw BitmapException(__FILE__, __LINE__, out.str());
}
Screen = new Bitmap(al_get_backbuffer(display));
/* dont destroy the backbuffer */
Screen->getData()->setDestroy(false);
Scaler = new Bitmap(width, height);
/* default drawing mode */
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
return 0;
}
void Bitmap::lock() const {
al_lock_bitmap(getData()->getBitmap(), ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);
}
void Bitmap::lock(int x, int y, int width, int height) const {
al_lock_bitmap_region(getData()->getBitmap(), x, y, width, height, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE);
}
void Bitmap::unlock() const {
al_unlock_bitmap(getData()->getBitmap());
}
Color Bitmap::getPixel(const int x, const int y) const {
- changeTarget(this, this);
+ // changeTarget(this, this);
return al_get_pixel(getData()->getBitmap(), x, y);
}
void Bitmap::putPixel(int x, int y, Color pixel) const {
changeTarget(this, this);
al_put_pixel(x, y, pixel);
}
void Bitmap::putPixelNormal(int x, int y, Color col) const {
putPixel(x, y, col);
}
void Bitmap::fill(Color color) const {
changeTarget(this, this);
al_clear_to_color(color);
}
void Bitmap::startDrawing() const {
}
void Bitmap::endDrawing() const {
}
void TranslucentBitmap::startDrawing() const {
al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA);
}
void TranslucentBitmap::endDrawing() const {
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
}
Color Bitmap::blendColor(const Color & input) const {
return input;
}
Color TranslucentBitmap::blendColor(const Color & color) const {
unsigned char red, green, blue;
unsigned char alpha = globalBlend.alpha;
al_unmap_rgb(color, &red, &green, &blue);
return makeColorAlpha(red, green, blue, alpha);
}
void Bitmap::Stretch( const Bitmap & where, const int sourceX, const int sourceY, const int sourceWidth, const int sourceHeight, const int destX, const int destY, const int destWidth, const int destHeight ) const {
/* TODO */
}
void Bitmap::StretchBy2( const Bitmap & where ){
/* TODO */
}
void Bitmap::StretchBy4( const Bitmap & where ){
/* TODO */
}
void Bitmap::drawRotate(const int x, const int y, const int angle, const Bitmap & where ){
changeTarget(this, where);
MaskedBlender blender;
al_draw_rotated_bitmap(getData()->getBitmap(), getWidth() / 2, getHeight() / 2, x, y, Util::radians(angle), ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const Bitmap & where ){
/* TODO */
}
void Bitmap::drawPivot( const int centerX, const int centerY, const int x, const int y, const int angle, const double scale, const Bitmap & where ){
/* TODO */
}
void Bitmap::drawStretched( const int x, const int y, const int new_width, const int new_height, const Bitmap & who ) const {
/* FIXME */
changeTarget(this, who);
MaskedBlender blender;
al_draw_scaled_bitmap(getData()->getBitmap(), 0, 0, getWidth(), getHeight(), x, y, new_width, new_height, 0);
#if 0
ALLEGRO_TRANSFORM save;
al_copy_transform(&save, al_get_current_transform());
ALLEGRO_TRANSFORM stretch;
al_identity_transform(&stretch);
// al_translate_transform(&stretch, x / ((double) new_width / getWidth()), y / ((double) new_height / getHeight()));
al_scale_transform(&stretch, (double) new_width / getWidth(), (double) new_height / getHeight());
al_translate_transform(&stretch, x, y);
// al_translate_transform(&stretch, -x / ((double) new_width / getWidth()), -y / ((double) (new_height / getHeight())));
al_use_transform(&stretch);
/* any source pixels with an alpha value of 0 will be masked */
// al_draw_bitmap(getData().getBitmap(), x, y, 0);
al_draw_bitmap(getData().getBitmap(), 0, 0, 0);
al_use_transform(&save);
#endif
}
void Bitmap::Blit(const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where) const {
// double start = al_get_time();
// changeTarget(this, where);
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
/*
if (&where != Screen){
al_draw_bitmap(getData().getBitmap(), wx, wy, 0);
}
*/
/* FIXME: deal with mx, my, width, height */
changeTarget(this, where);
Bitmap part(*this, mx, my, width, height);
// al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
al_draw_bitmap(part.getData()->getBitmap(), wx, wy, 0);
/*
double end = al_get_time();
Global::debug(0) << "Draw in " << (end - start) << " seconds" << std::endl;
*/
}
void Bitmap::drawHFlip(const int x, const int y, const Bitmap & where) const {
changeTarget(this, where);
MaskedBlender blender;
/* any source pixels with an alpha value of 0 will be masked */
al_draw_bitmap(getData()->getBitmap(), x, y, ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::drawHFlip(const int x, const int y, Filter * filter, const Bitmap & where) const {
/* FIXME: deal with filter */
changeTarget(this, where);
MaskedBlender blender;
/* any source pixels with an alpha value of 0 will be masked */
al_draw_bitmap(getData()->getBitmap(), x, y, ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
changeTarget(this, where);
MaskedBlender blender;
/* any source pixels with an alpha value of 0 will be masked */
al_draw_bitmap(getData()->getBitmap(), x, y, ALLEGRO_FLIP_VERTICAL);
}
void Bitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* FIXME: deal with filter */
changeTarget(this, where);
MaskedBlender blender;
/* any source pixels with an alpha value of 0 will be masked */
al_draw_bitmap(getData()->getBitmap(), x, y, ALLEGRO_FLIP_VERTICAL);
}
void Bitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
changeTarget(this, where);
MaskedBlender blender;
/* any source pixels with an alpha value of 0 will be masked */
al_draw_bitmap(getData()->getBitmap(), x, y, ALLEGRO_FLIP_VERTICAL | ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* FIXME: deal with filter */
changeTarget(this, where);
MaskedBlender blender;
/* any source pixels with an alpha value of 0 will be masked */
al_draw_bitmap(getData()->getBitmap(), x, y, ALLEGRO_FLIP_VERTICAL | ALLEGRO_FLIP_HORIZONTAL);
}
void Bitmap::BlitMasked(const int mx, const int my, const int width, const int height, const int wx, const int wy, const Bitmap & where) const {
/* TODO */
}
void Bitmap::BlitToScreen(const int upper_left_x, const int upper_left_y) const {
#if 0
if (getWidth() != Screen->getWidth() || getHeight() != Screen->getHeight()){
/*
this->Blit( upper_left_x, upper_left_y, *Buffer );
Buffer->Stretch(*Scaler);
Scaler->Blit(0, 0, 0, 0, *Screen);
*/
this->Stretch(*Scaler, 0, 0, getWidth(), getHeight(), upper_left_x, upper_left_y, Scaler->getWidth(), Scaler->getHeight());
Scaler->Blit(0, 0, 0, 0, *Screen);
} else {
this->Blit(upper_left_x, upper_left_y, *Screen);
}
#endif
/*
if (&where == Screen){
al_flip_display();
}
*/
changeTarget(this, Screen);
if (getData()->getBitmap() != Screen->getData()->getBitmap()){
Blit(*Screen);
}
al_flip_display();
}
void Bitmap::BlitAreaToScreen(const int upper_left_x, const int upper_left_y) const {
changeTarget(this, Screen);
/*
if (getData()->getBitmap() != Screen->getData()->getBitmap()){
Blit(upper_left_y, upper_left_y, *Screen);
}
*/
al_flip_display();
}
void Bitmap::draw(const int x, const int y, const Bitmap & where) const {
// TransBlender blender;
changeTarget(this, where);
MaskedBlender blender;
/* any source pixels with an alpha value of 0 will be masked */
al_draw_bitmap(getData()->getBitmap(), x, y, 0);
}
void Bitmap::draw(const int x, const int y, Filter * filter, const Bitmap & where) const {
/* FIXME */
changeTarget(this, where);
MaskedBlender blender;
/* any source pixels with an alpha value of 0 will be masked */
al_draw_bitmap(getData()->getBitmap(), x, y, 0);
}
void Bitmap::hLine(const int x1, const int y, const int x2, const Color color) const {
line(x1, y, x2, y, color);
}
void Bitmap::vLine(const int y1, const int x, const int y2, const Color color) const {
line(x, y1, x, y2, color);
}
void Bitmap::arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
changeTarget(this, this);
al_draw_arc(x, y, radius, ang1 - Util::pi/2, ang2 - ang1, color, 1);
}
void TranslucentBitmap::arc(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
TransBlender blender;
Bitmap::arc(x, y, ang1, ang2, radius, transBlendColor(color));
/*
changeTarget(this);
al_draw_arc(x, y, radius, ang1 + S_PI/2, ang2 - ang1, doTransBlend(color, globalBlend.alpha), 0);
*/
}
/* from http://www.allegro.cc/forums/thread/605684/892721#target */
void al_draw_filled_pieslice(float cx, float cy, float r, float start_theta,
float delta_theta, ALLEGRO_COLOR color){
ALLEGRO_VERTEX vertex_cache[ALLEGRO_VERTEX_CACHE_SIZE];
int num_segments, ii;
num_segments = fabs(delta_theta / (2 * ALLEGRO_PI) * ALLEGRO_PRIM_QUALITY * sqrtf(r));
if (num_segments < 2)
return;
if (num_segments >= ALLEGRO_VERTEX_CACHE_SIZE) {
num_segments = ALLEGRO_VERTEX_CACHE_SIZE - 1;
}
al_calculate_arc(&(vertex_cache[1].x), sizeof(ALLEGRO_VERTEX), cx, cy, r, r, start_theta, delta_theta, 0, num_segments);
vertex_cache[0].x = cx; vertex_cache[0].y = cy;
for (ii = 0; ii < num_segments + 1; ii++) {
vertex_cache[ii].color = color;
vertex_cache[ii].z = 0;
}
al_draw_prim(vertex_cache, NULL, NULL, 0, num_segments + 1, ALLEGRO_PRIM_TRIANGLE_FAN);
// al_draw_prim(vertex_cache, NULL, NULL, 0, 3, ALLEGRO_PRIM_TRIANGLE_FAN);
}
void Bitmap::arcFilled(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
changeTarget(this, this);
al_draw_filled_pieslice(x, y, radius, ang1 - Util::pi/2, ang2 - ang1, color);
}
void TranslucentBitmap::arcFilled(const int x, const int y, const double ang1, const double ang2, const int radius, const Color color ) const {
TransBlender blender;
Bitmap::arcFilled(x, y, ang1, ang2, radius, transBlendColor(color));
}
void Bitmap::floodfill( const int x, const int y, const Color color ) const {
/* TODO */
}
void Bitmap::line(const int x1, const int y1, const int x2, const int y2, const Color color) const {
al_draw_line(x1, y1, x2, y2, color, 1.5);
}
void TranslucentBitmap::line(const int x1, const int y1, const int x2, const int y2, const Color color) const {
TransBlender blender;
Bitmap::line(x1, y1, x2, y2, transBlendColor(color));
}
void Bitmap::circleFill(int x, int y, int radius, Color color) const {
changeTarget(this, this);
al_draw_filled_circle(x, y, radius, color);
}
void Bitmap::circle(int x, int y, int radius, Color color) const {
changeTarget(this, this);
al_draw_circle(x, y, radius, color, 0);
}
void Bitmap::rectangle( int x1, int y1, int x2, int y2, Color color ) const {
changeTarget(this, this);
al_draw_rectangle(x1, y1, x2, y2, color, 0);
}
void Bitmap::rectangleFill( int x1, int y1, int x2, int y2, Color color ) const {
changeTarget(this, this);
al_draw_filled_rectangle(x1 - 0.5, y1 - 0.5, x2 + 0.5, y2 + 0.5, color);
}
void Bitmap::triangle( int x1, int y1, int x2, int y2, int x3, int y3, Color color ) const {
changeTarget(this, this);
al_draw_filled_triangle(x1, y1, x2, y2, x3, y3, color);
}
void Bitmap::polygon( const int * verts, const int nverts, const Color color ) const {
/* TODO */
}
void Bitmap::ellipse( int x, int y, int rx, int ry, Color color ) const {
changeTarget(this, this);
al_draw_ellipse(x, y, rx, ry, color, 0);
}
void Bitmap::ellipseFill( int x, int y, int rx, int ry, Color color ) const {
changeTarget(this, this);
al_draw_filled_ellipse(x, y, rx, ry, color);
}
void Bitmap::applyTrans(const Color color) const {
TransBlender blender;
changeTarget(this, this);
al_draw_filled_rectangle(0, 0, getWidth(), getHeight(), transBlendColor(color));
}
void Bitmap::light(int x, int y, int width, int height, int start_y, int focus_alpha, int edge_alpha, int focus_color, Color edge_color) const {
/* TODO */
}
void Bitmap::drawCharacter( const int x, const int y, const int color, const int background, const Bitmap & where ) const {
/* TODO */
}
void Bitmap::save( const std::string & str ) const {
/* TODO */
}
void Bitmap::readLine(std::vector<Color> & line, int y){
/* TODO */
}
void TranslucentBitmap::draw(const int x, const int y, const Bitmap & where) const {
changeTarget(this, where);
TransBlender blender;
al_draw_tinted_bitmap(getData()->getBitmap(), getBlendColor(), x, y, 0);
}
void LitBitmap::draw( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::draw( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void LitBitmap::drawHVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::draw( const int x, const int y, Filter * filter, const Bitmap & where ) const {
changeTarget(this, where);
TransBlender blender;
al_draw_tinted_bitmap(getData()->getBitmap(), getBlendColor(), x, y, 0);
}
void TranslucentBitmap::drawHFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawHFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawVFlip( const int x, const int y, Filter * filter, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawHVFlip( const int x, const int y, const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::drawHVFlip( const int x, const int y, Filter * filter,const Bitmap & where ) const {
/* TODO */
}
void TranslucentBitmap::hLine( const int x1, const int y, const int x2, const Color color ) const {
/* TODO */
}
void TranslucentBitmap::circleFill(int x, int y, int radius, Color color) const {
TransBlender blender;
Bitmap::circleFill(x, y, radius, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::putPixelNormal(int x, int y, Color color) const {
TransBlender blender;
Bitmap::putPixelNormal(x, y, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::rectangle( int x1, int y1, int x2, int y2, Color color ) const {
TransBlender blender;
Bitmap::rectangle(x1, y1, x2, y2, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::rectangleFill(int x1, int y1, int x2, int y2, Color color) const {
TransBlender blender;
Bitmap::rectangleFill(x1, y1, x2, y2, doTransBlend(color, globalBlend.alpha));
}
void TranslucentBitmap::ellipse( int x, int y, int rx, int ry, Color color ) const {
TransBlender blender;
Bitmap::ellipse(x, y, rx, ry, doTransBlend(color, globalBlend.alpha));
}
void Bitmap::setClipRect( int x1, int y1, int x2, int y2 ) const {
/* TODO */
}
void Bitmap::getClipRect(int & x1, int & y1, int & x2, int & y2) const {
/* TODO */
}
int setGfxModeFullscreen(int x, int y){
return setGraphicsMode(FULLSCREEN, x, y);
}
int setGfxModeWindowed( int x, int y ){
return setGraphicsMode(WINDOWED, x, y);
}
int setGfxModeText(){
/* TODO */
return 0;
}
bool Bitmap::getError(){
/* TODO */
return false;
}
void Bitmap::transBlender(int r, int g, int b, int a){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.type = Translucent;
}
void Bitmap::addBlender(int r, int g, int b, int a){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.type = Add;
}
void Bitmap::differenceBlender( int r, int g, int b, int a ){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.type = Difference;
}
void Bitmap::multiplyBlender( int r, int g, int b, int a ){
globalBlend.red = r;
globalBlend.green = g;
globalBlend.blue = b;
globalBlend.alpha = a;
globalBlend.type = Multiply;
}
void Bitmap::drawingMode(int type){
/* TODO */
}
void Bitmap::shutdown(){
delete Screen;
Screen = NULL;
// delete allegroLock;
// allegroLock = NULL;
/*
delete Scaler;
Scaler = NULL;
delete Buffer;
Buffer = NULL;
*/
}
StretchedBitmap::StretchedBitmap(int width, int height, const Bitmap & parent):
Bitmap(parent, 0, 0, parent.getWidth(), parent.getHeight()),
width(width),
height(height),
where(parent){
scale_x = (double) parent.getWidth() / width;
scale_y = (double) parent.getHeight() / height;
al_set_target_bitmap(parent.getData()->getBitmap());
ALLEGRO_TRANSFORM transform;
al_identity_transform(&transform);
if (al_get_current_transform() != NULL){
al_copy_transform(&transform, al_get_current_transform());
}
al_scale_transform(&transform, scale_x, scale_y);
al_set_target_bitmap(getData()->getBitmap());
al_use_transform(&transform);
}
void StretchedBitmap::start(){
#if 0
ALLEGRO_TRANSFORM transform;
changeTarget(this, this);
al_copy_transform(&transform, al_get_current_transform());
// al_identity_transform(&transform);
// al_scale_transform(&transform, Bitmap::getWidth() / width, Bitmap::getHeight() / height);
al_scale_transform(&transform, scale_x, scale_y);
al_use_transform(&transform);
#endif
}
void StretchedBitmap::finish(){
#if 0
ALLEGRO_TRANSFORM transform;
changeTarget(this, this);
al_copy_transform(&transform, al_get_current_transform());
/* apply the inverse transform */
al_scale_transform(&transform, 1.0/scale_x, 1.0/scale_y);
// al_identity_transform(&transform);
al_use_transform(&transform);
#endif
}
TranslatedBitmap::TranslatedBitmap(int x, int y, const Bitmap & where):
Bitmap(where),
x(x),
y(y){
ALLEGRO_TRANSFORM transform;
changeTarget(this, where);
al_identity_transform(&transform);
if (al_get_current_transform() != NULL){
al_copy_transform(&transform, al_get_current_transform());
}
al_translate_transform(&transform, x, y);
al_use_transform(&transform);
}
void TranslatedBitmap::BlitToScreen() const {
Bitmap::BlitToScreen();
}
TranslatedBitmap::~TranslatedBitmap(){
ALLEGRO_TRANSFORM transform;
al_copy_transform(&transform, al_get_current_transform());
al_translate_transform(&transform, -x, -y);
al_use_transform(&transform);
}
Bitmap getScreenBuffer(){
return *Screen;
}
RestoreState::RestoreState(){
al_store_state(&state, ALLEGRO_STATE_ALL);
}
RestoreState::~RestoreState(){
al_restore_state(&state);
}
}
-static bool sameColor(Graphics::Color color1, Graphics::Color color2){
+static inline bool close(float x, float y){
+ static float epsilon = 0.001;
+ return fabs(x - y) < epsilon;
+}
+
+static inline bool sameColor(Graphics::Color color1, Graphics::Color color2){
+ float r1, g1, b1, a1;
+ float r2, g2, b2, a2;
+ al_unmap_rgba_f(color1, &r1, &g1, &b1, &a1);
+ al_unmap_rgba_f(color2, &r2, &g2, &b2, &a2);
+ return close(r1, r2) &&
+ close(g1, g2) &&
+ close(b1, b2) &&
+ close(a1, a2);
+ /*
unsigned char r1, g1, b1, a1;
unsigned char r2, g2, b2, a2;
al_unmap_rgba(color1, &r1, &g1, &b1, &a1);
al_unmap_rgba(color2, &r2, &g2, &b2, &a2);
return r1 == r2 &&
g1 == g2 &&
b1 == b2 &&
a1 == a2;
+ */
}
static uint32_t quantify(const ALLEGRO_COLOR & color){
unsigned char red, green, blue, alpha;
al_unmap_rgba(color, &red, &green, &blue, &alpha);
return (red << 24) |
(green << 16) |
(blue << 8) |
alpha;
}
bool operator<(const ALLEGRO_COLOR color1, const ALLEGRO_COLOR color2){
return quantify(color1) < quantify(color2);
}
bool operator!=(const ALLEGRO_COLOR color1, const ALLEGRO_COLOR color2){
return !(color1 == color2);
}
bool operator==(const ALLEGRO_COLOR color1, const ALLEGRO_COLOR color2){
return sameColor(color1, color2);
}
diff --git a/util/ebox.cpp b/util/ebox.cpp
index 6fe7b29f..d5d59e58 100644
--- a/util/ebox.cpp
+++ b/util/ebox.cpp
@@ -1,723 +1,725 @@
/* ebox version 3:
* by Jon Rafkind
*/
#include "ebox.h"
#include <stdio.h>
#include "funcs.h"
#include "bitmap.h"
#include <iostream>
using namespace std;
// extern "C" void rest( int i );
// using namespace Ebox2;
#ifndef debug
// #define debug printf("File: %s Line: %d\n", __FILE__, __LINE__ );
#define debug std::cout<<"File: "<<__FILE__<<" Line: "<<__LINE__<<std::endl;
#endif
// #define MIN_SIZE 8
const int MIN_SIZE = 8;
/* copy constructor but with a pointer */
EQuad::EQuad( EQuad * const head ):
width( head->width ),
height( head->height ),
full( head->full ),
min_x( head->min_x ),
min_y( head->min_y ),
parent( NULL ),
num_quads( head->num_quads ){
for ( int q = 0; q < 4; q++ )
quads[q] = NULL;
for ( int i = 0; i < head->numQuads(); i++ ){
// EQuad * tmp = head->getQuad( i );
quads[i] = new EQuad( head->getQuad( i ) );
quads[i]->parent = this;
}
}
EQuad::EQuad( int w, int h, EQuad * _parent ):
width( w ),
height( h ),
min_x( 0 ),
min_y( 0 ),
parent( _parent ),
num_quads( 0 ){
full = true;
for ( int i = 0; i < 4; i++ )
quads[i] = NULL;
}
EQuad::EQuad( const Graphics::Bitmap * who, int min_size, Graphics::Color mask_pixel, int _min_x, int _min_y, EQuad * _parent ):
width( who->getWidth() ),
height( who->getHeight() ),
full( false ),
min_x( _min_x ),
min_y( _min_y ),
parent( _parent ){
Graphics::Bitmap * b1, * b2, * b3, * b4;
EQuad * quad1, * quad2, * quad3, * quad4;
quad1 = quad2 = quad3 = quad4 = NULL;
if ( width > min_size && height > min_size ){
int w = who->getWidth() >> 1;
int h = who->getHeight() >> 1;
// b1 = create_sub_Bitmap( who, 0, 0, w, h );
b1 = new Graphics::Bitmap( *who, 0, 0, w, h );
quad1 = new EQuad( b1, min_size, mask_pixel, 0, 0, this );
// destroy_Bitmap( b1 );
delete b1;
// b2 = create_sub_Bitmap( who, w, 0, w, h );
b2 = new Graphics::Bitmap( *who, w, 0, w, h );
quad2 = new EQuad( b2, min_size, mask_pixel, w, 0, this );
delete b2;
// destroy_Bitmap( b2 );
// b3 = create_sub_Bitmap( who, 0, h, w, h );
b3 = new Graphics::Bitmap( *who, 0, h, w, h );
quad3 = new EQuad( b3, min_size, mask_pixel, 0, h, this );
delete b3;
// destroy_Bitmap( b3 );
// b4 = create_sub_Bitmap( who, w, h, w, h );
b4 = new Graphics::Bitmap( *who, w, h, w, h );
quad4 = new EQuad( b4, min_size, mask_pixel, w, h, this );
delete b4;
// destroy_Bitmap( b4 );
if ( quad1->empty() ){
delete quad1;
quad1 = NULL;
}
if ( quad2->empty() ){
delete quad2;
quad2 = NULL;
}
if ( quad3->empty() ){
delete quad3;
quad3 = NULL;
}
if ( quad4->empty() ){
delete quad4;
quad4 = NULL;
}
if ( quad1 && quad2 && quad3 && quad4 )
if ( quad1->full && quad2->full && quad3->full && quad4->full ){
delete quad1;
delete quad2;
delete quad3;
delete quad4;
quad1 = NULL;
quad2 = NULL;
quad3 = NULL;
quad4 = NULL;
full = true;
}
checkQuad( quad1 );
checkQuad( quad2 );
checkQuad( quad3 );
checkQuad( quad4 );
} else {
// printf("Size X:%d Y:%d\n", width, height );
int total = 0;
int denom = who->getWidth() * who->getHeight();
/* empty sprite? */
if (denom < 1){
denom = 1;
}
- for (int x = 0; x < who->getWidth(); x++){
- for (int y = 0; y < who->getHeight(); y++){
+ int width = who->getWidth();
+ int height = who->getHeight();
+ for (int x = 0; x < width; x++){
+ for (int y = 0; y < height; y++){
// int pixel = _getpixel16( who, x, y );
- Graphics::Color pixel = who->getPixel( x, y );
+ Graphics::Color pixel = who->getPixel(x, y);
if (pixel != mask_pixel){
++total;
}
if ( total * 100 / denom > 50 ){
/* we're done already,
* stop counting pixels
*/
goto short_circuit;
}
}
}
/* johnny 5 alive! */
short_circuit:
if ( total * 100 / denom > 50 ){
full = true;
}
}
for ( int i = 0; i < 4; i++ )
quads[i] = NULL;
int i = 0;
if ( quad1 ) quads[i++] = quad1;
if ( quad2 ) quads[i++] = quad2;
if ( quad3 ) quads[i++] = quad3;
if ( quad4 ) quads[i++] = quad4;
num_quads = numQuads();
}
bool EQuad::addQuad( EQuad * who ){
int n = numQuads();
if ( n < 4 ){
quads[n] = who;
full = false;
return true;
} else return false;
}
void EQuad::checkQuad( EQuad *& q ){
if ( q != NULL ){
while ( q->numQuads() == 1 ){
EQuad * const newquad = q->getQuad();
q->detach( newquad );
int x = q->getMinX();
int y = q->getMinY();
delete q;
q = newquad;
newquad->setMinX( newquad->getMinX() + x );
newquad->setMinY( newquad->getMinY() + y );
q->parent = this;
}
}
}
int EQuad::totalQuads(){
if ( full ) return 1;
int total = 0;
for ( int i = 0; i < numQuads(); i++ )
if ( quads[i] )
total += quads[i]->totalQuads();
/*
if ( quad1 ) total += quad1->totalQuads();
if ( quad2 ) total += quad2->totalQuads();
if ( quad3 ) total += quad3->totalQuads();
if ( quad4 ) total += quad4->totalQuads();
*/
return total;
}
void EQuad::setMinX( int x ){
min_x = x;
}
void EQuad::setMinY( int y ){
min_y = y;
}
/*
int EQuad::numQuads() const{
int total = 0;
/ *
if ( quad1 ) ++total;
if ( quad2 ) ++total;
if ( quad3 ) ++total;
if ( quad4 ) ++total;
* /
for ( total = 0; total < 4 && quads[total] != NULL; total++ );
return total;
}
*/
EQuad * EQuad::getQuad() const {
return quads[0];
/*
if ( quad1 ) return quad1;
if ( quad2 ) return quad2;
if ( quad3 ) return quad3;
if ( quad4 ) return quad4;
return NULL;
*/
}
EQuad * EQuad::getQuad( int x ) const {
return quads[x];
}
void EQuad::detach( EQuad * const who ){
// printf("Detach %p\n", who );
/*
if ( who == quad1 ) quad1 = NULL;
if ( who == quad2 ) quad2 = NULL;
if ( who == quad3 ) quad3 = NULL;
if ( who == quad4 ) quad4 = NULL;
*/
for ( int i = 0; i < numQuads(); i++ )
if ( who == quads[i] )
quads[i] = NULL;
EQuad * tmp[ 4 ];
int begin = 0;
for ( int i = 0; i < 4; i++ )
if ( quads[i] ){
tmp[begin++] = quads[i];
quads[i] = NULL;
}
for ( int q = 0; q < begin; q++ )
quads[q] = tmp[q];
}
int EQuad::calcSize(){
int total = sizeof(*this);
for ( int q = 0; q < numQuads(); q++ ){
total += quads[q]->calcSize();
}
return total;
}
bool EQuad::empty(){
if ( numQuads() == 0 ) return !full;
// if ( !quad1 && !quad2 && !quad3 && !quad4 ) return !full;
return false;
}
void EQuad::draw( const Graphics::Bitmap & work, int x, int y, Graphics::Color color, bool flipped ){
int mx = x + getMinX();
int my = y + getMinY();
// std::cout<<"getMinX: "<<getMinX()<<std::endl;
if ( flipped ){
if ( parent ){
mx = x + parent->getWidth() - (getMinX()+getWidth());
// mx = getMinX() - parent->getWidth()/2 + x;
// my = y + parent->getHeight()/2 - getMinY();
// my = y + getMinY();
// mx2 = mx - getWidth();
// mx2 = mx + getWidth();
/*
int i;
i = mx;
mx = mx2;
mx2 = i;
*/
}
}
int mx2 = mx + getWidth();
int my2 = my + getHeight();
for ( int i = 0; i < numQuads(); i++ )
quads[i]->draw( work, mx, my, color, flipped );
if ( full )
work.rectangle( mx, my, mx2, my2, color );
/*
if ( full )
work->rectangle( x+getMinX(), y+getMinY(), x+getMinX()+getWidth(), y+getMinY()+getHeight(), Bitmap::makeColor(255,64,32) );
else
work->rectangle( x+getMinX(), y+getMinY(), x+getMinX()+getWidth(), y+getMinY()+getHeight(), color );
*/
}
void EQuad::draw( const Graphics::Bitmap & work, int x, int y, Graphics::Color color, EQuad * who ){
bool cy = false;
for ( int i = 0; i < numQuads(); i++ )
if ( who == quads[i] )
cy = true;
int mx = x + getMinX();
int my = y + getMinY();
if ( cy )
who->draw( work, mx, my, color );
else {
for ( int i = 0; i < numQuads(); i++ )
quads[i]->draw( work, mx, my, color, who );
}
}
static bool boxCollide( int zx1, int zy1, int zx2, int zy2, int zx3, int zy3, int zx4, int zy4 ){
if ( zx1 < zx3 && zx1 < zx4 &&
zx2 < zx3 && zx2 < zx4 ) return false;
if ( zx1 > zx3 && zx1 > zx4 &&
zx2 > zx3 && zx2 > zx4 ) return false;
if ( zy1 < zy3 && zy1 < zy4 &&
zy2 < zy3 && zy2 < zy4 ) return false;
if ( zy1 > zy3 && zy1 > zy4 &&
zy2 > zy3 && zy2 > zy4 ) return false;
return true;
}
/* sure this could be simplified, but thats no fun :p */
int EQuad::getX1( bool xflipped ){
if ( parent ){
if ( xflipped ){
return parent->getWidth() - (getMinX() + getWidth());
} else {
return getMinX();
}
} else {
return getMinX();
}
}
int EQuad::getFullX1( bool xflipped ){
if ( parent ){
if ( xflipped ){
return parent->getFullX1( xflipped ) + parent->getWidth() - (getMinX() + getWidth());
} else {
return parent->getFullX1( xflipped ) + getMinX();
}
} else {
return getMinX();
}
}
int EQuad::getY1( bool yflipped ){
if ( parent ){
if ( yflipped ){
return parent->getHeight() - (getMinY() + getHeight());
} else {
return getMinY();
}
} else {
return getMinY();
}
}
int EQuad::getFullY1( bool yflipped ){
if ( parent ){
if ( yflipped ){
return parent->getFullY1( yflipped ) - (parent->getHeight() + getMinY() + getHeight());
} else {
return parent->getFullY1( yflipped ) + getMinY();
}
} else {
return getMinY();
}
}
void EQuad::gather( int mx, int my, int x1, int y1, int x2, int y2, vector< EQuad * > & collides, bool xflipped, bool yflipped ){
/*
int rx = mx + getX1();
int ry = my + getY1();
*/
int rx = mx;
int ry = my;
int rx2 = rx + getWidth();
int ry2 = ry + getHeight();
if ( ! boxCollide( rx, ry, rx2, ry2, x1, y1, x2, y2 ) ){
return;
}
for ( int i = 0; i < numQuads(); i++ ){
quads[i]->gather( rx + quads[i]->getX1( xflipped ), ry + quads[i]->getY1( yflipped ), x1, y1, x2, y2, collides, xflipped, yflipped );
}
if ( full ){
collides.push_back( this );
}
}
bool EQuad::collide( int mx, int my, int x1, int y1, int x2, int y2, EQuad ** last, bool xflipped, bool yflipped ){
/*
int rx = mx + getMinX();
int ry = my + getMinY();
if ( parent ){
if ( xflipped ){
rx = mx + parent->getWidth() - (getMinX()+getWidth());
}
if ( yflipped ){
ry = my + parent->getHeight() - (getMinY()+getHeight());
}
}
*/
int rx = mx + getX1( xflipped );
int ry = my + getY1( yflipped );
int rx2 = rx + getWidth();
int ry2 = ry + getHeight();
// rect( screen, rx, ry, rx2, ry2, makecol(255,255,0) );
bool cy = boxCollide( rx, ry, rx2, ry2, x1, y1, x2, y2 );
if ( !cy ) return false;
for ( int i = 0; i < numQuads(); i++ )
if ( quads[i]->collide( rx, ry, x1, y1, x2, y2, last ) )
return true;
if ( !full ) return false;
if ( cy ) *last = this;
return cy;
return false;
}
EQuad::~EQuad(){
/*
if ( quad1 ) delete quad1;
if ( quad2 ) delete quad2;
if ( quad3 ) delete quad3;
if ( quad4 ) delete quad4;
*/
for ( int q = 0; q < 4; q++ )
if ( quads[q] != NULL )
delete quads[q];
}
long long ECollide::totalTime = 0;
void ECollide::initECollide( const Graphics::Bitmap * who, Graphics::Color mask_pixel ){
/*
TimeDifference dif;
dif.startTime();
*/
head_quad = new EQuad( who, MIN_SIZE, mask_pixel, 0, 0, NULL );
last_collide = NULL;
/*
dif.endTime();
totalTime += dif.getTime();
cout<<"Total time taken: "<< totalTime / 1000 <<" ms" <<endl;
*/
}
ECollide::ECollide( const Graphics::Bitmap * who, Graphics::Color mask_pixel ){
initECollide( who, mask_pixel );
/*
head_quad = new EQuad( who, MIN_SIZE, mask_pixel, 0, 0, NULL );
last_collide = NULL;
*/
}
ECollide::ECollide( const Graphics::Bitmap & who, Graphics::Color mask_pixel ){
initECollide( &who, mask_pixel );
/*
head_quad = new EQuad( &who, MIN_SIZE, mask_pixel, 0, 0, NULL );
last_collide = NULL;
*/
}
#if 0
ECollide::ECollide( BITMAP * who, int mask_pixel ){
Bitmap tmp( who );
initECollide( &tmp, mask_pixel );
/*
head_quad = new EQuad( &tmp, MIN_SIZE, mask_pixel, 0, 0, NULL );
last_collide = NULL;
*/
}
#endif
ECollide::ECollide( int width, int height ){
last_collide = NULL;
head_quad = new EQuad( width, height, NULL );
}
ECollide::ECollide( const ECollide * e ){
initQuad( e->head_quad );
/*
last_collide = NULL;
head_quad = new EQuad( e->head_quad );
*/
}
ECollide::ECollide( const ECollide & e ){
initQuad( e.head_quad );
/*
last_collide = NULL;
head_quad = new EQuad( e.head_quad );
*/
}
ECollide::ECollide( EQuad * const head ){
initQuad( head );
/*
last_collide = NULL;
head_quad = new EQuad( head );
*/
}
void ECollide::initQuad( EQuad * const head ){
last_collide = NULL;
head_quad = new EQuad( head );
}
ECollide * ECollide::copy(){
return new ECollide( head_quad );
}
int ECollide::getMinHeight(){
return head_quad->getMinY();
}
int ECollide::getMaxHeight(){
return head_quad->getMinY() + head_quad->getHeight();
}
int ECollide::getMinWidth(){
return head_quad->getMinX();
}
int ECollide::getMaxWidth(){
return head_quad->getMinX() + head_quad->getWidth();
}
int ECollide::calcSize(){
int total = sizeof(*this);
if ( head_quad )
total += head_quad->calcSize();
return total;
}
bool ECollide::collide( int mx, int my, int x1, int y1, int x2, int y2, bool xflipped, bool yflipped ){
last_collide = NULL;
return head_quad->collide(mx,my,x1,y1,x2,y2, &last_collide, xflipped, yflipped );
}
bool ECollide::collide( int mx, int my, int x1, int y1, int x2, int y2, EQuad ** last, bool xflipped, bool yflipped ){
return head_quad->collide(mx,my,x1,y1,x2,y2, last, xflipped, yflipped );
}
void ECollide::gather( int mx, int my, int x1, int y1, int x2, int y2, vector< EQuad * > & e, bool xflipped, bool yflipped ){
return head_quad->gather( mx, my, x1, y1, x2, y2, e, xflipped, yflipped );
}
bool ECollide::Collision( int mx, int my, int ax, int ay, bool xflipped, bool ylfipped ){
return collide( mx, my, ax, ay, ax, ay );
}
bool ECollide::Collision( int mx, int my, int x1, int y1, int x2, int y2, bool xflipped, bool yflipped ){
return collide( mx, my, x1, y1, x2, y2 );
}
bool ECollide::Collision( ECollide * col, int mx, int my, int ax, int ay, bool my_xflipped, bool my_yflipped, bool him_xflipped, bool him_yflipped ){
if ( !col ) return false;
int x1 = mx > ax ? mx : ax;
int y1 = my > ay ? my : ay;
int x2 = (mx+getWidth()) < (ax+col->getWidth()) ? (mx+getWidth()) : (ax+col->getWidth());
int y2 = (my+getHeight()) < (ay+col->getHeight()) ? (my+getHeight()) : (ay+col->getHeight());
if ( x1 > x2 ) return false;
if ( y1 > y2 ) return false;
vector< EQuad * > collides1;
gather( mx, my, x1, y1, x2, y2, collides1, my_xflipped, my_yflipped );
vector< EQuad * > collides2;
col->gather( ax, ay, x1, y1, x2, y2, collides2, him_xflipped, him_yflipped );
for ( vector< EQuad * >::iterator it = collides1.begin(); it != collides1.end(); it++ ){
EQuad * e = *it;
int px1 = mx + e->getFullX1( my_xflipped );
int py1 = my + e->getFullY1( my_yflipped );
int px2 = px1 + e->getWidth();
int py2 = py1 + e->getHeight();
// Bitmap::Screen->rectangle( px1, py1, px2, py2, Bitmap::makeColor( 128, 128, 255 ) );
for ( vector< EQuad * >::iterator it2 = collides2.begin(); it2 != collides2.end(); it2++ ){
EQuad * e2 = *it2;
int zx1 = ax + e2->getFullX1( him_xflipped );
int zy1 = ay + e2->getFullY1( him_yflipped );
// printf( "Test %d,%d,%d,%d against %d,%d,%d,%d\n", px1, py1, px2, py2, zx1, zy1, zx1 + e2->getWidth(), zy1 + e2->getHeight() );
// Bitmap::Screen->rectangle( zx1, zy1, zx1 + e2->getWidth(), zy1 + e2->getHeight(), Bitmap::makeColor( Util::rnd( 255 ), 255, 255 ) );
// if ( e2->collide( zx1, zy1, px1, py1, px2, py2, &last_collide, him_xflipped, him_yflipped ) ){
if ( boxCollide( px1, py1, px2, py2, zx1, zy1, zx1 + e2->getWidth(), zy1 + e2->getHeight() ) ){
// Bitmap::Screen->rectangle( zx1, zy1, zx1 + e2->getWidth(), zy1 + e2->getHeight(), Bitmap::makeColor( 255, 255, 0 ) );
// cout << "Collided!" << endl;
// rest( 1000 );
return true;
}
}
}
// rest( 100 );
return false;
/*
return ( collide(mx,my,x1,y1,x2,y2,my_xflipped,my_yflipped) && col->collide(ax,ay,x1,y1,x2,y2,him_xflipped,him_yflipped) );
*/
}
/*
int ECollide::getWidth() const{
return head_quad->getWidth();
}
int ECollide::getHeight() const{
return head_quad->getHeight();
}
*/
void ECollide::draw( const Graphics::Bitmap & work, int x, int y, Graphics::Color color, bool flipped ){
head_quad->draw( work, x, y, color, flipped );
}
int ECollide::numQuads() const{
return head_quad->totalQuads();
}
void ECollide::draw( const Graphics::Bitmap & work, int x, int y, Graphics::Color color, EQuad * who ){
if ( head_quad == who )
head_quad->draw( work, x, y, color );
else head_quad->draw( work, x, y, color, who );
}
EQuad * ECollide::getLast(){
return last_collide;
}
ECollide::~ECollide(){
delete head_quad;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 11, 10:47 AM (3 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68526
Default Alt Text
(51 KB)

Event Timeline