java单机版坦克游戏(尚学堂)

2024-01-29 11:18

本文主要是介绍java单机版坦克游戏(尚学堂),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

界面客户端 TankClient.java

package com.rs;import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;import javax.swing.*;public class TankClient extends JFrame{public static final int GAME_WIDTH=800;//常量名字母大写public static final int GAME_HEIGHT=600;Tank myTank=new Tank(50,50,true,Tank.Direction.STOP, this);Wall w1=new Wall(200,200,20,150,this),w2=new Wall(300,100,300,20,this);List<Explode> explodes=new ArrayList<Explode>();List<Missile> missiles=new ArrayList<Missile>();List<Tank> tanks=new ArrayList<Tank>();Image offScreenImage=null;public void paint(Graphics g) {//面向对象方法g.drawString("Missiles-count:"+missiles.size(),10,45);g.drawString("Explodes-count:"+explodes.size(),10,60);g.drawString("Tanks-count:"+tanks.size(),10,75);g.drawString("Tanks-lift:"+myTank.getLife(),10,90);for(int i=0;i<missiles.size();i++){Missile m=missiles.get(i);m.hitTanks(tanks);m.hitTank(myTank);m.hitWall(w1);m.hitWall(w2);m.draw(g);}	for(int j=0;j<explodes.size();j++){Explode e=explodes.get(j);e.draw(g);}for(int k=0;k<tanks.size();k++){Tank t=tanks.get(k);t.collidesWithWall(w1);t.collidesWithWall(w2);t.collidesWithTank(tanks);t.draw(g);}myTank.draw(g);w1.draw(g);w2.draw(g);}public void update(Graphics g) {//双缓冲技术if(offScreenImage==null){offScreenImage=this.createImage(GAME_WIDTH,GAME_HEIGHT);}Graphics goffScreen=offScreenImage.getGraphics();Color c=goffScreen.getColor();//前景重刷goffScreen.setColor(Color.GRAY);goffScreen.fillRect(0,0,GAME_WIDTH,GAME_HEIGHT);goffScreen.setColor(c);paint(goffScreen);g.drawImage(offScreenImage,0,0,null);}public void lauchFrame(){for(int i=0; i<10; i++){tanks.add(new Tank(50+40*(i+1),50,false,Tank.Direction.D, this));}this.setTitle("<MyTankWar>");this.setBounds(320,150,GAME_WIDTH,GAME_HEIGHT);		setResizable(false);this.setDefaultCloseOperation(EXIT_ON_CLOSE);setBackground(Color.gray);setVisible(true);this.addKeyListener(new KeyMonitor());new Thread(new TankThread()).start();}private static final long serialVersionUID = 1L;public static void main(String[] args) {TankClient tc=new TankClient();tc.lauchFrame();}private class TankThread implements Runnable{public void run() {while(true){repaint();try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}}}}private class KeyMonitor extends KeyAdapter{public void keyReleased(KeyEvent e) {myTank.keyReleased(e);}public void keyPressed(KeyEvent e) {myTank.KeyPressed(e);			}		}
}

坦克类 Tank.java:

package com.rs;import java.awt.*;
import java.awt.event.*;
import java.util.*;public class Tank {public static final int XSPEED = 5;public static final int YSPEED = 5;public static final int WIDTH = 30;public static final int HEIGHT = 30;private int x, y,oldX,oldY;TankClient tc;private BloodBar bb=new BloodBar();private boolean live=true;private boolean good;private static Random random=new Random();//一个就够了,所以设为staticprivate int step = random.nextInt(12)+3;private int life = 100;private boolean bL = false, bU = false, bR = false, bD = false;enum Direction {L, LU, U, RU, R, RD, D, LD, STOP};// 枚举类型使用private Direction dir = Direction.STOP;// 坦克默认方向private Direction ptDir = Direction.D;// 炮筒默认方向public Tank(int x, int y, boolean good) {this.x = x;this.y = y;this.oldX=x;this.oldY=y;this.good = good;}public Tank(int x, int y, boolean good, Direction dir, TankClient tc) {this(x, y, good);this.dir=dir;this.tc = tc;}public void draw(Graphics g) {if(!live) {if(!good){tc.tanks.remove(this);}return;}Color c = g.getColor();if (good) {g.setColor(Color.CYAN);} else {g.setColor(Color.blue);}g.fillOval(x, y, WIDTH, HEIGHT);g.setColor(c);if(good) bb.draw(g);switch (ptDir) {case L:g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x, y+ Tank.HEIGHT / 2);break;case LU:g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x, y);break;case U:g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH/ 2, y);break;case RU:g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH,y);break;case R:g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH,y + Tank.HEIGHT / 2);break;case RD:g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH,y + Tank.HEIGHT);break;case D:g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x + Tank.WIDTH/ 2, y + Tank.HEIGHT);break;case LD:g.drawLine(x + Tank.WIDTH / 2, y + Tank.HEIGHT / 2, x, y+ Tank.HEIGHT);break;}move();}private void move() {this.oldX=x;this.oldY=y;switch (dir) {case L:x -= XSPEED;break;case LU:x -= XSPEED;y -= YSPEED;break;case U:y -= YSPEED;break;case RU:x += XSPEED;y -= YSPEED;break;case R:x += XSPEED;break;case RD:x += XSPEED;y += YSPEED;break;case D:y += YSPEED;break;case LD:x -= XSPEED;y += YSPEED;break;case STOP:break;}if (this.dir != Direction.STOP) {this.ptDir = this.dir;}if (x < 0)x = 0;if (y < 25)y = 25;if (x+Tank.WIDTH>TankClient.GAME_WIDTH) x =TankClient.GAME_WIDTH-Tank.WIDTH;if (y+Tank.HEIGHT>TankClient.GAME_HEIGHT)y=TankClient.GAME_HEIGHT-Tank.HEIGHT;if(!good){Direction[] dirs=Direction.values();if(step == 0){step = random.nextInt(12)+3;int rn=random.nextInt(dirs.length);dir=dirs[rn];}	step--;if(random.nextInt(40)>38) this.fire();}		}public void stay(){x=oldX;y=oldY;}public void KeyPressed(KeyEvent e) {// 键盘按下int key = e.getKeyCode();switch (key) {case KeyEvent.VK_LEFT:bL = true;break;case KeyEvent.VK_UP:bU = true;break;case KeyEvent.VK_RIGHT:bR = true;break;case KeyEvent.VK_DOWN:bD = true;break;}locateDirection();}void locateDirection() {if (bL && !bU && !bR && !bD)dir = Direction.L;else if (bL && bU && !bR && !bD)dir = Direction.LU;else if (!bL && bU && !bR && !bD)dir = Direction.U;else if (!bL && bU && bR && !bD)dir = Direction.RU;else if (!bL && !bU && bR && !bD)dir = Direction.R;else if (!bL && !bU && bR && bD)dir = Direction.RD;else if (!bL && !bU && !bR && bD)dir = Direction.D;else if (bL && !bU && !bR && bD)dir = Direction.LD;else if (!bL && !bU && !bR && !bD)dir = Direction.STOP;}public void keyReleased(KeyEvent e) {// 键盘松开int key = e.getKeyCode();switch (key) {case KeyEvent.VK_F:fire();break;case KeyEvent.VK_A:superFire();break;case KeyEvent.VK_LEFT:bL = false;break;case KeyEvent.VK_UP:bU = false;break;case KeyEvent.VK_RIGHT:bR = false;break;case KeyEvent.VK_DOWN:bD = false;break;}locateDirection();}public Missile fire() {if(!live) return null;int x = this.x + Tank.WIDTH / 2 - Missile.WIDTH / 2;int y = this.y + Tank.HEIGHT / 2 - Missile.HEIGHT / 2;Missile m = new Missile(x, y, good, ptDir, this.tc);tc.missiles.add(m);return m;}public Missile fire(Direction dir) {if(!live) return null;int x = this.x + Tank.WIDTH / 2 - Missile.WIDTH / 2;int y = this.y + Tank.HEIGHT / 2 - Missile.HEIGHT / 2;Missile m = new Missile(x, y, good, dir,  this.tc);tc.missiles.add(m);return m;}public Rectangle getRect() {return new Rectangle(x,y,WIDTH,HEIGHT);}public boolean isLive() {return live;}public void setLive(boolean live) {this.live = live;}public boolean isGood() {return good;}public boolean collidesWithWall(Wall w){if(this.live && this.getRect().intersects(w.getRect())){this.stay();return true;}return false;}public boolean collidesWithTank(java.util.List<Tank> tanks){for(int i=0;i<tanks.size();i++){Tank t=tanks.get(i);if(this!=t) {if(this.live && t.isLive() && this.getRect().intersects(t.getRect())){this.stay();t.stay();return true;}}}return false;}private void superFire() {Direction[] dirs=Direction.values();for(int i=0;i<8;i++) {fire(dirs[i]);}}public int getLife() {return life;}public void setLife(int life) {this.life = life;}private class BloodBar {public void draw(Graphics g){Color color=g.getColor();g.setColor(Color.red);g.drawRect(x, y+13, WIDTH, 5);int w=WIDTH*life/100;g.fillRect(x, y+13, w, 5);g.setColor(color);}}}

子弹类 Missile.java:

package com.rs;import java.awt.*;
import java.util.List;public class Missile {//Tank子弹类private static final int XSPEED = 10;private static final int YSPEED = 10;public static final int WIDTH=10;public static final int HEIGHT=10;int x,y;Tank.Direction dir;private boolean live=true;private boolean good;private TankClient tc;public Missile(int x, int y, Tank.Direction dir) {//自动生成构造方法this.x = x;this.y = y;this.dir = dir;}public Missile(int x, int y,boolean good, Tank.Direction dir,TankClient tc) {//自动生成构造方法this(x, y, dir);this.good=good;this.tc=tc;}public void draw(Graphics g){if(!live) {tc.missiles.remove(this);return;}Color c=g.getColor();if(!good){g.setColor(Color.blue);} else{g.setColor(Color.BLACK);}		g.fillOval(x,y,WIDTH,HEIGHT);g.setColor(c);	move();}private void move() {switch(dir){case L:x-=XSPEED;break;case LU:x-=XSPEED;y-=YSPEED;break;case U:y-=YSPEED;break;case RU:x+=XSPEED;y-=YSPEED;break;case R:x+=XSPEED;break;case RD:x+=XSPEED;y+=YSPEED;break;case D:y+=YSPEED;break;case LD:x-=XSPEED;y+=YSPEED;break;case STOP:break;}if(x<0||y<0||x>TankClient.GAME_WIDTH||y>TankClient.GAME_HEIGHT){//出界live=false;}}public boolean isLive() {return live;}public Rectangle getRect(){//四边形return new Rectangle(x,y,WIDTH,HEIGHT);}public boolean hitTank(Tank t){if(this.live && this.getRect().intersects(t.getRect()) && t.isLive() && this.good != t.isGood()) {if(t.isGood()) {t.setLife(t.getLife()-20);if(t.getLife()<=0) t.setLive(false);} else{t.setLive(false);}this.live=false;Explode e=new Explode(x,y,tc);tc.explodes.add(e);return true;}return false;}public boolean hitTanks(List<Tank> tanks){for(int i=0; i<tanks.size(); i++){if(hitTank(tanks.get(i))){return true;}}return false;}public boolean hitWall(Wall w){if(this.live && this.getRect().intersects(w.getRect())){this.live=false;return true;}return false;}}

爆炸效果 Explode.java:

package com.rs;import java.awt.*;public class Explode {// 爆炸(多幅图重碟在一起)int x, y;private boolean live = true;private TankClient tc;int[] diameter = { 5,  12,  26,  49,  20, 3 };int step = 0;public Explode(int x,int y,TankClient tc){this.x=x;this.y=y;this.tc=tc;}public void draw(Graphics g){if(!live) {tc.explodes.remove(this);return;}if(step == diameter.length){live=false;step=0;return;}Color c=g.getColor();g.setColor(Color.orange);g.fillOval(x, y, diameter[step], diameter[step]);g.setColor(c);step ++;}
}

障碍物 Wall.java:

package com.rs;import java.awt.Graphics;
import java.awt.Rectangle;public class Wall {int x,y,w,h;TankClient tc;public Wall(int x, int y, int w, int h, TankClient tc) {this.x = x;this.y = y;this.w = w;this.h = h;this.tc = tc;}public void draw(Graphics g){g.fillRect(x, y, w, h);}public Rectangle getRect(){return new Rectangle(x,y,w,h);}
}


这篇关于java单机版坦克游戏(尚学堂)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/656731

相关文章

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

Spring Boot中JSON数值溢出问题从报错到优雅解决办法

《SpringBoot中JSON数值溢出问题从报错到优雅解决办法》:本文主要介绍SpringBoot中JSON数值溢出问题从报错到优雅的解决办法,通过修改字段类型为Long、添加全局异常处理和... 目录一、问题背景:为什么我的接口突然报错了?二、为什么会发生这个错误?1. Java 数据类型的“容量”限制

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾

SpringBoot项目中报错The field screenShot exceeds its maximum permitted size of 1048576 bytes.的问题及解决

《SpringBoot项目中报错ThefieldscreenShotexceedsitsmaximumpermittedsizeof1048576bytes.的问题及解决》这篇文章... 目录项目场景问题描述原因分析解决方案总结项目场景javascript提示:项目相关背景:项目场景:基于Spring

Spring Boot 整合 SSE的高级实践(Server-Sent Events)

《SpringBoot整合SSE的高级实践(Server-SentEvents)》SSE(Server-SentEvents)是一种基于HTTP协议的单向通信机制,允许服务器向浏览器持续发送实... 目录1、简述2、Spring Boot 中的SSE实现2.1 添加依赖2.2 实现后端接口2.3 配置超时时

Spring Boot读取配置文件的五种方式小结

《SpringBoot读取配置文件的五种方式小结》SpringBoot提供了灵活多样的方式来读取配置文件,这篇文章为大家介绍了5种常见的读取方式,文中的示例代码简洁易懂,大家可以根据自己的需要进... 目录1. 配置文件位置与加载顺序2. 读取配置文件的方式汇总方式一:使用 @Value 注解读取配置方式二

一文详解Java异常处理你都了解哪些知识

《一文详解Java异常处理你都了解哪些知识》:本文主要介绍Java异常处理的相关资料,包括异常的分类、捕获和处理异常的语法、常见的异常类型以及自定义异常的实现,文中通过代码介绍的非常详细,需要的朋... 目录前言一、什么是异常二、异常的分类2.1 受检异常2.2 非受检异常三、异常处理的语法3.1 try-

Java中的@SneakyThrows注解用法详解

《Java中的@SneakyThrows注解用法详解》:本文主要介绍Java中的@SneakyThrows注解用法的相关资料,Lombok的@SneakyThrows注解简化了Java方法中的异常... 目录前言一、@SneakyThrows 简介1.1 什么是 Lombok?二、@SneakyThrows