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编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis