第一個JAVA小專案(太陽系行星運動模型)
1. 窗體的構建
對於遊戲來說,需要構建一個桌面窗體,建立MyFrame類,繼承Frame類,專用用於遊戲窗體的構建。在MyFrame類中建立launchFrame()方法,用於實現視窗的生成。
這三行程式碼分別用於設定窗體大小,位置和可見的,這三個方法繼承自Frame類。
setSize(Constant.GAME_HEIGHT,Constant.GAME_WIDTH);
setLocation(100, 100);
setVisible(true);
定義內部類PaintThread繼承Thread,重寫Runnable介面方法run(),一直執行 repaint()函式,Thread.sleep(40)是讓執行緒停止40ms。PaintThread().start()讓執行緒的run()方法執行,可以實現視窗的動態更新。
new PaintThread().start();
class PaintThread extends Thread{
public void run(){
while(true){
repaint();
try {
Thread.sleep(40);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
在addWindowListener方法中定義內部類WindowAdapter,內部內重寫了windowClosing()方法,用於窗體的退出(如果沒有這個方法,窗體將無法退出)
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
}
窗體構建類MyFrame 的完整程式碼如下:
package com.zhong.util;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class MyFrame extends Frame {
/**
* 載入視窗
*/
public void launchFrame(){
setSize(Constant.GAME_HEIGHT,Constant.GAME_WIDTH);
setLocation(100, 100);
setVisible(true);
new PaintThread().start();
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
}
class PaintThread extends Thread{
public void run(){
while(true){
repaint();
try {
Thread.sleep(40);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
2. 工具類
定義常量類Constant,用於儲存專案中的所有常量。程式碼如下:
package com.zhong.util;
/**
* 常量
* @author lenovo
*
*/
public class Constant {
public static final int GAME_WIDTH=800;
public static final int GAME_HEIGHT=800;
}
定義 GameUtil類,用於一般工具的實現。裡面的 getImage(String path)方法,用於從指定地址讀取圖片。完整程式碼如下:
package com.zhong.util;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
/**
*
* 常用工具類
* @author Kobe Zhong
*
*/
public class GameUtil {
private GameUtil(){
}
public static Image getImage(String path){
URL url=GameUtil.class.getClassLoader().getResource(path);
BufferedImage img=null;
try {
img=ImageIO.read(url);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return img;
}
}
3. 星球類
星球類Star是所有的星球所共有的屬性。
定義星球的屬性有圖片(代表每種星球),座標,寬度和長度(圖片的)。程式碼如下:
Image img;
double x,y;
int width,height;
定義星球類的過載建構函式,程式碼如下:
public Star(){
}
public Star(Image img){
this.img=img;
this.width=img.getWidth(null);
this.height=img.getHeight(null);
}
public Star(Image img,double x,double y){
this(img);
this.x=x;
this.y=y;
}
public Star(String imgpath,double x,double y){
this(GameUtil.getImage(imgpath),x,y);
}
定義星球類的draw()方法,可以在窗體上畫出星球的圖片。程式碼如下:
public void draw(Graphics g){
g.drawImage(img,(int)x,(int)y,null);
}
星球類Star的完整程式碼如下:
package com.zhong.solar;
import java.awt.Graphics;
import java.awt.Image;
import com.zhong.util.GameUtil;
public class Star {
Image img;
double x,y;
int width,height;
public void draw(Graphics g){
g.drawImage(img,(int)x,(int)y,null);
}
public Star(){
}
public Star(Image img){
this.img=img;
this.width=img.getWidth(null);
this.height=img.getHeight(null);
}
public Star(Image img,double x,double y){
this(img);
this.x=x;
this.y=y;
}
public Star(String imgpath,double x,double y){
this(GameUtil.getImage(imgpath),x,y);
}
}
4. 行星類
行星類Planet繼承星球類Star,還擁有自己所特有的屬性。
行星類包含長軸、短軸、運動速度、角度、中心恆星以及是否為衛星。屬性定義程式碼如下:
double longAxis;//長軸
double shortAxis;//短軸
double speed;
double degree;//角度
Star center;
boolean isSattilite;
行星Planet的過載建構函式的程式碼如下:
public Planet(Star center,String imgpath, double longAxis,double shortAxis, double speed) {
super(GameUtil.getImage(imgpath));
this.x=center.x+longAxis;
this.y=center.y;
// this.img=GameUtil.getImage(imgpath);
this.shortAxis = shortAxis;
this.longAxis = longAxis;
this.speed = speed;
this.center = center;
}
public Planet(Star center,String imgpath, double longAxis,double shortAxis, double speed,boolean isSattlite) {
this(center, imgpath, longAxis,shortAxis,speed);
this.isSattilite=isSattlite;
}
public Planet(Image img, double x, double y) {
super(img, x, y);
// TODO Auto-generated constructor stub
}
public Planet(String imgpath, double x, double y) {
super(imgpath, x, y);
// TODO Auto-generated constructor stub
}
行星的運動是繞著恆星中心,做橢圓運動,其座標變化的程式碼如下:
public void move(){
x=center.x+center.width/2+longAxis*Math.cos(degree);
y=center.y+center.height/2+shortAxis*Math.sin(degree);
degree+=speed;
}
行星運動軌跡也是橢圓,根據中心位置和長短軸的大小,畫出其軌跡即可,程式碼如下:
public void drawTrace(Graphics g){
double ovalX,ovalY,ovalWidth,ovalHeight;
ovalWidth=longAxis*2;
ovalHeight=shortAxis*2;
ovalX=center.x+center.width/2-longAxis;
ovalY=center.y+center.height/2-shortAxis;
Color c=g.getColor();
g.setColor(Color.BLUE);
g.drawOval((int)ovalX, (int)ovalY, (int)ovalWidth, (int)ovalHeight);
}
行星在窗體上的繪製重寫父類Star的draw()方法,並呼叫move()座標變化方法,還有是否為衛星的判斷,不是衛星就畫運動軌跡。具體程式碼如下:
public void draw(Graphics g){
super.draw(g);
move();
if(!isSattilite){
drawTrace(g);
}
}
行星類Planet的完整程式碼如下所示:
package com.zhong.solar;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import com.zhong.util.GameUtil;
public class Planet extends Star{
double longAxis;//長軸
double shortAxis;//短軸
double speed;
double degree;//角度
Star center;
boolean isSattilite;
public void draw(Graphics g){
super.draw(g);
move();
if(!isSattilite){
drawTrace(g);
}
}
public void drawTrace(Graphics g){
double ovalX,ovalY,ovalWidth,ovalHeight;
ovalWidth=longAxis*2;
ovalHeight=shortAxis*2;
ovalX=center.x+center.width/2-longAxis;
ovalY=center.y+center.height/2-shortAxis;
Color c=g.getColor();
g.setColor(Color.BLUE);
g.drawOval((int)ovalX, (int)ovalY, (int)ovalWidth, (int)ovalHeight);
}
public void move(){
x=center.x+center.width/2+longAxis*Math.cos(degree);
y=center.y+center.height/2+shortAxis*Math.sin(degree);
degree+=speed;
}
public Planet(Star center,String imgpath, double longAxis,double shortAxis, double speed) {
super(GameUtil.getImage(imgpath));
this.x=center.x+longAxis;
this.y=center.y;
// this.img=GameUtil.getImage(imgpath);
this.shortAxis = shortAxis;
this.longAxis = longAxis;
this.speed = speed;
this.center = center;
}
public Planet(Star center,String imgpath, double longAxis,double shortAxis, double speed,boolean isSattlite) {
this(center, imgpath, longAxis,shortAxis,speed);
this.isSattilite=isSattlite;
}
public Planet(Image img, double x, double y) {
super(img, x, y);
// TODO Auto-generated constructor stub
}
public Planet(String imgpath, double x, double y) {
super(imgpath, x, y);
// TODO Auto-generated constructor stub
}
}
5. 太陽系類(主方法)
定義SolarFrame為主類,繼承MyFrame。
載入背景圖片,並定義太陽,地球,火星,月球的物件,並初始化。程式碼如下:
Image bg=GameUtil.getImage("images/bg.jpg");
Star sun=new Star("images/sun.jpg", Constant.GAME_HEIGHT/2, Constant.GAME_WIDTH/2);
Planet earth =new Planet(sun, "images/earth.jpg",100,50,0.1 ) ;
Planet mars =new Planet(sun, "images/Mars.jpg",200,130,0.2 ) ;
Planet moon=new Planet(earth, "images/moon.jpg",20,13,0.01,true);
重寫paint()方法,將背景圖片,太陽,地球,火星和月球的圖片繪製。(注意:paint()方法為回撥方法,不需要在主函式呼叫它,在其父類的構造方法中已經呼叫,根據其所在物件重寫的功能具體實現)
public void paint(Graphics g){
g.drawImage(bg,0,0,null);
sun.draw(g);
earth.draw(g);
mars.draw(g);
moon.draw(g);
}
主方法中,定義SolarFrame物件,並呼叫它的launchFrame()方法(實現窗體的更新)。程式碼如下:
public static void main(String[] args) {
new SolarFrame().launchFrame();
}
package com.zhong.solar;
import java.awt.Graphics;
import java.awt.Image;
import com.zhong.util.Constant;
import com.zhong.util.GameUtil;
import com.zhong.util.MyFrame;
public class SolarFrame extends MyFrame{
Image bg=GameUtil.getImage("images/bg.jpg");
Star sun=new Star("images/sun.jpg", Constant.GAME_HEIGHT/2, Constant.GAME_WIDTH/2);
Planet earth =new Planet(sun, "images/earth.jpg",100,50,0.1 ) ;
Planet mars =new Planet(sun, "images/Mars.jpg",200,130,0.2 ) ;
Planet moon=new Planet(earth, "images/moon.jpg",20,13,0.01,true);
public void paint(Graphics g){
g.drawImage(bg,0,0,null);
sun.draw(g);
earth.draw(g);
mars.draw(g);
moon.draw(g);
}
public static void main(String[] args) {
new SolarFrame().launchFrame();
}
}