星系模擬器開發日誌(一) 如何科學地用C++畫圖

代碼下載地址:

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;
}

這是動態繪製上述拋物線的程序。
注意,每一幀繪製完成後我沒有清屏,這意味着它將繪製出整條軌跡。

畫到一半的效果圖:



發佈了53 篇原創文章 · 獲贊 17 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章