编程苦手GW——OpenGL学习练习,相互碰撞的彩色小球

时间:2022-09-10 17:24:16

相互碰撞的彩色小球

/*
绘制多个大小不一、颜色不一的小球,并绘制一矩形区域,让小球在矩形区域内随机运动,小球之间彼此接触或者碰到矩形边缘,小球改变运动方向。
*/


#include <GL/glut.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

float windowWidth = 900.0f, windowHeight = 900.0f; //屏幕宽度,高度
const GLfloat Pi = 3.1415926f; //定义圆周率

const int N = 50;
float x[N], y[N];
GLfloat cx[5] = { 220, 200, 710, 800, 500 }, cy[5] = { 220, 800, 330, 780, 550 }; //自定义4个圆的初始圆心坐标
GLfloat R[5] = { 150, 80, 120, 100, 50}; //自定义4个圆的圆半径
GLfloat a[5] = { 0.2, 0.4, 0.6, 0.8, 1.0 }, b[5] = { 0.1, 0.3, 0.5, 0.7, 0.4 }, c[5] = { 0.9, 0.8, 0.2, 0.1, 0.7 }; //自定义圆颜色
GLfloat vx[5] = { 4, 0.5, 3, 5, 1 }, vy[5] = { 1, 7, 5.3, 2, 3.4 }; //自设置x、y方向的初始速度
GLfloat Length = 800.0f, L1 = (windowWidth - Length) / 2, L2 = (windowHeight - Length) / 2, L3 = (windowWidth + Length) / 2, L4 = (windowHeight + Length) / 2;

void init(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
}

void DrawBall(GLint R,GLfloat cx, GLfloat cy, GLfloat a, GLfloat b, GLfloat c)
{
glEnable(GL_BLEND); //启用混合功能,将图形周围颜色混合
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POINT_SMOOTH); //点抗锯齿
glEnable(GL_LINE_SMOOTH); //线抗锯齿
glEnable(GL_POLYGON_SMOOTH); //多边形抗锯齿
glColor3f(a, b, c);
glBegin(GL_POLYGON);
for (int i = 0; i < N; i++)
{
x[i] = cx + R*cos(2 * Pi*i / N);
y[i] = cy + R*sin(2 * Pi*i / N);
glVertex2f(x[i], y[i]);
}
glEnd();
}

void DrawSquare(void)
{
glColor3f(0.0f, 0.0f, 0.0f); //设置绘图颜色
glRectf(L1,L2,L3,L4); //绘制矩形
}

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer

DrawSquare();

DrawBall(R[0], cx[0], cy[0], a[0], b[0], c[0]);
DrawBall(R[1], cx[1], cy[1], a[1], b[1], c[1]);
DrawBall(R[2], cx[2], cy[2], a[2], b[2], c[2]);
DrawBall(R[3], cx[3], cy[3], a[3], b[3], c[3]);
DrawBall(R[4], cx[4], cy[4], a[4], b[4], c[4]);

glutSwapBuffers(); //双缓冲下使用该函数交换两个缓冲区内容
glFlush();
}

void timerFunc(int value)
{
srand((unsigned)time(NULL)); //用时间做种,每次产生随机数不一样
for (int i = 0; i < 5; i++)
{
if (cx[i] <= L1 + R[i]) //定义小球碰到边界折返
{
vx[i] = -vx[i];
cx[i] = L1 + R[i] + 1;
}
if (cy[i] < L2 + R[i])
{
vy[i] = -vy[i];
cy[i] = L2 + R[i] + 1;
}
if (cx[i] > L3 - R[i])
{
vx[i] = -vx[i];
cx[i] = L3 - R[i] - 1;
}
if (cy[i] > L4 - R[i])
{
vy[i] = -vy[i];
cy[i] = L4 - R[i] - 1;
}
for (int j = 4; j > i; j--) //小球相撞反向、变色
{
if (pow((cx[i] - cx[j]), 2) + pow((cy[i] - cy[j]), 2) <= pow((R[i] + R[j]), 2))
{
vx[i] = -vx[i];
vx[j] = -vx[j];
vy[i] = -vy[i];
vy[j] = -vy[j];
a[i] = rand() % (100 - i) / 100.0;
b[i] = rand() % (99 - i) / 100.0;
c[i] = rand() % (98 - i) / 100.0;
a[j] = rand() % (97 - j) / 100.0;
b[j] = rand() % (96 - j) / 100.0;
c[j] = rand() % (95 - j) / 100.0;
}
}
cx[i] += vx[i]; //小球位置的改变
cy[i] += vy[i];
}

glutPostRedisplay(); //标记当前窗口需要重新绘制
glutTimerFunc(33, timerFunc, 1); //创建定时器回调函数
}

void reshape(int w, int h)
{
if (h == 0)
h = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h) //构建三维坐标
glOrtho(0.0f, windowWidth, 0.0f, windowHeight * h / w, 1.0f, -1.0f);
else
glOrtho(0.0f, windowWidth * w / h, 0.0f, windowHeight, 1.0f, -1.0f);

glMatrixMode(GL_MODELVIEW); //设定当前矩阵为视景矩阵
glLoadIdentity();
}

void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
}
}

int main(int argc, char** argv)
{
glutInit(&argc, argv); //对GLUT进行初始化,并处理所有的命令行参数;调用于其他任何GLUT函数前
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); //指定使用RGBA模式或颜色索引模式,使用单缓冲或双缓冲窗口
glutInitWindowSize(windowWidth, windowHeight); //指定窗口大小,以像素为单位
glutInitWindowPosition(100, 100); //指定窗口左上角的屏幕位置
glutCreateWindow("Whatever"); //argv[0]显示可执行程序路径;创建一个支持OpenGL渲染环境的窗口,返回一个唯一的标识符标识窗口;在调用glutMainLoop()函数前,该窗口并不显示
glutDisplayFunc(display); //显示回调函数,每当GLUT确定一个窗口的内容需要重新显示时,通过该函数注册的那个回调函数就会被执行
glutReshapeFunc(reshape); //当窗口大小发生改变时采取行动
glutKeyboardFunc(keyboard); //允许把键盘上一个键的按钮与一个函数相关联,通过按键调用函数
glutTimerFunc(33, timerFunc, 1); //设置定时器回调函数
init();
glutMainLoop(); //调用以启动程序,所以已经创建的窗口将会在这时显示,对这些窗口的渲染也开始生效。事件处理循环开始启动,已注册的显示回调函数被触发
return 0;
}

小球速度设置过快容易碰撞粘连抖动,尚不知如何改进OTZ。。
只好低速运动啦。。
且方向变化只是简单粗暴的对称折返,还不造如何较精准地发生角度偏转。。

过程截图如下:
编程苦手GW——OpenGL学习练习,相互碰撞的彩色小球
编程苦手GW——OpenGL学习练习,相互碰撞的彩色小球

——続く——