首页 > 编程语言 >坦克大战项目实践(Java)

坦克大战项目实践(Java)

时间:2023-04-17 18:33:59浏览次数:31  
标签:Java 游戏 KeyEvent ArrayList 元素 实践 大战 new 坦克

 

一、设计简介

该项目是设计一个坦克大战小游戏,该游戏算不上精美,但是有始有终。有明确的游戏开始、单人模式、双人模式、游戏暂停和游戏失败等事件。设计内容包含图片双缓存技术,解决游戏屏幕闪动问题;还包含了击毁坦克的爆炸特效与子弹消失;还包含了碰撞检测,包括墙体和边界的。

二、相关工作

由于该游戏设计是实现了图形化界面,因此要有游戏元素的gif图片。在网上找到的图片要么是格式不对,要么就是像素太高,直接覆盖了整个画布,无法展示准确游戏元素。况且,这也与设计中游戏元素尺寸不符。所以,对于坦克元素玩家一、坦克元素玩家二、敌方坦克元素、围墙元素和基地元素都是我自己通过系统画图软件设计。可以自己调整像素值,使其符合游戏元素尺寸设定。如图2.1到2.5所示。

selecttank player2U enemy1U walls base

图2.1 图2.2 图2.3 图2.4 图2.5

可见,这些游戏元素都是灰色打底,那是因为设计的游戏界面就是灰色背景,为了带来视觉上的和谐,所以将图片背景填充为灰色。再者,就是坦克移动要有四个方向,所以每个坦克游戏元素,也都有对应的四个方向图片这里以玩家一的坦克为例,如图2.6到2.9。

player1D player1L player1R player1U

图2.6 图2.7 图2.8 图2.9

还有就是爆炸特效用到的一连串图片,由小到大排列。这里就不在一一展示,放在下文实验结果和实验原理中展示。

三、设计原理

3.1图片双缓存技术原理。使用双 缓存的方法来解决屏幕闪动,大体的思路是重新创建一个空的图片,把所有组件,先绘制到空的图片上,再把绘制好图片,一次性绘制到主窗口中。

//定义双缓存图片

Image offScreemImage=null;

......

//创建和容器一样大小的Image图片

if(offScreemImage==null) {

offScreemImage=this.createImage(width,height);

}

//获得该图片的画笔

Graphics gImage=offScreemImage.getGraphics();

//设置画笔颜色,设置背景颜色

gImage.setColor(Color.gray);

//绘制实心矩形,填充整个画布(Image)图片

gImage.fillRect(0, 0, width, height);

//改变画笔颜色

gImage.setColor(Color.blue);

//改变文字大小和样式

gImage.setFont(new Font("仿宋",Font.BOLD,50));

......

//将缓存区绘制好的图形整个绘制到窗口容器的画布中

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

3.2键盘监视器原理。首先编写的GamePanel类是继承JFrame类的,这样才有创建窗口,监听键盘鼠标等事件的功能。而编写的KeyMonitor类,又是继承KeyAdapter类。这里出现了一个@Override的符号,含义是重写父类中的方法。

//键盘监视器

class KeyMonitor extends KeyAdapter{

//按下键盘

@Override

public void keyPressed(KeyEvent e) {//继承KeyAdapter类的keyPressed()方法

//返回键值

int key=e.getKeyCode();

switch (key) {

case KeyEvent.VK_1:

a=1;

y=150;

break;

case KeyEvent.VK_2:

a=2;

y=250;

break;

......

default:

playerOne.keyPressed(e);

playerTwo.keyPressed(e);

}

}

//松开键盘

@Override//重写父类@Override

public void keyReleased(KeyEvent e) {

playerOne.keyReleased(e);

playerTwo.keyReleased(e);

}

}

3.3坦克移动原理。这里键盘事件值得注意的是,为了让坦克移动可以按住移动键,而不是朝一个方向移动要快速按下该方向键。这里对坦克移动做了设计。还有就是坦克移动要改变其方向,图片元素也要跟着改变。坦克移动的设计代码如下。

//按下键盘,变为true,执行对应方法。

//按住时,因为程序快速执行true和false的变换,所以一直处于运动状态,松开时不在为ture所以不再移动

public void keyPressed(KeyEvent e) {

int key =e.getKeyCode();

switch (key) {

case KeyEvent.VK_LEFT:

left=true;

break;

......

default:

break;

}

}

 

//松开键盘,自动变为false。

public void keyReleased(KeyEvent e) {

int key =e.getKeyCode();

switch (key) {

case KeyEvent.VK_LEFT:

left=false;

break;

......

}

}

public void move(){//除了构造函数,其他函数不会自动调用

if(left) {

leftward();

}

......

}

3.4线程原理。对于游戏界面的重绘,是需要调用repaint()的,由repaint()调用update()来刷新界面,删去以前的界面,变为现在的界面。然后对paint()函数进行重写覆盖父类。其中paint()函数是系统线程自动调用的。

repaint();//重绘构建,但是会闪烁-->双缓冲

try {

Thread.sleep(25);//线程暂停25ns

}catch(Exception e) {

e.printStackTrace();

}

再有就是关于坦克发射子弹冷却时间的考量。这里就需要引入新的线程。

//新线程

class AttackCD extends Thread{

public void run() {

//将攻击功能设置为冷却状态

attackCoolDown=false;

//休眠1秒

try {

Thread.sleep(attackCoolDownTime);

}catch(Exception e) {

e.printStackTrace();

}

//将攻击功能解除冷却

attackCoolDown=true;

//线程终止

this.stop();

}

3.5碰撞检测原理。与围墙和边界的碰撞都采取先检测,在移动的规则。以防止坦克开进墙里的情况。所以传参数的时候,也是传下一个位置的坐标。如:

if(hitWall(x+speed, y) && moveToBorder(x+speed, y)) {

this.x+=speed;

3.6继承原理。我认为该坦克大战游戏设计,贯穿设计核心的就是继承关系。首先创建游戏元素类GameObject,作为游戏的父类。然后是创建了坦克类Tank,继承了GameObject类。然后是玩家一的坦克类,和玩家二的坦克类,都继承Tank类。子弹类Bulllet也是继承GameObject类。关于子类的构造函数,可以快速调用父类的构造函数。Super(x,y,z....);

3.7游戏元素列表原理。通过创建游戏元素列表,方便游戏元素的增删。特殊的,对于子弹类元素的删除,必须再创建一个remove()列表,否则删除子弹就会报错。我想,这应该和子弹的自动移动有关。

//游戏元素列表

ArrayList<Bullet> bulletList=new ArrayList<Bullet>();

ArrayList<Bot> botList=new ArrayList<Bot>();

ArrayList<Bullet> removeList=new ArrayList<Bullet>();

ArrayList<Tank> playerList=new ArrayList<Tank>();

ArrayList<Wall> wallList=new ArrayList<Wall>();

ArrayList<Base> baseList=new ArrayList<Base>();

ArrayList<Blast> blastList=new ArrayList<Blast>();

四、实现结果

4.1游戏主界面。

1

4.2游戏开始,以选择双人模式为例。

2

4.3按P,游戏暂停。

4

4.4击毁墙壁,并且击毁敌方坦克产生爆炸特效。

5

4.5玩家坦克被摧毁,或者我方基地被摧毁,游戏失败。

3

4.6敌方坦克被消灭,游戏胜利。

6

五、项目心得

通过本项目,我受益颇多。深切感受到了面向对象编程的魅力,丰富的游戏元素抽象为丰富的类,再衍生出子类,继承或者重写覆盖父类中的方法。还有键盘监听事件的巧妙运用,在设计过程中出现了很多严重的BUG,比如玩家坦克被击毁后还可以发射炮弹,这也在我为坦克添加布尔变量alive后得以解决。该设计虽然算不上功能丰富,但是也是可以称得上一个小休闲游戏了。程序也难免依然存在未发现的BUG,但是作为第一个Java小程序,做成这样有头有尾,编写了近千行代码,还是很有成就感的。

在代码编写过程中,我也遇到一些陌生的知识符号,比如说@Override,经在网上查阅后了解,是对父类的重写。还有就是GamePanel类中的paint()方法,我起初奇怪,没有调用它,为何会在屏幕中调用实现,经过我的一番推理,我觉得launch()方法中的repaint()应该和它相关,经过查阅资料,确实是系统自动调用。

标签:Java,游戏,KeyEvent,ArrayList,元素,实践,大战,new,坦克
From: https://www.cnblogs.com/nuist7bloger/p/17326734.html

相关文章

  • java查看对象占用内存的大小
    1.首先引入jar包lucene-core-4.7.2.jar<dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><version>4.0.0</version></dependency><depende......
  • 通过JAVA语言如何获取淘宝/天猫搜索词推荐
    Java是一种跨平台的、面向对象的高级编程语言,主要用来进行网站后台开发和AndroidAPP开发,同时它是全球最受欢迎的编程语言之一,在世界编程语言排行榜TIOBE中,Java一直霸占着前三名,有好多年甚至都是获得了第一名。那么为什么Java会如此受欢迎呢?Java是一种半编译型语言,开发比......
  • Java与Mysql锁相关知识总结
    锁的定义在计算机程序中锁用于独占资源,获取到锁才可以操作对应的资源。锁的实现锁在计算机底层的实现,依赖于CPU提供的CAS指令(compareandswsp),对于一个内存地址,会比较原值以及尝试去修改的值,通过值是否修改成功,来表示是否强占到了这个锁。JVM中的锁jvm中,有2个常用的锁synchr......
  • javascript
    1970.1.1互联网开始时间**JavaScript(开发Web页面的脚本语言)**是面向Web的编程语言,获得了所有网页浏览器的支持,是目前使用最广泛的脚本编程语言之一,也是网页设计和Web应用必须掌握的基本工具。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最......
  • 关于Java中值传递和址传递
    参数传递在Java中有两种类型值和址其实本质都是一份拷贝在调用函数的时候进行压栈传进来的参数会被开辟一份新的空间传基本类型是把值传过去传引用数据类型是实例指向实参voidm(intv){//基本数据类型传值是一份拷贝不会影响实参v++}voidm(int[]arr){//底层i......
  • Java集合框架
    Java集合框架概述Java集合框架是一个抽象数据类型的框架,它提供了一组接口和类,可用于处理各种类型的数据结构,如列表、队列、集、映射等。Java集合框架的主要特点是:1、可扩展性:Java集合框架提供了一组可扩展的接口和类,可让开发人员根据自己的需要实现新的数据结构和算法。2、高性能:Ja......
  • Java8新特性4_强大的Stream
    StreamAPI了解StreamJava8中有两个比较大的改变Lambda表达式StreamAPI(java.util.stream.*)Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找,过滤和映射数据等操作。使用StreamAPI对集合数据进行操作,就类似于使用SQL执行的......
  • Java8新特性5_并行流
    并行流与顺序流并行流并行流就是把一个内容分成多个数据库,并用不同的线程分别处理每个数据块的流Java8中将并行流进行了优化,我们可以很容易的对数据进行并行操作,StreamAPI可以声明性的通过parallel()与sequential()在并行流与顺序流之间进行切换Fork/Join框架概念Fork/J......
  • Java8新特性6_Optional容器类
    Optional类概念Optional类是一个容器类,代表一个值存在或者不存在,原来null表示一个值不存在,现在Optional可以更好的表达这个概念,并且可以规避空指针异常常用方法Optional.of:创建一个Optional实例Optional.empty:创建一个空的Optional实例Optional.ofNullable:若t不为null......
  • Java8新特性1_HashMap变化
    Java8新特性主要特性Lambda表达式函数式接口方法引用与构造器引用StreamAPI接口中默认方法与静态方法新时间日期API最大化减少空指针异常(Optional)。。。。HashMap1.7在JDK1.7到JDK1.8的时候,对HashMap做了优化首先JDK1.7的HashMap当出现Hash碰撞的时候,最后插入的......