Java多线程游戏——坦克大战

一.游戏登陆界面

package TankFight;import javax.swing.*;
import java.awt.*;public class GameUI {public void initUI() {JFrame jf = new JFrame();jf.setSize(1100, 900);//设置窗口大小jf.setTitle("坦克大战" );//设置窗口标题jf.setLocationRelativeTo(null);//设置窗口居中jf.setDefaultCloseOperation(3);//设置用户在此窗体上点击关闭按钮时默认执行的操作//游戏面板JPanel gamePanel = new JPanel();gamePanel.setBackground(Color.black);jf.add(gamePanel,BorderLayout.CENTER);jf.setVisible(true);Graphics g = gamePanel.getGraphics();//画笔//监听器Threadlistener mouse = new Threadlistener(g,gamePanel);jf.addKeyListener(mouse);//让窗体获取焦点jf.requestFocus();}public static void main(String[] args) {GameUI ui = new GameUI();ui.initUI();}
}

二.移动物体类(后面坦克类和子弹类的父类)

package TankFight;public class MoveObject {private int x, y, size = 100;//坐标,尺寸private int speedX = 0, speedY = 0;//水平竖直方向速度private int direction;  //控制方向public MoveObject(){}public MoveObject(int x,int y){this.x = x;this.y = y;}//移动方法public void move(){y += speedY;x += speedX;}//获取坐标方法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 getSize() {return size;}public void setSize(int size) {this.size = size;}public int getSpeedX() {return speedX;}public void setSpeedX(int speedX) {this.speedX = speedX;}public int getSpeedY() {return speedY;}public void setSpeedY(int speedY) {this.speedY = speedY;}public int getDirection() {return direction;}public void setDirection(int direction) {this.direction = direction;}
}

三.坦克类

在此之前我们首先搜素坦克上下左右四个方向的图片各一张,放入picture包下,分别命名tank1,tank2,tank3,tank4。

package TankFight;import javax.swing.*;
import java.awt.*;public class MyTank extends MoveObject{public JPanel gamePanel;public ImageIcon[] tankImage = new ImageIcon[4];//地图1 砖块  2 石头   3 草地   4 水public int[][] Barriersmap ={{ 1, 1, 1, 1, 0, 1, 1, 1, 1},{ 2, 2, 1, 1, 0, 1, 1, 2, 2},{ 0, 0, 0, 0, 0, 0, 0, 0, 0},{ 3, 3, 3, 3, 0, 3, 3, 3, 3},{ 1, 1, 1, 1, 0, 1, 1, 1, 1},{ 3, 3, 0, 0, 0, 0, 0, 3, 3},{ 1, 1, 0, 1, 1, 1, 0, 1, 1},{ 1, 1, 0, 1, 4, 1, 0, 1, 1},{ 1, 1, 0, 1, 1, 1, 0, 1, 1}};public MyTank(int x, int y, JPanel gamePanel){super(x,y);this.gamePanel = gamePanel;this.setSize(60);//加载图片for(int i=0;i<4;i++){tankImage[i] = new ImageIcon("picture//tank"+i+".jpg");}//设置默认方法}//画我方坦克public void drawTank(Graphics g){ImageIcon image = isDirection();g.drawImage(image.getImage(),getX(),getY(),getSize(),getSize(),null);}//根据当前方法,选择合适的图片public ImageIcon isDirection(){if(getSpeedX() > 0 ){//向右移动setDirection(3);} else if(getSpeedX() < 0 ){//向左移动setDirection(2);}else if(getSpeedY() < 0 ){//向下移动setDirection(0);}else if(getSpeedY() > 0 ){//向上移动setDirection(1);}ImageIcon image =  tankImage[getDirection()];return image;}//移动方法public void move(){int xl=(getX())/100,yl=(getY())/100;int size=getSize();int xdl=(getX())/100,ydl=(getY()+size)/100;int xr=(getX()+size)/100,yr=(getY())/100;int xdr=(getX()+size)/100,ydr=(getY()+size)/100;System.out.println(xl+" "+yl+" "+Barriersmap[yl][xl]);switch(getDirection())//判断方向,加载不同方向对应的坦克图片,设置速度{case 0:if(Barriersmap[yl][xl]==1||Barriersmap[yr][xr]==1||Barriersmap[yl][xl]==2||Barriersmap[yr][xr]==2){setSpeedY(0);}break;case 1:if(Barriersmap[ydl][xdl]==1||Barriersmap[ydr][xdr]==1||Barriersmap[ydl][xdl]==2||Barriersmap[ydr][xdr]==2){setSpeedY(0);}break;case 2:if(Barriersmap[yl][xl]==1||Barriersmap[ydl][xdl]==1||Barriersmap[yl][xl]==2||Barriersmap[ydl][xdl]==2){setSpeedX(0);}break;case 3:if(Barriersmap[yr][xr]==1||Barriersmap[ydr][xdr]==1||Barriersmap[yr][xr]==2||Barriersmap[ydr][xdr]==2){setSpeedX(0);}break;}super.move();//移动}}

四.子弹类

package TankFight;import java.awt.*;public class Bullet extends MoveObject {public int direc;//方向public MyTank mt;//坦克public boolean stop=false;//停止public Bullet(int x, int y, MyTank mt) {super(x, y);this.direc = mt.getDirection();this.mt = mt;setSize(10);//尺寸setSpeedY(-3);//速度}public void drawbullet(Graphics g) {g.setColor(Color.red);g.fillOval(getX(), getY(), getSize(), getSize());}//按方向重写move@Overridepublic void move() {if(!stop){switch (direc) {case 0:setSpeedY(-4);setSpeedX(0);break;case 1:setSpeedY(4);setSpeedX(0);break;case 2:setSpeedY(0);setSpeedX(-4);break;case 3:setSpeedY(0);setSpeedX(4);break;}super.move();}}
}

五.音乐类

从外网下载音乐包导入(自行),并下载你想要的坦克大战背景音乐加入music包下命名为bg1.mp3

package TankFight;import javazoom.jl.player.Player;import java.io.File;
import java.io.FileInputStream;public class Music {//播放音乐类static Player player;public static void playMusic(){//匿名内部类new Thread(new Runnable() {@Overridepublic void run() {String path = "music/bg1.mp3";FileInputStream fis = null;try {//输入文件流fis = new FileInputStream(new File(path));player = new Player(fis);player.play();} catch (Exception e) {throw new RuntimeException(e);}}}).start();}public static void close(){player.close();}
}

六.线程启动页面类

package TankFight;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

//线程启动页面
public class ThreadGame implements Runnable {
    public Graphics g;//画笔
    public boolean start = false;//启动
    public  MyTank mt;//坦克
    public int mapsize =100;//地图尺寸
    public int changeablemapsize=100;
    public JPanel gamePanel;
    public BufferedImage bufferedImage;
    public ArrayList<MoveObject> listTank;//保存其他坦克
    public ArrayList<Bullet> listBullet;  //保存子弹
    //地图素材
    public Image[] mapArr = new Image[4];
    public Image boom=new ImageIcon("picture/boom.jpg").getImage();
    public int score=0;
    public int[][] Barriersmap;
    public int[][] countmap=new int[9][9];

    //初始化属性
    public ThreadGame(Graphics g,MyTank mt, ArrayList<Bullet> listBullet,JPanel gamePanel) {
        this.g = g;
        this.mt = mt;
        this.gamePanel=gamePanel;
        this.listBullet = listBullet;
        this.Barriersmap=mt.Barriersmap;

        //初始化图片素材
        for (int i = 1; i <= 4; i++) {
            mapArr[i-1] = new ImageIcon("picture//map" + i + ".png").getImage();
        }
    }
    public void isStart(boolean start) {
        this.start = start;
    }

    public void Drawmap(Graphics g){
        //画出障碍物
        for(int i = 0; i< Barriersmap.length; i++)
        {
            for(int j = 0; j< Barriersmap[0].length; j++)
            {
                if (Barriersmap[i][j] == 1) {
                    g.drawImage(mapArr[1], j * mapsize, i * mapsize, mapsize, mapsize, null);
                } else if (Barriersmap[i][j] == 2) {
                    g.drawImage(mapArr[0], j * mapsize, i * mapsize, mapsize, mapsize, null);
                } else if (Barriersmap[i][j] == 3) {
                    g.drawImage(mapArr[2], j * mapsize, i * changeablemapsize,changeablemapsize, changeablemapsize, null);
                } else if (Barriersmap[i][j] == 4) {
                    g.drawImage(mapArr[3], j * mapsize, i * mapsize, mapsize, mapsize, null);
                }

            }
        }
    }
    //启动线程后自动执行的方法
    //run 执行完,该线程的内存被回收,不能再启动
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":启动...");
        //创建缓冲区
        //作为容器,从中获取画笔绘画
        bufferedImage = new BufferedImage(gamePanel.getWidth(),
                gamePanel.getHeight(),BufferedImage.TYPE_INT_RGB);
        Graphics bufferg =bufferedImage.getGraphics();
        while (true) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException ex) {
                throw new RuntimeException(ex);
            }

            if (!start) {
                //绘制开始按钮
                drawStr(bufferg,"按空格键开始游戏");
                continue;
            }

            bufferg.setColor(Color.black);
            bufferg.fillRect(0,0,gamePanel.getWidth(),gamePanel.getHeight());

            Drawmap(bufferg);

            //画控制方坦克
            mt.drawTank(bufferg);
            mt.move();

            //分数区
            drawScore(bufferg,"SCORE:"+score);

            //子弹
            for(int i=0;i<listBullet.size();i++){
                Bullet bullet=listBullet.get(i);
                bullet.drawbullet(bufferg);
                bullet.move();

            }

            attack(bufferg);
            //将缓冲区内绘画显示出来
            g.drawImage(bufferedImage,0,0,null);

        }
    }
    public void attack(Graphics bufferg){
        //子弹攻击功能
        for(int i=0;i<listBullet.size();i++){
            Bullet bullet=listBullet.get(i);
            bullet.drawbullet(bufferg);
            bullet.move();
            int x=bullet.getX()/100,y=bullet.getY()/100;
            if(x>=0&&x<9&&y>=0&&y<9)
            {
                if((Barriersmap[y][x]==1||Barriersmap[y][x]==2)&&!bullet.stop)
                {
                    bufferg.setColor(Color.black);
                    countmap[y][x]++;
                    System.out.println(countmap[y][x]);
                    bullet.setSize(0);
                    bullet.stop=true;
                    if(countmap[y][x]==10)
                    {
                        Barriersmap[y][x]=0;
                        score++;
                    }
                }
            }
        }

        g.drawImage(bufferedImage,0,0,null);

    }

    public void drawStr(Graphics bufferg,String s){//写文字
        bufferg.setColor(Color.RED);
        bufferg.setFont(new Font("楷体",0,50));
        bufferg.drawString(s,400,400);
        g.drawImage(bufferedImage,0,0,null);
    }
    public void drawScore(Graphics bufferg,String s){//写分数
        bufferg.setColor(Color.RED);
        bufferg.setFont(new Font("楷体",0,30));
        bufferg.drawString(s,935,50);
        g.drawImage(bufferedImage,0,0,null);
    }
}

七.监听器类

主要是键盘监听器:1.↑↓←→键控制方向 2.j键发射子弹 3.空格键启动音乐

package TankFight;

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

public class Threadlistener implements KeyListener {
    public Graphics g;
    public ThreadGame tg;
    public int bu_small =25;
    public int bu_big =55;
    public JPanel gamePanel;
    public MyTank mt;
    public ArrayList<Bullet> listBullet = new ArrayList<>();
    public Threadlistener(Graphics g,JPanel gamePanel){
        this.g=g;
        this.gamePanel=gamePanel;

        //初始化的时候就创建线程
        if (tg == null) {
            //创建我方坦克
            mt = new MyTank(210,700,gamePanel);
            //限制线程只启动一次
            //2.实现Runnable接口启动方式
            tg = new ThreadGame(g,mt,listBullet,gamePanel);
            new Thread(tg).start();
        }
    }
    public void keyTyped(KeyEvent e){}
    public void keyPressed(KeyEvent e){
        int key = e.getKeyCode();
        switch(key){
            case KeyEvent.VK_UP:
                if(mt.getSpeedX()==0)
                     mt.setSpeedY(-3);
                break;
            case KeyEvent.VK_LEFT:
                if(mt.getSpeedY()==0)
                    mt.setSpeedX(-3);
                break;
            case KeyEvent.VK_RIGHT:
                if(mt.getSpeedY()==0)
                    mt.setSpeedX(3);
                break;
            case KeyEvent.VK_DOWN:
                if(mt.getSpeedX()==0)
                    mt.setSpeedY(3);
                break;
            case KeyEvent.VK_SPACE:
                tg.start=true;
                Music.playMusic();
                break;
            case KeyEvent.VK_J:
                switch (mt.getDirection())
                {
                    case 0:
                        Bullet bullet = new Bullet(mt.getX()+ bu_small, mt.getY(),mt);
                        listBullet.add(bullet);
                        break;
                    case 1:
                        bullet = new Bullet(mt.getX()+ bu_small, mt.getY()+ bu_big,mt);
                        listBullet.add(bullet);
                        break;
                    case 2:
                        bullet = new Bullet(mt.getX(), mt.getY()+ bu_small,mt);
                        listBullet.add(bullet);
                        break;
                    case 3:
                        bullet = new Bullet(mt.getX()+ bu_big, mt.getY()+ bu_small,mt);
                        listBullet.add(bullet);
                        break;
                }
                break;

        }
    }
    public void keyReleased(KeyEvent e) {
        int key = e.getKeyCode();
        switch (key) {
            case KeyEvent.VK_UP:
                mt.setSpeedY(0);
                break;
            case KeyEvent.VK_LEFT:
                mt.setSpeedX(0);
                break;
            case KeyEvent.VK_RIGHT:
                mt.setSpeedX(0);
                break;
            case KeyEvent.VK_DOWN:
                mt.setSpeedY(0);
                break;
        }
    }
}
八.任务线程

package TankFight;import java.util.ArrayList;//任务线程
public class TimeThread extends Thread{public long time =20;public ArrayList<MoveObject> listTank;public TimeThread(ArrayList<MoveObject> listTank){this.listTank=listTank;}public void run(){while(true){try {Thread.sleep(time);} catch (InterruptedException e) {throw new RuntimeException(e);}MoveObject tank=new MoveObject();listTank.add(tank);}}
}

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

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

相关文章

[PM]产品运营

生命周期 运营阶段 主要工作 拉新 新用户的定义 冷启动 拉新方式 促活 用户活跃的原因 量化活跃度 运营社区化/内容化 留存 用户流失 培养用户习惯 用户挽回 变现 变现方式 付费模式 广告模式 数据变现 变现指标 传播 营销 认识营销 电商营销中心 拼团活动 1.需求整理 2.…

大数据之路 读书笔记 Day7 实时技术 简介及流式技术架构

回顾&#xff1a; Day6 离线数据开发之数据开发平台Day5 数据同步遇到的问题与解决方案 1. 简介 阿里巴巴在流式数据处理方面采用了多种技术和框架&#xff0c;这些技术的特点包括&#xff1a; 高可伸缩性&#xff1a; 阿里巴巴使用Apache Flink进行大规模数据处理&#xff0c…

docker 容器内安装pdo_mysql扩展

1. 首先确定php配置文件&#xff08;php.ini&#xff09;打开了pdo_mysql注释。&#xff08;php.ini位置&#xff1a;运行容器时挂载文件时&#xff0c;指定的php.ini位置&#xff09; 2. 进入倒php容器内&#xff1a;docker exec -it 容器名 bash 3. 确认php扩展目录没有pdo…

Springboot项目远程部署gitee仓库(docker+Jenkins+maven+git)

创建仓库 创建一个Springboot项目&#xff0c;勾选web将该项目创建git本地仓库&#xff0c;再创建远程仓库推送上去 创建TestController RestControllerRequestMapping("/test")public class TestController {GetMapping("/hello")public String sayHell…

6.Kafka Acks详解

目录 概述Replication(分区副本)In-sync replicasAcknowledgementsacks0acks1acksallAck实用建议Minimum in-sync replicaCaveat(警告) 概述 本文对 kafka 的一些核心概念进行解释&#xff0c;也是 kafka 需要调优的一些地方。 官方原文速递 Replication(分区副本) 对于每个分…

如何识别Android init 中的缓慢操作

Android 14 开机时间优化措施汇总-CSDN博客 Android 14 开机时间优化措施-CSDN博客根据systrace报告优化系统时需要关注的指标和优化策略-CSDN博客Android系统上常见的性能优化工具-CSDN博客Android上如何使用perfetto分析systrace-CSDN博客Android系统设置kernel log level的…

222.买卖股票的最佳时机(力扣)

代码解决 class Solution { public:int maxProfit(vector<int>& prices) {// 初始化最小买入价为第一个价格int min1 prices[0];// 初始化最大利润为0int max1 0;// 从第二天开始遍历价格数组for (int i 1; i < prices.size(); i) {// 计算当前价卖出的利润&a…

windows edge自带的pdf分割工具(功能)

WPS分割pdf得会员&#xff0c;要充值&#xff01;网上一顿乱找&#xff0c;发现最简单&#xff0c;最好用&#xff0c;免费的还是回到Windows。 Windows上直接在edge浏览器打开PDF&#xff0c;点击 打印 按钮,页面下选择对应页数 打印机 选择 另存为PDF&#xff0c;然后保存就…

硬件开发——UART/I2C/SPI协议

硬件开发——UART/I2C/SPI协议 小狼http://blog.csdn.net/xiaolangyangyang 1、UART 电压&#xff1a; TTL电平&#xff1a;1&#xff1a;&#xff08;3.3V~5V&#xff09;&#xff0c;0&#xff1a;&#xff08;0V&#xff09;RS232电平&#xff1a;1&#xff1a;&#xff0…

【C++题解】1212. 移动数组元素

问题&#xff1a;1212. 移动数组元素 类型&#xff1a;数组找数 题目描述&#xff1a; 在一个不重复的数组中&#xff0c;请将这个数组的最小数和数组第一个数交换&#xff0c;最大数和数组最后一个数交换。 输入&#xff1a; 第一行有一个整数 n ( 5≤n≤100 &#xff09;…

Windows 11登录密码遗忘后如何在登录

在现代社会中&#xff0c;随着信息技术的迅猛发展&#xff0c;计算机操作系统如Windows 11已经成为我们日常生活和工作中不可或缺的一部分。然而&#xff0c;有时我们可能会遇到忘记登录密码的尴尬情况。为了帮助大家解决这个问题&#xff0c;本文将详细讲解如何快速破解Window…

浅谈端到端(自动驾驶)

一、 引言 端到端是近期非常火的话题&#xff0c;尤其在自动驾驶、具身智能等领域。去年UniAD的发布&#xff0c;给大家普及了端到端的网络设计&#xff0c;带动了行业的发展。产业界&#xff0c;特斯拉FSD Beta V12效果惊艳&#xff0c;近期理想也推出了双系统的E2E自动驾驶系…

MySQL 分组函数

目录 1. 单/多行处理 2. 分组函数分类 3. 分组函数组合使用 4. 注意 1. 单/多行处理 分组函数又被叫做多行处理函数&#xff08;多个输入&#xff0c;一个输出&#xff09;&#xff1b; 前面提到的数据处理函数又叫做单行处理函数&#xff08;一个输入&#xff0c;一个输出…

<Qt> 信号和槽

目录 一、信号和槽概述 二、信号和槽的使用​​​​​​ &#xff08;一&#xff09;connect函数 &#xff08;二&#xff09;实现一个点击按钮关闭窗口的功能 &#xff08;三&#xff09;再谈connect 三、自定义槽函数 四、自定义信号 五、带参数的信号和槽 六、信号…

哈喽GPT-4o,程序员如何通过GPT-4o保护自己的合法权益

目录 一、法律研究Prompt&#xff1a;派遣合同和劳务外包合同有什么区别&#xff1f;详细说一下在被裁员时的区别&#xff1f; 二、法律条文检索Prompt&#xff1a;检索《劳动合同法》&#xff0c;以下情况属于第几条&#xff0c;如果公司进行技能考试&#xff0c;并以技能考试…

在Ubuntu上安装redis

Ubuntu上安装redis 一、通过下载redis的压缩包安装二、通过apt包管理器安装Redis三、修改redis的配置文件四、控制redis启动 Redis是一种开源的内存数据存储&#xff0c;可以用作数据库、缓存和消息代理等。本文将会介绍两种不同的安装方式&#xff0c;包括通过压缩包安装以及通…

Linux 性能优化:轻松入门

文章目录 前言一、磁盘性能优化1、 磁盘 RAID 模式选择2、文件系统优化 二、优化 CPU1、性能监控 &#xff1a;2、进程优先级调整 &#xff1a;3、进程与 CPU 绑定 &#xff1a; 三、优化内存四、网络性能优化1、调整 TCP 缓冲区大小2、修改系统级别的文件描述符的数量3、调整 …

js中基础数据类型与引用数据类型的种类以及区分

一、js有哪几种数据类型&#xff1f;几种新增数据类型&#xff1f; 1.分基础类型和引用型类型 基础数据类型有&#xff1a; number、String、boolean、undefined、null 引用数据类型有 Object&#xff08;Array/数组和 function/函数 也属于对象的一种&#xff09; 新增的数据类…

微信小程序:3.页面开发

页面配置 注意 1.不需要添加window作为父级 窗口表现 "navigationBarBackgroundColor": "#ffffff","navigationBarTextStyle": "black","navigationBarTitleText": "第二个页面","backgroundColor": &…

求职学习day5

安排明天hr面 投一下平安可能。 hr面准备&#xff0c;复习java核心技术&#xff0c;复习java项目。 正视自己&#xff0c;调整心态。 也是很早接触了javaguide但是没有持续学习&#xff0c;项目介绍 | JavaGuide&#xff0c;面试前复习一下感觉还是很有收获的。 还有一些…