Java基础 - 坦克大战(第二章,实现坦克旋转与移动)

272 篇文章 4 订阅
14 篇文章 4 订阅

本章内容 - 让坦克动起来

Java事件处理机制

1.监听键盘事件 - KeyListener接口

package com.tao.event_;

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

/**
 * Create By 刘鸿涛
 * 2022/1/12 20:40
 */
public class BallMove extends JFrame {
    Mypanel mp = null;

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

    //构造器
    public BallMove() {
        mp = new Mypanel();
        this.add(mp);
        this.setSize(400, 300);  //窗口大小
        this.setLocationRelativeTo(null);           //居中
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //关闭
        this.setVisible(true);                  //可见
        //窗口JFrame对象可以监听键盘事件,即可以监听到面板真的发生了键盘事件
        this.addKeyListener(mp);
    }
}

//面板,可以画出小球
//KeyListener 是监听器,可以监听键盘事件
class Mypanel extends JPanel implements KeyListener {
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.fillOval(10, 10, 20, 20);
    }

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

    }

    //当某个键按下,该方法会触发
    @Override
    public void keyPressed(KeyEvent e) {
        System.out.println((char)e.getKeyCode() + "被按下..");
    }

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

    }
}

请添加图片描述

2.演示通过键盘键位控制小球移动

package com.tao.event_;

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

/**
 * Create By 刘鸿涛
 * 2022/1/12 20:40
 */
public class BallMove extends JFrame {
    Mypanel mp = null;

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

    //构造器
    public BallMove() {
        mp = new Mypanel();
        this.add(mp);
        this.setSize(400, 300);  //窗口大小
        this.setLocationRelativeTo(null);           //居中
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //关闭
        this.setVisible(true);                  //可见
        //窗口JFrame对象可以监听键盘事件,即可以监听到面板真的发生了键盘事件
        this.addKeyListener(mp);
    }
}

//面板,可以画出小球
//KeyListener 是监听器,可以监听键盘事件
class Mypanel extends JPanel implements KeyListener {

    //为了让小球可以移动,把他的左上角的坐标(X, Y)设置为变量
    int x = 10;
    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) {
//        System.out.println((char)e.getKeyCode() + "被按下..");
        //根据用户按下的不同键位,来处理小球的移动(上下左右的键位)

        //ctrl + b 详细查询VK_DOWN的十六进制编码
        if(e.getKeyCode() == KeyEvent.VK_DOWN){ //KeyEvent.VK_DOWN就是向下箭头对应的code = 0*28(16进制表示法) = 16进制28 = 十进制40
            y++;
            System.out.println("下");

        } else if(e.getKeyCode() == KeyEvent.VK_UP){
            y--;
            System.out.println("上");
        }else if(e.getKeyCode() == KeyEvent.VK_LEFT){
            x--;
            System.out.println("左");
        }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
            x++;
            System.out.println("右");
        }
//        面板重绘
        this.repaint();
    }

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

    }
}

基本说明

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

示意图

请添加图片描述

事件处理机制深入理解

  1. 前面我们提到几个重要的概念,事件源,事件,事件监听器我们下面来全面的介绍他们。
  2. 事件源:事件源是一个产生事件的对象,比如按钮,窗口等
  3. 事件:事件就是承载事件源状态改变时的对象,比如当键盘事件、鼠标事件、窗口事件等等,会生成一个事件对象,该对象保存着当前事件很多信息,如果KeyEvent对象有含义被按下键的Code值。java.awt.event包 和javax.swing.event包中定义了各种事件类型
事件类说明
ActionEvent通常在按下按钮,或双击一个列表项或选中某个菜单时发生
AdjustmentEvent当操作一个滚动条时发生
ComponentEvent当一个组件隐藏,移动,改变大小时发送
ContainerEvent当一个组件从容器中加入或者删除时发生
FocusEvent当一个组件获得或失去焦点时发生
ItemEvent当一个复选框或是列表项被选中时,当一个选择框或选择菜单被选中
KeyEvent当从键盘的按键被按下,松开时发生
MouseEvent当鼠标被拖动,移动,点击,按下…
TextEvent当文本区和文本域的文本发生改变时发生
WindowEvent当一个窗口激活,关闭,失效,恢复,最小化…

事件监听器接口:

请添加图片描述

  1. 当事件源产生一个事件,可以传送给事件监听者处理
  2. 事件监听者实际上就是一个类,该类实现了某个事件监听器接口比如前面我们案例中MyPanle就是一个类,它实现了KeyListener接口,他就可以作为一个事件监听者,对接受到的事件进行处理
  3. 事件监听器接口有多种,不同的事件监听器接口可以监听不同的事件,一个类可以实现多个监听接口
  4. 这些接口在java.awt.event包和javax.swing.event包中定义。

实现坦克上下左右旋转

  • 实现原理,坐标旋转
     //根据坦克方向,来绘制对应形状坦克
     //
        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 + 9, y + 18, 20,20);               //炮塔
                g.drawLine(x + 19, y - 10,x + 19,y + 20);           //炮筒
                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 + 18, y + 9, 20,20);               //炮塔
                g.drawLine(x - 10, y + 19,x + 20,y + 19);           //炮筒
                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 + 9, y + 18, 20,20);               //炮塔
                g.drawLine(x + 19, y + 50,x + 19,y + 20);           //炮筒
                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 + 18, y + 9, 20,20);               //炮塔
                g.drawLine(x + 50, y + 19,x + 20,y + 19);           //炮筒
                break;
            default:
                System.out.println("暂时没有处理");
        }

实现坦克移动

  • 首先画出坦克4个方位旋转图像,然后case选择中接收方向,通过封装的坦克x,y位置,以及move方法,修正参数,调用repaint()重新绘图,实现坦克移动
package com.tao.tankgame02;

/**
 * Create By 刘鸿涛
 * 2022/1/12 4:38
 */
public class Tank {
    private int x;  //坦克的横坐标
    private int y;  //坦克的纵坐标
    private int direct; //坦克方向返回值
    private int speed = 50;  //坦克的速度

    public int getDirect() {
        return direct;
    }

    public void moveUp(){
        y -= speed;
    }
    public void moveRight(){
        x += speed;
    }
    public void moveDown(){
        y += speed;
    }
    public void moveLeft(){
        x -= speed;
    }

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

package com.tao.tankgame02;

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

/**
 * Create By 刘鸿涛
 * 2022/1/12 4:41
 * 坦克大战的绘图区域
 */
public class MyPanel extends JPanel implements KeyListener {
    //定义我的坦克
    Hero hero = null;
    public MyPanel(){

        hero = new Hero(100,100);   //初始化自己的坦克
        hero.setSpeed(1000);               //初始化坦克速度
    }

    @Override
    public void paint(Graphics g){
        super.paint(g);
        g.fillRect(0,0,1000,750);    //填充矩形,默认黑色
        //画出坦克 - 封装方法
        drawTank(hero.getX(),hero.getY(),g,hero.getDirect(),1);        //type坦克类型
    }

    //编写方法,画出坦克

    /**
     *
     * @param x 坦克的左上角x坐标
     * @param y 坦克的左上角y坐标
     * @param g 画笔
     * @param direct    坦克方向(上下左右)
     * @param 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 + 9, y + 18, 20,20);               //炮塔
                g.drawLine(x + 19, y - 10,x + 19,y + 20);           //炮筒
                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 + 18, y + 9, 20,20);               //炮塔
                g.drawLine(x - 10, y + 19,x + 20,y + 19);           //炮筒
                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 + 9, y + 18, 20,20);               //炮塔
                g.drawLine(x + 19, y + 50,x + 19,y + 20);           //炮筒
                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 + 18, y + 9, 20,20);               //炮塔
                g.drawLine(x + 50, y + 19,x + 20,y + 19);           //炮筒
                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_D){  //右
            hero.setDirect(3);
            hero.moveRight();
//            hero.setX(hero.getX() + 1);
        }else if(e.getKeyCode() == KeyEvent.VK_S){  //下
            hero.setDirect(2);
            hero.moveDown();
//            hero.setY(hero.getY() + 1);
        }else if(e.getKeyCode() == KeyEvent.VK_A){  //左
            hero.setDirect(1);
            hero.moveLeft();
//            hero.setX(hero.getX() - 1);
        }
        repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

鬼鬼骑士

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

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

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

打赏作者

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

抵扣说明:

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

余额充值