十四、坦克大战(上)

news2024/11/15 11:36:12

文章目录

  • 一、坦克大战游戏演示(略)
  • 二、java绘图坐标体系
  • 三、java绘图技术
    • 3.1 快速入门
    • 3.2 绘图原理
    • Graphics类
  • 四、java事件处理机制
  • 五、绘制坦克
    • 5.1 坦克抽象类、己方坦克、敌方坦克
    • 5.2 自定义面板
    • 5.3 绘图界面

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

二、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);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2094583.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LVGL 控件之日历(lv_calendar)

目录 一、日历1、组成2、创建日历3、日期的设置/显示3.1 设置当前日期3.2 显示日期3.3 日历头 4、设置日期高亮5、设置日名6、事件7、API 函数 一、日历 1、组成 日历部件由两个部分组成&#xff1a; 主体背景 LV_PART_MAIN&#xff1b;各个按钮 LV_PART_ITEMS&#xff08;指…

kubeadm部署 Kubernetes(k8s) 高可用集群【V1.20 】

kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。 calico.yaml kubernertes-dashboard.yaml 1. 安装要求 在开始之前&#xff0c;部署Kubernetes集群机器需要满足以下几个条件&#xff1a; 7台机器&#xff0c;操作系统Openeuler22.03 LTS SP4硬件配置&#…

【GPT】Coze使用开放平台接口-【1】创建插件

本文档主要描述在 coze 里面把开放平台的接口创建为插件&#xff0c;供别人调用。本系列调用的接口&#xff0c;都是调用快商通 AI 开放平台的接口 注意&#xff1a;如果是团队需要的&#xff0c;建议直接在团队空间里面创建这些&#xff0c;不然在个人空间创建得很爽&#xff…

Linux——命令行文件的管理(创建,复制,删除,移动文件,硬链接与软链接)

目录 一、创建文件和目录 二、复制文件和目录 三、删除文件和目录 四、移动文件和目录 五、硬链接和软链接&#xff08;软链接也指符号链接&#xff09; 索引节点&#xff08;inode) 硬链接 软链接&#xff08;符号链接&#xff09; 一、创建文件和目录 mkdir命令可以创…

PCIe 复位:必须了解的PERST#

1.什么是PERST# PERST#作为 Fundamental Reset&#xff0c;是直接通过边带信号PERST#&#xff08;PCI Express Reset&#xff09;产生的。Fundamental Reset会复位整个PCIe设备&#xff0c;初始化所有与状态机相关的硬件逻辑&#xff0c;端口状态以及配置空间中的配置寄存器…

使用谷歌翻译的推荐理由及其他翻译工具推荐~

在现在快节奏的工作中&#xff0c;翻译工具已成为我们日常当中不可或缺的助手。其中&#xff0c;谷歌翻译以其高效、准确的特点&#xff0c;在众多翻译软件中脱颖而出。以下&#xff0c;我为您详细介绍为何推荐在工作中使用谷歌翻译&#xff0c;并同时提供其他三款优秀的翻译工…

linux内核驱动:pca953xIO扩展芯片驱动总结

目录 前言一、PCA9536芯片介绍二、驱动说明三、配置流程四、应用操作方式 前言 本笔记总结使用ti 的PCA953x进行SOC的GPIO扩展时步骤&#xff0c;基于linux内核版本5.10.xxx&#xff1b; 一、PCA9536芯片介绍 【1】PCA9536是基于i2c接口的GPIO扩展芯片&#xff0c;最大支持到…

【Java学习】多线程JUC万字超详解

所属专栏&#xff1a;Java学习 1. 多线程的概念 线程&#xff1a;线程是操作系统能够进行运算调度的最小单位&#xff0c;它被包含在进程之中&#xff0c;是进程的实际运作单位 下面这些每一个能够运行的软件就是一个进程 并发&#xff1a;在同一时刻&#xff0c;有多个…

网络编程学习:TCP/IP协议

TCP/IP协议简介 TCP/IP协议包含了一系列的协议&#xff0c;也叫TCP/IP协议族&#xff08;TCP/IP Protocol Suite&#xff0c;或TCP/IP Protocols&#xff09;&#xff0c;简称TCP/IP。 分层结构 为了能够实现不同类型的计算机和不同类型的操作系统之间进行通信&#xff0c;引…

Java中的锁(四)利用读写锁实现高性能网页缓存

文章目录 背景Ehcache2源码解析-如何实现缓存网页读写锁ReentrantReadWriteLock解析读写锁的特性读写锁是如何实现的&#xff1f; 如何将Ehcach2-web的源码迁移到Ehcach3中&#xff1f;/ 如何自定义Filter实现高性能网页缓存&#xff1f; 背景 在我们的销售页面&#xff0c;有…

Django+Vue酒店推荐系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 需要的环境3.2 Django接口层3.3 实体类3.4 config.ini3.5 启动类3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质创作者&…

Linux文件操作(二)

Linux文件操作&#xff08;二&#xff09; 导语文件和目录维护chmodchownlink及其变体dir及其变体chdir和getcwd 扫描目录opendirreaddirtelldirseekdirclosedir示例程序 错误处理strerrorperror /procfcntlmmap相关mmapmsyncmunmap 总结参考文献 导语 文件操作的第二部分&…

juzige/Monitoring-System-基于Java语言的光伏监控系统

Photovoltaic-Monitoring-System-Based-on-Java-Language 基于Java语言的光伏监控系统光伏发电系统光伏软件系统光伏监控系统源码光伏发电系统源码-智电云 一、 介绍 光伏光伏发电预测逆变器监控逆变器数据采集光伏运维光伏电站光伏功率预测光伏监控系统光伏发电系统光伏软件…

【CSS in Depth 2 精译_022】3.6 一招搞定容器内元素间距的问题 + 3.7 本章小结

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09; 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位&#xff08;已完结&#xff09; 2.1 相对…

jQuery入门(六)jQuery实现瀑布流分页案例

一、瀑布流分页案例分析 1.1) 功能分析&#xff1a; 鼠标下拉&#xff0c;加载分页数据(10条) &#xff0c;如下图&#xff1a; 案例分析&#xff1a; 1.2) 如何确定当前显示的数据已经浏览完毕&#xff1f; 公式&#xff1a;(滚动条距底部的距离 滚动条上下滚动的距离 当…

【Python篇】Python 类和对象:详细讲解(下篇)

文章目录 Python 类和对象&#xff1a;详细讲解&#xff08;下篇&#xff09;15. 接口和协议&#xff08;Interfaces and Protocols&#xff09;15.1 什么是接口&#xff1f;15.2 协议的基本概念例子&#xff1a;定义飞行协议详细解释输出示例 16. 装饰器模式&#xff08;Decor…

A02、Java编程性能调优(02)

1、Stream如何提高遍历集合效率 1.1、什么是Stream 现在很多大数据量系统中都存在分表分库的情况。例如&#xff0c;电商系统中的订单表&#xff0c;常常使用用户 ID 的 Hash 值来实现分表分库&#xff0c;这样是为了减少单个表的数据量&#xff0c;优化用户查询订单的速度。 …

ZYNQ-Utlscale-RFSOC看门狗

ZYNQ-Utlscale-RFSOC看门狗复位 ZYNQ-Utlscale-RFSOC 看门狗的程序网上里程很少&#xff0c;开源资料也是几乎没有&#xff0c;最近需要用到这个功能&#xff0c;来来回回搞了一周才搞定。刚开始参考ZYNQ7000的资源&#xff0c;发现MPSOC不适用。很感谢下面的几篇文章&#xf…

探索TinyDB:轻量级数据库的优雅之旅

文章目录 探索TinyDB&#xff1a;轻量级数据库的优雅之旅背景&#xff1a;为何选择TinyDB&#xff1f;TinyDB是什么&#xff1f;如何安装TinyDB&#xff1f;简单库函数使用方法场景应用常见Bug及解决方案总结 探索TinyDB&#xff1a;轻量级数据库的优雅之旅 背景&#xff1a;为…

【电子通识】电子元器件可靠性基本概念

什么是电子元器件 电子元器件是电子产品的基本组成单元&#xff0c; 是电子元件和电子器件的总称。 通常电子元件指的是无源元件&#xff0c; 电子器件指的是有源器件。无源元件是对所供给的电能执行被动操作&#xff08;如耗散、储蓄或释放等&#xff09;的元件&#xff0c; 如…