这是我本学期计算机图形学课程设计课题。
程序功能:
弹跳的球体:一个着色的三维球体,沿着一条给定的轨道(正弦曲线)不断弹跳并同时翻滚,要求按ESC停止转动翻滚按↑加快弹跳速度,按↓减慢弹跳速度。设置了一段蓝色经曲面以便能看出经线也在转动。
输入输出的要求:
在屏幕上不断地连续弹跳并同时翻滚,按↑加快移动速度,按↓减慢移动速度。
程序清单:
#include<graphics.h> /*图形系统头文件*/
#include<conio.h>
#include<dos.h>
#include<math.h>
#include<bios.h> /*控制方向键头文件*/
#include<stdlib.h>
#define PI 3.1415926
int A=50;
float w=0.2;
static double yy=0.0,xx=0.0;
char ch;
void convey() /*轨迹方程函数*/
{ xx=xx+10.0;
yy=200-A*sin(w*xx);
if(xx>=500&&yy>=400) {xx=10.0;yy=0.0;} /*设置球体运动的最大坐标*/
return;
}
void quittime01(int t2) /*按↑键加速球体运动*/
{ int t3;t3=t2;
delay(10000-200*t3);
return;
}
void quittime02(int t4) /*按↓键减速球体运动*/
{ int t5;t5=t4;
delay(20000+200*t5);
return;
}
void keyboard(int t1) /*定义判断是否按键控制速度函数*/
{int t2,t4;
if(kbhit()) /*判断是否按方向键*/
{
ch=getch();
switch(ch)
{
case 72: {t2=t1;
quittime01(t2); /*调用quittime01()函数*/
return; }
case 80: {t4=t1;
quittime02(t4);
return; }
default:break;
}
}
else
{ delay(10000);return;}
}
void sphere(float R,int alfa,int beta)
{ /*R为球体半径,alfa、beta分别为半径与经纬线的夹角*/
float x[4],y[4],z[4]; /*定义旋转变换前点坐标数组*/
float x1[4],z1[4]; /*定义旋转变换后点坐标数组*/
int i,j,k;
float sx[4],sy[4];
int shfill[10]; /*定义存放了5个顶点坐标序列的数组*/
double yn;
double a1,a2,b1,b2,c,d;
c=alfa*PI/180.0; /*每次旋转的角度*/
d=beta*PI/180.0;
cleardevice();
for(j=0;j<180;j=j+20)
{
a1=j*PI/180.0;
a2=(j+20)*PI/180.0;
for(i=0;i<360;i=i+20)
{
b1=i*PI/180;
b2=(i+20)*PI/180;
x[0]=R*sin(a1)*cos(b1); /*求出图形旋转前点的坐标*/
y[0]=R*sin(a1)*sin(b1);
z[0]=R*cos(a1);
x[1]=R*sin(a2)*cos(b1);
y[1]=R*sin(a2)*sin(b1);
z[1]=R*cos(a2);
x[2]=R*sin(a2)*cos(b2);
y[2]=R*sin(a2)*sin(b2);
z[2]=R*cos(a2);
x[3]=R*sin(a1)*cos(b2);
y[3]=R*sin(a1)*sin(b2);
z[3]=R*cos(a1);
for(k=0;k<4;k++) /*求出图形旋转后点的坐标*/
{
x1[k]=x[k]*cos(c)-y[k]*sin(c);
z1[k]=-x[k]*sin(c)*sin(d)-y[k]*cos(c)*sin(d)+z[k]*cos(d);
sx[k]=100-x1[k]; /*将三维坐标转化为屏幕坐标*/
sy[k]=100-z1[k];
}
yn=-(x1[2]-x1[0])*(z1[3]-z1[1])+(x1[3]-x1[1])*(z1[2]-z1[0]);
if(yn>=0.0) /*对可见部分进行画线,实现消隐*/
{
moveto(sx[0],sy[0]);
lineto(sx[1],sy[1]);
lineto(sx[2],sy[2]);
lineto(sx[3],sy[3]);
lineto(sx[0],sy[0]);
shfill[0]=(int)sx[0],shfill[1]=(int)sy[0];
shfill[2]=(int)sx[1],shfill[3]=(int)sy[1];
shfill[4]=(int)sx[2],shfill[5]=(int)sy[2];
shfill[6]=(int)sx[3],shfill[7]=(int)sy[3];
shfill[8]=(int)sx[0],shfill[9]=(int)sy[0];
if(i==20) /*对一段经曲面进行填充为绿色*/
{ setfillstyle(1,2); }
else
setfillstyle(1,15);
fillpoly(5,shfill); /*用当前颜色填充多边形*/
}
}
}
}
void main()
{
int gdrive=DETECT,gmode,k,t,i=0; /*自动探测图形显示器适配器种类*/
int size; void *buf[10];
initgraph(&gdrive,&gmode,""); /*初始化图形系统*/
setcolor(RED); /*设置当前画笔颜色为红色*/
for(k=36;k<=360;k=k+36)
{
sphere(50,k,k); /*调用sphere函数*/
size=imagesize(50,40,150,150);
/*将保护位图象所需的字节数赋值给size*/
if(size!=-1)
buf[i]=malloc(size); /* 分配size字节的内存空间*/
if(buf[i])
getimage(50,40,150,150,buf[i]); /*在屏幕指定的位置将一个位图保存到内存*/
i++;
}
cleardevice();
for(t=0;t<=45;t++)
{ cleardevice();
putimage(xx,yy,buf[t%10],COPY_PUT); /*在指定位置以拷贝形式输出一个位图*/
keyboard(t);
convey();
}
for(i=0;i<10;i++)
free(buf[i]); /*释放内存空间*/
getch();
closegraph(); /*关闭图形系统*/
}