Java太阳系行星运动模型
太阳系行星运动模型
- 基本思路
- 此程序的核心算法
- 遇到的问题和解决办法
- 完整代码和运行效果
基本思路
首先,为了让行星运动看起来更加地逼真,采用斜二测画法计算行星的轨道,并将其绘制出来,再将无背景的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太阳系行星运动模型相关推荐
- java太阳系_Java太阳系小游戏分析和源代码
Java太阳系小游戏分析和源代码 -20150809 近期看了面向对象的一些知识.然后跟着老师的解说做了一个太阳系各行星绕太阳转的小游戏,来练习巩固一下近期学的知识: 用到知识点:类的继承.方法的重载 ...
- 使用css3的动画模拟太阳系行星公转
本文介绍使用css3的animation画一个太阳系行星公转的动画,再加以改进,讨论如何画椭圆的运行轨迹.然后分析京东和人人网使用animation的实际案例,最后结合css3的clip-path做一 ...
- pcie1 4 速度_太阳系行星们谁转得最快?八大行星自转速度排行榜,地球排第五...
不知道大家有没有玩儿过陀螺呢?玩儿陀螺的技术如果很好的话,它可以在地上飞快地旋转并且能够旋转很长的时间. 有趣的是,宇宙中的很多星球就像陀螺一样绕着一个中心轴旋转着.这就是星球的自转.在太阳系中有八颗 ...
- html+div+动画效果,html+css3太阳系行星运转动画效果的实现代码
原标题:html+css3太阳系行星运转动画效果的实现代码 做一个太阳系八大行星的运转动画,不包括行星的卫星,所有行星围绕太阳公转,行星采用纯色,暂时没有自转. 效果静态图: 动画中包括:太阳及各行星 ...
- OpenGL/C++实战——C++实现太阳系行星系统
注:本教程版权归实验楼所有,有兴趣的同学也可点进官网蓝桥网课:C++实现太阳系行星系统学习(免费课程) 文章目录 框架设计 认识 OpenGL 和 GLUT 类设计 stars.hpp solarsy ...
- C/C++编程日记:C++ 实现太阳系行星项目系统
项目简介:使用 C++实现 OpenGL GLUT 实现一个简单的太阳系行星系统,将涉及一些三维图形技术的数学基础.OpenGL 里的三维坐标系.OpenGL 里的光照模型.GLUT 的键盘事件处理. ...
- 150行Python代码模拟太阳系行星运转
今天我们用Python来模拟一下太阳系行星运动轨迹玩玩~ 先上成品图(运行效果含音乐的呦) 想要实现这样的效果并不难 1.准备材料 首先我们需要准备这样一些材料 宇宙背景图 背景透明的行星图 2:编写 ...
- solar2 android,Solar2(太阳系行星2)
iefans下载为用户提供的太阳系行星2ios版是一款非常简单有趣好玩的益智休闲模拟游戏,在太阳系行星2ios版手游中,你能够自由建立属于自己的行星系统,可以通过收集物资,不断的把自己的行星发展壮大, ...
- Python 用Ursina 3D引擎做一个太阳系行星模拟器
这次,我们再来用Ursina引擎来做一个太阳系行星模拟器吧! 想要了解Ursina 3D引擎的基本使用方法的话,查看我的另一篇文章: 手把手教你用Python编一个<我的世界> 1. 认识 ...
- C/C++编程分享:C++ 实现太阳系行星项目系统
项目简介:使用 C++实现 OpenGL GLUT 实现一个简单的太阳系行星系统,将涉及一些三维图形技术的数学基础.OpenGL 里的三维坐标系.OpenGL 里的光照模型.GLUT 的键盘事件处理. ...
最新文章
- SDUT2389Ballot evaluation
- ios15使用NSXMLParser解析XML
- 11.22Daily Scrum(2)
- Spring容器,控制反转,依赖注入
- MNIST数据集处理
- python 处理CSV数据
- James McCrae
- 机房走线槽安装现场需要检查的内容
- 国二java好过还是office好过,计算机二级考哪一个科目比较容易过,Ms office 较为简单实用...
- db4o php,db4o官方停止支持及面向对象数据库的一些感想
- List转json 顺序不一致
- ubuntu从源码编译安装python
- 如何清除Hacktool.Rootkit病毒,如何让msdirectx.sys此文件彻底删除,谢谢!
- 虚拟服务器添加打印机,在VMware Workstation 7虚拟机中应用主机打印机
- 关于antd table展开行expandable的坑和解决办法
- DNS域名解析详细说明
- 查看MXNet模型结构
- 锻造互联网青铜时代 (转)
- 安装11.2.0.3时,OUI的log报错:OUI-10066:Not All The Dependencies For The Component ... Could Be Found
- 输入关键字生成对联_百度“智能春联”玩出新年味 输入关键词秒出春联
热门文章
- php wind8.5,PHPWind 8.5 正式版源码下载
- moodle基本配置
- 手把手学习企业型网站之三firework做顶部的banner+nav
- taro Button按钮组件
- Android: eoeAndroid ~
- Win10华硕atk驱动怎么安装_正版win10下载好后怎么安装?正版win10安装教程
- 笔记本锁定计算机功能键,如何锁上笔记本键盘_怎样锁定笔记本键盘
- Ipmonitor9迁移安装后认证不可用的问题
- 计算机控制系统的框图,计算机控制系统原理框图.doc
- SQL Server 2012 下载和安装详细教程