项目-坦克大战-让坦克动起来

为什么写这个项目

  • 好玩
  • 涉及到java各个方面的技术
    1,java面向对象
    2,多线程
    3,文件i/o操作
    4,数据库
  • 巩固知识

java绘图坐标体系

坐标体系-介绍

在这里插入图片描述

坐标体系-像素

  • 计算机在屏幕上显示的内容都是由屏幕上的每一个像素组成的
  • 像素是一个密度单位,而厘米是长度单位,两者无法比较
    例如“计算机显示器的分辨率是800*600,表示计算机屏幕上的每一行由800个点组成,共有600行。整个计算机屏幕共有480000个像素。

介绍-快速入门

入门案例-在面板上绘制一个圆

public class DrawCircle extends JFrame {//JFrame 对应窗口,可以理解成一个画框

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

    //1,定义一个面板
    private MyPanel mp = null;

    public DrawCircle() {//构造器
        //2,初始化面板
        mp = new MyPanel();
        //3,把面板放入到画框
        this.add(mp);
        //4,设置窗口的大小
        this.setSize(800, 800);
        //5,(默认退出)当点击窗口的小×,程序完全退出
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //6,可以显示
        this.setVisible(true);
    }
}

//1,先定义一个MyPanel类,继承JPanel类, 画图形,在画板上画
class MyPanel extends JPanel {
    /*
    1,MyPanel 对象就是一个画板
    2,Graphics g  可以把g理解成一支画笔
    3,Graphics 提供了很多绘图方法
     */
    //paint方法被调用:当组件第一次在屏幕显示时,程序会自动调用paint()方法来绘制组件
    @Override
    public void paint(Graphics g) {//绘图方法
        super.paint(g);//调用父类的方法完成初始化
        System.out.println("paint方法被调用了~");
        //画一个圆形  drawOval(x1,y1,y2,y2)
//        g.drawOval(0,0,100,100);

        //画直线 drawLine(int x1,int y1,int x2,int y2)
//        g.drawLine(10, 10, 100, 100);

        //画矩形边框 drawRect(int x, int y, int width, int height)
        //g.drawRect(10, 10, 100, 100);

        //画椭圆边框 drawOval(int x, int y, int width, int height)

        //填充矩形 fillRect(int x, int y, int width, int height)
        //填充椭圆 fillOval(int x, int y, int width, int height)

        //设置画笔的颜色
//        g.setColor(Color.blue);
//        g.drawOval(0,0,100,100);

        //画图片  drawImage(Image img, int x, int y, ..)
        //1,获取图片资源   /表示在该项目的根目录去获取  图片资源
//        Image image = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/01.jpg"));
//        g.drawImage(image,10,10,740,500,this);
        //画字符串 drawString(String str, int x, int y)//写字
         //给画笔设置颜色和字体
        g.setColor(Color.red);
        //public abstract void setFont(Font font);  调用setFont方法,需要传入一个对象
        g.setFont(new Font("隶书", Font.BOLD, 50));//Font.BOLD 表示粗体
        //给画笔设置内容
        //这里设置的 100, 100, 是 "北京你好"左下角
        g.drawString("北京你好", 100, 100);
        //设置画笔的字体 setFont(Font font)
        //设置画笔的颜色 setColor(Color c) 
    }
}

在这里插入图片描述

在这里插入图片描述

绘图原理

  • Component类提供了两个和绘图相关最重要的方法
    1,paint(Graphics g) 绘制组件的外观
    2,repaint() 刷新组件的外观
  • 当组件第一次在屏幕显示时,程序会自动调用paint()方法来绘制组件
  • 在以下情况下paint() 将会被调用
    1,窗口最小化,再最大化
    2,窗口的大小发生变化
    3,repaint方法被调用

Graphics 类

Graphics类可以理解为:就是画笔。为我们提供了各种绘制图形的方法

绘出坦克

  • 坦克父类 Tank
    定义坦克的横坐标和纵坐标,进行初始化,并调用set get方法,以供其他类来使用
  • 自己的坦克类,继承坦克父类 Hero
    重写父类的构造器
  • 画板类 MyPanel 继承Jpanel类
    1,定义自己的坦克,并初始化自己的坦克
    2,重写Jpanel类中的paint方法(传入画笔)
    3,通过画笔填充一个矩形区域 g.fillRect();
    4,创建drawTank方法,设置参数(int x, int y, Graphics g, int direct, int type) direct:用与控制方向 type:用于控制颜色
    5,在paint方法中调用drawTank方法
  • 窗体类 TankGame01
    1,创建画板对象,并进行初始化
    2,把画板传入窗体
    3,设置窗体大小
    4,设置窗体默认退出
    5,设置窗体可见

坦克父类

//坦克父类
public class Tank {
    private int x;//坦克的横坐标
    private int y;//坦克的纵坐标

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

    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 class Hero extends Tank{
//重写父类的构造器
    public Hero(int x, int y) {
        super(x, y);
    }
}

画板类


//画板类
public class MyPanel extends JPanel {
    //	1,定义自己的坦克,并初始化自己的坦克
    Hero hero = null;

    public MyPanel() {//初始化自己的坦克
        hero = new Hero(100,100);
    }

    //2,重写Jpanel类中的paint方法(传入画笔)
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        //	3,通过画笔填充一个矩形区域   g.fillRect();
        g.fillRect(0,0,1000,750);//填充矩形,默认为黑色
        //	5,在paint方法中调用drawTank方法
        drawTank(hero.getX(),hero.getY(),g,0,1);
        drawTank(hero.getX() +100,hero.getY(),g,0,0);
    }
    /*
    int x 坦克的横坐标
    int y 坦克的纵坐标
    Graphics g  画笔
    int direct  坦克的方向
    int type  坦克的类型
     */
    //4,创建drawTank方法,设置参数(int x, int y, Graphics g, int direct, int type)  direct:用与控制方向   type:用于控制颜色
    public void drawTank(int x, int y, Graphics g, int direct, int type){
        //根据不同类型的坦克,设置不同的颜色
        switch(type){
            case 0://我们的坦克
                g.setColor(Color.cyan);
                break;
            case 1://敌人的坦克
                g.setColor(Color.yellow);
                break;
        }

        //根据坦克的方向,来绘制坦克
        switch (direct){
            case 0://表示向上
                g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
                g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
                g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子
                g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
                g.drawLine(x + 20, y + 30, x + 20, y);//画出炮筒
                break;
            default:
                System.out.println("暂时没有处理");
        }
    }
}


窗体类

//窗体类
public class TankGame01 extends JFrame {//窗体
    public static void main(String[] args) {
        new TankGame01();
    }

    private MyPanel mp = null;//1,创建画板对象
    public TankGame01(){
        mp = new MyPanel();//画板初试化
        this.add(mp);//2,把画板传入窗体
        this.setSize(1000,750);//3,设置窗体大小
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//4,设置窗体默认退出
        this.setVisible(true);//	5,设置窗体可见

    }

}

java事件处机制

事件处理机制入门案例:小球移动代码

小球案例中的事件源、事件/对象和事件监听者分别是什么

  • 事件源:键盘
  • 事件:按下鼠标
  • 事件监听者:MyPanel_类(实现KeyListener键盘监听器接口)
public class BallMove extends JFrame{//窗体

    public static void main(String[] args) {
        BallMove ballMove = new BallMove();
    }
    //创建画板对象
    private MyPanel_ mp = null;

    public BallMove() {
        mp = new MyPanel_();//初始化画板
        this.add(mp);//给窗体添加组件-画板
        this.setSize(500,500);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //窗体JFrame对象可以监听键盘事件,面板时间了键盘监听器
        // 即可以监听到面板发生的监听事件
        this.addKeyListener(mp);
        this.setVisible(true);
    }
}
class MyPanel_ extends JPanel implements KeyListener {//画板 实现键盘监听器
    int x = 10;
    int y = 10;
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillOval(x,y,10,10);
    }
    //有字符输出时,该方法就会触发
    @Override
    public void keyTyped(KeyEvent e) {

    }
    //当某个键按下,该方法会触发
    @Override
    public void keyPressed(KeyEvent e) {
//        System.out.println("按键");
        if (e.getKeyCode() == KeyEvent.VK_DOWN){
            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++;
        }

        //重绘
        repaint();
    }
    //当某个键释放(松开),该方法会触发
    @Override
    public void keyReleased(KeyEvent e) {

    }
}

java事件处理是采取“委派事件模型”。当事件发生时,产生事件的对象,会把此“信息”传递给“事件的监听者”处理,。这里所说的“信息”实际上是java.awt.event事件类库里某个类所创建的对象,把他成为“事件的对象”在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

让坦克动起来

在前面绘制好坦克的基础上实现改变方向和移动

改变坦克的方向

  • 坦克父类 Tank
    定义坦克方向的属性,进行初试化,并创建set get方法
  • 自己的坦克类,继承坦克父类 Hero
    不变
  • 画板类 MyPanel 继承Jpanel 实现 KeyListener 键盘监听器接口
    1,在drawTank方法中,设置方向:向上 向下 向左 向右
    2,在实现KeyListener 键盘监听器接口时,重写接口中的方法
    3,在keyPressed方法中,将键盘输入与方向相结合
    4,在keyPressed中调用repaint方法进重绘,使的画出的图形改变时,仍然可以画出
  • 窗体类 TankGame02
    让窗体监听画板发生的监事件

使坦克动移动起来

  • 坦克父类 Tank
    1,定义 可以上下左右移动的方法。使得在MyPanel 类中可以直接调用方法进行移动
    2,定义speed属性,进行初始化,并添加set get方法
  • 自己的坦克类,继承坦克父类 Hero
    不变
  • 画板类 MyPanel 继承Jpanel 实现 KeyListener 键盘监听器接口
    1,在MyPanel 类中调用setSpeed设置speed的大小
    3,在keyPressed方法中,调用hero中的 上下左右方法
  • 窗体类 TankGame02
    不变

坦克父类

//坦克父类
public class Tank {
    private int x;//坦克的横坐标
    private int y;//坦克的纵坐标
    private int direct;//坦克方向   //direct表示方法:  0:向上   1:向右    2:向下    3:向左
    private int speed = 1;

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }
    //定义 可以上下左右移动的方法
    public void moveUp() {
        y -= speed;
    }

    public void moveDown() {
        y += speed;
    }

    public void moveLeft() {
        x -= speed;
    }

    public void moveRight() {
        x += speed;
    }


    public Tank(int direct) {
        this.direct = direct;
    }

    public int getDirect() {
        return direct;
    }

    public void setDirect(int direct) {
        this.direct = direct;
    }

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

    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 class Hero extends Tank {

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

画板类

//画板类
public class MyPanel extends JPanel implements KeyListener {
    //定义我的坦克
    Hero hero = null;

    public MyPanel() {//初始化自己的坦克
        hero = new Hero(100,100);
        hero.setSpeed(5);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        //3,通过画笔填充一个矩形区域   g.fillRect();
        g.fillRect(0,0,1000,750);//填充矩形,默认为黑色

        drawTank(hero.getX(),hero.getY(),g,hero.getDirect(),1);
//        drawTank(hero.getX() +100,hero.getY(),g,hero.getDirect(),0);
//        drawTank(hero.getX() +200,hero.getY(),g,hero.getDirect(),0);
//        drawTank(hero.getX() +300,hero.getY(),g,hero.getDirect(),1);
    }
    /*
    int x 坦克的横坐标
    int y 坦克的纵坐标
    Graphics g  画笔
    int direct  坦克的方向
    int type  坦克的类型
     */

    public void drawTank(int x, int y, Graphics g, int direct, int type){
        //根据不同类型的坦克,设置不同的颜色
        switch(type){
            case 0://敌人的坦克
                g.setColor(Color.cyan);
                break;
            case 1://我的坦克
                g.setColor(Color.yellow);
                break;
        }

        //根据坦克的方向,来绘制坦克
        //direct表示方法:  0:向上   1:向右    2:向下    3:向左
        switch (direct){
            case 0://表示向上
                g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
                g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
                g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子
                g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
                g.drawLine(x + 20, y + 30, x + 20, y);//画出炮筒
                break;
            case 1://表示向右
                g.fill3DRect(x, y, 60, 10, false);//画出坦克上边轮子
                g.fill3DRect(x, y+30, 60, 10, false);//画出坦克下边轮子
                g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克盖子
                g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子
                g.drawLine(x + 30, y + 20, x + 60, y+20);//画出炮筒
                break;
            case 2://表示向下
                g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
                g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
                g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子
                g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
                g.drawLine(x + 20, y + 30, x + 20, y+60);//画出炮筒
                break;
            case 3://表示向左
                g.fill3DRect(x, y, 60, 10, false);//画出坦克上边轮子
                g.fill3DRect(x, y+30, 60, 10, false);//画出坦克下边轮子
                g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克盖子
                g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子
                g.drawLine(x + 30, y + 20, x , y+20);//画出炮筒
                break;
            default:
                System.out.println("暂时没有处理");
        }
    }
    //有字符输出时,该方法就会触发
    @Override
    public void keyTyped(KeyEvent e) {

    }
    //当某个键按下,该方法会触发
    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_W){
            //改变坦克方向
            hero.setDirect(0);
            //让坦克动起来
            hero.moveUp();
        } else if (e.getKeyCode() == KeyEvent.VK_S) {
            hero.setDirect(2);
            hero.moveDown();
        } else if (e.getKeyCode() == KeyEvent.VK_A) {
            hero.setDirect(3);
            hero.moveLeft();
        } else if (e.getKeyCode() == KeyEvent.VK_D) {
            hero.setDirect(1);
            hero.moveRight();
        }

        //重绘
        repaint();
    }
    //当某个键释放(松开),该方法会触发
    @Override
    public void keyReleased(KeyEvent e) {

    }
}

窗体类

//窗体类
public class TankGame02 extends JFrame {//窗体
    public static void main(String[] args) {
        new TankGame02();
    }
    private MyPanel mp = null;//创建画板对象
    public TankGame02(){
        mp = new MyPanel();//画板初试化
        this.add(mp);//把画板传入窗体
        this.setSize(1000,750);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //窗体JFrame对象可以监听键盘事件,面板实现了键盘监听器
        // 即可以监听到面板发生的监听事件
        this.addKeyListener(mp);
        this.setVisible(true);
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

drippingblues 靶机实战

信息收集: Nmap: 存活: 靶机ip:192.168.10.110 端口: 服务: 发现ftp服务可以匿名登录。且用户名是FTP。 发现一个压缩包,下载并爆破。 得到密码 072528035。发现关键字 drip。里面还有一个 secret.zip(…

GIT基础01 基础命令与分支

前言 我们知道git是开发中比较常见的版本控制工具 我们可以先提出一个场景: 老板让你去修改方案 第一次修改 打回 第二次修改 打回 第n次修改 老板让你使用第一次的版本 阁下如何应对??? 我对每个版本进行编号?? 是一种方案 但是这里也是有缺陷的 比如说在很多版本中找…

将 Vue、React、Angular、HTML 等一键打包成 macOS 和 Windows 平台客户端应用

应用简介 PPX 基于 pywebview 和 PyInstaller 框架,构建 macOS 和 Windows 平台的客户端。本应用的视图层支持 Vue、React、Angular、HTML 中的任意一种,业务层支持 Python 脚本。考虑到某些生物计算场景数据量大,数据私密,因此将…

odoo16 银行对账单导入改造

解决问题: odoo原生功能的话 是不能在系统上临时处理文件内容的,只会提示文件内容格式不对。 原始文件格式 在头部与尾部 格式问题,例如csv文件和 C53 文件,做一个前置弹框处理数据之后再导入 camt效果: csv效果:

Ajax额

原生Ajax xml 已被json取代 http 请求方法urlhttp版本号 network 谷歌浏览器查看请求报文和响应报文 F12 network header里面有 请求头 响应头 点击view source 可以查看请求响应行 请求体在请求行头下面 get请求有url参数,请求体变为query String…

九、e2studio VS STM32CubeIDE之const修饰BSP函数的形参

目录 一、概述/目的 二、通过串口发送函数对比 2.1 stm32 hal库 VS renesas FSP 2.2 const修改函数形参的作用 2.2.1 值传递-副本 2.2.2 指针传递(就近原则) 2.2.2.1 const修饰:*P 2.2.2.2 const修饰:指针变量P 2.2.2.3 …

工业物联网解决方案:机房动环监控系统

工业物联网解决方案:机房动环监控系统 工业物联网(IIoT)作为数字化转型的关键驱动力,正深刻改变着各行各业的运作模式,其中机房动环监控系统是实现智能化运维管理的重要组成部分。该系统通过集成传感器技术、大数据分…

基于51单片机的时钟万年历—可农历显示

基于51单片机的时钟万年历 (仿真+程序+原理图+设计报告) 功能介绍 具体功能: 1、可以显示年、月、日、时、分、秒、星期、农历; 2、按键可以设置闹钟及报警; 3、按键可以调整时…

Mimikatz安装 lsass进程 SAM NTML

目录 什么是Mimikatz Mimikatz在windows上安装及使用 mimkatz语法 lsass进程 SAM NTML 什么是Mimikatz Mimikatz是一款开源的Windows安全工具,由法国安全研究员Benjamin Delpy开发。它最初被设计为用于学习C语言和进行Windows安全性实验的工具。然而&#xf…

常用地图API平台对比:高德、百度、腾讯、必应、天地图

本文介绍高德、百度、腾讯、必应与天地图等5个地图开发API平台,并对其各自的优势与相对不足加以对比与主观分析。 最近,一些工作需要用到地图开发API方面的内容;在此之前,我还从来没有接触过地图开发相关API的知识与实践&#xff…

DigitalOcean 的PostgreSQL、MySQL、Redis、Kafka托管数据库,现已支持自定义指标收集功能

近期,我们的几个托管数据库(PostgreSQL、MySQL、Redis和Kafka)引入了自定义数据指标功能(scrapable metrics)。这些指标使您更具体、更细致地了解数据库的性能,包括延迟、资源利用率和错误率。然后&#xf…

SpringSecurity安全过滤器工作原理

前面通过三篇文章,从底层代码的角度分析了SpringSecurity的初始化过程。 接下来我们就要具体看一下,Spring Security的安全过滤器初始化、装配好之后,到底是怎么工作的。 还是按图索骥 下面我们简单从底层源码分析一下,请求是怎…

赋能业务全球化,明道云HAP通过亚马逊云科技 FTR认证

近日,明道云作为融合多元能力的超级应用平台,成功通过了AWS(Amazon Web Service)的FTR(Foundational Technical Review)认证。FTR是亚马逊云科技为合作伙伴解决方案提供的一项全面技术审核机制,…

Verilog代码bug:一种特殊的组合逻辑环

Verilog代码bug:一种特殊的组合逻辑环 组合逻辑环(Combinational Loop)是什么,别的文章已经写的很多了,本文就不赘述了,本文主要记录遇到过的一种特殊的逻辑环; 代码如下所示: mo…

苹果电脑卡顿反应慢怎么办 苹果电脑卡顿严重解决方法 mac电脑太卡了怎么办

作为Mac用户,你是否正在经历或者曾经遭遇过电脑卡顿、反应慢的困扰?这可能是由于多种原因导致的,包括自启动程序过多、系统与应用未及时更新、内存管理不当等。今天和你一起来探讨下,苹果电脑卡顿反应慢时怎么办。希望能够帮助你解…

知乎广告推广投放流程以及价格?

知乎作为一个拥有庞大高质量用户群体的知识分享平台,成为了众多品牌不可忽视的广告投放渠道。知乎不仅汇聚了各行各业的专业人士,其独特的社区氛围也为品牌提供了精准触达目标受众的机会。知乎广告推广的投放流程、费用标准,云衔科技提供的专…

css如何实现边框模糊的效果

其实并不难&#xff0c;用属性 filter: blur(数字px); 即可。效果如下&#xff1a; 图上的圆形内有色彩的渐变&#xff0c;同样也是用filter: blur(数字px); 实现的&#xff0c;代码如下&#xff1a;、 <template><div id"root" :style"{}">…

Jenkins构建流程

Jenkins是DevOps【(Development和Operations的混成词&#xff09;是一种重视“软件开发人员&#xff08;Dev&#xff09;”和“IT运维技术人员&#xff08;Ops&#xff09;”之间沟通合作的文化、运动或惯例)】的重要一环&#xff0c;是一款开源的CI&CD软件。也就是持续集成…

【35分钟掌握金融风控策略27】贷中风控策略与客户运营体系

目录 贷中风控策略与客户运营体系 贷中风控日标 贷中风控数据源 贷中风控策略与客户运营体系 贷中是风控的第二道防线&#xff0c;贷中阶段风控的重点工作就是存量客户风控及运营。在当下&#xff0c;新客市场趋于饱和且获客成本越来越高&#xff0c;所以&#xff0c;在做好…

手撸XXL-JOB(四)——远程调用定时任务

Java Socket网络编程 网络编程是Java编程中的重要组成部分&#xff0c;包括服务端和客户端两部分内容。Socket是Java网络编程的基本组件之一&#xff0c;用于在应用程序之间提供双向通信&#xff0c;Socket提供了一种标准的接口&#xff0c;允许应用程序通过网络发送和接收数据…