资源素材
太阳系只有8颗行星,加上太阳,一共9张图。没有的朋友可以到文末下载地址下载。
def openSolor(solar):
def loadImg(name):
str1= os.path.join(basePath, name+ '.png')
img= Image.open(str1)
solar[name]= img
basePath= r'D:\太阳系\素材'
#
loadImg('sun')
loadImg('venus')
loadImg('jupiter')
loadImg('earth')
loadImg('mars')
loadImg('mercury')
loadImg('neptune')
loadImg('pluto')
loadImg('uranus')
loadImg('saturn')
基本运动原理
每颗行星的运行轨迹都是椭圆形的。这里我们使用参数方程来计算坐标:
x=cos(arc)*a
y=sin(arc)*b
其中,a、b为椭圆的长、短轴,arc为运行角度,x、y为水平面坐标。
先上一张静态效果图吧!
参数的设置
为了好看,实际参数不能是真实的。但至少应满足一些关键条件。首先,不要弄错行星的顺序。行星轨道之间的距离不是等距的,而是逐渐增加的。
二是火星和木星之间直接有一条小行星带,所以这两颗行星的轨道之间最好留个空隙。另外,行星的外圈,公转速度越慢。
def initSolar(posList):
def getNumber():
return random.randint(0,35)*10
posList['sun']={'pos': (0,360), 'rate': 2, 'scale':1, 'radx': 1, 'layer':360}
posList['mercury']={'rate': 0.15, 'radx':500, 'arc': getNumber(), 'rady': 200, 'speed':15}
posList['venus']={'rate': 0.2, 'radx':550, 'arc': getNumber(), 'rady': 250, 'speed':10}
posList['earth']={'rate': 0.2, 'radx':630, 'arc': getNumber(), 'rady': 320, 'speed':8}
posList['mars']={'rate': 0.2, 'radx':740, 'arc': getNumber(), 'rady': 410, 'speed':6}
posList['jupiter']={'rate': 0.7, 'radx':1050, 'arc': getNumber(), 'rady': 650, 'speed':4}
posList['saturn']={'rate': 1, 'radx':1250, 'arc': getNumber(), 'rady': 800, 'speed':3}
posList['uranus']={'rate': 0.3, 'radx':1480, 'arc': getNumber(), 'rady': 970, 'speed':2}
posList['neptune']={'rate': 0.3, 'radx':1740, 'arc': getNumber(), 'rady': 1160, 'speed':2}
投影
大体效果是将行星围绕太阳的轨道平面对准水平面,投影到垂直屏幕上。投影算法并不难。
x= math.sin(math.radians(a))* radx+ x0
y= math.cos(math.radians(a))* rady+ y0
showX= x
showY= midY- H/(D+y)*y
其中,x、y为旋转平面坐标,showX、showY为投影到垂直平面的坐标。 H是平面的高度,D是屏幕到太阳系的距离。
从数据上看,我们的太阳系模型是一个很小的模型,或者说电脑屏幕很大。因为两者其实大小差不多,这样从观察者的角度来看,可以有明显的近大远小的效果。从这个效果我们可以知道数据和真实值的差距是非常大的。
近大远小的效果,只与y相关。
data['scale']= (y0+D)/(y+D)
遮挡效果
为了有真实感,行星之间、行星与轨道之间、轨道与太阳之间等的遮挡效果是最关键的。
我们的做法是先画下半区,再画太阳,再画上半区。下半区先画出远处的行星;在上半区,最先画出近日点行星。以保证正确的遮挡效果。
drawOrb(img, solar, posList, 0, 90, True)
pasteSolor(img, solar, posList)
drawOrb(img, solar, posList, 90, 180, False)
稍微复杂一点的是行星与自身轨道的遮挡关系。必须要达到一球一线的效果才好看。而且传球的位置也不固定。在这里,我们将轨道分成两半,根据行星所在的角度来绘制。
一部分轨道被行星挡住,另一部分轨道被行星挡住,但留出一些空间,以达到更自然的穿球效果。
drawArc(arc1, arc)
rate= posList[name]['rate']* posList[name]['scale']
pic= solarImg[name].resize(effect.tupleRound(effect.tupleMul(solarImg[name].size, rate)), Image.ANTIALIAS)
pos= effect.tupleRound(effect.tupleAdd(posList[name]['pos'], effect.tupleMul(pic.size, -0.5)))
r, g, b, alpha= pic.split()
img.paste(pic, pos, mask= alpha)
# 穿球点,随arc不同而不同
# 90度位置,在中心穿球,
# 越接近0或180度,越接近球边缘
# 根据这种性质,采用cos来模拟
darc= abs(round(math.cos(math.radians(arc))*solarImg[name].size[1]*rate/50))
# darc= abs(round(math.cos(math.radians(arc))*5))
# print(name, arc, darc)
drawArc(arc+darc, arc2)
素材链接:
提取码:5bjj
本文为原创文章,版权归知行编程网所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ 如何在python中创建一个对象数组08/25
- ♥ python numpy.dot之点积运算11/30
- ♥ python变量类型的使用01/05
- ♥ 如何实现python汇率换算代码09/01
- ♥ python f.write中文乱码怎么解决10/06
- ♥ 如何使用python脚本定时清空文件内容?12/05
内容反馈