zoukankan      html  css  js  c++  java
  • Java小项目——飞机大战(一、实现线程绘制背景和我方飞机,键盘控制飞机运动)

    1 总体需求分析

    1.1 类

    1、主类

    2、我方飞机类

    3、线程类

    2.2 效果图

    2 实现

    2.1 飞机类 MyPlane

    飞机类包括以下参数:

    位置x、y

    速度vx、vy

    图片图标myicom:设置为飞机的图片

    飞机类包括以下方法:

    有参构造方法:初始化x、y,保证第一次绘制飞机能够有坐标

    public MyPlane(int x, int y) {
        this.x = x;
        this.y = y;
    }

    绘制飞机方法:用参数画笔g来绘制飞机,再更新vx和vy,

    public void drawPlane(Graphics g) {
        g.drawImage(myicon.getImage(), x, y, null);
        x += vx;
        y += vy;
    }

    代码:

    package com.java8.planewarsV1;
    
    import javax.swing.*;
    import java.awt.*;
    
    public class MyPlane {
        private int x, y;
        private int vx, vy;
    
        private ImageIcon myicon = new ImageIcon(this.getClass().getResource("PaperPlane.png"));
    
        /**
         * 我方飞机的构造函数
         * @param x:绘制坐标x
         * @param y:绘制坐标y
         */
        public MyPlane(int x, int y) {
            this.x = x;
            this.y = y;
        }
    
        /**
         * 绘制飞机对象的函数,每次调用,则绘制一次飞机
         * @param g:画笔
         */
        public void drawPlane(Graphics g) {
            g.drawImage(myicon.getImage(), x, y, null);
            x += vx;
            y += vy;
        }
    
        /**
         * setVx
         * setVy
         * 用于在按键后,设置其每次移动的大小,并在释放的时候清0
         * @param vx
         */
        public void setVx(int vx) {
            this.vx = vx;
        }
    
        public void setVy(int vy) {
            this.vy = vy;
        }
    }
    

     

    2.2 主界面类 GameUI

    界面类和监听器类:两个写在一个类中,方便参数的传入和传出

    界面类:主要实现一个面板JFrame jf,jf上添加键盘监听器,jf上获取画笔g

    监听器类:KeyListener。按space空格开始游戏,按上下左右控制飞机运动。

    GameUI类的参数为:

    private JFrame jf;
    private Graphics g;
    private MyPlane myPlane;
    private MyThread myThread;
    private ImageIcon bgicon = new ImageIcon(this.getClass().getResource("bg.jpeg"));
    
    private int speed = 5;
    

    空格 VK_SPACE:

    1.创建飞机对象,初始化飞机的x和y;2.若线程为null,则创建myThread线程,传入mayplane飞机、g画笔、jf对象; 3.使用Thread()方法,运行myThread线程,开始不断绘制飞机类

    // 按下空格,开启线程
    // 线程每隔0.02s就绘制背景图、飞机
    if(myThread == null){
        //1.创建飞机对象
        myPlane = new MyPlane((jf.getWidth() - 150) / 2,
                jf.getHeight() - 150);
        //2.创建myThread线程
        myThread = new MyThread(myPlane,g,jf);
        //3.使用Thread()方法,运行myThread线程
        new Thread(myThread).start();
    }

    左右上下 KeyEvent.VK_LEFT:

    设置飞机类的x/y速度为+speed或者-speed

    case KeyEvent.VK_LEFT:
        myPlane.setVx(-speed);
        break;

    代码:

    package com.java8.planewarsV1;
    
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    
    public class GameUI implements KeyListener {
    
        private JFrame jf;
        private Graphics g;
        private MyPlane myPlane;
        private MyThread myThread;
        private ImageIcon bgicon = new ImageIcon(this.getClass().getResource("bg.jpeg"));
    
        private int speed = 5;
    
    
        public static void main(String arg[]) {
            GameUI gameUI = new GameUI();
            gameUI.showUI();
        }
    
    
        private void showUI() {
            jf = new JFrame();
            jf.setTitle("飞机大战1.0");
            jf.setSize(800, 800);
            jf.setLocationRelativeTo(null);
            jf.setDefaultCloseOperation(3);
    
            jf.setVisible(true);
    
            g = jf.getGraphics();
            g.drawImage(bgicon.getImage(),0,0,null);
            
            jf.addKeyListener(this);
    
        }
    
    
        public void keyTyped(KeyEvent e) {
    
        }
    
        /***
         * 按下对应按钮,获取按钮的值e.getKeyCode(),进行不同操作
         * 空格:开始游戏;上下左右:对应移动
         * @param e
         */
        public void keyPressed(KeyEvent e) {
            int key = e.getKeyCode();
            switch (key) {
                case KeyEvent.VK_LEFT:
                    myPlane.setVx(-speed);
                    break;
                case KeyEvent.VK_RIGHT:
                    myPlane.setVx(speed);
                    break;
                case KeyEvent.VK_UP:
                    myPlane.setVy(-speed);
                    break;
                case KeyEvent.VK_DOWN:
                    myPlane.setVy(speed);
                    break;
                case KeyEvent.VK_SPACE:
                    // 按下空格,开启线程
                    // 线程每隔0.02s就绘制背景图、飞机
                    if(myThread == null){
                        //1.创建飞机对象
                        myPlane = new MyPlane((jf.getWidth() - 150) / 2,
                                jf.getHeight() - 150);
                        //2.创建myThread线程
                        myThread = new MyThread(myPlane,g,jf);
                        //3.使用Thread()方法,运行myThread线程
                        new Thread(myThread).start();
                    }
                    break;
            }
        }
    
    
        /**
         * 清空上一次操作的speed
         * @param e
         */
        public void keyReleased(KeyEvent e) {
            int key = e.getKeyCode();
            switch (key) {
                case KeyEvent.VK_LEFT:
                    myPlane.setVx(0);
                    break;
                case KeyEvent.VK_RIGHT:
                    myPlane.setVx(0);
                    break;
                case KeyEvent.VK_UP:
                    myPlane.setVy(0);
                    break;
                case KeyEvent.VK_DOWN:
                    myPlane.setVy(0);
                    break;
            }
        }
    }
    

    2.3 MyThread

    重写线程run():

    线程暂停0.02s绘制一次;在bufferedImage内绘制背景+绘制飞机(bg);将bufferedImage绘制到jf上(g)

    绘制飞机线程构造函数:

    需要传入飞机、画笔g、面板jf

    /**
     * 绘制飞机线程构造函数
     */
    public MyThread(MyPlane myPlane, Graphics g,JFrame jf){
        this.myPlane = myPlane;
        this.g = g;
        this.jf = jf;
    }

    缓存技术bufferedImage:

    使用bufferedImage的画笔bg,来绘制背景、绘制飞机。解决了画面交替绘制闪烁问题。

    /**
     * 使用缓存技术bufferedImage,解决画面交替绘制闪烁问题
     * 1 首先将所有物体绘制于bufferedImage内
     * 2 再将bufferedImage绘制于JFrame内
     */
    //1.创建bufferedImage对象:大小为jf大小,类型为RGB
    BufferedImage bufferedImage = new BufferedImage(jf.getWidth(),jf.getHeight(),BufferedImage.TYPE_INT_BGR);
    //2.获取bufferedImage对象的画笔:bg
    Graphics bg = bufferedImage.createGraphics();
    //3.绘制背景和飞机,于bufferedImage对象上
    bg.drawImage(bgicon.getImage(),0,0,null);
    myPlane.drawPlane(bg);
    //4.绘制bufferedImage,到JFrame上
    g.drawImage(bufferedImage,0,0,null);

    代码:

    package com.java8.planewarsV1;
    
    import javax.swing.*;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    
    public class MyThread implements Runnable{
    
        private MyPlane myPlane;
        private Graphics g;
        private JFrame jf;
        private ImageIcon bgicon = new ImageIcon(this.getClass().getResource("bg.jpeg"));
    
        /**
         * 绘制飞机线程构造函数
         */
        public MyThread(MyPlane myPlane, Graphics g,JFrame jf){
            this.myPlane = myPlane;
            this.g = g;
            this.jf = jf;
        }
    
        /**
         * 不使用线程,每次绘制之间间隔过长;
         * 使用线程,加速绘制飞机移动轨迹。
         */
        public void run() {
    
            while(true) {
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                /**
                 * 使用缓存技术bufferedImage,解决画面交替绘制闪烁问题
                 * 1 首先将所有物体绘制于bufferedImage内
                 * 2 再将bufferedImage绘制于JFrame内
                 */
                //1.创建bufferedImage对象:大小为jf大小,类型为RGB
                BufferedImage bufferedImage = new BufferedImage(jf.getWidth(),jf.getHeight(),BufferedImage.TYPE_INT_BGR);
                //2.获取bufferedImage对象的画笔:bg
                Graphics bg = bufferedImage.createGraphics();
                //绘制背景和飞机,于bufferedImage对象上
                bg.drawImage(bgicon.getImage(),0,0,null);
                myPlane.drawPlane(bg);
                //绘制bufferedImage,到JFrame上
                g.drawImage(bufferedImage,0,0,null);
    
            }
        }
    }
    

     

  • 相关阅读:
    Python 基础之 线程与进程
    python 基础之 模块
    Python 基础之socket编程(三)
    Python 基础之socket编程(二)
    Python全栈开发之11、进程和线程
    用 Python实现一个ftp+CRT(不用ftplib)
    Python全栈开发之10、网络编程
    Python全栈开发之9、面向对象、元类以及单例
    Python全栈开发之8、装饰器详解
    用python实现一个无界面的2048
  • 原文地址:https://www.cnblogs.com/iriswang/p/11084635.html
Copyright © 2011-2022 走看看