代码下载地址:
http://pan.baidu.com/s/1eQjiETc
2015.8.11更新:
最近突然有一个想法:写一个程序,用来模拟太阳系的行星运动,甚至是任意星球的运动。感觉这个想法非常excited,所以就准备开始写。程序的名字就叫“星系模拟器”吧,或者也可以称作“拉普拉斯的长者?”,英文名Solar Simulator
为了避免写完后过一个月看不懂代码的悲剧重演,我准备把整个开发过程都记在这里。
工具:
①一只NOIP选手
②一台电脑
③稍有的物理学常识
2015.8.13更新:
首先说一下思路。
①每个物体都是一个质点,只考虑万有引力
②先假设所有物体都在二维平面上运动,三维的以后再说
③每个物体都用一个小点表示
④怎么模拟运动呢?最早想的是能不能用方程,然后我突然想到“三体问题没有解析解”这回事……果断大模拟
先解决“在屏幕上显示图形”这回事。毕竟作为一只NOIP选手,我以前写过的都是“黑白屏幕的傻X程序”。
先找了半天,找了两个备选方案:一是按着《C++图形与游戏编程基础》用Dark GDK,但它只兼容vs2008,而且功能非常受限。二是用DirectX,但找了找教程发现相当于学习windows编程,上来就给一堆乱码般的函数和类名跪了,写个显示亮点的小程序我至于吗我……
后来经光神指点,找到一个好东西:Easy Graphics Engine(EGE),主页http://tcgraphics.sourceforge.net/,在VS2015下的安装教程见http://www.jianshu.com/p/b12163e5a0b7
环境已备好(VS2015 Community+EGE),可以开始了。
EGE的函数名称啥的都很直白,我也不介绍了,主页里写的非常清楚。先写个“画东西”的小程序压压惊吧:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <graphics.h>
#include <time.h>
#include <cstdio>
#include <cmath>
using namespace std;
int main() {
//初始化一个200*200的图像区域
initgraph(200, 200);
//设置绘图颜色
setcolor(WHITE);
//画空心圆
circle(100, 100, 3);
//设置填充颜色
setfillcolor(WHITE);
//填充圆
floodfill(100, 100,WHITE);
//等待按任意键
getch();
//关闭图像
closegraph();
return 0;
}
效果图:
我们将用这样的“亮点”表示物体,当然屏幕肯定比200*200大。
EGE中,坐标(x,y)代表距离左边x,距离上边y,不要搞反了
EGE还可以画像素。画一个抛物线作为练习:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <graphics.h>
#include <time.h>
#include <cstdio>
#include <cmath>
using namespace std;
#pragma warning(disable:4996)//无视掉freopen的警告
const int gsize = 600;
int main() {
//打开图像
initgraph(gsize, gsize);
//绘图
for (float x = 0, y = 0 ; y < gsize ; x+=0.001, y = x*x/500) {
putpixel(int(x+0.5), int(y+0.5), WHITE);//画像素
}
//关闭图像
getch();
closegraph();
return 0;
}
方程y=x^2/500
效果图:
接下来该画动图了。按照EGE官网上的教程,写了一个画动图的程序:
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <graphics.h>
#include <time.h>
#include <cstdio>
#include <cmath>
using namespace std;
#pragma warning(disable:4996)//无视掉freopen的警告
void mainloop()//主循环
{
//将线条和填充颜色设为白色
setcolor(WHITE);
setfillcolor(WHITE);
float x = 0, y = 0;
for (; is_run(); delay_fps(60))//每秒60帧
{
//cleardevice();//清屏
y = x*x / 500.0;
fillellipsef(x, y, 3, 3);//画以(x,y)为中心,长短轴均为3的椭圆
x += 1.0;//更新x
}
}
int main(void)
{
//设置初始化图形,差不多就是默认
setinitmode(INIT_DEFAULT | INIT_NOFORCEEXIT);
//初始化窗口
initgraph(600, 600);
//初始化随机种子
randomize();
//设置更新窗口模式,为手动模式
setrendermode(RENDER_MANUAL);
//主循环
mainloop();
//关闭窗口
closegraph();
return 0;
}
这是动态绘制上述抛物线的程序。
注意,每一帧绘制完成后我没有清屏,这意味着它将绘制出整条轨迹。
画到一半的效果图: