图片版坦克大战源代码之坦克类(二)
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);
}
}
}
图片版坦克大战源代码之坦克类(二)相关推荐
- c语言编写坦克大战设计报告,c语言编写坦克大战源代码
<c语言编写坦克大战源代码>由会员分享,可在线阅读,更多相关<c语言编写坦克大战源代码(10页珍藏版)>请在人人文库网上搜索. 1.include tank.h#include ...
- android坦克大战源代码,android的坦克大战 - 源码下载|源代码 - 源码中国
压缩包 : TankWar坦克大战.rar 列表 TankWar坦克大战\TankWar\.classpath TankWar坦克大战\TankWar\.project TankWar坦克大战\Tan ...
- c语言坦克大战源代码vc 6.0,坦克大战(VC6.0) - 源码下载|源代码 - 源码中国
压缩包 : 坦克大战.rar 列表 坦克大战\BattleCity.aps 坦克大战\BattleCity.dsp 坦克大战\BattleCity.dsw 坦克大战\BattleCity.ncb 坦克 ...
- java 坦克大战暂停_【 java版坦克大战--事件处理】 坦克动起来了
折腾了这么久,坦克总算能动了.只贴代码编辑不给上首页,花了半个小时的时间写了n多注释. 再顺便把绘图的原理发在这里: 绘图原理 Component类提供了两个和绘图有关的重要方法: ① paint ...
- Fc坦克大战java_java的坦克大战
一个渣渣写坦克大战的步骤: 1.首先创造好一个坦克和一个GAME框架,并且坦克能够跟着键盘键位移动 案例:在我的博客文件中保存,它的名字是:tankwar0100.rar 主要解决了:1.坦克背景框 ...
- 坦克大战_我方坦克发射子弹
Members package com.wxh.tank3;//坦克类,父类 class Tank {// 表示坦克的横坐标int x = 0;// 坦克的纵坐标int y = 0;// 坦克方向// ...
- android 坦克,Android坦克大战游戏《坦克骑士 Tank Riders》
<坦克骑士 Tank Riders>是一款3D坦克战斗游戏,玩家在游戏当中将操控一个造型非常Q的小坦克在激烈的战斗中寻求出路.与红白机时代的坦克大战玩法完全不同,坦克骑士更具有冒险性质,而 ...
- Java基础 坦克大战01绘制坦克
java绘图坐标体系 坐标体系-像素 1.绘图还必须搞清一个非常重要的概念-像素 一个像素等于多少厘米? 2.计算机在屏幕上显示的内容都是由屏幕上的每一个像素组成的.例如,计算机显示器的分辨率是800 ...
- 坦克大战代码_坦克大战系列文章-坦克大战简介
前言 本篇主要对坦克大战Robocode做一个简单的介绍,对java最初的人工智能算法演练工具做一个了解 坦克大战简介 今天我们要谈的是java 最初的基于人工智能算法的仿真模拟坦克大战,全称Robo ...
- cocos2d-x游戏开发系列教程-坦克大战游戏之坦克的显示
1.先定义坦克的一些属性 class Tank : public CCSprite { public :Tank();~Tank();static Tank* createTankWithTankTy ...
最新文章
- fedora14 an mysql_Fedora 14下 MySQL 更改密码
- 数码管字体属于什么字体_photoshop里这方法就能知道图片上文字使用的是什么字体...
- 虚拟化-第二篇-DC,vCenter,ESXI的安装和配置
- Select count(*) 的优化
- android升级功能键,Android 按键添加转载
- SQL语言之数据控制语言(Oracle)
- 不含抽象方法的抽象类 java_Java:抽象类继承非抽象类,且不包含抽象方法有何负面作用吗?...
- OpenCV使用Kinect和其他OpenNI兼容的深度传感器
- LeetCode 390. 消除游戏(类似约瑟夫环,找映射规律)
- 43个热门Flex和ActionScript 3.0 APIs,技巧和工具
- embedding在推荐系统中的应用总结,这些你知道吗?
- Gallery 3D+倒影 滑动切换图片示例(转)
- Python学习:Mysql(二)
- 完整版商城PHP源码小程序,前后端+后台+小程序;访问地址在文末
- 手机、电话号码、邮箱、域名、身份证号的测试用例
- 超好用的mac虚拟机软件:VM虚拟机 mac中文版
- Codeforces Round #660 (Div. 2) B. Captain Flint and a Long Voyage
- c语言.jpg图片转成数组_JPG图片怎么转换成PDF?可以试试这些转换方法!
- k8s调度过程中的资源分配问题
- 快手程序员爆料:有大厂背书就是好,这就是光环效应
热门文章
- mysql sql优化与调优机制详解_MySQL性能调优——锁定机制与锁优化分析详解
- OpenCV_Corner Detect with Harris and goodFeaturesToTrack( 基于Harris及适合跟踪的优质特征的角点检测)
- 图像语义分割(1)-FCN:用于语义分割的全卷积神经网络
- 图像3A算法及伽马校正原理及部分实现
- 视频+课件|基于多视图几何方式的三维重建
- Flask框架 之重定向、cookie和session
- Web静态服务器-7-gevent版
- HTML DOM 的nodeType属性
- 使用authentication进行身份验证,与Forms表单登陆
- ubuntu 彻底卸载软件