飞机大战小游戏是练习面向对象的常用项目, 用于练习面向对象编程的方法. 在学完 Java 基础和面向对象基础后, 经过一个星期零散时间的学习, 跟着视频教程写了个飞机大战小游戏项目! 通过这个小游戏项目更深刻了解了面向对象的编程思维, 练习了 Java 面向对象的编程方法. 下面简单介绍一下该项目, 并贴出源码, 源码中添加了大量注释, 其中也有个人的一些见解和看法.
游戏的基本功能已经实现, 其中仍不乏一些小的 bug, 项目还有很多可以改进的细节. 考虑以后慢慢改进完善, 在这里先对基本项目展示.
游戏小项目的层次构造:
MyGameFrame 类 (游戏窗口主类)
- package cn.ftf.game;
- import java.awt.Color;
- import java.awt.Font;
- import java.awt.Frame;
- import java.awt.Graphics;
- import java.awt.Image;
- import java.awt.event.KeyAdapter;
- import java.awt.event.KeyEvent;
- import java.awt.event.WindowAdapter;
- import java.awt.event.WindowEvent;
- import java.util.Date;
- /**
- * 飞机游戏的主窗口, 项目的主类!
- * @author 房廷飞
- *
- */
- public class MyGameFrame extends Frame{ // 继承窗口类
- Image sky=GameUtil.getImage("images/sky.jpg"); // 导入飞机和背景导入飞机和背景
- Image planeImg=GameUtil.getImage("images/plane.png");
- Plane plane=new Plane(planeImg,250,250); // 新建了一个 class 飞机类, 方便对飞机的细节设置, 这里调用即可. 体现面向对象的思想!
- Shell[] shells = new Shell[20]; // 初始化炮弹 20 个 // 新建一个 class 炮弹类, 方便对炮弹的细节设置, 这里调用即可! 体现面向对象的思想!
- Explode bao; // 声明一下爆炸类 // 新建一个 class 爆炸类, 方便对爆炸的细节设置, 这里调用即可! 体现面向对象的思想!
- Date startTime=new Date(); // 新建一个时间对象, 用来获取此时时间
- Date endTime; // 声明一个时间对象
- int contime; // 游戏持续的时间
- //paint 类不用被调用, 自动执行
- @Override
- public void paint(Graphics g) { // 自动被调用, g 相当于一个画笔
- g.drawImage(sky, 0, 0, null);
- plane.drawSelf(g); // 传画笔, 画飞机
- for(int i=0;i<shells.length;i++) {
- shells[i].draw(g); // 传画笔, 画炮弹
- boolean peng=shells[i].getRect().intersects(plane.getRect()); // 矩形检测, 判断炮弹和飞机是否碰上!
- if(peng) {
- plane.live=false;
- if(bao==null) { // 使第一次碰上触发爆炸效果, 而不是在重叠的同时触发多次!
- bao=new Explode(plane.x,plane.y); // 新建一个爆炸类
- bao.draw(g); // 调用 draw 方法, 触发爆炸效果!
- }
- endTime=new Date(); // 这里新建一个时间对象, 用来获取此时时间
- contime=(int)((endTime.getTime()-startTime.getTime()))/1000; // 得到游戏运行时间差!(秒)
- }
- if(!plane.live) {
- g.setColor(Color.red); // 设置字体颜色!
- g.setFont(new Font("宋体",Font.BOLD,50)); // 设置字体时间!
- g.drawString("游戏时间:"+contime+"秒!", 200, 300); // 写字!
- }
- }
- }
- // 帮助我们反复重画窗口
- class PanitThread extends Thread{
- @Override
- // 重写 run 方法, 实现窗口重画!
- public void run() {
- while(true) {
- repaint();// 重画
- // 程序睡眠的写法!
- try {
- Thread.sleep(40); // 游戏画质: 40 帧
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- }
- // 定义键盘监听内部类
- class KeyMonitor extends KeyAdapter{
- // 重写 keyPressed 类
- @Override
- public void keyPressed(KeyEvent e) {
- plane.addDirection(e);
- System.out.println("按下"+e.getExtendedKeyCode());
- }
- @Override
- public void keyReleased(KeyEvent e) {
- plane.minusDirection(e);
- System.out.println("抬起"+e.getExtendedKeyCode());
- }
- }
- /*// 练习画笔, 可展开
- @Override
- public void paint(Graphics g) { // 自动被调用, G 相当于一个画笔
- Color c=g.getColor(); // 保存初始颜色
- Font f =g.getFont(); // 保存初始字体
- g.drawLine(100, 100, 300, 300); // 画线
- g.setColor(Color.BLACK); // 设置颜色
- g.drawRect(100, 100, 300, 300); // 画矩形
- g.drawOval(100, 100, 300, 300); // 画椭圆
- g.fillRect(100, 100, 10, 10); // 画实心矩形
- g.setFont(new Font("宋体",Font.BOLD,50)); // 设置字体
- g.drawString("房廷飞",200,200); // 写文字
- g.drawImage(ball, 250, 250, null); // 画图片
- g.setColor(c); // 恢复颜色
- g.setFont(f); // 恢复字体
- }
- */
- public void launchFrame() {
- this.setTitle("飞机大战 --- 房廷飞"); // 窗口的标题, this. 指 MyGameFrame 类的
- this.setSize(Constant.GAME_WIDH, Constant.GAME_HEIGHT); // 设置窗口显示的大小, 这里把窗口的大小写在一个常量类中, 通过调用避免了多处修改的麻烦, 方便了维护和修改!
- this.setLocation(1000, 20); // 设置窗口出现的位置
- this.setVisible(true); // 设置让窗口显示出来
- /*
- * JFrame 类的关闭窗口结束程序
- */
- //this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置用户关闭窗口结束程序!
- // 匿名内部类
- /*
- this.addWindowFocusListener(new WindowAdapter() {
- @Override
- public void windowClosing(WindowEvent e) {
- System.exit(0);
- }
- });
- */
- /*
- * 使关闭窗口结束程序运行, 不然关闭窗口程序仍在运行!
- * 匿名内部类, 这里仅作了解
- * 这是使用 Frame 类的
- */
- this.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e){
- System.exit(0);
- }
- });
- new PanitThread().start(); // 启动反复重画窗口, 实现动画的效果!
- addKeyListener(new KeyMonitor()); // 给窗口增加键盘监听
- // 初始化 50 个炮弹
- for(int i=0;i<shells.length;i++) {
- shells[i]=new Shell();
- }
- }
- // 主程序开始运行, 项目的入口!
- public static void main(String[] args) {
- System.out.println("出现窗口!");
- MyGameFrame m=new MyGameFrame(); // 新建一个窗口对象!
- m.launchFrame(); // 运行窗口类 MyGameFrame 的 launchFrame 方法!
- }
- /*
- * 添加双缓存技术, 解决游戏画面闪烁问题!
- * 下面这段代码暂时抄下
- */
- private Image offScreenImage = null;
- public void update(Graphics g) {
- if(offScreenImage == null)
- offScreenImage = this.createImage(Constant.GAME_WIDH,Constant.GAME_HEIGHT);// 这是游戏窗口的宽度和高度
- Graphics gOff = offScreenImage.getGraphics();
- paint(gOff);
- g.drawImage(offScreenImage, 0, 0, null);
- }
- }
GameObject 类 (游戏物体的父类)
- package cn.ftf.game;
- import java.awt.Graphics;
- import java.awt.Image;
- import java.awt.Rectangle;
- //import javax.sound.midi.Receiver;
- /**
- * 建一个游戏物体的父类, 方便各模块调用
- * @author 房廷飞
- *
- */
- public class GameObject {
- Image img;
- double x,y;
- int speed=20;
- int width,height;
- // 画出自己
- public void drawSelf(Graphics g) {
- g.drawImage(img,(int)x,(int)y,null);
- }
- // 多建几个构造器, 方便以后调用
- public GameObject(Image img, double x, double y, int speed, int width, int height) {
- super();
- this.img = img;
- this.x = x;
- this.y = y;
- this.speed = speed;
- this.width = width;
- this.height = height;
- }
- public GameObject(Image img, double x, double y) {
- super();
- this.img = img;
- this.x = x;
- this.y = y;
- }
- public GameObject() {
- // TODO Auto-generated constructor stub
- }
- // 返回宽度长度等, 方便以后碰撞检测
- public Rectangle getRect() {
- return new Rectangle((int)x,(int)y,width,height);
- }
- }
Plane 类 (飞机对象类)
- package cn.ftf.game;
- import java.awt.Graphics;
- import java.awt.Image;
- import java.awt.event.KeyEvent;
- // 写一个飞机类方便以后调用
- public class Plane extends GameObject{ // 继承游戏物体父类
- boolean left,right,up,down;
- boolean live=true;
- public void drawSelf(Graphics g) {
- if(live) {
- g.drawImage(img,(int) x,(int) y, null);
- if(left) {
- x-=speed;
- }
- if(right) {
- x+=speed;
- }
- if(up) {
- y-=speed;
- }
- if(down) {
- y+=speed;
- }
- }
- }
- public Plane(Image img,double x,double y) {
- this.img=img;
- this.x=x;
- this.y=y;
- this.speed=20;
- this.height=img.getHeight(null);
- this.width=img.getWidth(null);
- }
- // 按下某个键, 增加相应的方向
- public void addDirection(KeyEvent e) {
- switch (e.getKeyCode()) {
- case KeyEvent.VK_LEFT:
- left=true;
- break;
- case KeyEvent.VK_RIGHT:
- right=true;
- break;
- case KeyEvent.VK_UP:
- up=true;
- break;
- case KeyEvent.VK_DOWN:
- down=true;
- break;
- default:
- break;
- }
- }
- public void minusDirection(KeyEvent e) {
- switch (e.getKeyCode()) {
- case KeyEvent.VK_LEFT:
- left=false;
- break;
- case KeyEvent.VK_RIGHT:
- right=false;
- break;
- case KeyEvent.VK_UP:
- up=false;
- break;
- case KeyEvent.VK_DOWN:
- down=false;
- break;
- default:
- break;
- }
- }
- }
Shell 类 (炮弹对象类)
- package cn.ftf.game;
- import java.awt.Color;
- import java.awt.Graphics;
- /**
- * 炮弹类
- * @author 房廷飞
- *
- */
- public class Shell extends GameObject{
- double degree;
- public Shell() {
- x=400;
- y=40;
- width=10;
- height=10;
- speed=3;
- degree=Math.random()*Math.PI*2;
- }
- public void draw(Graphics g) {
- Color c=g.getColor();
- g.setColor(Color.YELLOW);
- g.fillOval((int)x, (int)y, width, height);
- // 炮弹沿任意角度去飞
- x+=speed*Math.cos(degree);
- y+=speed*Math.sin(degree);
- if(x<0||x>Constant.GAME_WIDH-10) {
- degree=Math.PI-degree;
- }
- if(y<30||y>Constant.GAME_HEIGHT-10) {
- degree=-degree;
- }
- g.setColor(c);
- }
- }
Explode 类 (爆炸效果类)
- package cn.ftf.game;
- import java.awt.Graphics;
- import java.awt.Image;
- // 爆炸类
- public class Explode {
- double x,y;
- static Image[] imgs = new Image[7];
- static {
- for(int i=0;i<7;i++){
- imgs[i] = GameUtil.getImage("images/baoImages/"+i+".png");
- imgs[i].getWidth(null);
- }
- }
- int count=0;
- public void draw(Graphics g){
- if(count<=6){
- for(int i=0;i<7;i++)
- {
- System.out.println("轮播开始!"+count);
- g.drawImage(imgs[count], (int)x,(int)y, null);
- count++;
- }
- }
- }
- public Explode(double x,double y){
- this.x = x;
- this.y = y;
- }
- }
Constant 类 (常量类)
- package cn.ftf.game;
- // 将一些常量放在这里以调用, 防止多处修改常量
- /**
- * 飞机大战游戏小项目 - 常量设置中心
- * @author 房廷飞
- *
- */
- public class Constant {
- public static final int GAME_WIDH=800;
- public static final int GAME_HEIGHT=600;
- //public static final int GAME_SLEEP=40; // 画质
- }
以上是该小项目的全部代码, 算是对面向对象编程的一个综合实践, 下面是游戏运行截图:
仅作学习用, 先继续往下学习新知识, 以后还会解决里面的一些小 bug, 并进一步优化, 届时再做分享!
2019-03-22 21:37:02 房廷飞 期待明天更好的自己!
来源: http://www.bubuko.com/infodetail-2996431.html