【Java-20】Java實現行星運動
阿新 • • 發佈:2019-01-10
效果圖(除了行星運動還有滾動程式碼特效)
主要思想
solarFengzhuang繼承自視窗載入類,lunch是父類載入視窗方法,且父類中還有paint方法,paint方法在此子類中被重寫,lunch一旦載入就會顯示出視窗,之後會啟動執行緒,執行緒工作是個迴圈過程,每隔40毫秒迴圈一次,每次迴圈會在視窗呼叫paint方法,在這個專案中,每個迴圈會畫一次太陽、地球、行星、月亮,而這個畫的操作我們把它封裝到一個類中,先把太陽封裝起來,封裝的類有需要載入的太陽圖片、位置、以及畫的方法,類搞好之後我們建立一個太陽物件,建立時候對其初始化,就是把引數傳進去然後由物件呼叫畫的方法,對於地球、行星、月亮由於其位置還與圍繞的星位置有關故類應該與太陽不同,繼承即可
對於字幕來說,先將字幕讀入到字串string,中然後分割到字串陣列str[]中,在paint方法內每次都輸出每一個字串,只不過字串位置要隨著變數變化而變化
同時還要明確,對於字串、圖片、橢圓來說使用g.drawx畫的輸入位置都是圖片左上角位置,要想畫理想位置,應該用x-圖片寬度
以下是Java詳盡註釋程式碼
1.視窗載入類
package nextpackage; import java.awt.Color; import java.awt.Font; import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Random; /** * 加載出視窗 * * @author My_2 * */ public class gameFrame extends Frame { /** * 載入視窗 */ public void lunch() { setSize(Constant.Frame_wide, Constant.Frame_high);// 畫布大小,windows類下面方法,繼承得到的 setLocation(0, 0);// 畫布左上角位置 setVisible(true);// 畫布可見 // addWindowListener方法作用是調出來的視窗能×掉 // 呼叫addWindowListener方法,WindowAdapter屬於方法addWindowListener的內部類 // new WindowAdapter()為建立物件,這個物件要重寫方法 addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); new Painthread().start();// 啟動執行緒 } // window是Frame的父類,paint是Frame的一個方法 class Painthread extends Thread {//載入視窗時候會啟動執行緒,一啟動就會呼叫畫視窗,迴圈呼叫paint() public void run() { while (true) { repaint(); try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
2.太陽及行星類
package nextpackage; import java.awt.Graphics; import java.awt.Image; public class Star { String path=null; Image Img2; int x,y;//圖片左上角 double wide,heigh;//定義圖片高度寬度,因為我們輸入座標是圖片左上角座標,我們需要用圖片左上角座標減去圖片寬高一半才是圖片真正中心座標 public Star(String path1,int x1,int y1) { this.path=path1; this.x=x1; this.y=y1; Img2 = GameFunc.getImage(path); this.wide=Img2.getWidth(null); this.heigh=Img2.getHeight(null); } public Star()//不能少,因為後面有繼承這個類,子類構造方法只初始化了自己變數,故會預設super() { } public void draw(Graphics g) { g.drawImage(Img2, (int)(this.x-this.wide/2), (int)(this.y-this.heigh/2), null);// 載入圖片,圖片,位置,null } } package nextpackage; import java.awt.Graphics; /** * 地球繼承太陽的類 * @author admin *引數:所繞的行星,太陽、長短半軸、速度、引數方程角度 */ public class enrth extends Star { Star satr;//所繞的行星 Star center;//太陽位置 double a,b;//長短半軸 double spend,angle;//速度、引數方程角度 public enrth(Star satr,Star center,String path,double a,double b,double spend) { this.satr=satr; this.center=center; this.a=a; this.b=b; this.spend=spend; this.path=path; Img2 = GameFunc.getImage(this.path); this.wide=Img2.getWidth(null);//圖片有高度寬度 this.heigh=Img2.getHeight(null); } // public enrth(String path,int x,int y) { // super(path,x,y); // } // 重寫 public void draw(Graphics g) { // 上層paint()方法會反覆呼叫,每次更新x,y this.x=(int)(satr.x+a*Math.cos(angle)); // System.out.print(this.x+"\n"); this.y=(int)(satr.y+b*Math.sin(angle)); this.angle=this.angle+this.spend; // 線 if (this.center == this.satr) { g.drawLine((int)(this.x),(int)(this.y), satr.x, satr.y); } // 畫地球 g.drawImage(Img2, (int)(this.x-this.wide/2), (int)(this.y-this.heigh/2), null); // 橢圓軌跡,月亮繞地球不需要 if (this.center == this.satr) { g.drawOval((int) (satr.x - a), (int) (satr.y - b), (int) (2 * a),(int) (2 * b)); } } }
3.呼叫類
package nextpackage;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class solarFengzhuang extends gameFrame{
String path=null;
Image Img2;
//字幕每行字幕位置
double string_x[];
double string_y[];
String str[];
/**
* 建構函式,建立物件時候首先呼叫這個方法
* @param path1
*/
public solarFengzhuang()
{
String string= readString("C:/Users/慧天地/Desktop/Java_bao/data/a/data.txt");
str=string.split("\n");
string_x=new double[str.length];
string_y=new double[str.length];
for(int i=0;i<str.length;i++){
System.out.println(str[i]);
string_x[i]=1000;
string_y[i]=1000+20*i;
}
}
/**
* 讀檔案中東西至字串
* @param FILE_IN
* @return
*/
private static String readString(String FILE_IN)
{
String str="";
File file=new File(FILE_IN);
try {
FileInputStream in=new FileInputStream(file);
// size 為字串的長度 ,這裡一次性讀完
int size=in.available();
byte[] buffer=new byte[size];
in.read(buffer);
in.close();
str=new String(buffer,"GB2312");
} catch (IOException e) {
// TODO Auto-generated catch block
return null;
}
return str;
}
Star star = new Star("Image/sun2.png",500,500);//建立太陽物件
enrth QQ=new enrth(star,star,"Image/mu.png",150,80,0.01);//其他行星物件
enrth earth=new enrth(star,star,"Image/earth.png",400,200,0.02);//地球物件
enrth satellite_360=new enrth(earth,star,"Image/month.png",100,60,0.1);//月亮物件
public void paint(Graphics g) {// 回撥
//g.drawImage(Img2, 0, 0, null);// 載入圖片同時載入一個視窗,圖片,位置,null
Color color=g.getColor();//儲存畫筆顏色
g.setColor(Color.RED);//將畫筆顏色置為紅色
// 下面也是一種設顏色方法,應首選下面
// Color c=new Color(255, 0, 0);
// g.setColor(c);
Font font=new Font("黑體",Font.BOLD,50);
g.setFont(font);//setFont方法傳入內容決定了要建立物件
g.drawString("銀河系", Constant.Frame_wide/2-80, 100);
g.setColor(color);
Font font1=new Font("Courier",Font.LAYOUT_LEFT_TO_RIGHT,15);
g.setFont(font1);//setFont方法傳入內容決定了要建立物件
for(int i=0;i<str.length;i++){
// System.out.println(str[i]);
g.drawString(str[i], (int)(string_x[i]), (int)(string_y[i]));
//string_x[i]-=10;
string_y[i]-=7;//7這個值控制了字幕速度
}
star.draw(g);//畫太陽
earth.draw(g);//畫地球
QQ.draw(g);
satellite_360.draw(g);
}
public static void main(String[] arg) {
// solarFengzhuang繼承自視窗載入類,lunch是父類載入視窗方法,且父類中還有paint方法,paint方法在此子類中
// 被重寫,lunch一旦載入就會顯示出視窗,之後會啟動執行緒,執行緒工作是個迴圈過程,每隔40毫秒迴圈一次,每次迴圈會在視窗呼叫
// paint方法,在這個專案中,每個迴圈會畫一次太陽、地球、行星、月亮,而這個畫的操作我們把它封裝到一個類中,先把太陽封裝起
// 來,封裝的類有需要載入的太陽圖片、位置、以及畫的方法,類搞好之後我們建立一個太陽物件,建立時候對其初始化,就是把引數傳進去
// 然後由物件呼叫畫的方法,對於地球、行星、月亮由於其位置還與圍繞的星位置有關故類應該與太陽不同,繼承即可
// 對於字幕來說,先將字幕讀入到字串string,中然後分割到字串陣列str[]中,在paint方法內每次都輸出每一個字串,
// 只不過字串位置要隨著變數變化而變化
// 同時還要明確,對於字串、圖片、橢圓來說使用g.drawx畫的輸入位置都是圖片左上角位置,要想畫理想位置,應該用x-圖片寬度
solarFengzhuang myFrame2 = new solarFengzhuang();
myFrame2.lunch();
}
}