十四、坦克大战(上)

一、坦克大战游戏演示(略)

二、java绘图坐标体系

在这里插入图片描述

在这里插入图片描述

三、java绘图技术

3.1 快速入门

在这里插入图片描述

package com.gyh.draw;

import javax.swing.*;
import java.awt.*;

/**
 * @author Gao YongHao
 * @version 1.0
 * 演示如何在面板上画出圆形
 */
public class DrawCircle extends JFrame { // JFrame 对应窗口,可以理解成一个画框

    // 定义一个面板
    private MyPanel mp;


    public static void main(String[] args) {
        new DrawCircle();
    }

    public DrawCircle() { // 构造器
        // 初始化面板
        this.mp = new MyPanel();
        // 把面板放入到窗口(画框)
        this.add(this.mp);
        // 设置窗口的大小
        this.setSize(400, 300);
        // 当点击窗口的小X,程序就退出
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);//可以显示
    }


}


// 1. 先定义一个MyPanel,继承JPanel类,画图形,就在面板上画
class MyPanel extends JPanel {


    //说明:
    // 1. MyPanel 对象就是一个画板
    // 2. Graphics g 把 g 理解成一支画笔
    // 3. Graphics 提供了很多绘图的方法

    @Override
    public void paint(Graphics g) { //绘图方法
        super.paint(g);// 调用父类的方法完成初始化
//        System.out.println("paint");
        g.drawOval(10, 10, 100, 100);
    }
}

3.2 绘图原理

在这里插入图片描述

Graphics类

在这里插入图片描述

package com.gyh.draw;

import javax.swing.*;
import java.awt.*;

/**
 * @author Gao YongHao
 * @version 1.0
 * 演示如何在面板上画出圆形
 */
public class DrawCircle extends JFrame { // JFrame 对应窗口,可以理解成一个画框

    // 定义一个面板
    private MyPanel mp;


    public static void main(String[] args) {
        new DrawCircle();
    }

    public DrawCircle() { // 构造器
        // 初始化面板
        this.mp = new MyPanel();
        // 把面板放入到窗口(画框)
        this.add(this.mp);
        // 设置窗口的大小
        this.setSize(400, 300);
        // 当点击窗口的小X,程序就退出
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);//可以显示
    }


}


// 1. 先定义一个MyPanel,继承JPanel类,画图形,就在面板上画
class MyPanel extends JPanel {


    //说明:
    // 1. MyPanel 对象就是一个画板
    // 2. Graphics g 把 g 理解成一支画笔
    // 3. Graphics 提供了很多绘图的方法

    @Override
    public void paint(Graphics g) { //绘图方法
        super.paint(g);// 调用父类的方法完成初始化
//        System.out.println("paint");
//        g.drawOval(10, 10, 100, 100);

        // 演示绘制不同的图形..
        // 画直线 drawLine(int x1,int y1,int x2,int y2)
        g.drawLine(10, 10, 100, 100);

        // 画矩形边框 drawRect(int x1,int y1,width x2,height y2)
        g.drawRect(10, 10, 100, 100);

        // 画椭圆边框 drawOval(int x1,int y1,width x2,height y2)
        g.drawOval(10, 10, 10, 10);

        // 填充矩形 fillRect(int x1,int y1,width x2,height y2)
        // 设置画笔的颜色 setColor(Color)
        g.setColor(Color.BLUE);
        g.fillRect(10, 10, 100, 100);

        // 填充椭圆 fillOval(int x1,int y1,width x2,height y2)
        g.fillOval(10, 10, 100, 100);

        // 画图片 drawImage(Image img, int x,int y,..)
        // 1. 获取图片资源,/1.PNG 表示在该项目的根目录去获取 bg.png 图片资源
        Image image = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/1.PNG"));
        g.drawImage(image, 10, 10, 97, 127, this);

        // 给画笔设置颜色和字体
        g.setColor(Color.GREEN);
        g.setFont(new Font("隶书", Font.BOLD, 50));
        g.drawString("北京你好", 100, 100);
    }
}

四、java事件处理机制

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

package com.gyh.draw;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class TestEvent extends JFrame {

    private MyPanel2 mp;

    public static void main(String[] args) {
        TestEvent TestEvent = new TestEvent();
    }

    // 构造器
    public TestEvent() {
        mp = new MyPanel2();
        this.add(mp);
        this.setSize(400, 300);
        this.addKeyListener(mp); // 将监听器加入
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
}

// KeyListener 是监听器,可以监听键盘事件
class MyPanel2 extends JPanel implements KeyListener {

    // 为了使小球可以移动,我们设置坐标为变量
    private int x = 10;
    private int y = 10;

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillOval(x, y, 20, 20); // 默认黑色

    }

    // 有字符输出时,该方法就会触发
    @Override
    public void keyTyped(KeyEvent e) {

    }


    // 当某个键按下,该方法会触发
    @Override
    public void keyPressed(KeyEvent e) {

        // 根据用户按下的不同键,来处理小球的移动(上下左右的键)
        // 在java中,会给每一个键分配一个值(int)
        if (e.getKeyCode() == KeyEvent.VK_DOWN) { // KeyEvent.VK_DOWN 就是向下的箭头对应的code
            y++;
        } else if (e.getKeyCode() == KeyEvent.VK_UP) {
            y--;
        } else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            x--;
        } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            x++;
        }
        // 让面板重绘
        this.repaint();
    }

    // 当某个键释放(松开了),该方法会触发
    @Override
    public void keyReleased(KeyEvent e) {
//        System.out.println((char) e.getKeyCode());
    }
}

五、绘制坦克

5.1 坦克抽象类、己方坦克、敌方坦克

package com.gyh.draw;

import java.awt.*;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public abstract class Tank {
    private int x;// 坦克的横坐标(中心)
    private int y;// 坦克的纵坐标(中心)
    private int width = 40;// 坦克的宽
    private int height = 60;// 坦克的高
    private Color c; // 坦克的颜色

    private Direction d = Direction.UP; // 方向(默认为向上)

    enum Direction {
        UP, DOWN, LEFT, RIGHT;
    }

    public Tank(int x, int y, int width, int height, Color c) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.c = c;
    }

    public Tank(int x, int y, Color c) {
        this.x = x;
        this.y = y;
        this.c = c;
    }

    private void drawTankLeftOrRight(Graphics g) {
        // 上面的矩形的宽和高
        int topWidth = height, topHeight = width / 4;
        // 上面矩阵的坐标
        int topX = x - topWidth / 2, topY = y - 2 * topHeight;
//        int topX = x, topY = y;
        // 绘制上面的矩形
        g.fill3DRect(topX, topY, topWidth, topHeight, false);
        // 绘制中间的矩形
        g.fill3DRect(topX + topWidth / 6, topY + topHeight, topWidth * 2 / 3, 2 * topHeight, false);
        // 绘制中间的圆形
        g.fillOval(topX + topWidth / 3, topY + topHeight, 2 * topHeight, 2 * topHeight);
        // 绘制中间的直线(左或右)
        if (d == Direction.LEFT) {
            g.drawLine(topX, topY + topHeight * 2, topX + topWidth / 3, topY + topHeight * 2);
        } else {
            g.drawLine(topX + topWidth * 2 / 3, topY + topHeight * 2, topX + topWidth, topY + topHeight * 2);
        }
        // 绘制下面的矩形
        g.fill3DRect(topX, topY + 3 * topHeight, topWidth, topHeight, false);


    }

    private void drawTankUpOrDown(Graphics g) {

        // 左边矩形的宽和高
        int leftWidth = width / 4, leftHeight = height;

        // 左边矩形的位置坐标
        int leftX = x - 2 * leftWidth, leftY = y - height / 2;
//        int leftX = x, leftY = y;
        g.fill3DRect(leftX, leftY, leftWidth, leftHeight, false);

        // 中间矩形
        g.fill3DRect(leftX + leftWidth, leftY + leftHeight / 6, leftWidth * 2, leftHeight * 2 / 3, false);

        //中间圆形
        g.fillOval(leftX + leftWidth, leftY + leftHeight / 3, leftWidth * 2, leftWidth * 2);

        //中间直线(上与下有区别)
        if (d == Direction.UP) {
            g.drawLine(leftX + leftWidth * 2, leftY + leftHeight / 3, leftX + leftWidth * 2, leftY);
        } else {
            g.drawLine(leftX + leftWidth * 2, leftY + leftHeight * 2 / 3, leftX + leftWidth * 2, leftY + leftHeight);
        }


        // 右边矩形
        g.fill3DRect(leftX + leftWidth * 3, leftY, leftWidth, leftHeight, false);
    }


    public void drawTank(Graphics g) {
        // 设置颜色
        g.setColor(c);

        if (d == Direction.UP || d == Direction.DOWN) {
            drawTankUpOrDown(g);
        } else {
            drawTankLeftOrRight(g);
        }
    }

    public Direction getD() {
        return d;
    }

    public void setD(Direction d) {
        this.d = d;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }
}
package com.gyh.draw;

import java.awt.*;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Hero extends Tank {

    public Hero(int x, int y, int width, int height) {
        super(x, y, width, height, Color.yellow);
    }

    public Hero(int x, int y) {
        super(x, y, Color.yellow);
    }

}

package com.gyh.draw;

import java.awt.*;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Enemy extends Tank {

    public Enemy(int x, int y, int width, int height) {
        super(x, y, width, height, Color.cyan);
    }

    public Enemy(int x, int y) {
        super(x, y, Color.cyan);
    }
}

5.2 自定义面板

package com.gyh.draw;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Vector;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class MyPanel1 extends JPanel implements KeyListener {
    // 背景的宽和高
    private static final int BACKGROUND_WIDTH = 1000;
    private static final int BACKGROUND_HEIGHT = 750;

    // 坦克的宽和高
    private static final int WIDTH = 40;
    private static final int HEIGHT = 60;

    // 定义我的坦克
    Hero hero;

    // 定义敌方坦克
    Vector<Enemy> enemys;
    // 定义敌方坦克数
    int enemyTankNum = 3;

    public MyPanel1() {
        hero = new Hero(100, 100, WIDTH, HEIGHT);// 初始化自己的坦克
        enemys = new Vector<>();
        for (int i = 0; i < enemyTankNum; i++) {
            Enemy e = new Enemy(200+i*100, 200);
            e.setD(Tank.Direction.DOWN);
            enemys.add(e);

        }

    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0, 0, BACKGROUND_WIDTH, BACKGROUND_HEIGHT); // 填充矩形,默认是黑色
        hero.drawTank(g);
        for (Enemy e : enemys) {
            e.drawTank(g);
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        int speed = 4;
        int dis = 0;
        if (e.getKeyCode() == KeyEvent.VK_DOWN) { // 向下
            hero.setD(Tank.Direction.DOWN); // 朝下
            // 设置
            dis = (dis = hero.getY() + speed) + HEIGHT / 2 > BACKGROUND_HEIGHT ? BACKGROUND_HEIGHT - HEIGHT / 2 : dis;
            hero.setY(dis); // 向下走
        } else if (e.getKeyCode() == KeyEvent.VK_UP) { // 向上
            hero.setD(Tank.Direction.UP); // 朝上
            dis = (dis = hero.getY() - speed) - HEIGHT / 2 < 0 ? HEIGHT / 2 : dis;
            hero.setY(dis);
        } else if (e.getKeyCode() == KeyEvent.VK_LEFT) { // 向左
            hero.setD(Tank.Direction.LEFT);
            dis = (dis = hero.getX() - speed) - HEIGHT / 2 < 0 ? HEIGHT / 2 : dis;
            hero.setX(dis);
        } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { // 向右
            hero.setD(Tank.Direction.RIGHT);
            dis = (dis = hero.getX() + speed) + HEIGHT / 2 > BACKGROUND_WIDTH ? BACKGROUND_WIDTH - HEIGHT / 2 : dis;
            hero.setX(dis);
        }
        repaint();

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }
}

5.3 绘图界面

package com.gyh.draw;

import javax.swing.*;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class GyhTankGame01 extends JFrame {
    // 定义一个 MyPanel1
    MyPanel1 mp;

    public static void main(String[] args) {
        new GyhTankGame01();
    }

    public GyhTankGame01() {
        mp = new MyPanel1();
        this.add(mp); // 把面板(就是游戏的绘图区域)
        this.setSize(1200, 800);
        this.addKeyListener(mp);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ModelBulider

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值