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);

        }
    }
}

 

 

posted @ 2018-08-28 15:53  怡人Iris  阅读(1922)  评论(0编辑  收藏  举报