模拟太阳系项目
2016-12-22 17:53
381 查看
这个其实是之前看视频的时候老师教的一个项目,但是也敲了,但是只能看懂代码不能自己设计出来,并且还苦于没有找到图片素材也就没有继续下去了;
今天抽了一下时间;现在网上找一些图片然后利用之前学的那皮毛都不到的ps,p了一下图,虽然依旧没有那么好但是也够用了落;
先分析一下这个面向对象设计的代码的一些特性的展示;以及自己学会了什么;
1;利用建图片工具包,给这段代码带来很好的移值性,
2;充分利用继承,很好的减少了重复编写相同代码,并且很好的联系;
3;很好的扩展性,可以扩展到银河系,因为将太阳只是作为Star的一个对象;因此还可以创造其他对象来建立其他系别;plant可以即包括行星也包括卫星,因为设置了围绕旋转的星球这个可以改变的;
4;构造方法的创建;
5;方法的创建,使代码可读性更高;
先看一下运行结果,因为是动态的,我只截了3张图来表示;
再看一下分析思路吧,设计也差不多,只是要先宏观概括更好
关于其设计;
其程序的运行步骤就是;
先创建对象,然后画出;
这里分开,背景可直接画出,
太阳在Star类中draw画出;
行星在Plant类画出,并且因为存在继承关系并且它还有画出其椭圆轨迹以及移动,
最后在showFrame方法中不断开启线程到达图片移动的效果;
因为线程的不断开启就引入了双缓冲;
至于各自的构造方法就看自己了;
第一部分;在gameUtil包中;
1;Constant类,常量类,设置了窗口的长宽,方便后期修改,提高程序的健壮性和可
扩展性;
2;GamepictureUtil类;图片加载类;得到图片路径将该图片变成image对象返回;
后期的使用就是例如
Image bg = GamePictureUtil.getImages(“路径(scr中的路径)”);
就将这个路径下的地址通过这个静态方法将图片变成Image对象返回;bg为这个对象的
引用;
3;MyFrame类;继承java.awt.Frame类;这个类就实现了窗口中一些基本的设置;
例如;设置窗口的大小,位置,是否可见,以及窗口是否可以关闭,这里因为后面要加
载图片因此还需要一个内部类来启动线程,不断重画窗口,来到达窗口是不消失的,因
为在不断重画;
4;为什么要创建一个gameUtil包,并且在里面添加这些类呢;
可移值性;因为这个包里面的类,基本上是实现游戏窗口时都需要的类因此单独成一个
包,下次则直接将这个包拷贝过去,就完成了。
第二部分;就要实现模拟太阳系的具体类了;
可分为;太阳和行星(卫星);
当然我们也是需要一个窗口类,类实现操作的。
现在分析;其实面向对象和面向过程一样,都是从main函数开始分析的;
在SolarFarame中main方法中创建了一个SolarFarame对象的时候,则此时就进行了画
图得一系列工作,再调用Frame中的showFrame方法,完成了窗口的显示,注意这里还不
断重启线程,这里就可以完成行星的移动了,只需改变其坐标即可,下次线程他就会自
动再次画出即显示在其他地方,具体的流程就是这样的;
至于Frame中的showFrame方法中,是比较简单的,就是完成一些最后窗口的显示;
细说一下创建对象时太阳系模型的显示吧?
关于其显示就是
先显示背景,就是先通过路径得到对象,引用指向之后再画出即可;
太阳,行星也是一样的,不同的是他们不同背景,他们创建了单独的类来通过构成方法
来设置参数,最后还是画出来;
大概的流程就是这样,至于细节就十分重要了,这也是体现面向对象多种好处的时候;
1;因为无论是背景还是太阳,还是行星我们都要将其画出显示在窗口上,因此我们可
以在SolarFarame类中创建一个专门显示图片的方法;paint
因为太阳行星不同于背景,创建了独立的类,因此太阳和行星就调用自己的类来显示图
片,(还有一个原因是,他们要设置的参数都不同,因此单独成类创建方法画出也是很
好的;)
进一步分析显示太阳行星;
这里又有注意了,太阳和行星这间也存在相同的地方;
例如都是图片需要显示,只是行星多了需要画出运动轨迹,需要移动;
因此可以得出,行星可以继承太阳;
因此单独的对于画出图片,只需要太阳类中创建显示的方法即可;
关于画出,它重写了父类的draw方法,因为行星还需要画出其运动轨迹,并且他还是移
动的,因此要不断在不同的位置显示,因此他需要重写;
接下来我们按着思路看他轨迹画出吧;椭圆的画出;
在awt中都提供了这些方法;
public abstract void drawOval(int x, int y, int width, int height);
我们所需要做的是,计算出他这些参数即可,坐标xy已经长轴短轴
中间那个是设置颜色,注意设置颜色前要保存原颜色,之后要还原回去;注意;防止画
笔颜色出现混乱;
我们再看他的移动吧;按照其运动轨迹移动就ok了;关于行星的移动,前面也说了一点
,我们只需改变其图片的xy坐标即可,在下个线程的时候,再次画出的时候就可以表示
成移动了;
关于太阳系模型的基本思路就几乎完成了,几乎,我们还缺少分享构造方法了。并且在
这里我们构造方法的设置应该是几乎接近源码那样吧?这个不多说自己看代码吧;
按照这个思路下来我们运行的结果应该是闪的,我们还少了一个东西,直接百度图片加
载时的双缓冲即可完成;因为都需要,这放到SolarFrame类即可;
贴一下所有代码吧;
今天抽了一下时间;现在网上找一些图片然后利用之前学的那皮毛都不到的ps,p了一下图,虽然依旧没有那么好但是也够用了落;
先分析一下这个面向对象设计的代码的一些特性的展示;以及自己学会了什么;
1;利用建图片工具包,给这段代码带来很好的移值性,
2;充分利用继承,很好的减少了重复编写相同代码,并且很好的联系;
3;很好的扩展性,可以扩展到银河系,因为将太阳只是作为Star的一个对象;因此还可以创造其他对象来建立其他系别;plant可以即包括行星也包括卫星,因为设置了围绕旋转的星球这个可以改变的;
4;构造方法的创建;
5;方法的创建,使代码可读性更高;
先看一下运行结果,因为是动态的,我只截了3张图来表示;
再看一下分析思路吧,设计也差不多,只是要先宏观概括更好
关于其设计;
其程序的运行步骤就是;
先创建对象,然后画出;
这里分开,背景可直接画出,
太阳在Star类中draw画出;
行星在Plant类画出,并且因为存在继承关系并且它还有画出其椭圆轨迹以及移动,
最后在showFrame方法中不断开启线程到达图片移动的效果;
因为线程的不断开启就引入了双缓冲;
至于各自的构造方法就看自己了;
第一部分;在gameUtil包中;
1;Constant类,常量类,设置了窗口的长宽,方便后期修改,提高程序的健壮性和可
扩展性;
package gameUtil; /** * 设置常量类,提高程序的健壮性; * @author Administrator * */ public class Constant { /** * 将窗口的长宽设置为常量,已供其他类使用,也便于修改; */ public static final int WIGHT = 788;//窗口的宽度 public static final int HIGTH = 610;//窗口的高度 }
2;GamepictureUtil类;图片加载类;得到图片路径将该图片变成image对象返回;
package gameUtil; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.URL; import javax.imageio.ImageIO; /** * 这个有点点其他知识; * 通过这个类的static方法实现通过输入图片路径(scr中的路径)返回图片对象; * @author Administrator * */ public class GamePictureUtil { /** * 设置为私有构成方法,不允许对象创建; */ private GamePictureUtil() { } /** * 接收图片路径返回图片对象; * @param path * @return */ public static Image getImages(String path){ URL u = GamePictureUtil.class.getClassLoader ().getResource(path); BufferedImage img = null; try { img = ImageIO.read(u); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return img; } }
后期的使用就是例如
Image bg = GamePictureUtil.getImages(“路径(scr中的路径)”);
就将这个路径下的地址通过这个静态方法将图片变成Image对象返回;bg为这个对象的
引用;
3;MyFrame类;继承java.awt.Frame类;这个类就实现了窗口中一些基本的设置;
例如;设置窗口的大小,位置,是否可见,以及窗口是否可以关闭,这里因为后面要加
载图片因此还需要一个内部类来启动线程,不断重画窗口,来到达窗口是不消失的,因
为在不断重画;
package gameUtil; import java.awt.Frame; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; /* * 显示窗口; */ public class MyFrame extends Frame{ /** * 显示出现窗口 * 线程实现,动态图片。 */ public void showFrame(){ setSize(Constant.WIGHT,Constant.HIGTH);//设置窗口大小,以 Eclipse的左上角为原点、 setLocation(100, 100);//设置坐标,这里的坐标也是左上角 setVisible(true);//设置窗口可见,默认是不可见的 new PaintThread().start();//启动线程,反复调用paint。 addWindowListener(new WindowAdapter() {//实现窗口关闭内部 类 public void windowClosing(WindowEvent e) { System.exit(0); } }); } /** * 定义一个重画窗口的内部类(线程实现);了解即可,懂得调用即可。 * @author Administrator * */ class PaintThread extends Thread{//通过线程,内部类 public void run(){ while(true){ try { repaint(); Thread.sleep(30);//1s等于100s,一 秒休息25次; } catch (InterruptedException e) { e.printStackTrace(); } } } } }
4;为什么要创建一个gameUtil包,并且在里面添加这些类呢;
可移值性;因为这个包里面的类,基本上是实现游戏窗口时都需要的类因此单独成一个
包,下次则直接将这个包拷贝过去,就完成了。
第二部分;就要实现模拟太阳系的具体类了;
可分为;太阳和行星(卫星);
当然我们也是需要一个窗口类,类实现操作的。
现在分析;其实面向对象和面向过程一样,都是从main函数开始分析的;
在SolarFarame中main方法中创建了一个SolarFarame对象的时候,则此时就进行了画
图得一系列工作,再调用Frame中的showFrame方法,完成了窗口的显示,注意这里还不
断重启线程,这里就可以完成行星的移动了,只需改变其坐标即可,下次线程他就会自
动再次画出即显示在其他地方,具体的流程就是这样的;
至于Frame中的showFrame方法中,是比较简单的,就是完成一些最后窗口的显示;
细说一下创建对象时太阳系模型的显示吧?
关于其显示就是
先显示背景,就是先通过路径得到对象,引用指向之后再画出即可;
太阳,行星也是一样的,不同的是他们不同背景,他们创建了单独的类来通过构成方法
来设置参数,最后还是画出来;
大概的流程就是这样,至于细节就十分重要了,这也是体现面向对象多种好处的时候;
1;因为无论是背景还是太阳,还是行星我们都要将其画出显示在窗口上,因此我们可
以在SolarFarame类中创建一个专门显示图片的方法;paint
public void paint(Graphics g){ g.drawImage(bg, 0, 0, null); sun.draw(g); earth.draw(g); }
因为太阳行星不同于背景,创建了独立的类,因此太阳和行星就调用自己的类来显示图
片,(还有一个原因是,他们要设置的参数都不同,因此单独成类创建方法画出也是很
好的;)
进一步分析显示太阳行星;
这里又有注意了,太阳和行星这间也存在相同的地方;
例如都是图片需要显示,只是行星多了需要画出运动轨迹,需要移动;
因此可以得出,行星可以继承太阳;
因此单独的对于画出图片,只需要太阳类中创建显示的方法即可;
Image img; double x,y;//坐标 double width,higth; public void draw(Graphics g){ g.drawImage(img, (int)x, (int)y, null); } 子类行星也可以这样画出,我们也看下行星是怎么画出的吧; public void draw(Graphics g){ super.draw(g); drawTrace(g); move(); }
关于画出,它重写了父类的draw方法,因为行星还需要画出其运动轨迹,并且他还是移
动的,因此要不断在不同的位置显示,因此他需要重写;
接下来我们按着思路看他轨迹画出吧;椭圆的画出;
在awt中都提供了这些方法;
public abstract void drawOval(int x, int y, int width, int height);
我们所需要做的是,计算出他这些参数即可,坐标xy已经长轴短轴
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.higth/2)-shortAxis; Color c = g.getColor(); g.setColor(Color.blue); g.drawOval((int)ovalX, (int)ovalY, (int)ovalWidth, (int) ovalHeight); g.setColor(c); }
中间那个是设置颜色,注意设置颜色前要保存原颜色,之后要还原回去;注意;防止画
笔颜色出现混乱;
我们再看他的移动吧;按照其运动轨迹移动就ok了;关于行星的移动,前面也说了一点
,我们只需改变其图片的xy坐标即可,在下个线程的时候,再次画出的时候就可以表示
成移动了;
public void move(){ x = center.x+center.width/2+longAxis*Math.cos(degree)- img.getWidth(null)/2; y = center.y+center.higth/2+shortAxis*Math.sin(degree)- img.getHeight(null)/2; degree += speed;//不需要再画出,在showFrame不断重启线程就可 以完成改变; }
关于太阳系模型的基本思路就几乎完成了,几乎,我们还缺少分享构造方法了。并且在
这里我们构造方法的设置应该是几乎接近源码那样吧?这个不多说自己看代码吧;
按照这个思路下来我们运行的结果应该是闪的,我们还少了一个东西,直接百度图片加
载时的双缓冲即可完成;因为都需要,这放到SolarFrame类即可;
Image ImageBuffer = null; Graphics GraImage = null; public void update(Graphics g){ //覆盖update方法,截取默认的调 用过程 ImageBuffer = createImage(this.getWidth(), this.getHeight()); //创建图形缓冲区 GraImage = ImageBuffer.getGraphics(); //获取图形缓冲区的 图形 上下文 paint(GraImage); //用paint方法中编写的绘图过程对图形缓冲 区绘图 GraImage.dispose(); //释放图形上下文资源 g.drawImage(ImageBuffer, 0, 0, this); //将图形缓冲区绘制到屏 幕上 }
贴一下所有代码吧;
package gameUtil; /** * 设置常量类,提高程序的健壮性; * @author Administrator * */ public class Constant { /** * 将窗口的长宽设置为常量,已供其他类使用,也便于修改; */ public static final int WIGHT = 788;//窗口的宽度 public static final int HIGTH = 610;//窗口的高度 }
package gameUtil;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
/**
* 这个有点点其他知识;
* 通过这个类的static方法实现通过输入图片路径(scr中的路径)返回图片对象;
* @author Administrator
*
*/
public class GamePictureUtil {
/**
* 设置为私有构成方法,不允许对象创建;
*/
private GamePictureUtil() {
}
/**
* 接收图片路径返回图片对象;
* @param path
* @return
*/
public static Image getImages(String path){
URL u = GamePictureUtil.class.getClassLoader().getResource(path);
BufferedImage img = null;
try {
img = ImageIO.read(u);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return img;
}
}
package gameUtil;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/*
* 显示窗口;
*/
public class MyFrame extends Frame{
/**
* 显示出现窗口
* 线程实现,动态图片。
*/
public void showFrame(){
setSize(Constant.WIGHT,Constant.HIGTH);//设置窗口大小,以Eclipse的左上角为原点、
setLocation(100, 100);//设置坐标,这里的坐标也是左上角
setVisible(true);//设置窗口可见,默认是不可见的
new PaintThread().start();//启动线程,反复调用paint。
addWindowListener(new WindowAdapter() {//实现窗口关闭内部类
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
/**
* 定义一个重画窗口的内部类(线程实现);了解即可,懂得调用即可。
* @author Administrator
*
*/
class PaintThread extends Thread{//通过线程,内部类
public void run(){
while(true){
try {
repaint();
Thread.sleep(30);//1s等于100s,一秒休息25次;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
package solarFrame; import java.awt.Graphics; import java.awt.Image; import gameUtil.Constant; import gameUtil.GamePictureUtil; import gameUtil.MyFrame; public class SolarFrame extends MyFrame{ Image bg = GamePictureUtil.getImages("img/background1.png"); Star sun = new Star("img/sun.jpg",Constant.WIGHT/2,Constant.HIGTH/2); Plant earth = new Plant("img/earth.jpg",300,200,0.01,sun); Plant mercury = new Plant("img/mercury.jpg",100,50,0.1,sun); Plant mras = new Plant("img/mras.jpg",150,100,0.05,sun); Plant moon = new Plant("img/moon.jpg",50,50,0.05,earth); Image ImageBuffer = null; Graphics GraImage = null; public void update(Graphics g){ //覆盖update方法,截取默认的调用过程 ImageBuffer = createImage(this.getWidth(), this.getHeight()); //创建图形缓冲区 GraImage = ImageBuffer.getGraphics(); //获取图形缓冲区的图形 上下文 paint(GraImage); //用paint方法中编写的绘图过程对图形缓冲区绘图 GraImage.dispose(); //释放图形上下文资源 g.drawImage(ImageBuffer, 0, 0, this); //将图形缓冲区绘制到屏幕上 } public void paint(Graphics g){ g.drawImage(bg, 0, 0, null); sun.draw(g); earth.draw(g); mercury.draw(g); mras.draw(g); moon.draw(g); } public static void main(String[] args) { new SolarFrame().showFrame(); } } package solarFrame; import java.awt.Graphics; import java.awt.Image; import gameUtil.GamePictureUtil; public class Star { Image img; double x,y;//坐标 double width,higth; public void draw(Graphics g){ g.drawImage(img, (int)x, (int)y, null); } Star(){ } Star(Image img){ this.img = img; this.width = img.getWidth(null); this.higth = img.getHeight(null); } Star(Image img, double x, double y){ this(img); this.x = x; this.y = y; } Star(String imgpath, double x, double y){ this(GamePictureUtil.getImages(imgpath), x, y); } } package solarFrame; import java.awt.Color; import java.awt.Graphics; import java.awt.Image; import java.util.Arrays; import gameUtil.GamePictureUtil; public class Plant extends Star{ double longAxis; double shortAxis; double degree; double speed; Star center; public void draw(Graphics g){ super.draw(g); drawTrace(g); move(); } 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.higth/2)-shortAxis; Color c = g.getColor(); g.setColor(Color.blue); g.drawOval((int)ovalX, (int)ovalY, (int)ovalWidth, (int)ovalHeight); g.setColor(c); } public void move(){ x = center.x+center.width/2+longAxis*Math.cos(degree)-img.getWidth(null)/2; y = center.y+center.higth/2+shortAxis*Math.sin(degree)-img.getHeight(null)/2; degree += speed;//不需要再画出,在showFrame不断重启线程就可以完成改变; } public Plant(String imgpath, double longAxis, double shortAxis,double speed, Star center) { super(GamePictureUtil.getImages(imgpath)); this.center = center; this.x = center.x+longAxis; this.y = center.y+shortAxis; this.img = GamePictureUtil.getImages(imgpath); this.longAxis = longAxis; this.shortAxis = shortAxis; this.speed = speed; } Plant(Image img, double x, double y) { super(img, x, y); } Plant(String imgpath, double x, double y){ super(imgpath,x,y); } }
相关文章推荐
- Unity 小项目:模拟太阳系
- 一步一步学WF系列(六)——工作流模拟投票项目
- 模拟项目2007
- 分布式流水作业系统项目经理挂掉的处理办法(Hadoop模拟思考系列)
- 如何在Tomcat本地模拟域名访问你的项目
- Android实时监控项目第一篇:项目分析及AVD模拟效果图
- 黑马程序员:DVD管理系统项目之三--使用io流模拟迷你SQL
- 系统集成项目管理工程师软考辅导——3年真题透解与全真模拟
- 开源项目之飞行模拟游戏 GL-117
- OpenGL 简易太阳系模拟 总结
- Excel 中统计某个项目出现的次数,以及模拟SQL的Group by效果
- 企业网络项目PT模拟
- 模拟QQ-Socket通信线程项目总结
- 分布式流水作业系统项目经理挂掉的处理办法(Hadoop模拟思考系列)
- 上学时的sql项目(模拟ATM),今日复习顺便共享一下
- 综合应用WPF/WCF/WF/LINQ之三十四:在XBAP项目中模拟弹出一个自定义的“模态窗口”
- 传智播客银联项目,模拟跨行取款
- 校园网络项目PT模拟
- 【开源项目】花密(Flower Password)VB版之模拟按键模块
- 手机可以模拟NFC卡片吗?项目中如何解决不能模拟NFC Tag UID的问题