package imageban;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.io.IOException;
import java.util.ArrayList;
import tankImage.ImageUtil;

/**
 * 抽象的坦克类,定义了坦克的相关属性
 * 该坦克类具有了坦克的运动,装载子弹,发射子弹,调整运动方向的功能
 * @author dell
 *
 */
public abstract class Tank implements RectangleInter {
private boolean alive = true;//坦克的生命,初始值为true

private int x, y;// 坦克的横坐标和纵坐标
private int WIDTH = 30, HEIGHT = 30;//坦克的宽度和高度
private int SPEED = 5;//坦克运行的速度
Direction dir = Direction.D;//坦克运行的方向,默认向下
private Image image;//坦克图片
// 坦克炮弹夹
private ArrayList<Missile> danJia = new ArrayList<Missile>();
public ArrayList<Missile> getDanJia() {
return danJia;
}

public void setDanJia(ArrayList<Missile> danJia) {
this.danJia = danJia;
}
public boolean isAlive() {
return alive;
}

public void setAlive(boolean alive) {
this.alive = alive;
}

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 getWIDTH() {
return image.getWidth(null);
}

public int getHEIGHT() {
return image.getHeight(null);
}

public int getSPEED() {
return SPEED;
}

public Image getImage() {
return image;
}

/**
* 根据坦克的运动方向设置图片
* @param image
*/
public void setImage(Image image) {
this.image = image;
}
 
public Tank(String imagePath, int x, int y) {
try {
this.image = ImageUtil.getImage(imagePath);//初始化图片
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 设置x y 坐标
this.x = x;
this.y = y;

}
/**
* 该抽象类只负责绘画坦克的炮筒
*/
@Override
public void draw(Graphics g) {

}

/**
* 获得包围图片的矩形

* @return Rectangle 矩形
*/
public Rectangle getImageRect() {
return new Rectangle(this.getX(), this.getY(), this.getImage()
.getWidth(null), this.getImage().getHeight(null));
}

@Override
public Rectangle getRect() {
return new Rectangle(x, y, WIDTH, HEIGHT);
}

/**
* 定义坦克的运动方法及解决出界问题
* 坦克之所以会运动,本质上是应为代表坦克位置的x,y坐标的位置发生了变化,或增或者减
* 当然在运动的过程中如果坦克越界(跑出战场)的话,当然不能让它们当逃兵,所以需要把调整
* 它们的方向
*/
public void move() {

switch (dir) {
case L:
x -= SPEED;
break;
case R:
x += SPEED;
break;
case U:
y -= SPEED;
break;
case D:
y += SPEED;
break;
case STOP:
break;
}

// 解决坦克出界问题
if (x < 0)
dir = Direction.R;// 如果靠近左边界,那么就往右运动
if (y < 30)
dir = Direction.D;// 如果靠近上边界,那么就往下运动
if (x + this.getWIDTH() > WarField.WIDTH)
dir = Direction.L;// 如果靠近右边界,向左运动
if (y + this.getHEIGHT() > WarField.HEIGHT)
dir = Direction.U;// 如果靠近下边界,向上运动

}

/**
* 之所以把它们设置成为抽象类,是因为敌方坦克和我方坦克的这三个方法实现方式不一样,所以这里没有
* 提供具体的实现
*/
//装载子弹
public abstract void loadMissiles();

// 设置坦克运动的方向
public abstract void locateDirection() throws IOException;

// 坦克发射炮弹
public abstract void fire(Graphics g);

}

********************************************************************************

package imageban;

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import tankImage.EnemyImage;

/**
 * 敌方坦克,具有自动发炮弹,自动随机运动的工能
 * 
 * @author dell
 * 
 */
public class Enemy extends Tank implements RectangleInter {
Random random = new Random();//随机数对象
int changeDirectionFrequency = random.nextInt(12) + 5;
int loadMissileFrequency = random.nextInt(5);// 装载子弹的间隔频率
EnemyImage enemyImage = new EnemyImage("images/enemy",3);//敌方坦克的图片

/**
* 注意必须调用super(x,y),否则报错这是原因之一,另一个则是,如果不调用父类的构造器 的话,导致如果该
* 子类调用getRectange(),该方法里面的参数没有得到初始化而不能获得具体你想要的值

* 刚开始new 出一个敌方坦克的时候,就指定(命令)它要打的我方坦克myTank(哪一个坦克),

* @param x
* @param y
* @param myTank
*            ,敌人要打的那个坦克,即为我的坦克
*/

public Enemy(String imagePath,int x,int y){
super(imagePath,x,y);
}
/**
* 在这里没有判断坦克是否死亡,就return,没有想MyTank里一样
* 因为在子弹打击敌方坦克的时候有这一句起到了类似的作用
* enemyBase.remove(i);//敌方坦克基地删除死亡的坦克,此时坦克不画出来了
*/
@Override
public void draw(Graphics g) {
Color c = g.getColor();
g.drawImage(this.getImage(), this.getX(), this.getY(), null);// //绘画坦克
g.setColor(c); 
fire(g);//开炮
move();//移动

}

/**
* 敌方坦克的运动。运动时坦克自动调整方向
*/
public void move() {

super.move();
//设置坦克的方向
locateDirection();
loadMissiles();//在运动中随机装载子弹
}

/*
* 随机取得坦克的运动方向
*/
public void locateDirection() {
if (changeDirectionFrequency == 0) {
changeDirectionFrequency = random.nextInt(12) + 5;
int step = random.nextInt(4);
Direction[] d = Direction.values();
dir = d[step];
// 为了不让敌方坦克停止,如果dir = stop则重新赋值为dir= d[--step]也就是上一步的方向
if (dir == Direction.STOP)
dir = d[--step];
}
changeDirectionFrequency--;
         this.setImage(dir);
}

public void setImage(Direction dir){
switch(dir){
case L:
this.setImage(enemyImage.getImage(1));
break;
case U:
this.setImage(enemyImage.getImage(3));
break;
case R:
this.setImage(enemyImage.getImage(2));
break;
case D:
this.setImage(enemyImage.getImage(0));
break;
}
}

/**
* 装载子弹,其功能是每个一段频率让它装入一次子弹,之所以在fireMissileJiange = random.nextInt(6)
* 后面加1,是应为如果是fireMissileJiange =
* random.nextInt(6)==0的情况下,在往下执行会发现fireMissileJiange --
* 永远不会有fireMissileJiange ==0的情况出现了,也就装载不了弹药了,此为细节应该注意
*/
public void loadMissiles() {
if (this.loadMissileFrequency == 0) {
loadMissileFrequency= random.nextInt(20) + 1;//随机设定装载子弹的频率
// 向弹夹里添加子弹
this.getDanJia().add(new Missile(this.getX() + this.getWIDTH() / 2
- Missile.WIDTH / 2, this.getY() + this.getHEIGHT() / 2
- Missile.HEIGHT / 2, dir));
}

this.loadMissileFrequency--;

}

/**
* 发射炮弹,也就是让子弹画出来,Graphics 类型的参数

* @param g
*/
public void fire(Graphics g) {
for (int i = 0; i < this.getDanJia().size(); i++) {
this.getDanJia().get(i).draw(g);//从弹夹中拿出子弹
this.getDanJia().get(i).hitMyTank( MyTank.getMyTank(),g);
// 如果子弹打中坦克死了,就冲弹夹中删除该子弹
if (!this.getDanJia().get(i).isAlive()) {
this.getDanJia().remove(i);
}
}
}

}

**************************************************************************************

package imageban;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.io.IOException;
import music.Music;
import tankImage.ImageUtil;
import tankImage.MyImage;

/**
 * 我的坦克,除了拥有父类的属性之外又定义了坦克的生命值,为100 当每次中弹的时候,生命值减去20、当生命值为<=0时,坦克结束生命,将不再重新绘画
 * 我方坦克的运动方向是由键盘的上下左右键来控制的,每当按下ctrl键时坦克装载子弹
 * 
 * @author dell
 * 
 */
public class MyTank extends Tank {
Music music = new Music();
public int life = 100;// 坦克的生命值
private boolean bL = false, bU = false, bR = false, bD = false;// 我方坦克的八个运动方向,初始值为false
Direction pt = Direction.D;// 坦克炮筒的方向默认向下
// 提供一个敌方坦克基地的对象,确定该坦克应该打击的是哪一个敌方坦克军团
EnemysBase enemybase = EnemysBase.getEnemyBase();
MyImage myImage = new MyImage("images/MyTank",3);//提供坦克的图片

public MyImage getMyImage() {
return myImage;
}

/*
* 由于在该游戏中我方坦克始终只有一个,所以可以使用单例模式我方坦克的起始位置是在战场类WarField 的正中央
*/
public static MyTank myTank = new MyTank("images/myTank1.gif",
WarField.WIDTH / 2, WarField.HEIGHT / 2);//默认的是向下的坦克图片

private MyTank(String imagePath, int x, int y) {
super(imagePath, x, y);
}

/**
* 监听键盘的上下左右键,如果按下某一个方向,则哪一个方向就设置为true 同时需要调整坦克运行的方向

* @param e
*/
public void keyPressed(KeyEvent e) {
int dir = e.getKeyCode();
switch (dir) {
case KeyEvent.VK_LEFT:
bL = true;
break;
case KeyEvent.VK_RIGHT:
bR = true;
break;
case KeyEvent.VK_UP:
bU = true;
break;
case KeyEvent.VK_DOWN:
bD = true;
break;
}

// 调整方向
try {
locateDirection();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}

public int getLife() {
return life;
}

public void setLife(int life) {
this.life = life;
}

/*
* 监听键盘的方向键,当从哪一个方向松开按键,则对应的哪一个方向就设置为false
* 同时如果按下ctrl键然后松开,那么就开始往弹夹里装载子弹,同时调整坦克的方向
*/
public void keyReleased(KeyEvent e) {
int dir = e.getKeyCode();
switch (dir) {
case KeyEvent.VK_CONTROL:
if(!this.isAlive())
return;
this.loadMissiles();
music.playSound("images/fire.wav",1);
break;
case KeyEvent.VK_LEFT:
bL = false;
break;
case KeyEvent.VK_RIGHT:
bR = false;
break;
case KeyEvent.VK_UP:
bU = false;
break;
case KeyEvent.VK_DOWN:
bD = false;
break;
}

// 调整坦克运动的方向
try {
locateDirection();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}

/**
* 我方坦克的运动
*/
public void move() {
super.move();
this.setImage(dir);//在运动中根据不同的方向设置图片
}

/**
* 用来判定坦克的运行方向或者说是调整坦克的运动方向 用炮筒来纪录坦克停止状态之前的运动方向

* @throws IOException
*/
public void locateDirection() throws IOException {
if (bL && !bU && !bR && !bD) {
pt = dir = Direction.L;
}

else if (!bL && bU && !bR && !bD) {
pt = dir = Direction.U;
}

else if (!bL && !bU && bR && !bD) {
pt = dir = Direction.R;
}
else if (!bL && !bU && !bR && bD) {
pt = dir = Direction.D;
}
else if (!bL && !bU && !bR && !bD)
dir = Direction.STOP;

}

/**
* 装载子弹
*/
public void loadMissiles() {
this.getDanJia().add(
new Missile(this.getX() + this.getWIDTH() / 2 - Missile.WIDTH
/ 2, this.getY() + this.getHEIGHT() / 2
- Missile.HEIGHT / 2, pt));
}

/**
* 绘画坦克
*/
@Override
public void draw(Graphics g) {
if (!this.isAlive()){
try {
g.drawImage(ImageUtil.getImage("images/over.gif"), WarField.WIDTH/2, WarField.HEIGHT/2, null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return;// 如果死了,就不绘画了
}

Color c = g.getColor();
g.setColor(Color.red);
g.drawImage(this.getImage(), this.getX(), this.getY(), null);// 绘画坦克
g.setColor(c);
move();// 坦克移动

fire(g);// 开火
this.drawLife(g);// 绘画生命条
}

/**
* 坦克开火,开火既是绘画出弹夹中子弹的对象, 绘画子弹的时候,要判断是否打击到敌方坦克
*/
public void fire(Graphics g) {
for (int i = 0; i < this.getDanJia().size(); i++) {
this.getDanJia().get(i).draw(g);// 从弹夹中获得子弹
this.getDanJia().get(i).hitEnemy(enemybase,g);// 判断是否打击到敌方坦克
// 如果子弹打中坦克死了,就冲弹夹中删除该子弹
if (!this.getDanJia().get(i).isAlive()) {
this.getDanJia().remove(i);
}
}
}

/*
* 获得一个单例我方坦克
*/
public static MyTank getMyTank() {
return myTank;
}

/**
* 在坦克战场的左下角处画一个蓝色的矩形条代表坦克的生命值

* @param g
*/
public void drawLife(Graphics g) {
Color c = g.getColor();
g.setColor(Color.blue);
g.drawRect(30, 700, 80, 10);// 画一个矩形框,长度为80宽度为10
int w = 80 * life / 100;// 根据坦克生命的比例画出坦克的生命条
g.fillRect(30, 700, w, 10);
g.setColor(c);
}

/**
* 根据坦克的四个不同的方向,确定坦克的图片
* @param dir
*/
public void setImage(Direction dir){
switch(dir){
case L:
this.setImage(myImage.getImage(2));//设置图片为向左的坦克图片
break;
case U:
this.setImage(myImage.getImage(3));//设置图片为向上的坦克图片
break;
case R:
this.setImage(myImage.getImage(0));//设置图片为向右的坦克图片
break;
case D:
this.setImage(myImage.getImage(1));//设置图片为向下的坦克图片
break;
}
}
}

*******************************************************************************************************************

package imageban;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;

import music.Music;

/**
 * 子弹类,为坦克的炮弹
 * @author dell
 *
 */
public class Missile implements RectangleInter {
private int x;// 初始时子弹的横坐标位置
private int y;// 出事时子弹的纵坐标位置
public static final int WIDTH = 10;//子弹的宽度
public static final int HEIGHT = 10;//子弹的高度
Direction ptDir;//按照坦克炮筒的方向来决定运动方向
private int SPEED = 10;//子弹运动的速度
private boolean alive = true;//子弹是否活着,默认为true
    Music music = new Music();//提供一个音乐播放器
 
public boolean isAlive() {
return alive;
}

public void setAlive(boolean alive) {
this.alive = alive;
}

/**

* @param x
*            横坐标
* @param y
*            纵坐标
* @param dir运动方向
* @param t
*            要装炮弹的坦克
*/
public Missile(int x, int y, Direction dir) {
super();
this.x = x;
this.y = y;
this.ptDir = dir;
}

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

/**
* 绘画坦克
*/
@Override
public void draw(Graphics g) {

if (!this.alive)
return;

Color c = g.getColor();
g.setColor(Color.red);
g.fillOval(x, y, WIDTH, HEIGHT);
g.setColor(c);
move();
}

@Override
public Rectangle getRect() {
return new Rectangle(x, y, WIDTH, HEIGHT);
}

/*
* 坦克移动(non-Javadoc)
* @see youxi3.RectangleInter#move()
*/
public void move() {
switch (ptDir) {
case L:
x -= SPEED;
break;
case U:
y -= SPEED;
break;
case R:
x += SPEED;
break;
case D:
y += SPEED;
break;
}

/*
* 如果越界了,那么子弹就死亡了
*/
if(x < 0 || y < 0 || x > WarField.WIDTH || y > WarField.HEIGHT) {
alive = false;
}
}
/**
 *子弹打击敌方坦克,子
 * @param enemyBase敌方坦克的坦克基地。
 */
public void hitEnemy(EnemysBase enemyBase,Graphics g) {
enemyBase = EnemysBase.getEnemyBase();//获取一个单态实例的敌方坦克坦克基地
for(int i=0;i<enemyBase.size();i++){
Enemy enemy = enemyBase.getEnemy(i);//获取基地了的敌方坦克
if(this.getRect().intersects(enemy.getImageRect())){//如果子弹和坦克相交
enemy.setAlive(false);//敌方坦克的生命设置为false
this.setAlive(false);//子弹的生命设置为false
enemyBase.remove(i);//敌方坦克基地删除死亡的坦克,此时坦克不画出来了
music.playSound("images/blast.wav",1); //打击的时候播放音乐
   Explode explode = new Explode("images/blast0.gif",this.getX(),this.getY(),9);
explode.draw(g);
}
}

}

/**
* 子弹打击我方坦克
* @param enemy敌方坦克
* @param myTank我方坦克
*/
public void hitMyTank(MyTank myTank,Graphics g) {
if (this.getRect().intersects(myTank.getImageRect())) {//如果子弹和坦克相交
myTank.setLife(myTank.getLife()-20);//我方坦克生命值减少20
if(myTank.getLife()<=0){
myTank.setAlive(false);//如果生命值小于等于0设置我方坦克死亡//
myTank.getMyImage().removeAll();//坦克死亡时移除所有图片
}

this.setAlive(false);//子弹也设置为死亡
music.playSound("images/blast.wav",1);//打击时播放音乐
Explode explode = new Explode("images/blast0.gif",this.getX(),this.getY(),9);
explode.draw(g);
}
}

}

图片版坦克大战源代码之坦克类(二)相关推荐

  1. c语言编写坦克大战设计报告,c语言编写坦克大战源代码

    <c语言编写坦克大战源代码>由会员分享,可在线阅读,更多相关<c语言编写坦克大战源代码(10页珍藏版)>请在人人文库网上搜索. 1.include tank.h#include ...

  2. android坦克大战源代码,android的坦克大战 - 源码下载|源代码 - 源码中国

    压缩包 : TankWar坦克大战.rar 列表 TankWar坦克大战\TankWar\.classpath TankWar坦克大战\TankWar\.project TankWar坦克大战\Tan ...

  3. c语言坦克大战源代码vc 6.0,坦克大战(VC6.0) - 源码下载|源代码 - 源码中国

    压缩包 : 坦克大战.rar 列表 坦克大战\BattleCity.aps 坦克大战\BattleCity.dsp 坦克大战\BattleCity.dsw 坦克大战\BattleCity.ncb 坦克 ...

  4. java 坦克大战暂停_【 java版坦克大战--事件处理】 坦克动起来了

    折腾了这么久,坦克总算能动了.只贴代码编辑不给上首页,花了半个小时的时间写了n多注释. 再顺便把绘图的原理发在这里: 绘图原理 Component类提供了两个和绘图有关的重要方法: ①   paint ...

  5. Fc坦克大战java_java的坦克大战

    一个渣渣写坦克大战的步骤: 1.首先创造好一个坦克和一个GAME框架,并且坦克能够跟着键盘键位移动 案例:在我的博客文件中保存,它的名字是:tankwar0100.rar 主要解决了:1.坦克背景框 ...

  6. 坦克大战_我方坦克发射子弹

    Members package com.wxh.tank3;//坦克类,父类 class Tank {// 表示坦克的横坐标int x = 0;// 坦克的纵坐标int y = 0;// 坦克方向// ...

  7. android 坦克,Android坦克大战游戏《坦克骑士 Tank Riders》

    <坦克骑士 Tank Riders>是一款3D坦克战斗游戏,玩家在游戏当中将操控一个造型非常Q的小坦克在激烈的战斗中寻求出路.与红白机时代的坦克大战玩法完全不同,坦克骑士更具有冒险性质,而 ...

  8. Java基础 坦克大战01绘制坦克

    java绘图坐标体系 坐标体系-像素 1.绘图还必须搞清一个非常重要的概念-像素 一个像素等于多少厘米? 2.计算机在屏幕上显示的内容都是由屏幕上的每一个像素组成的.例如,计算机显示器的分辨率是800 ...

  9. 坦克大战代码_坦克大战系列文章-坦克大战简介

    前言 本篇主要对坦克大战Robocode做一个简单的介绍,对java最初的人工智能算法演练工具做一个了解 坦克大战简介 今天我们要谈的是java 最初的基于人工智能算法的仿真模拟坦克大战,全称Robo ...

  10. cocos2d-x游戏开发系列教程-坦克大战游戏之坦克的显示

    1.先定义坦克的一些属性 class Tank : public CCSprite { public :Tank();~Tank();static Tank* createTankWithTankTy ...

最新文章

  1. fedora14 an mysql_Fedora 14下 MySQL 更改密码
  2. 数码管字体属于什么字体_photoshop里这方法就能知道图片上文字使用的是什么字体...
  3. 虚拟化-第二篇-DC,vCenter,ESXI的安装和配置
  4. Select count(*) 的优化
  5. android升级功能键,Android 按键添加转载
  6. SQL语言之数据控制语言(Oracle)
  7. 不含抽象方法的抽象类 java_Java:抽象类继承非抽象类,且不包含抽象方法有何负面作用吗?...
  8. OpenCV使用Kinect和其他OpenNI兼容的深度传感器
  9. LeetCode 390. 消除游戏(类似约瑟夫环,找映射规律)
  10. 43个热门Flex和ActionScript 3.0 APIs,技巧和工具
  11. embedding在推荐系统中的应用总结,这些你知道吗?
  12. Gallery 3D+倒影 滑动切换图片示例(转)
  13. Python学习:Mysql(二)
  14. 完整版商城PHP源码小程序,前后端+后台+小程序;访问地址在文末
  15. 手机、电话号码、邮箱、域名、身份证号的测试用例
  16. 超好用的mac虚拟机软件:VM虚拟机 mac中文版
  17. Codeforces Round #660 (Div. 2) B. Captain Flint and a Long Voyage
  18. c语言.jpg图片转成数组_JPG图片怎么转换成PDF?可以试试这些转换方法!
  19. k8s调度过程中的资源分配问题
  20. 快手程序员爆料:有大厂背书就是好,这就是光环效应

热门文章

  1. mysql sql优化与调优机制详解_MySQL性能调优——锁定机制与锁优化分析详解
  2. OpenCV_Corner Detect with Harris and goodFeaturesToTrack( 基于Harris及适合跟踪的优质特征的角点检测)
  3. 图像语义分割(1)-FCN:用于语义分割的全卷积神经网络
  4. 图像3A算法及伽马校正原理及部分实现
  5. 视频+课件|基于多视图几何方式的三维重建
  6. Flask框架 之重定向、cookie和session
  7. Web静态服务器-7-gevent版
  8. HTML DOM 的nodeType属性
  9. 使用authentication进行身份验证,与Forms表单登陆
  10. ubuntu 彻底卸载软件