C++ 实现太阳系行星系统

11 篇文章 1 订阅

整个天体系统中,他们都是一颗星球(Star),区别行星和恒星只需要通过它们是否具有父节点即可;其次,对于不同的星球而言,它们通常具有自身的材质,并且不同的材质会表现出自身是否发光,由此我们有了初步的对象模型。故我们将星球分为:普通能够自转并绕某个点公转的星球(Star), 具有特殊材质的星球(Planet), 能够发光的星球(LightPlanet)。

一、编程模型假设:

  1. 星球的运行轨道为圆形;
  2. 自转速度保持相同;
  3. 每次刷新绘制的时候假设时间经过了一天。
二、整体思路:

  1. 初始化星球对象;
  2. 初始化 OpenGL 引擎, 实现 onDraw 和 onUpdate;
  3. 星球应该自己负责处理自己的属性、绕行关系、变换相关绘制,因此在设计星球的类时应该提供一个绘制 draw() 方法;
  4. 星球也应该自己处理自己自转公转等更新显示的绘制,因此在设计星球类时候也应该提供一个更新方法 update();
  5. 在 onDraw() 中应调 用星球的 draw() 方法;
  6. 在 onUpdate() 中调用星球的 update() 方法;
  7. 在 onKeyboard() 键盘调整整个太阳系的显示.
三、 每个星球而言,都具有如下的属性:

  1. 颜色 color
  2. 公转半径 radius
  3. 自转速度 selfSpeed
  4. 公转速度 speed
  5. 距离太阳中心的距离 distance
  6. 绕行的星球 parentStar
  7. 当前的自转的角度 alphaSelf
  8. 当前的公转角度 alpha
因此有如下的类:

class Star {
public:
    // 星球的运行半径
    GLfloat radius;
    // 星球的公转、自传速度
    GLfloat speed, selfSpeed;
    // 星球的中心与父节点星球中心的距离
    GLfloat distance;
    // 星球的颜色
    GLfloat rgbaColor[4];
    // 父节点星球
    Star* parentStar;
    // 构造函数,构造一颗星球时必须提供
    // 旋转半径、旋转速度、自转速度、绕行(父节点)星球
    Star(GLfloat radius, GLfloat distance,
         GLfloat speed,  GLfloat selfSpeed,
         Star* parent);
    // 对一般的星球的移动、旋转等活动进行绘制
    void drawStar();
    // 提供默认实现,负责调用 drawStar()
    virtual void draw() { drawStar(); }
    // 参数为每次刷新画面时的时间跨度
    virtual void update(long timeSpan);
protected:
    Float alphaSelf, alpha;
};
class Planet : public Star {
public:
    // 构造函数
    Planet(GLfloat radius, GLfloat distance,
           GLfloat speed,  GLfloat selfSpeed,
           Star* parent, GLfloat rgbColor[3]);
    // 增加对具备自身材质的行星绘制材质
    void drawPlanet();
    // 继续向其子类开放重写功能
    virtual void draw() { drawPlanet(); drawStar(); }
};
class LightPlanet : public Planet {
public:
    LightPlanet(GLfloat Radius, GLfloat Distance,
                GLfloat Speed,  GLfloat SelfSpeed,
                Star* Parent, GLfloat rgbColor[]);
    // 增加对提供光源的恒星绘制光照
    void drawLight();
    virtual void draw() { drawLight(); drawPlanet(); drawStar(); }
};
在太阳系中,太阳系显然是由各个行星组成的;并且,对于太阳系而言,太阳系中行星运动后的视图刷新应该由太阳系来完成。据此太阳系成员变量应为包含行星的变量,成员函数应作为处理太阳系内的视图刷新及键盘响应等事件,所以,我们可以设计  SolarSystem  类:

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;
};
程序的基本框架:main.cpp

//  main.cpp
#include <GL/glut.h>
#include "solarsystem.hpp"
#define WINDOW_X_POS 50
#define WINDOW_Y_POS 50
#define WIDTH 700
#define HEIGHT 700
SolarSystem solarsystem;//实例化一个太阳系
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);
    glutInitDisplayMode(GLUT_RGBA |  GLUT_DOUBLE);
    glutInitWindowPosition(WINDOW_X_POS, WINDOW_Y_POS);
    glutCreateWindow("SolarSystem at Shiyanlou");
    glutDisplayFunc(onDisplay);
    glutIdleFunc(onUpdate);
    glutKeyboardFunc(onKeyboard);
    glutMainLoop();
    return 0;
}
本实验框架及思路来自实验楼,运行的效果如下图所示:






  • 9
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值