GLUT使用の太阳系天体绘制

承接上文,这里继续对上面在centos7虚拟机成功运行的solarsystem进行成员函数和回调函数的实现。

#include<cmath>
void Star::drawStar() {

    glEnable(GL_LINE_SMOOTH);//启用抗锯齿のLINE_SMOOTH
    glEnable(GL_BLEND);//启用混合
    int n = 1440;
    // 保存 OpenGL 当前的矩阵环境
    glPushMatrix();
    {
        // 公转
        // 如果是行星,且距离不为0,那么 且向原点平移一个半径
        // 这部分用于处理卫星
        if (parentStar != 0 && parentStar->distance > 0) {
            //将绘制的图形沿 z 轴旋转 alpha
            glRotatef(parentStar->relution_angle, 0, 0, 1);
            // x 轴方向上平移 distance , y,z 方向不变
            glTranslatef(parentStar->distance, 0.0, 0.0);
        }
        // 绘制运行轨道
        glBegin(GL_LINES);
        for(int i=0; i<n; ++i)
            glVertex2f(distance * cos(2 * PI * i / n),
                       distance * sin(2 * PI * i / n));
        glEnd();
        // 绕 z 轴旋转 alpha
        glRotatef(revolution_angle, 0, 0, 1);
        // x 轴方向平移 distance, y,z 方向不变
        glTranslatef(distance, 0.0, 0.0);

        // 自转
        glRotatef(rotation_angle, 0, 0, 1);

        // 绘制行星颜色
        glColor3f(rgbaColor[0], rgbaColor[1], rgbaColor[2]);
        glutSolidSphere(radius, 40, 32);
    }
    // 恢复绘制前的矩阵环境
    glPopMatrix();

}
void Star::update(long timeSpan) {
    revolution_angle += timeSpan * revolutionSp;  // 更新角度
    rotation_angle += rotationSp;     // 更新自转角度
}

glEnable(),激活openGL中的功能;
glPushMatrix() 和 glPopMatrix()
将当前矩阵保存到堆栈栈顶(保存当前矩阵)。前者在我们进行了一些移动旋转的操作后,对变换后的角度和位置进行保存,后者是在进行操作后使用,会恢复到上一次保存的位置和角度,适当理解为栈的入栈出栈;

glBegin() 和 glEnd() :绘制时使用,glBegin()指定图形类型。其中常用参数有:GL_POINTS 表示绘制点、 GL_LINES 表示绘制依次画出的点及他们之间的连线、GL_TRIANGLES 则是在每绘制的三个点中完成一个三角形、GL_POLYGON 则是绘制一个从第一个点到第 n 个点的多边形,上面就是画一个边很多的多边形来模拟圆的效果。

glRotatef(revolution_angle, 0, 0, 1)
当前图形绕(0,0,1)旋转revolution_angle度

glTranslatef(distance, 0.0, 0.0)
当前图形沿(0.0,0.0)方向平移distance距离

glutSolidSphere(radius, 40, 32)
以radius为半径,40经线条数,32纬线条数绘制球体
上面是天体基本属性的描绘,然后是行星和恒星的描绘
行星是不发光的,所以这里需要对它们的光照效果进行设计

void Planet::drawPlanet() {
    GLfloat mat_ambient[]  = {0.0f, 0.0f, 0.5f, 1.0f};
    GLfloat mat_diffuse[]  = {0.0f, 0.0f, 0.5f, 1.0f};
    GLfloat mat_specular[] = {0.0f, 0.0f, 1.0f, 1.0f};
    GLfloat mat_emission[] = {rgbaColor[0], rgbaColor[1], rgbaColor[2], rgbaColor[3]};
    GLfloat mat_shininess  = 90.0f;

    glMaterialfv(GL_FRONT, GL_AMBIENT,   mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE,   mat_diffuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR,  mat_specular);
    glMaterialfv(GL_FRONT, GL_EMISSION,  mat_emission);
    glMaterialf (GL_FRONT, GL_SHININESS, mat_shininess);
}

上面用到的主要是glMaterialf和glMaterialfv两个函数,下面是函数原型:

void glMaterialf(GLenum face, GLenum pname, TYPE param);
void glMaterialfv(GLenum face, GLenum pname, TYPE *param);

前者用于设计镜面指数,镜面指数的值的大小直接体现在物体的表面粗糙程度上,值越小材质越粗糙,受到点光源照射,就会产生很大的亮点;值越大,就越接近镜面,亮点越小。这里只需要设置一个值即可;
后者用来设置需要设置一个数组。

进行了行星的设置就该轮到发光发热的恒星了,恒星是一个天体系统里面的主要光源,所以这里是使用创造光源的函数 glLightfv对它进行绘制:

void Fixed_star::drawsun() {

    GLfloat sun_position[] = {0.0f, 0.0f, 0.0f, 1.0f};
    GLfloat sun_ambient[]  = {0.0f, 0.0f, 0.0f, 1.0f};
    GLfloat sun_diffuse[]  = {1.0f, 1.0f, 1.0f, 1.0f};
    GLfloat sun_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
    glLightfv(GL_LIGHT0, GL_POSITION, sun_position); // 指定零号光源的位置
    glLightfv(GL_LIGHT0, GL_AMBIENT,  sun_ambient);  // 表示各种光线照射到该材质上,经过很多次反射后追踪遗留在环境中的光线强度
    glLightfv(GL_LIGHT0, GL_DIFFUSE,  sun_diffuse);  // 漫反射后的光照强度
    glLightfv(GL_LIGHT0, GL_SPECULAR, sun_specular); // 镜面反射后的光照强度

}
void glLightfv (GLenum light, GLenum pname, 
				const GLfloat *params)

第一个参数是你设置的类型,第几号光源;
第二个参数是你设置光源的参数类型:
GL_POSITION,光源位置
GL_AMBIENT,光照强度
GL_DIFFUSE,漫反射后光照强度
GL_SPECULAR,镜面反射后光照强度
第三个参数就是你对应的数值大小,即根据你前面定好了的光照源类型,进行数据大小设定。

进入正题,给我们的太阳系进行方法实现

//
//
// solarsystem
//
#include "solarsystem.h"
// 公转半径
#define SUN_RADIUS 48.74
#define MER_RADIUS  7.32
#define VEN_RADIUS 18.15
#define EAR_RADIUS 19.13
#define MOO_RADIUS  6.15
#define MAR_RADIUS 10.19
#define JUP_RADIUS 42.90
#define SAT_RADIUS 36.16
#define URA_RADIUS 25.56
#define NEP_RADIUS 24.78

// 距太阳的距离
#define MER_DIS   62.06
#define VEN_DIS  115.56
#define EAR_DIS  168.00
#define MOO_DIS   26.01
#define MAR_DIS  228.00
#define JUP_DIS  333.40
#define SAT_DIS  428.10
#define URA_DIS 848.00
#define NEP_DIS 949.10

// 运动速度
#define MER_SPEED   87.0
#define VEN_SPEED  225.0
#define EAR_SPEED  365.0
#define MOO_SPEED   30.0
#define MAR_SPEED  687.0
#define JUP_SPEED 1298.4
#define SAT_SPEED 3225.6
#define URA_SPEED 3066.4
#define NEP_SPEED 6014.8
//自转速度
#define SELFROTATE 3

#define REST 700
#define REST_Z (REST)
#define REST_Y (-REST)

enum STARS{
	Sun, Mercury, Venus, Earth, Moon,
	Mars, Jupiter, Saturn, Uranus, Neptune
};
#define TIMEPAST 1 // 假设每次更新都经过了一天
void SolarSystem::onUpdate() {

    for (int i=0; i<STARS_NUM; i++)
        stars[i]->update(TIMEPAST); // 更新星球的位置

    this->onDisplay(); // 刷新显示
}
void SolarSystem::onDisplay() {

    // 清除 viewport 缓冲区
    glClear(GL_COLOR_BUFFER_BIT  |  GL_DEPTH_BUFFER_BIT);
    // 清空并设置颜色缓存
    glClearColor(.7f, .7f, .7f, .1f);
    // 指定当前矩阵为投影矩阵
    glMatrixMode(GL_PROJECTION);
    // 将指定的矩阵指定为单位矩阵
    glLoadIdentity();
    // 指定当前的观察视景体
    gluPerspective(75.0f, 1.0f, 1.0f, 40000000);
    // 指定当前矩阵为视景矩阵堆栈应用术后的矩阵操作
    glMatrixMode(GL_MODELVIEW);
    // 指定当前的矩阵为单位矩阵
    glLoadIdentity();
    // 定义视图矩阵,并与当前矩阵相乘
    gluLookAt(viewX, viewY, viewZ, centerX, centerY, centerZ, upX, upY, upZ);

    // 设置第一个光源(0号光源)
    glEnable(GL_LIGHT0);
    // 启用光源
    glEnable(GL_LIGHTING);
    // 启用深度测试,根据坐标的远近自动隐藏被遮住的图形
    glEnable(GL_DEPTH_TEST);

    // 绘制星球
    for (int i=0; i<STARS_NUM; i++)
        stars[i]->draw();

    // 我们在 main 函数中初始化显示模式时使用了 GLUT_DOUBLE
    // 需要使用 glutSwapBuffers 在绘制结束后实现双缓冲的缓冲区交换
    glutSwapBuffers();
}
#define OFFSET 20
void SolarSystem::onKeyboard(unsigned char key, int x, int y) {

    switch (key)    {
        case 'w': viewY += OFFSET; break; // 摄像机Y 轴位置增加 OFFSET
        case 's': viewZ += OFFSET; break;
        case 'S': viewZ -= OFFSET; break;
        case 'a': viewX -= OFFSET; break;
        case 'd': viewX += OFFSET; break;
        case 'x': viewY -= OFFSET; break;
        case 'r':
            viewX = 0; viewY = REST_Y; viewZ = REST_Z;
            centerX = centerY = centerZ = 0;
            upX = upY = 0; upZ = 1;
            break;
        case 27: exit(0); break;
        default: break;
    }

}
#define SET_VALUE_3(name, value0, value1, value2) \
                   ((name)[0])=(value0), ((name)[1])=(value1), ((name)[2])=(value2)
SolarSystem::SolarSystem() {

    // 定义视角,在前面我们已经讨论过视角的初始化了
    viewX = 0;
    viewY = REST_Y;
    viewZ = REST_Z;
    centerX = centerY = centerZ = 0;
    upX = upY = 0;
    upZ = 1;

    // 太阳
    GLfloat rgbColor[3] = {1, 0, 0};
    stars[Sun]     = new Fixed_star(SUN_RADIUS, 0, 0, SELFROTATE, 0, rgbColor);
    // 水星
    SET_VALUE_3(rgbColor, .2, .2, .5);
    stars[Mercury] = new Planet(MER_RADIUS, MER_DIS, MER_SPEED, SELFROTATE, stars[Sun], rgbColor);
    // 金星
    SET_VALUE_3(rgbColor, 1, .7, 0);
    stars[Venus]   = new Planet(VEN_RADIUS, VEN_DIS, VEN_SPEED, SELFROTATE, stars[Sun], rgbColor);
    // 地球
    SET_VALUE_3(rgbColor, 0, 1, 0);
    stars[Earth]   = new Planet(EAR_RADIUS, EAR_DIS, EAR_SPEED, SELFROTATE, stars[Sun], rgbColor);
    // 月亮
    SET_VALUE_3(rgbColor, 1, 1, 0);
    stars[Moon]    = new Planet(MOO_RADIUS, MOO_DIS, MOO_SPEED, SELFROTATE, stars[Earth], rgbColor);
    // 火星
    SET_VALUE_3(rgbColor, 1, .5, .5);
    stars[Mars]    = new Planet(MAR_RADIUS, MAR_DIS, MAR_SPEED, SELFROTATE, stars[Sun], rgbColor);
    // 木星
    SET_VALUE_3(rgbColor, 1, 1, .5);
    stars[Jupiter] = new Planet(JUP_RADIUS, JUP_DIS, JUP_SPEED, SELFROTATE, stars[Sun], rgbColor);
    // 土星
    SET_VALUE_3(rgbColor, .5, 1, .5);
    stars[Saturn]  = new Planet(SAT_RADIUS, SAT_DIS, SAT_SPEED, SELFROTATE, stars[Sun], rgbColor);
    // 天王星
    SET_VALUE_3(rgbColor, .4, .4, .4);
    stars[Uranus]  = new Planet(URA_RADIUS, URA_DIS, URA_SPEED, SELFROTATE, stars[Sun], rgbColor);
    // 海王星
    SET_VALUE_3(rgbColor, .5, .5, 1);
    stars[Neptune] = new Planet(NEP_RADIUS, NEP_DIS, NEP_SPEED, SELFROTATE, stars[Sun], rgbColor);

}
SolarSystem::~SolarSystem() {
    for(int i = 0; i<STARS_NUM; i++)
        delete stars[i];
}

好了,功能实现完成,然后来编译运行看看能不能行了。

[root@jack course]# g++ main.cpp stars.cpp solarsystem.cpp -lglut -lGL -lGLU -o solarsystem
[root@jack course]# ./solarsystem

在这里插入图片描述
基本能实现功能,不过还是差了点吧,挺满足了,现在重新更新一下代码,因为磕磕碰碰的,也有不少查错:
头文件:

#include<GL/glut.h>
class Star {
public:
// 星球的运行半径
GLfloat radius;
// 星球的公转、自传速度
GLfloat rotationSp, revolutionSp;
// 星球的中心与父节点星球中心的距离
GLfloat distance;
// 星球的颜色
GLfloat rgbaColor[4];
// 父节点星
Star* parentStar;
// 构造函数,构造一颗星球时必须提供
// 旋转半径、旋转速度、自转速度、绕行(父节点)星球
Star(GLfloat radius, GLfloat distance,
GLfloat rotationSp, GLfloat revolutionSp,
Star* parentStar);
// 对一般的星球的移动、旋转等活动进行绘制
void drawStar(); 								
// 提供默认实现,负责调用 drawStar()
virtual void draw() { drawStar();}
// 参数为每次刷新画面时的时间跨
virtual void update(long timeSpan);						
protected:
GLfloat rotation_angle, revolution_angle;						
};
										
class Planet : public Star {
public:
// 构造函数
Planet(GLfloat radius, GLfloat distance,
	GLfloat rotationSp, GLfloat revolutionSp,
	Star* parent, GLfloat rgbColor[3]);
// 增加对具备自身材质的行星绘制材质
void drawPlanet();
// 继续向其子类开放重写功能
virtual void draw() { drawPlanet(); drawStar(); }
};

class Fixed_star : public Planet {
public:
Fixed_star(GLfloat radius,GLfloat distance, GLfloat rotationSp,
                         GLfloat revolutionSp, Star* parent,GLfloat rgbColor[3]);
// 增加对提供光源的恒星绘制光照
void drawsun();
virtual void draw() { drawsun(); drawPlanet(); drawStar(); }
};
#include"stars.h"
#include<GL/glut.h>
#define STARS_NUM 10
class SolarSystem {

public:

	SolarSystem();
	~SolarSystem();

	void onDisplay();
	void onUpdate();
	void onKeyboard(unsigned char key, int x, int y);

private:
	Star *stars[STARS_NUM];

	// 定义观察视角的参数
	GLdouble viewX, viewY, viewZ;
	GLdouble centerX, centerY, centerZ;
	GLdouble upX, upY, upZ;
};

方法实现

//
//  stars.cpp
//  solarsystem
//
#include "stars.h"
#include<cmath>

#define PI 3.1415926535
//Star methods
Star::Star(GLfloat radius, GLfloat distance,
           GLfloat rotationSp, GLfloat revolutionSp,
           Star* parentStar){
    this->radius = radius;
    this->rotationSp = rotationSp;
    this->rotation_angle= this->revolution_angle = 0;
    this->distance = distance;

    for (int i = 0; i < 4; i++)
        this->rgbaColor[i] = 1.0f;

    this->parentStar = parentStar;
    if (revolutionSp > 0)
        this->revolutionSp = 360.0f / revolutionSp;
    else
        this->revolutionSp = 0.0f;
}
void Star::drawStar() {

    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_BLEND);
    int n = 1440;
    // 保存 OpenGL 当前的矩阵环境
    glPushMatrix();
    {
        // 公转
        // 如果是行星,且距离不为0,那么 且向原点平移一个半径
        // 这部分用于处理卫星
        if (parentStar != 0 && parentStar->distance > 0) {
            //将绘制的图形沿 z 轴旋转 alpha
            glRotatef(parentStar->revolution_angle, 0, 0, 1);
            // x 轴方向上平移 distance , y,z 方向不变
            glTranslatef(parentStar->distance, 0.0, 0.0);
        }
        // 绘制运行轨道
        glBegin(GL_LINES);
        for(int i=0; i<n; ++i)
            glVertex2f(distance * cos(2 * PI * i / n),
                       distance * sin(2 * PI * i / n));
        glEnd();
        // 绕 z 轴旋转 alpha
        glRotatef(revolution_angle, 0, 0, 1);
        // x 轴方向平移 distance, y,z 方向不变
        glTranslatef(distance, 0.0, 0.0);

        // 自转
        glRotatef(rotation_angle, 0, 0, 1);

        // 绘制行星颜色
        glColor3f(rgbaColor[0], rgbaColor[1], rgbaColor[2]);
        glutSolidSphere(radius, 40, 32);
    }
    // 恢复绘制前的矩阵环境
    glPopMatrix();

}
void Star::update(long timeSpan) {
    revolution_angle += timeSpan * revolutionSp;  // 更新角度
    rotation_angle += rotationSp;     // 更新自转角度
}

//Planet methods
Planet::Planet(GLfloat radius, GLfloat distance,
               GLfloat rotationSp,  GLfloat revolutionSp,
               Star* parent, GLfloat rgbColor[3]) :
Star(radius, distance, rotationSp, revolutionSp, parent) {
    rgbaColor[0] = rgbColor[0];
    rgbaColor[1] = rgbColor[1];
    rgbaColor[2] = rgbColor[2];
    rgbaColor[3] = 1.0f;
}
void Planet::drawPlanet() {
    GLfloat mat_ambient[]  = {0.0f, 0.0f, 0.5f, 1.0f};
    GLfloat mat_diffuse[]  = {0.0f, 0.0f, 0.5f, 1.0f};
    GLfloat mat_specular[] = {0.0f, 0.0f, 1.0f, 1.0f};
    GLfloat mat_emission[] = {rgbaColor[0], rgbaColor[1], rgbaColor[2], rgbaColor[3]};
    GLfloat mat_shininess  = 90.0f;

    glMaterialfv(GL_FRONT, GL_AMBIENT,   mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE,   mat_diffuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR,  mat_specular);
    glMaterialfv(GL_FRONT, GL_EMISSION,  mat_emission);
    glMaterialf (GL_FRONT, GL_SHININESS, mat_shininess);
}

//Fixed_star methods
Fixed_star::Fixed_star(GLfloat radius,GLfloat distance, GLfloat rotationSp,
                         GLfloat revolutionSp, Star* parent,GLfloat rgbColor[3]):
				Planet(radius, distance, rotationSp, revolutionSp, parent, rgbColor) {;}
void Fixed_star::drawsun() {

    GLfloat sun_position[] = {0.0f, 0.0f, 0.0f, 1.0f};
    GLfloat sun_ambient[]  = {0.0f, 0.0f, 0.0f, 1.0f};
    GLfloat sun_diffuse[]  = {1.0f, 1.0f, 1.0f, 1.0f};
    GLfloat sun_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
    glLightfv(GL_LIGHT0, GL_POSITION, sun_position); // 指定零号光源的位置
    glLightfv(GL_LIGHT0, GL_AMBIENT,  sun_ambient);  // 表示各种光线照射到该材质上,经过很多次反射后追踪遗留在环境中的光线强度
    glLightfv(GL_LIGHT0, GL_DIFFUSE,  sun_diffuse);  // 漫反射后的光照强度
    glLightfv(GL_LIGHT0, GL_SPECULAR, sun_specular); // 镜面反射后的光照强度

}

solarsystem.cpp上面就有了,这里不做详说
主文件

//
//main.cpp
//solarsystem
//
#include <GL/glut.h>//glut基本头文件
#include "solarsystem.h"
//创建图形窗口的基本宏
#define WINDOW_X_POS 50
#define WINDOW_Y_POS 50
#define WIDTH 700
#define HEIGHT 700

SolarSystem solarsystem;
//用于注册glut的回调
void onDisplay(void) {
	solarsystem.onDisplay();
	}
void onUpdate(void) {
	solarsystem.onUpdate();
	}
void onKeyboard(unsigned char key, int x, int y) {
	solarsystem.onKeyboard(key, x, y);
	}

int main(int argc, char*  argv[]) {
	glutInit(&argc, argv);//对GLUT初始化,并处理所有命令行参数
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
	//指定使用RGBA模式
	//另外指定了双缓冲窗口
	glutInitWindowPosition(WINDOW_X_POS, WINDOW_Y_POS);
	//指定窗口创建时左上角位于屏幕的位置
	glutCreateWindow("SolarSystem");//指定创建的窗口标题为SolarSystem
	glutDisplayFunc(onDisplay);	//回调函数,当GLUT确定窗口内容需要更新时					//指定函数onDisplay就会被执行
	glutIdleFunc(onUpdate);		//指定函数onUpdate								//当事件循环处于空闲,执行此函数
	glutKeyboardFunc(onKeyboard);	//将键盘上的键与函数相关联,按键被按下或者释放,函数调用
	glutMainLoop();									
	return 0;
}
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是OpenGL绘制太阳系的示例代码: ```c++ #include <GL/glut.h> static int year = 0, day = 0; void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1.0, 1.0, 0.0); // 太阳黄色 glutSolidSphere(1.0, 20, 16); // 绘制太阳 glPushMatrix(); glRotatef((GLfloat) year, 0.0, 1.0, 0.0); glTranslatef(2.0, 0.0, 0.0); glRotatef((GLfloat) day, 0.0, 1.0, 0.0); glColor3f(0.0, 0.0, 1.0); // 地球蓝色 glutSolidSphere(0.2, 10, 8); // 绘制地球 glPushMatrix(); glRotatef((GLfloat) day, 0.0, 1.0, 0.0); glTranslatef(0.5, 0.0, 0.0); glColor3f(0.5, 0.5, 0.5); // 月亮灰色 glutSolidSphere(0.05, 5, 4); // 绘制月亮 glPopMatrix(); glPopMatrix(); glutSwapBuffers(); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -5.0); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 'd': day = (day + 10) % 360; glutPostRedisplay(); break; case 'D': day = (day - 10) % 360; glutPostRedisplay(); break; case 'y': year = (year + 5) % 360; glutPostRedisplay(); break; case 'Y': year = (year - 5) % 360; glutPostRedisplay(); break; default: break; } } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500); glutCreateWindow("Solar System"); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glEnable(GL_DEPTH_TEST); glutMainLoop(); return 0; } ``` 在这个例子中,我们定义了两个全局变量 year 和 day,分别表示地球绕太阳一周的年数和地球自转一周的天数。在 display 函数中,我们先绘制太阳,然后将地球绕太阳转动 year 度,再将地球自转 day 度,最后绘制地球和月亮。在 reshape 函数中,我们设置了投影矩阵和模型视图矩阵,使得整个太阳系可以被观察到。在 keyboard 函数中,我们定义了按键操作,通过改变 year 和 day 的值来控制太阳系的运动。 编译运行上述代码,可以得到一个简单的太阳系模拟程序。按下 d 和 D 键可以改变地球自转的速度,按下 y 和 Y 键可以改变地球绕太阳转动的速度。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值