OpenGL GLUT实现类DVD屏保方块弹跳动画的问题求解
动画实现修复方案
不要逐段硬编码运动轨迹公式,DVD类弹跳动画的核心实现逻辑非常简单:维护x、y两个方向的独立速度值,物体做匀速直线运动,碰到边界时直接反转对应方向的速度符号即可,不需要手动计算每一段的直线方程。
原代码问题梳理
- 头文件重复引用:同时引入
GL/glut.h和GL/freeglut.h,Windows环境下容易出现编译冲突 - 运动逻辑错误:仅定义了x方向步长,y值靠硬编码直线公式计算,第二段公式存在语法错误(小数点误写为逗号、常数项缺失),也没有覆盖所有运动段,无法实现循环弹跳
- 状态判断冗余:用
turun、balik等布尔值手动标记运动方向,每新增一段运动就要加新的判断分支,维护成本极高 - 碰撞逻辑缺失:没有对边界做通用碰撞检测,碰到边界后无法自动反转方向
核心实现思路
- 新增y方向速度变量
deltay,根据初始路径要求计算初始速度:起点为(-15, 0),第一个碰撞点为上边界y=15上的(-8, 15),x方向总位移为7,y方向总位移为15,因此速度比deltay:deltax = 15:7,取原代码的deltax=0.5,则deltay = 0.5 * 15 /7 ≈ 1.0714,刚好能走到第一个目标点 - 每帧直接更新坐标:
xpos += deltax; ypos += deltay; - 通用碰撞检测:碰到左右竖边界(x=-15、x=15)时反转x方向速度,碰到上下横边界(y=-15、y=15)时反转y方向速度;碰撞后校正坐标到边界位置,避免步长导致的卡边问题
- 原代码里绘制的x=-8、x=0、x=8、y=0为参考线,不需要作为碰撞边界,不影响运动逻辑
修正后可运行代码
#include<windows.h> #include<GL/glu.h> #include<GL/glut.h> // 坐标与速度变量 float xpos = -15.0f; float deltax = 0.5f; float ypos = 0.0f; float deltay = 0.5f * 15.0f / 7.0f; // 初始速度匹配第一个落点(-8,15) void myInit(void) { glClearColor(0.0, 0.0, 0.0, 1.0); glColor3f(1.0, 1.0, 1.0); glPointSize(2.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-15.0f, 15.0f, -15.0f, 15.0f); } void myDisplay(void) { glClear(GL_COLOR_BUFFER_BIT); // 绘制参考线 glColor3f(1.0, 1.0, 1.0); glBegin(GL_LINES); // x轴参考线 glVertex2f(-15.0, 0.0); glVertex2f(15.0, 0.0); // x=-8竖参考线 glVertex2f(-8.0, 15.0); glVertex2f(-8.0, -15.0); // x=8竖参考线 glVertex2f(8.0, 15.0); glVertex2f(8.0, -15.0); // y轴参考线 glVertex2f(0.0, 15.0); glVertex2f(0.0, -15.0); glEnd(); // 绘制方块 glColor3f(1.0, 1.0, 1.0); glBegin(GL_POLYGON); glVertex2f(-0.2 + xpos, 0.2 + ypos); glVertex2f(-0.2 + xpos, -0.2 + ypos); glVertex2f(0.2 + xpos, -0.2 + ypos); glVertex2f(0.2 + xpos, 0.2 + ypos); glEnd(); glutSwapBuffers(); } void Timer(int) { glutPostRedisplay(); glutTimerFunc(10, Timer, 0); // 调小间隔让动画更流畅 // 更新坐标 xpos += deltax; ypos += deltay; // 左右边界碰撞检测 if (xpos >= 15.0f) { xpos = 15.0f; deltax = -deltax; } if (xpos <= -15.0f) { xpos = -15.0f; deltax = -deltax; } // 上下边界碰撞检测 if (ypos >= 15.0f) { ypos = 15.0f; deltay = -deltay; } if (ypos <= -15.0f) { ypos = -15.0f; deltay = -deltay; } } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow("Animasi"); glutDisplayFunc(myDisplay); myInit(); glutTimerFunc(0, Timer, 0); glutMainLoop(); return 0; }
编译运行后方块会从(-15,0)出发,精准到达(-8,15)点后反弹,后续自动在四个边界间往复弹跳,和DVD屏保逻辑完全一致。如果需要调整运动速度,等比例修改deltax和deltay的值即可,不需要改动其他逻辑。
内容的提问来源于stack exchange,提问作者Scylen
相关产品推荐
相关产品推荐

