Pong Collision Detection - Allegro Library

Started by
8 comments, last by mentefinale 17 years, 6 months ago
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++;
		}

Advertisement
If thats your exact code then the problem is this:

// set ball into motion
ball1.set_moving;

It should be
ball1.set_moving();

Without the () the function will not be called
Hi, Yes, i just caught that mistake myself, and recompiled. Unfortunatly it wasn't the fix. Thank you though.
Alright well the next question I have is where are you actually drawing the ball during the main loop?
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 10volatile 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[j] == 'a')				{					draw_sprite(buffer, a, i*TILE_W, j*TILE_H);				}				if (map[j] == 'b')				{					draw_sprite(buffer, b, i*TILE_W, j*TILE_H);				}				if (map[j] == 'c')				{					draw_sprite(buffer, c, i*TILE_W, j*TILE_H);				}				if (map[j] == 'd')				{					draw_sprite(buffer, d, i*TILE_W, j*TILE_H);				}				if (map[j] == 'e')				{					draw_sprite(buffer, e, i*TILE_W, j*TILE_H);				}				if (map[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.
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??
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.
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.
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.
Thank yout for all of the replies. I'm currently unable to test the last poster's response. But I will definitely try when it when i am able. Thanks again.

This topic is closed to new replies.

Advertisement