Hi all,
I am just starting with animated sprites and i am trying to make a little "tech demo" as i call it, because its not enough to be a full game but i'm just experimenting. I have several ball sprites that bounce around the screen. The mouse cursor is a target and i want the user to "shoot" the balls. Each time a ball is shot it disappears. I have everything except detecting when the target mouse cursor is over the right sprite to destroy it. It kind of works but sometimes a ball not even close to the target dissapears.
There are 3 files, a sprite class, a sprite handler class, and then the main file that holds my program. The sprite and sprite handler classes i got from a game programming book i am reading, they just help me manage the sprite objects. And I am sure these classes are correct and the problem lies inside the main.cpp file, which is the one i made. I am just posting the other classes here as well for reference. Does anyone know how to make the collision detection in this more precise so it only destroys balls that the mouse is on top of? Also, the user has to hit the mouse button in order to "hit" the ball with the target. It is written in C++ and allegro. Thanks.
sprite.cpp
#include <allegro.h>
#include "sprite.h"
sprite::sprite() {
image = NULL;
alive = 1;
direction = 0;
animcolumns = 0;
animstartx = 0;
animstarty = 0;
x = 0.0f;
y = 0.0f;
width = 0;
height = 0;
xdelay = 0;
ydelay = 0;
xcount = 0;
ycount = 0;
velx = 0.0;
vely = 0.0;
speed = 0.0;
curframe = 0;
totalframes = 1;
framecount = 0;
framedelay = 10;
animdir = 1;
faceAngle = 0;
moveAngle = 0;
}
sprite::~sprite() {
//remove bitmap from memory
if (image != NULL)
destroy_bitmap(image);
}
int sprite::load(char *filename) {
image = load_bitmap(filename, NULL);
if (image == NULL) return 0;
width = image->w;
height = image->h;
return 1;
}
void sprite::draw(BITMAP *dest)
{
draw_sprite(dest, image, (int)x, (int)y);
}
void sprite::drawframe(BITMAP *dest)
{
int fx = animstartx + (curframe % animcolumns) * width;
int fy = animstarty + (curframe / animcolumns) * height;
masked_blit(image,dest,fx,fy,(int)x,(int)y,width,height);
}
void sprite::updatePosition()
{
//update x position
if (++xcount > xdelay)
{
xcount = 0;
x += velx;
}
//update y position
if (++ycount > ydelay)
{
ycount = 0;
y += vely;
}
}
void sprite::updateAnimation()
{
//update frame based on animdir
if (++framecount > framedelay)
{
framecount = 0;
curframe += animdir;
if (curframe < 0) {
curframe = totalframes-1;
}
if (curframe > totalframes-1) {
curframe = 0;
}
}
}
int sprite::inside(int x,int y,int left,int top,int right,int bottom)
{
if (x > left && x < right && y > top && y < bottom)
return 1;
else
return 0;
}
int sprite::pointInside(int px,int py)
{
return inside(px, py, (int)x, (int)y, (int)x+width, (int)y+height);
}
int sprite::collided(sprite *other, int shrink)
{
int wa = (int)x + width;
int ha = (int)y + height;
int wb = (int)other->x + other->width;
int hb = (int)other->y + other->height;
if (inside((int)x, (int)y, (int)other->x+shrink, (int)other->y+shrink, wb-shrink, hb-shrink) ||
inside((int)x, ha, (int)other->x+shrink, (int)other->y+shrink, wb-shrink, hb-shrink) ||
inside(wa, (int)y, (int)other->x+shrink, (int)other->y+shrink, wb-shrink, hb-shrink) ||
inside(wa, ha, (int)other->x+shrink, (int)other->y+shrink, wb-shrink, hb-shrink))
return 1;
else
return 0;
}
spritehandler.cpp
#include "spritehandler.h"
spritehandler::spritehandler(void)
{
count = 0;
}
spritehandler::~spritehandler(void)
{
//delete the sprites
for (int n = 0; n < count; n++)
delete sprites[n];
}
void spritehandler::add(sprite *spr)
{
if (spr != NULL) {
sprites[count] = spr;
count++;
}
}
void spritehandler::create()
{
sprites[count] = new sprite();
count++;
}
sprite *spritehandler::get(int index)
{
return sprites[index];
}
main.cpp This is my program
[source="cpp"]
#include "allegro.h"
#include "sprite.h"
#include "spritehandler.h"
#include <ctime>
#define BLACK makecol(0,0,0)
#define WHITE makecol(255,255,255)
#define NUM_BRICKS 100
#define WIDTH 640
#define HEIGHT 480
#define MODE GFX_AUTODETECT_WINDOWED
spritehandler *balls;
int numB = 20;
void bounceSprite(sprite *spr)
{
if (spr->x < 0)
{
spr->x = 0;
spr->velx = rand() % 2 + 4;
spr->animdir *= -1;
} // end if
else if (spr->x > WIDTH-spr->width)
{
spr->x = WIDTH - spr->width;
spr->velx = rand() %2 - 6;
spr->animdir *= -1;
} // end else if
else if (spr->y < 0)
{
spr->y = 0;
spr->vely = rand() %2 +4;
spr->animdir *= -1;
} // end else if
else if (spr->y > HEIGHT - spr->height)
{
spr->y = HEIGHT - spr->height;
spr->vely = rand() % 2 - 6;
spr->animdir *= -1;
} // end else if
} // end bouncingSprite
void checkCollisions(sprite *spr, spritehandler *sprh)
{
int cx1, cy1, cx2, cy2;
for (int i = 0; i < numB; i++)
{
if (spr->collided(sprh->get(i), 5))
{
numB--;
break;
} // end if
} // end for
} // end checkCollisions
int main(void)
{
balls = new spritehandler();
BITMAP *buffer;
BITMAP *bg;
allegro_init();
set_color_depth(32);
set_gfx_mode(MODE, WIDTH, HEIGHT, 0, 0);
install_keyboard();
install_timer();
install_mouse();
srand(time(NULL));
bg = load_bmp("bg.bmp", NULL);
//create back buffer
buffer = create_bitmap(WIDTH, HEIGHT);
int mb;
for (int i = 0; i < numB; i++)
{
sprite *ball = new sprite();
ball->load("sphere.bmp");
//set sprite properties
ball->x = rand() % (WIDTH-64);
ball->y = rand() % (HEIGHT-64);
ball->width = 64;
ball->height = 64;
ball->velx = rand() %2 + 4;
ball->vely = rand() %2 + 4;
ball->animcolumns = 8;
ball->curframe = 1;
ball->totalframes = 32;
ball->animdir = 1;
ball-> framedelay = 2;
balls->add(ball);
} // end for
//load the mouse cursor
sprite *mouse = new sprite();
mouse->load("crosshair.bmp");
scare_mouse();
set_mouse_sprite(mouse->image);
set_mouse_sprite_focus(15,15);
show_mouse(buffer);
while (!key[KEY_ESC])
{
mb = (mouse_b & 1);
blit(bg, buffer, 0, 0, 0, 0, WIDTH, HEIGHT);
for (int i = 0; i < numB; i++)
{
balls->get(i)->updatePosition();
balls->get(i)->updateAnimation();
bounceSprite(balls->get(i));
} // end for
mouse->x = mouse_x;
mouse->y = mouse_y;
if (mb)
{
checkCollisions(mouse, balls);
} // end if
//draw the sprites
for (int i = 0; i < numB; i++)
balls->get(i)->drawframe(buffer);
show_mouse(buffer);
//update the screen
acquire_screen();
blit(buffer,screen,0,0,0,0,WIDTH,HEIGHT);
release_screen();
rest(10);
} // end while
allegro_exit();
return 0;
} // end main
END_OF_MAIN()