太阳系行星运动模型

  • 基本思路
  • 此程序的核心算法
    • 遇到的问题和解决办法
      • 完整代码和运行效果

基本思路

首先,为了让行星运动看起来更加地逼真,采用斜二测画法计算行星的轨道,并将其绘制出来,再将无背景的PNG行星图片按照一定的大小比例绘制在对应的轨道上的某一点。同时,为了让行星运动起来,我们需要用一个循环,不停地计算行星的坐标,并将其绘制。在这之前,要将之前绘制的所有图片进行擦除,也就是清屏(这一操作放在循环当中)。在执行循环的过程中要在绘制图片和清屏之前加上一个时间间隔,这样才能让我们看到图片。这样呈现出的效果就是每个行星在其对应的轨道上运动。这个过程采用一个线程来执行。

此程序的核心算法

计算轨道的方程和计算行星的坐标在原理上是一致的,绘制轨道就是把行星在轨道上的每一点的坐标计算出来,并画上一个点,为了让效果更加明显,我采用了绘制一个半径为2个像素点的圆形的办法。

接下来我们考虑如何来计算轨道上每个点的坐标。因为考虑到行星运动近似圆周运动,因此我们采用将极坐标转化为直角坐标系的办法,即确定了轨道半径和角度,便可以计算出该坐标了。

数学公式如下:
y=√2/4 × r × sin(θ)
x=r × cos(θ)+y

在程序中定义的角度angle是一般的角度,要将它转换成弧度制,于是前面的θ应该写成(angle/180)*π。具体的实现方法如下:

/*** * @param r 半径* @param angle 角度* @return 行星相对运动中心的Y坐标*/public int setY(double r,double angle) {//由于屏幕中的原点是在左上角,因此y坐标添加一个负号return -(int)(r*Math.sin((angle/180)*Math.PI)*Math.sqrt(2)/4);}public int setX(double r,double angle,int y) {return (int)(r*Math.cos((angle/180)*Math.PI))-y;}

计算出的这些坐标需要加上屏幕中心点的坐标(让轨道移动到屏幕中间)。

遇到的问题和解决办法

在绘制行星的过程中要考虑哪个行星先画,原则上y坐标较小的先画(在屏幕上y坐标更小意味着它距离观测点更远)。这样,当行星图片重叠时,相对观测点更近的图片后画便可以覆盖更远的那张图片,可以呈现更加真实的效果。当考虑多个行星的重叠问题时,它的情况变得十分复杂,目前只能对处于中央的太阳、水星、金星做了相应的处理,对于其他的行星通过控制他们间的距离避免图像重叠问题。但这种方法使得离太阳的距离比例不够协调(虽然本来比例就无法真实还原,因为太阳相对地球等行星,它的半径过于大,并且木星与太阳的距离是地球与太阳的距离的29倍之多)。

除了行星间的图片重叠问题,还有轨道绘制问题,一般情况下,轨道最先画,确保轨道不会挡住行星,但考虑到中央的太阳会将水星与金星的一部分轨道覆盖,所以这部分的轨道绘制也要做特殊处理。

还有一个小问题,轨道是具有宽度的,要让行星的中心位于轨道的中心就要做相应的调整。具体实现如下:

for (int i = 0; i < 2700; i++) { //中间会发生重叠的轨道分为两部分分开画int y1 = setY(r[1], line_angle-20);int x1 = setX(r[1], line_angle-20, y1);g.fillOval(x1 + CENTRAL_X - 2, y1 + CENTRAL_Y - 2, 4, 4);int y2 = setY(r[2], line_angle-20);int x2 = setX(r[2], line_angle-20, y2);g.fillOval(x2 + CENTRAL_X - 2, y2 + CENTRAL_Y - 2, 4, 4);line_angle += 0.1;
}
if (y[1] > 0) {// 水星在太阳前if (y[2] > 0) {// 金星在太阳前g.drawImage(Sun.getImage(), CENTRAL_X - size[0] / 2, CENTRAL_Y - size[0] / 2, size[0], size[0],null);for (int i = 0; i < 900; i++) {//另一半轨道int y1 = setY(r[1], line_angle-20);int x1 = setX(r[1], line_angle-20, y1);g.fillOval(x1 + CENTRAL_X - 2, y1 + CENTRAL_Y - 2, 4, 4);int y2 = setY(r[2], line_angle-20);int x2 = setX(r[2], line_angle-20, y2);g.fillOval(x2 + CENTRAL_X - 2, y2 + CENTRAL_Y - 2, 4, 4);line_angle += 0.1;}g.drawImage(Mercury.getImage(), x[1] + CENTRAL_X - size[1] / 2, y[1] + CENTRAL_Y - size[1] / 2,size[1], size[1], null);g.drawImage(Venus.getImage(), x[2] + CENTRAL_X - size[2] / 2, y[2] + CENTRAL_Y - size[2] / 2,size[2], size[2], null);} else {// 金星在太阳后g.drawImage(Venus.getImage(), x[2] + CENTRAL_X - size[2] / 2, y[2] + CENTRAL_Y - size[2] / 2,size[2], size[2], null);g.drawImage(Sun.getImage(), CENTRAL_X - size[0] / 2, CENTRAL_Y - size[0] / 2, size[0], size[0],null);for (int i = 0; i < 900; i++) {//另一半轨道int y1 = setY(r[1], line_angle-20);int x1 = setX(r[1], line_angle-20, y1);g.fillOval(x1 + CENTRAL_X - 2, y1 + CENTRAL_Y - 2, 4, 4);int y2 = setY(r[2], line_angle-20);int x2 = setX(r[2], line_angle-20, y2);g.fillOval(x2 + CENTRAL_X - 2, y2 + CENTRAL_Y - 2, 4, 4);line_angle += 0.1;}g.drawImage(Mercury.getImage(), x[1] + CENTRAL_X - size[1] / 2, y[1] + CENTRAL_Y - size[1] / 2,size[1], size[1], null);}
} else {//水星在太阳后if (y[2] > 0) {//金星在太阳前g.drawImage(Mercury.getImage(), x[1] + CENTRAL_X - size[1] / 2, y[1] + CENTRAL_Y - size[1] / 2,size[1], size[1], null);g.drawImage(Sun.getImage(), CENTRAL_X - size[0] / 2, CENTRAL_Y - size[0] / 2, size[0], size[0],null);for (int i = 0; i < 900; i++) {//另一半轨道int y1 = setY(r[1], line_angle-20);int x1 = setX(r[1], line_angle-20, y1);g.fillOval(x1 + CENTRAL_X - 2, y1 + CENTRAL_Y - 2, 4, 4);int y2 = setY(r[2], line_angle-20);int x2 = setX(r[2], line_angle-20, y2);g.fillOval(x2 + CENTRAL_X - 2, y2 + CENTRAL_Y - 2, 4, 4);line_angle += 0.1;}g.drawImage(Venus.getImage(), x[2] + CENTRAL_X - size[2] / 2, y[2] + CENTRAL_Y - size[2] / 2,size[2], size[2], null);} else {//金星在太阳后g.drawImage(Venus.getImage(), x[2] + CENTRAL_X - size[2] / 2, y[2] + CENTRAL_Y - size[2] / 2,size[2], size[2], null);g.drawImage(Mercury.getImage(), x[1] + CENTRAL_X - size[1] / 2, y[1] + CENTRAL_Y - size[1] / 2,size[1], size[1], null);g.drawImage(Sun.getImage(), CENTRAL_X - size[0] / 2, CENTRAL_Y - size[0] / 2, size[0], size[0],null);for (int i = 0; i < 900; i++) {//另一半轨道int y1 = setY(r[1], line_angle-20);int x1 = setX(r[1], line_angle-20, y1);g.fillOval(x1 + CENTRAL_X - 2, y1 + CENTRAL_Y - 2, 4, 4);int y2 = setY(r[2], line_angle-20);int x2 = setX(r[2], line_angle-20, y2);g.fillOval(x2 + CENTRAL_X - 2, y2 + CENTRAL_Y - 2, 4, 4);line_angle += 0.1;}}
}

完整代码和运行效果

由于屏幕大小有限,天王星和海王星没有绘制。
(点开视频前请将音量调小一点,该视频声音略大)

Java模拟太阳系行星运动模型

package com.Solar201028;import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JWindow;public class SunSystem extends JFrame{public static void main(String[] agrs) {SunSystem sun=new SunSystem();sun.mysun();}public void mysun() {this.setTitle("太阳系行星运动模型");this.setSize(1900,1020);this.setLocationRelativeTo(null);this.setDefaultCloseOperation(3);JPanel mainjp=new JPanel();this.add(mainjp);//主面板Listener move=new Listener();mainjp.addMouseListener(move);this.setVisible(true);Graphics g=mainjp.getGraphics();move.setG(g);}}
package com.Solar201028;import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;import javax.swing.JButton;public class Listener implements MouseListener{private int begin=0;private Planet planet=new Planet();public void setG(Graphics g) {planet.setG(g);}@Overridepublic void mouseClicked(MouseEvent e) {}@Overridepublic void mousePressed(MouseEvent e) {}@Overridepublic void mouseReleased(MouseEvent e) {if(begin==0) {begin++;planet.start();}planet.turn();//控制开始与暂停}@Overridepublic void mouseEntered(MouseEvent e) {}@Overridepublic void mouseExited(MouseEvent e) {}}
package com.Solar201028;import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Random;import javax.swing.ImageIcon;public class Planet extends Thread{private static final int CENTRAL_X=942;//中心X坐标private static final int CENTRAL_Y=490;//中心Y坐标private static final int LINE_SIZE=4;//轨道宽度//依次为太阳,水星,金星,地球,月球,火星,木星,土星,天王星,海王星的尺寸private int[] size= {200,15,30,36,12,25,80,100,70,70};//依次为,水星,金星,地球,月球,火星,木星,土星,天王星,海王星的轨道半径,第一位0空出,使数组与size对应private double[] r= {0,90,160,300,60,450,600,820,900,1000};private int[] x=new int[9];//行星的X坐标private int[] y=new int[9];//行星的Y坐标private double[] angle=new double[9]; //绘制行星所需角度private double line_angle=0;//绘制轨道时所需的角度private URI uri;private URL url;private AudioClip ac; private boolean turn=false;private Graphics G; //面板画布public void setG(Graphics g) {this.G=g;}public void turn() {this.turn=!this.turn;}/*** * @param r 半径* @param angle 角度* @return 行星相对运动中心的Y坐标*/public int setY(double r,double angle) {return -(int)(r*Math.sin((angle/180)*Math.PI)*Math.sqrt(2)/4);}public int setX(double r,double angle,int y) {return (int)(r*Math.cos((angle/180)*Math.PI))-y;}public void run() {for(int i =0;i<angle.length;i++) {angle[i]=new Random().nextInt(360); //让行星从轨道上随机的一个位置出发}//创建缓冲图片BufferedImage buff=new BufferedImage(1900,1000,BufferedImage.TYPE_INT_ARGB);Graphics g=buff.getGraphics();ImageIcon background=new ImageIcon("image/cosmos.jpg");ImageIcon Sun =new ImageIcon("image/太阳.png");ImageIcon Mercury =new ImageIcon("image/水星.png");ImageIcon Venus =new ImageIcon("image/金星.png");ImageIcon Earth =new ImageIcon("image/地球.png");ImageIcon Moon = new ImageIcon("image/月球.png");ImageIcon Mars = new ImageIcon("image/火星.png");ImageIcon Jupiter = new ImageIcon("image/木星.png");ImageIcon Saturn = new ImageIcon("image/土星.png");
//      ImageIcon Uranus = new ImageIcon("image/天王星.png");
//      ImageIcon Neptune = new ImageIcon("image/海王星.png");//添加背景音乐File f1 = new File("music/Cornfield Chase.wav");try {uri = f1.toURI();url = uri.toURL();} catch (MalformedURLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}ac = Applet.newAudioClip(url);ac.loop();while (true) {try {Thread.sleep(42);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}if (turn) {g.drawImage(background.getImage(), 0, 0, buff.getWidth(), buff.getHeight(), null);for (int i = 1; i < 8; i++) {y[i] = setY(r[i], angle[i]);x[i] = setX(r[i], angle[i], y[i]);}g.setColor(Color.BLACK);for (int i = 0; i < 3600; i++) {//轨道for (int j = 3; j < 8; j++) {if (j == 4) {int y0 = setY(r[j], line_angle);int x0 = setX(r[j], line_angle, y0);g.fillOval(x0 + x[3] + CENTRAL_X - 2, y0 + y[3] + CENTRAL_Y - 2, 4, 4); //月球轨道} else {int y0 = setY(r[j], line_angle);int x0 = setX(r[j], line_angle, y0);g.fillOval(x0 + CENTRAL_X - 2, y0 + CENTRAL_Y - 2, 4, 4);}}line_angle += 0.1;}for (int i = 0; i < 2700; i++) { //中间会发生重叠的轨道分为两部分分开画int y1 = setY(r[1], line_angle-20);int x1 = setX(r[1], line_angle-20, y1);g.fillOval(x1 + CENTRAL_X - 2, y1 + CENTRAL_Y - 2, 4, 4);int y2 = setY(r[2], line_angle-20);int x2 = setX(r[2], line_angle-20, y2);g.fillOval(x2 + CENTRAL_X - 2, y2 + CENTRAL_Y - 2, 4, 4);line_angle += 0.1;}if (y[1] > 0) {// 水星在太阳前if (y[2] > 0) {// 金星在太阳前g.drawImage(Sun.getImage(), CENTRAL_X - size[0] / 2, CENTRAL_Y - size[0] / 2, size[0], size[0],null);for (int i = 0; i < 900; i++) {int y1 = setY(r[1], line_angle-20);int x1 = setX(r[1], line_angle-20, y1);g.fillOval(x1 + CENTRAL_X - 2, y1 + CENTRAL_Y - 2, 4, 4);int y2 = setY(r[2], line_angle-20);int x2 = setX(r[2], line_angle-20, y2);g.fillOval(x2 + CENTRAL_X - 2, y2 + CENTRAL_Y - 2, 4, 4);line_angle += 0.1;}g.drawImage(Mercury.getImage(), x[1] + CENTRAL_X - size[1] / 2, y[1] + CENTRAL_Y - size[1] / 2,size[1], size[1], null);g.drawImage(Venus.getImage(), x[2] + CENTRAL_X - size[2] / 2, y[2] + CENTRAL_Y - size[2] / 2,size[2], size[2], null);} else {// 金星在太阳后g.drawImage(Venus.getImage(), x[2] + CENTRAL_X - size[2] / 2, y[2] + CENTRAL_Y - size[2] / 2,size[2], size[2], null);g.drawImage(Sun.getImage(), CENTRAL_X - size[0] / 2, CENTRAL_Y - size[0] / 2, size[0], size[0],null);for (int i = 0; i < 900; i++) {int y1 = setY(r[1], line_angle-20);int x1 = setX(r[1], line_angle-20, y1);g.fillOval(x1 + CENTRAL_X - 2, y1 + CENTRAL_Y - 2, 4, 4);int y2 = setY(r[2], line_angle-20);int x2 = setX(r[2], line_angle-20, y2);g.fillOval(x2 + CENTRAL_X - 2, y2 + CENTRAL_Y - 2, 4, 4);line_angle += 0.1;}g.drawImage(Mercury.getImage(), x[1] + CENTRAL_X - size[1] / 2, y[1] + CENTRAL_Y - size[1] / 2,size[1], size[1], null);}} else {//水星在太阳后if (y[2] > 0) {//金星在太阳前g.drawImage(Mercury.getImage(), x[1] + CENTRAL_X - size[1] / 2, y[1] + CENTRAL_Y - size[1] / 2,size[1], size[1], null);g.drawImage(Sun.getImage(), CENTRAL_X - size[0] / 2, CENTRAL_Y - size[0] / 2, size[0], size[0],null);for (int i = 0; i < 900; i++) {int y1 = setY(r[1], line_angle-20);int x1 = setX(r[1], line_angle-20, y1);g.fillOval(x1 + CENTRAL_X - 2, y1 + CENTRAL_Y - 2, 4, 4);int y2 = setY(r[2], line_angle-20);int x2 = setX(r[2], line_angle-20, y2);g.fillOval(x2 + CENTRAL_X - 2, y2 + CENTRAL_Y - 2, 4, 4);line_angle += 0.1;}g.drawImage(Venus.getImage(), x[2] + CENTRAL_X - size[2] / 2, y[2] + CENTRAL_Y - size[2] / 2,size[2], size[2], null);} else {//金星在太阳后g.drawImage(Venus.getImage(), x[2] + CENTRAL_X - size[2] / 2, y[2] + CENTRAL_Y - size[2] / 2,size[2], size[2], null);g.drawImage(Mercury.getImage(), x[1] + CENTRAL_X - size[1] / 2, y[1] + CENTRAL_Y - size[1] / 2,size[1], size[1], null);g.drawImage(Sun.getImage(), CENTRAL_X - size[0] / 2, CENTRAL_Y - size[0] / 2, size[0], size[0],null);for (int i = 0; i < 900; i++) {int y1 = setY(r[1], line_angle-20);int x1 = setX(r[1], line_angle-20, y1);g.fillOval(x1 + CENTRAL_X - 2, y1 + CENTRAL_Y - 2, 4, 4);int y2 = setY(r[2], line_angle-20);int x2 = setX(r[2], line_angle-20, y2);g.fillOval(x2 + CENTRAL_X - 2, y2 + CENTRAL_Y - 2, 4, 4);line_angle += 0.1;}}}g.drawImage(Earth.getImage(), x[3] + CENTRAL_X - size[3] / 2, y[3] + CENTRAL_Y - size[3] / 2, size[3],size[3], null);g.drawImage(Moon.getImage(), x[4] + x[3] + CENTRAL_X - size[4] / 2,y[4] + y[3] + CENTRAL_Y - size[4] / 2, size[4], size[4], null);g.drawImage(Mars.getImage(), x[5] + CENTRAL_X - size[5] / 2, y[5] + CENTRAL_Y - size[5] / 2, size[5],size[5], null);g.drawImage(Jupiter.getImage(), x[6] + CENTRAL_X - size[6] / 2, y[6] + CENTRAL_Y - size[6] / 2, size[6],size[6], null);g.drawImage(Saturn.getImage(), x[7] + CENTRAL_X - size[7] / 2, y[7] + CENTRAL_Y - size[7] / 2, size[7],size[7], null);// 将缓冲图片画到面板上G.drawImage(buff, 0, 0, null);// 运动速度angle[1] += 4;angle[2] += 1.5;angle[3] += 1;angle[4] += 12;angle[5] += 0.5;angle[6] += 0.1;angle[7] += 0.06;}}}
}

背景音乐和图片就不提供了,有兴趣的读者可以自行寻找图片和背景音乐。

Java太阳系行星运动模型相关推荐

  1. java太阳系_Java太阳系小游戏分析和源代码

    Java太阳系小游戏分析和源代码 -20150809 近期看了面向对象的一些知识.然后跟着老师的解说做了一个太阳系各行星绕太阳转的小游戏,来练习巩固一下近期学的知识: 用到知识点:类的继承.方法的重载 ...

  2. 使用css3的动画模拟太阳系行星公转

    本文介绍使用css3的animation画一个太阳系行星公转的动画,再加以改进,讨论如何画椭圆的运行轨迹.然后分析京东和人人网使用animation的实际案例,最后结合css3的clip-path做一 ...

  3. pcie1 4 速度_太阳系行星们谁转得最快?八大行星自转速度排行榜,地球排第五...

    不知道大家有没有玩儿过陀螺呢?玩儿陀螺的技术如果很好的话,它可以在地上飞快地旋转并且能够旋转很长的时间. 有趣的是,宇宙中的很多星球就像陀螺一样绕着一个中心轴旋转着.这就是星球的自转.在太阳系中有八颗 ...

  4. html+div+动画效果,html+css3太阳系行星运转动画效果的实现代码

    原标题:html+css3太阳系行星运转动画效果的实现代码 做一个太阳系八大行星的运转动画,不包括行星的卫星,所有行星围绕太阳公转,行星采用纯色,暂时没有自转. 效果静态图: 动画中包括:太阳及各行星 ...

  5. OpenGL/C++实战——C++实现太阳系行星系统

    注:本教程版权归实验楼所有,有兴趣的同学也可点进官网蓝桥网课:C++实现太阳系行星系统学习(免费课程) 文章目录 框架设计 认识 OpenGL 和 GLUT 类设计 stars.hpp solarsy ...

  6. C/C++编程日记:C++ 实现太阳系行星项目系统

    项目简介:使用 C++实现 OpenGL GLUT 实现一个简单的太阳系行星系统,将涉及一些三维图形技术的数学基础.OpenGL 里的三维坐标系.OpenGL 里的光照模型.GLUT 的键盘事件处理. ...

  7. 150行Python代码模拟太阳系行星运转

    今天我们用Python来模拟一下太阳系行星运动轨迹玩玩~ 先上成品图(运行效果含音乐的呦) 想要实现这样的效果并不难 1.准备材料 首先我们需要准备这样一些材料 宇宙背景图 背景透明的行星图 2:编写 ...

  8. solar2 android,Solar2(太阳系行星2)

    iefans下载为用户提供的太阳系行星2ios版是一款非常简单有趣好玩的益智休闲模拟游戏,在太阳系行星2ios版手游中,你能够自由建立属于自己的行星系统,可以通过收集物资,不断的把自己的行星发展壮大, ...

  9. Python 用Ursina 3D引擎做一个太阳系行星模拟器

    这次,我们再来用Ursina引擎来做一个太阳系行星模拟器吧! 想要了解Ursina 3D引擎的基本使用方法的话,查看我的另一篇文章: 手把手教你用Python编一个<我的世界> 1. 认识 ...

  10. C/C++编程分享:C++ 实现太阳系行星项目系统

    项目简介:使用 C++实现 OpenGL GLUT 实现一个简单的太阳系行星系统,将涉及一些三维图形技术的数学基础.OpenGL 里的三维坐标系.OpenGL 里的光照模型.GLUT 的键盘事件处理. ...

最新文章

  1. SDUT2389Ballot evaluation
  2. ios15使用NSXMLParser解析XML
  3. 11.22Daily Scrum(2)
  4. Spring容器,控制反转,依赖注入
  5. MNIST数据集处理
  6. python 处理CSV数据
  7. James McCrae
  8. 机房走线槽安装现场需要检查的内容
  9. 国二java好过还是office好过,计算机二级考哪一个科目比较容易过,Ms office 较为简单实用...
  10. db4o php,db4o官方停止支持及面向对象数据库的一些感想
  11. List转json 顺序不一致
  12. ubuntu从源码编译安装python
  13. 如何清除Hacktool.Rootkit病毒,如何让msdirectx.sys此文件彻底删除,谢谢!
  14. 虚拟服务器添加打印机,在VMware Workstation 7虚拟机中应用主机打印机
  15. 关于antd table展开行expandable的坑和解决办法
  16. DNS域名解析详细说明
  17. 查看MXNet模型结构
  18. 锻造互联网青铜时代 (转)
  19. 安装11.2.0.3时,OUI的log报错:OUI-10066:Not All The Dependencies For The Component ... Could Be Found
  20. 输入关键字生成对联_百度“智能春联”玩出新年味 输入关键词秒出春联

热门文章

  1. php wind8.5,PHPWind 8.5 正式版源码下载
  2. moodle基本配置
  3. 手把手学习企业型网站之三firework做顶部的banner+nav
  4. taro Button按钮组件
  5. Android: eoeAndroid ~
  6. Win10华硕atk驱动怎么安装_正版win10下载好后怎么安装?正版win10安装教程
  7. 笔记本锁定计算机功能键,如何锁上笔记本键盘_怎样锁定笔记本键盘
  8. Ipmonitor9迁移安装后认证不可用的问题
  9. 计算机控制系统的框图,计算机控制系统原理框图.doc
  10. SQL Server 2012 下载和安装详细教程