Sign in to follow this  
mentefinale

Pong Collision Detection - Allegro Library

Recommended Posts

I have two questions, sorry for the long code posts but i hope it's relevant. (1)Why won't the ball move, i'm confounded because it worked when i didn't use the class and actually coded it in the main file as "if(ball1.direction == NORTHEAST)" etc.. it moved. (2)Why isn' the ball colliding? This can't be solved I suppose until the first problem is. Again it worked when i coded it in the same manner as above in the main.cpp file, not accessing the CBall Class. Any Help would be very much appreciated. I'm not quite tearing my hair out but i'm certainly stumped! I'm working on it daily. Again thank you in advance for any help in the matter. -Jay Here's the source code to CBall (header file)
#define NORTHEAST 1
#define NORTHWEST 2
#define SOUTHEAST 3
#define SOUTHWEST 4

#define HEIGHT 480
#define WIDTH 640

class CBall {
 public:
	int x, y, xv, yv, direction, prev_dir;
	void set_velocity(int,int);
	void set_moving();
	void set_direction(int);
	void set_position(int, int);
	void collide_w();	// checks ball's collision with walls
}ball;

void CBall::set_velocity(int a,int b)
{
  xv = a;
  yv = b;
}
void CBall::set_position(int a,int b)
{
  x = a;
  y = b;
}
void CBall::set_moving()
{
	if (ball.direction == NORTHEAST)
	{
		ball.x += ball.xv;
		ball.y -= ball.yv;
	}
	if (ball.direction == SOUTHEAST)
	{
		ball.x += ball.xv;
		ball.y += ball.yv;
	}
	if (ball.direction == SOUTHWEST)
	{
		ball.x -= ball.xv;
		ball.y += ball.yv;
	}
	if (ball.direction == NORTHWEST)
	{
		ball.x -= ball.xv;
		ball.y -= ball.yv;
	}
}
void CBall::set_direction(int dir)
{
	direction = dir;
}
void CBall::collide_w()
{
	// check ball boundaries with BOTTOM wall
	if (ball.y >= (HEIGHT-10))
	{
		if (ball.direction == SOUTHEAST)
		{
			ball.direction = NORTHEAST;
		}
		if (ball.direction == SOUTHWEST)
		{
			ball.direction = NORTHWEST;
		}
	}
	// check ball boundaries with TOP wall
	if (ball.y <= 0)
	{
		if (ball.direction == NORTHWEST)
		{
			ball.direction = SOUTHWEST;
		}
		if (ball.direction == NORTHEAST)
		{
			ball.direction = SOUTHEAST;
		}
	}
	// check ball boundaries with LEFT wall
	if (ball.x <= 0)
	{
		if (ball.direction == SOUTHWEST)
		{
			ball.direction = SOUTHEAST;
		}
		if (ball.direction == NORTHWEST)
		{
			ball.direction = NORTHEAST;
		}
	}
	// check ball boundaires with RIGHT wall
	if (ball.x >= (WIDTH-10))
	{
		if (ball.direction == SOUTHEAST)
		{
			ball.direction = SOUTHWEST;
		}
		if (ball.direction == NORTHEAST)
		{
			ball.direction = NORTHWEST;
		}
	}
}

Here's the relevant code in the main.cpp file
CBall ball1;
	ball1.set_velocity(2,2);
	ball1.set_position(120,240);
	ball1.set_direction(NORTHEAST);

	// main game loop
	while (done != true)
	{
		
		// while loop for logic
		while (speed_counter > 0)
		{
			if(key[KEY_ESC])
			{
				done = true;
			}
			if(key[KEY_ENTER])
			{
				allegro_message("Paused");
			}

			paddle_x = mouse_x;

			// paddle collision detection
			if (paddle_x <= 0)
			{
				// collision with left wall
				paddle_x = 0;
			}
			if (paddle_x >= 560)
			{
				// collision with right wall
				paddle_x = 560;
			}
			
			// set ball into motion
			ball1.set_moving();
			//check collisions for ball1
			ball1.collide_w();	
			
					
			speed_counter--;
			//frame_counter++;
		}

Share this post


Link to post
Share on other sites
I seem to have lost my mind. This game is a breakout clone. Not pong. I suppose my questions are still apply regardless. Hope this clears up some potential confusion with the code.

The game logic and drawing code are separate. The main file looks as follows.

#include <allegro.h> // You must include the Allegro Header file
#include <time.h>
#include <iostream.h>
#include <fstream.h>
#include <string.h>
#include <stdio.h>
#include "ball class.h"

#define WIDTH 640
#define HEIGHT 480

#define TILE_W 40
#define TILE_H 10

volatile long speed_counter = 0; // A long integer which will store the value of the
// speed counter.
void increment_speed_counter() // A function to increment the speed counter
{
speed_counter++; // This will just increment the speed counter by one. :)
}
END_OF_FUNCTION(increment_speed_counter);

int main(int argc, char *argv[])
{
//int frame_counter = 0; // A counter for understanding fps

bool done = false;
bool ball_waiting = true; // ball is waiting for deployment on paddle
bool ball_in_play = false; // ball is currently moving

char map[16][48]; // 192 tile map

short unsigned int map_x, map_y;
short unsigned int paddle_x, paddle_y;
short unsigned int ball_tile_x, ball_tile_y;

int color; // tests for color of brick
unsigned short int i,j;

map_x = 0;
map_y = 0;

paddle_x = (WIDTH/2);
paddle_y = (HEIGHT-20);

ball_tile_x = 0;
ball_tile_y = 0;

ifstream map_file_read; // level to be read

srand (time(NULL)); // seed the random number generator

allegro_init(); // Initialize Allegro

install_keyboard(); // Initialize keyboard routines
install_timer(); // initialize the timer routine
install_mouse(); // initialize the mouse routines

enable_hardware_cursor();
// Set normal arrow pointer
select_mouse_cursor(MOUSE_CURSOR_ARROW);

LOCK_VARIABLE(speed_counter); //Used to set the timer - which regulates the game's
LOCK_FUNCTION(increment_speed_counter);//speed.

install_int_ex(increment_speed_counter, BPS_TO_TIMER(60));//Set our BPS

set_color_depth(16); // Set the color depth
set_gfx_mode(GFX_AUTODETECT_WINDOWED, WIDTH, HEIGHT, 0, 0);
set_window_title("Bumper Blocks");

BITMAP *buffer = create_bitmap(WIDTH,HEIGHT);

BITMAP *a = load_bitmap("a.bmp", NULL);
BITMAP *b = load_bitmap("b.bmp", NULL);
BITMAP *c = load_bitmap("c.bmp", NULL);
BITMAP *d = load_bitmap("d.bmp", NULL);
BITMAP *e = load_bitmap("e.bmp", NULL);
BITMAP *f = load_bitmap("f.bmp", NULL);

BITMAP *paddle = load_bitmap("paddle.bmp", NULL);
BITMAP *ball = load_bitmap("ball.bmp", NULL);

map_file_read.open("map_file.txt");

for (map_y=0; map_y<48; map_y++)
{
for (map_x=0; map_x<16; map_x++)
{
// read map info here
map[map_x][map_y] = map_file_read.get();

}
}
map_file_read.close();

//show_mouse(buffer);

CBall ball1;
ball1.set_velocity(2,2);
ball1.set_position(120,240);
ball1.set_direction(NORTHEAST);

// main game loop
while (done != true)
{

// while loop for logic
while (speed_counter > 0)
{
if(key[KEY_ESC])
{
done = true;
}
if(key[KEY_ENTER])
{
allegro_message("Paused");
}

paddle_x = mouse_x;

// paddle collision detection
if (paddle_x <= 0)
{
// collision with left wall
paddle_x = 0;
}
if (paddle_x >= 560)
{
// collision with right wall
paddle_x = 560;
}

// set ball into motion
ball1.set_moving();
//check collisions for ball1
ball1.collide_w();


speed_counter--;
//frame_counter++;
}
// end of logic while loop

//draw tile map
for (short unsigned int i=0; i<16; i++)
{
for (short unsigned int j=0; j<48; j++)
{
if (map[i][j] == 'a')
{
draw_sprite(buffer, a, i*TILE_W, j*TILE_H);
}
if (map[i][j] == 'b')
{
draw_sprite(buffer, b, i*TILE_W, j*TILE_H);
}
if (map[i][j] == 'c')
{
draw_sprite(buffer, c, i*TILE_W, j*TILE_H);
}
if (map[i][j] == 'd')
{
draw_sprite(buffer, d, i*TILE_W, j*TILE_H);
}
if (map[i][j] == 'e')
{
draw_sprite(buffer, e, i*TILE_W, j*TILE_H);
}
if (map[i][j] == 'f')
{
draw_sprite(buffer, f, i*TILE_W, j*TILE_H);
}

}
}

draw_sprite(buffer, paddle, paddle_x, paddle_y);// draw paddle
draw_sprite(buffer, ball, ball1.x, ball1.y); // draw ball1

textprintf_ex(buffer, font, 2, (HEIGHT-20), makecol(255,255,255), -1, "mouse_x = %d", mouse_x);
textprintf_ex(buffer, font, 2, (HEIGHT-10), makecol(255,255,255), -1, "mouse_y = %d", mouse_y);
textprintf_ex(buffer, font, 2, (HEIGHT-30), makecol(255,255,255), -1, "paddle_x = %d", paddle_x);
textprintf_ex(buffer, font, 2, (HEIGHT-40), makecol(255,255,255), -1, "ball1.y = %d", ball1.y);
textprintf_ex(buffer, font, 2, (HEIGHT-50), makecol(255,255,255), -1, "ball1.x = %d", ball1.x);

textprintf_ex(buffer, font, 2, (HEIGHT-60), makecol(255,255,255), -1, "ball_tile_x = %d", ball_tile_x);
textprintf_ex(buffer, font, 2, (HEIGHT-70), makecol(255,255,255), -1, "ball_tile_y = %d", ball_tile_y);

textprintf_ex(buffer, font, 2, (HEIGHT-80), makecol(255,255,255), -1, "ball1.direction = %d", ball1.direction);
textprintf_ex(buffer, font, 2, (HEIGHT-90), makecol(255,255,255), -1, "ball1.xv = %d", ball1.xv);
textprintf_ex(buffer, font, 2, (HEIGHT-100), makecol(255,255,255), -1, "ball1.yv = %d", ball1.yv);

// draw the buffer to the screen
blit(buffer, screen, 0,0,0,0,WIDTH,HEIGHT);
clear_bitmap(buffer);
}

//destroy_bitmap(tile_grid);
destroy_bitmap(buffer);
destroy_bitmap(a);
destroy_bitmap(b);
destroy_bitmap(c);
destroy_bitmap(d);
destroy_bitmap(e);
destroy_bitmap(f);
destroy_bitmap(paddle);
destroy_bitmap(ball);


return 0; // Exit with no errors
}

END_OF_MAIN() // This must be called right after the closing bracket of your MAIN function.
// It is Allegro specific.


Share this post


Link to post
Share on other sites
Have you run in debug to make sure that your speedcounter is not always 0? Also I dont really understand the api that you are using but dont really know why its volatile either??

Share this post


Link to post
Share on other sites
Yes i have. Everything "seems" to be working properly. Again i assert that when i pretended like the CBall class didn't exist and typed out the code "manually" it worked. ex. defining the variables and setting them, doing collision detection in the main.cpp. I have never come accross this problem ever. It's a new one for me!

Thank you for trying though, i do appreciate it.

Share this post


Link to post
Share on other sites
void CBall::set_moving()
{
if (ball.direction == NORTHEAST)
{
ball.x += ball.xv;
ball.y -= ball.yv;
}
}

All throughout your CBall functions you have ball.x or ball.something

Really you should just use the x or this->x, i have never seen anyone use the class name to access it and it may not be wrong but it sure looks wrong to me.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
When you declare your CBall class, you are also declaring an instance of it called ball, like so:

class CBall
{
...
} ball;

Then, in your implementations, you are referring not to the current instance of the ball but actually the CBall object you created. Instead of referring to ball, refer to this: this->x, etc. That should solve your problem.

Also: seperate your class into a header file (.h) and a class file (.cpp). The header file gets the prototypes and the the inlines and the class gets the implementations. Then, whenever you need to use the class, put #include "headerfile.h" at the top of your code file.

You should also use "include gaurds":

#ifndef MYCLASS_H
#define MYCLASS_H

class MyClass
{
};

#endif

The # statements prevent the class from being defined more often than it needs to, thus preventing linkage errors.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this