Monday, May 23, 2011

Bouncing Ball

Hi, I was having trouble with my half accomplished game. The problem was that I couldnt increase the speed of the moving ball. Even if I put absolutely no timer then also ball was moving with very less speed. I asked my friends on the lunch table and they gave me the solution that I should be increasing the step count OR i should always draw the ball in the origin space and translate it. SO I tried BOTH :-) Increasing step count did help and it doesn't look bad. I was expecting that I will get a little discrete moves but that didnt happen. I still get enough smooth output. Now I went for divide and conquer apporach and decided to get the ball properly rolling first. :-) So here is my program which will show the ball bouncing on the edges of the windows. User can resize the window. He can increase and decrease the speed of moving ball by using the UP and DOWN arrow keys. thanks :-)
#include "stdafx.h"

#include <iostream>
#include <stdlib.h>

#include <GL/glut.h>

#include "math.h"

using namespace std;

int MAX_X=1200;
int MAX_Y=900;
const int MIN_X=0;
const int MIN_Y=0;
int m_x=0;
int m_y=0;

int ball_x=500;
int ball_y=500;
int radius = 30;
int poly_circle[20][2];
int circle_segments = 0;


// BY default ball will go up
int x_dir = 1;
int y_dir = -1;
int base_y;
int base_x;
float move_mag = 5.0;

void init_circle() {
int x1=0;
int y1=0;
int cnt=0;
float angle = 0;
float x2,y2;
for (angle = 0; angle < 360; angle+=25.0,cnt++) {
float rad_angle = angle * 3.14 / 180;
x2 = x1+radius * sin((double)rad_angle);
y2 = y1+radius * cos((double)rad_angle);
poly_circle[cnt][0] = x2;
poly_circle[cnt][1] = y2;
}
poly_circle[cnt][0]=poly_circle[0][0];
poly_circle[cnt][1]=poly_circle[0][1];
circle_segments = cnt;
}



void drawScene();

void move_ball() {
ball_x = ball_x + (move_mag*x_dir);
ball_y = ball_y + (move_mag*y_dir);
}

void change_y_dir() {
y_dir = -y_dir;
}
void change_x_dir() {
x_dir = -x_dir;
}
void change_both_dir() {
change_y_dir();
change_x_dir();
}

int crossed_x_limits() {
if((ball_x-radius)<=MIN_X) {
return 1;
}
if((ball_x+radius)>=MAX_X) {
return 1;
}
return 0;
}


int crossed_y_limits() {
if(ball_y-radius<=MIN_Y) {
return 1;
}
if(ball_y+radius>=MAX_Y) {
return 1;
}
return 0;
}


// the mouse callback function:
void mouse_move(int x, int y)
{
m_x = x;
m_y = y;

drawScene();
}


void handleResize(int w, int h) {

glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
MAX_X = w;
MAX_Y = h;
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
}


void drawCircle(float radius, float x1, float y1)
{
float angle = 0;
float x2,y2,cx,cy,fx,fy;
int cache = 0;

glPushMatrix();//(NEW) Create a new matrix
glTranslatef(x1,y1,0);//(NEW) Rotate the triangle on z axis based on how much time has passed

glBegin(GL_LINES);
for(int i=0; i<circle_segments;++i) {
glVertex2f(poly_circle[i][0],poly_circle[i][1]);
glVertex2f(poly_circle[i+1][0],poly_circle[i+1][1]);
}
glEnd();

glPopMatrix();//(NEW) stops current transformations to the matrix
}

void play_ball() {
move_ball();

if (crossed_x_limits()) {
change_x_dir();
} else if (crossed_y_limits()) {
change_y_dir();
} else {
// Do nothing
}
}

void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glLineWidth(4);
// Draw the ball
play_ball();
drawCircle(radius,ball_x,ball_y);

glutSwapBuffers();
}

//Called every 25 milliseconds
void update(int value) {

drawScene();

glutPostRedisplay();
glutTimerFunc(25, update, 0);
}

void idle_func(void) {
drawScene();
}

void initRendering() {
glEnable(GL_DEPTH_TEST);

}

void handleKeypress(unsigned char key, int x, int y) {
switch (key) {
case 27: //Escape key
exit(0);

}
}

void specialKey(int key, int x, int y) {
switch (key) {
case 101: //UP arrow key
if (move_mag<radius-1) {
move_mag+=0.5;
}
break;
case 103: //DOWN arrow key
if (move_mag>1) {
move_mag-=0.5;
}
break;
}
}


int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(MAX_X, MAX_Y);

glutCreateWindow("Bouncing Ball");
initRendering();
init_circle();

glutDisplayFunc(drawScene);
glutSpecialFunc(specialKey);
glutReshapeFunc(handleResize);
glutMotionFunc(mouse_move);
glutPassiveMotionFunc(mouse_move);
glutTimerFunc(25 , update, 0);
//glutIdleFunc(idle_func);

glutMainLoop();
return 0;
}

No comments:

Post a Comment