模拟太阳系项目
发布日期:2021-06-29 11:11:31 浏览次数:2 分类:技术文章

本文共 11512 字,大约阅读时间需要 38 分钟。

这个其实是之前看视频的时候老师教的一个项目,但是也敲了,但是只能看懂代码不能自己设计出来,并且还苦于没有找到图片素材也就没有继续下去了;

今天抽了一下时间;现在网上找一些图片然后利用之前学的那皮毛都不到的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); }}

转载地址:https://blog.csdn.net/zw1996/article/details/53817795 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:c语言基础语法六——结构体(完结)
下一篇:java中的形参为引用类型的问题

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月08日 06时56分51秒