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

为什么写这个项目

  • 好玩
  • 涉及到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);
    }

}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值