本文主要是介绍Java 面向对象战舰小游戏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Java面向对象战舰小游戏
- 前言
- 思路:
- 战舰项目代码
- 1. 战舰特征和行为
- 水雷艇特征和行为
- 侦查艇特征和行为
- 鱼雷艇特征和行为
- 水雷特征和行为
- 深水炸弹特征和行为
- 2. 归纳共有特征
- 3.初始化
- 4. 画图
- 5. 重写方法
- 定时器
- 新建潜水艇对象
- 新建水雷
- 新建深水炸弹
- 重写所有类的move方法
- 6. 把超过窗口和相互碰撞的物体删掉
- 删除超过窗口的对象
- 删除相互碰撞的物体
- 7.最终代码
- Battleship
- Bomb
- Images
- Mine
- MineSubmarine
- ObserveSubmarine
- SeaObject
- TorpedoSubmarine
- World
代码和图片下载 https://download.csdn.net/download/gydennis/78761288
前言
这是面向对象的小游戏,运用的的知识点有:父子类,继承,构造方法,重载,重写,静态块,修饰词
思路:
1.首先写出项目中会运运用到的物体,在这个项目中,我们会用到:
敌人:三种潜艇:水雷潜艇(Mine Submarine),侦查潜艇(Observe Submarine),鱼雷艇(Torpedo Submarine)
玩家:战舰(Battleship)
道具:水雷(Mine),深水炸弹(Bomb)。
2.每个物体写出它们的特征,并把它们共有的特征归纳,放到超类(父类)里面,再把它们共有的行为写出普通方法写到超类里面,如果是行为一样但是每个行为发生的过程不一样,就写成抽象类(abstract)放到超类.
3.进行初始化,定义每个物体的初始坐标,高度等等特征的初始值。注意这时候图片初始值写成静态块,因为静态块初始化会声明类的时候自动执行,调用的时候直接类.变量就直接出来了,复用性较好。其他的例如窗口高,宽等不变的可以直接定义为常量,其他的特征为实例变量。然后添加访问权限
4. 开始画窗口,然后把物体画到窗口里面
5. 重写方法,让物体移动起来,并发射水雷或者炸弹。
6. 把超过窗口,或者爆炸的物体删掉
战舰项目代码
项目名称我建的叫SubmarineDemo,package的名字叫submarine
6个物体的特征和行为
1. 战舰特征和行为
战舰有宽, 高, x坐标, y坐标, 生命数量, 移动速度
方法是左右移动,发射深水炸弹,爆炸
class Battleship {// 战舰类//战舰有宽 高 x坐标 y坐标 生命数量 移动速度int width; //宽int height; //高int x; //x坐标int y; //y坐标int life; //生命数量int speed; //移动速度//左右移动void move(){}//发射深水炸弹void shootBombs(){}
}
我们设计几个敌方战舰:水雷艇,鱼雷艇,潜水艇
它们的攻击方式是发射: 水雷和深水炸弹
这些的初始代码其实都跟战舰相同,只是没有生命值,因为他只有一条命
下面是它们初始化代码
水雷艇特征和行为
public class MineSubmarine {//水雷艇有宽 高 x坐标 y坐标 移动速度int width; //宽int height; //高int x; //x坐标int y; //y坐标int speed; //移动速度//向右移动void move(){}//发射水雷void newMine(){}
}
侦查艇特征和行为
public class ObserveSubmarine {//侦查艇//侦查艇有宽 高 x坐标 y坐标 生命数量 移动速度int width; //宽int height; //高int x; //x坐标int y; //y坐标int speed; //移动速度//向右移动void move(){}
}
鱼雷艇特征和行为
public class TorpedoSubmarine {//鱼雷艇//鱼雷艇有宽 高 x坐标 y坐标 移动速度int width; //宽int height; //高int x; //x坐标int y; //y坐标int speed; //移动速度//向右移动void move(){}
}
水雷特征和行为
public class Mine {//水雷有宽 高 x坐标 y坐标 移动速度int width; //宽int height; //高int x; //x坐标int y; //y坐标int speed; //移动速度//向上移动void move(){}
}
深水炸弹特征和行为
public class Bomb {//深水炸弹有宽 高 x坐标 y坐标 移动速度int width; //宽int height; //高int x; //x坐标int y; //y坐标int speed; //移动速度//向下移动void move(){}
}
2. 归纳共有特征
它们的共有特征有宽,高,x坐标,y坐标,移动速度
所以我们新建一个父类,把共有特征和方法放进去,父类叫SeaObject。因为它们都是在海里运行的所以叫Sea Object(海洋物体)
共有的特征有: 宽, 高, x坐标, y 坐标,移动速度
共有的方法:
1.移动,因为每个类的移动行为都不一样,所以写成抽象模式,强制重写
abstract public class SeaObject {int width; //宽int height; //高int x; //x坐标int y; //y坐标int speed; //移动速度abstract void move();
}
因为我们把move,每个类的移动行为都不一样,所以写成抽象模式,让派生类强制重写
代码:
Battleship
package submarine;public class Battleship extends SeaObject{int life; //生命数量//左右移动void move(){}//发射深水炸弹void shootBombs(){}
}
Bomb
package submarine;public class Bomb extends SeaObject{//向下移动void move(){}
}
Mine
package submarine;public class Mine extends SeaObject {//向上移动void move(){}
}
Minesubmarine
package submarine;public class MineSubmarine extends SeaObject{//向右移动void move(){}//发射水雷void shoot(){}
}
ObserveSubmarine
package submarine;public class ObserveSubmarine extends SeaObject{//向右移动void move(){}
}
SeaObject
package submarine;abstract public class SeaObject {int width; //宽int height; //高int x; //x坐标int y; //y坐标int speed; //移动速度abstract void move();
}
TorpedoSubmarine 鱼雷艇
package submarine;public class TorpedoSubmarine extends SeaObject{//向右移动void move(){}
}
3.初始化
常量:
- 6个类的长,宽高都是固定的
- 窗口的长宽高都是固定的
变量
- 6个类的一开始坐标(x和y),注意左上角的坐标是(0,0)
- 速度
下面是各个数据
类名 | 长 | 宽 | 初始坐标(x,y) |
---|---|---|---|
Battleship | 66 | 26 | (270.142) |
Bomb | 9 | 12 | 按空格键出来,这里不定义 |
mine | 11 | 11 | 生成水雷艇后定时器自动生成 |
MineSubmarine | 63 | 19 | 在窗口左边自动生成 |
TorpedoSubmarine | 64 | 20 | 在窗口左边自动生成 |
ObserveSubmarine | 63 | 19 | 在窗口左边自动生成 |
窗口 | 641 | 479 | 无 |
6个类的除了我们设bomb和mine我们设成3,其他类速度是随机数从1-3不等
这里我们新建一个World类专门写main,在加上一个窗口的初始化
这里给类初始值得方法叫做构造方法。注意这里bomb和mine之间的xy的值不是固定的,所以要把它们在超类里重新定义(重载一个构造方法,相同方法名 不同参数列表)
然后给他们加修饰符(访问权限),注意泛生类的访问权限大于或等于超类,一般加public即可
代码
Battleship战舰
package submarine;public class Battleship extends SeaObject{//战舰的宽public static final int WIDTH = 66;//战舰的高public static final int HEIGHT = 26;//生命数量private int life;//初始化Battleship(){//把船放到海平面上的任意位置,x,y是左上角//初始位置是(200,150-Battleship.HEIGHT),速度是3super(Battleship.WIDTH,Battleship.HEIGHT,200,150-Battleship.HEIGHT,3);//初始命是5life = 5;}//左右移动public void move(){}//发射深水炸弹public void shootBombs(){}
}
Bomb炸弹
package submarine;public class Bomb extends SeaObject{//炸弹的宽public static final int WIDTH = 9;//炸弹的高public static final int HEIGHT = 12;//深水炸弹初始化Bomb(int x,int y){super(Bomb.WIDTH,Bomb.HEIGHT,x,y,3);}//向下移动public void move(){}}
水雷Mine
package submarine;public class Mine extends SeaObject {//水雷的宽public static final int WIDTH = 11;//水雷的高public static final int HEIGHT = 11;//水雷初始化Mine(int x,int y){super(Bomb.WIDTH,Bomb.HEIGHT,x,y,3);}//向上移动public void move(){}
}
MineSubmarine 水雷艇
package submarine;public class MineSubmarine extends SeaObject{//水雷艇的宽public static final int WIDTH = 63;//水雷艇的高public static final int HEIGHT = 19;//向右移动public void move(){}//水雷潜艇初始化MineSubmarine(){super(MineSubmarine.WIDTH,MineSubmarine.HEIGHT);}//发射水雷public void newMine(){}}
ObserveSubmarine 侦查艇
package submarine;public class ObserveSubmarine extends SeaObject{//侦查艇的宽public static final int WIDTH = 63;//侦查艇的高public static final int HEIGHT = 19;//侦查潜艇初始化ObserveSubmarine(){super(ObserveSubmarine.WIDTH,ObserveSubmarine.HEIGHT);}//向右移动public void move(){}
}
Seaobject超类
package submarine;import java.util.Random;public abstract class SeaObject {int width; //宽int height; //高int x; //x坐标int y; //y坐标int speed; //移动速度public abstract void move();SeaObject(int width,int height,int x,int y,int speed ){//bomb还有minethis.width = width;this.height = height;this.x = x;this.y = y;this.speed = speed;}SeaObject(int width,int height){this.width = width;this.height = height;x = -width;//潜艇进场是在窗口最左边进场//海平面以下随机生成,随机高度在150到(最低减去一个潜艇的高度)Random rand = new Random();y = rand.nextInt(World.HEIGHT-World.SEA_LEVEL_HEIGHT-MineSubmarine.HEIGHT+1)+150;speed = rand.nextInt(3);}}
TorpedoSubmarine 鱼雷艇
package submarine;public class TorpedoSubmarine extends SeaObject{//鱼雷艇的宽public static final int WIDTH = 64;//鱼雷艇的高public static final int HEIGHT = 20;//水雷潜艇的初始化TorpedoSubmarine(){super(TorpedoSubmarine.WIDTH,TorpedoSubmarine.HEIGHT);}//向右移动public void move(){}
}
World主方法
package submarine;public class World {//海平面public static final int SEA_LEVEL_HEIGHT = 150;//窗口宽public static final int WIDTH = 641;//窗口长public static final int HEIGHT = 479;//主方法public static void main(String[] args) {}
}
4. 画图
这里我们用了现在不怎么用的方法,这里就不说了,直接是赋值黏贴过来的
- 这里需要import Graphics,Jframe和JPanel三个类
- main还要继承JFrame
- 直接在main里面添加代码,复制黏贴就行
JFrame frame = new JPanel ();
World world = new World();
world.setFocusable(true);
frame.add(world);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(WIDTH+16, HEIGHT+39);
frame.setLocationRelativeTo(null);
frame.setVisible(true);//1)设置窗口可见 2)尽快调用paint()方法
我们需要写一个paint方法来画
- 最主要把图片画出来的方法是paintIcon,有兴趣的自己了解即可,但现在没什么人用了。写了一个Image
- 画的动作是一样的,就是对象图片调用paintIcon方法,所以把他们写在超类SeaObject里面
- 把每个类都画一个在画布上
Battleship
package submarine;import javax.swing.*;public class Battleship extends SeaObject{//战舰的宽public static final int WIDTH = 66;//战舰的高public static final int HEIGHT = 26;//生命数量private int life;//初始化Battleship(){//把船放到海平面上的任意位置,x,y是左上角//初始位置是(200,150-Battleship.HEIGHT),速度是3super(Battleship.WIDTH,Battleship.HEIGHT,200,150-Battleship.HEIGHT,3);//初始命是5life = 5;}//左右移动public void move(){}//发射深水炸弹public void shootBombs(){}//画布上画battleship对象public ImageIcon getObject(){return Images.battleship;}
}
Bomb
package submarine;import javax.swing.*;public class Bomb extends SeaObject{//炸弹的宽public static final int WIDTH = 9;//炸弹的高public static final int HEIGHT = 12;//深水炸弹初始化Bomb(int x,int y){super(Bomb.WIDTH,Bomb.HEIGHT,x,y,3);}//向下移动public void move(){}//画布上画bomb对象public ImageIcon getObject(){return Images.bomb;}}
Images
package submarine;
import javax.swing.ImageIcon;
/** 图片类 */
public class Images {// 公开的 静态的 图片数据类型 变量名public static ImageIcon battleship; //战舰图片public static ImageIcon obsersubm; //侦察潜艇图片public static ImageIcon torpesubm; //鱼雷潜艇图片public static ImageIcon minesubm; //水雷潜艇图片public static ImageIcon mine; //水雷图片public static ImageIcon bomb; //深水炸弹图片public static ImageIcon sea; //海洋图public static ImageIcon gameover; //游戏结束图static{ //给静态图片赋值battleship = new ImageIcon("img/battleship.png");obsersubm = new ImageIcon("img/obsersubm.png");torpesubm = new ImageIcon("img/torpesubm.png");minesubm = new ImageIcon("img/minesubm.png");mine = new ImageIcon("img/mine.png");bomb = new ImageIcon("img/bomb.png");sea = new ImageIcon("img/sea.png");gameover = new ImageIcon("img/gameover.png");}public static void main(String[] args) {//写完上面对象之后,测试,返回8表示读取成功System.out.println(battleship.getImageLoadStatus()); //返回8表示读取成功System.out.println(obsersubm.getImageLoadStatus());System.out.println(torpesubm.getImageLoadStatus());System.out.println(minesubm.getImageLoadStatus());System.out.println(mine.getImageLoadStatus());System.out.println(bomb.getImageLoadStatus());System.out.println(sea.getImageLoadStatus());System.out.println(gameover.getImageLoadStatus());}}
Mine
package submarine;import javax.swing.*;public class Mine extends SeaObject {//水雷的宽public static final int WIDTH = 11;//水雷的高public static final int HEIGHT = 11;//水雷初始化Mine(int x,int y){super(Bomb.WIDTH,Bomb.HEIGHT,x,y,3);}//向上移动public void move(){}//画布上画mine对象public ImageIcon getObject(){return Images.mine;}
}
MineSubmarine
package submarine;import javax.swing.*;public class MineSubmarine extends SeaObject{//水雷艇的宽public static final int WIDTH = 63;//水雷艇的高public static final int HEIGHT = 19;//向右移动public void move(){}//水雷潜艇初始化MineSubmarine(){super(MineSubmarine.WIDTH,MineSubmarine.HEIGHT);}//发射水雷public void newMine(){}//画布上画MineSubmarine对象public ImageIcon getObject(){return Images.minesubm;}
}
ObserveSubmarine
package submarine;import javax.swing.*;public class ObserveSubmarine extends SeaObject{//侦查艇的宽public static final int WIDTH = 63;//侦查艇的高public static final int HEIGHT = 19;//侦查潜艇初始化ObserveSubmarine(){super(ObserveSubmarine.WIDTH,ObserveSubmarine.HEIGHT);}//向右移动public void move(){}//画布上画ObserveSubmarine对象public ImageIcon getObject(){return Images.obsersubm;}
}
SeaObject
package submarine;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.ImageIcon;
public abstract class SeaObject {int width; //宽int height; //高int x; //x坐标int y; //y坐标int speed; //移动速度public abstract void move();SeaObject(int width,int height,int x,int y,int speed ){//bomb还有minethis.width = width;this.height = height;this.x = x;this.y = y;this.speed = speed;}SeaObject(int width,int height){this.width = width;this.height = height;x = width;//潜艇进场是在窗口最左边进场//海平面以下随机生成,随机高度在150到(最低减去一个潜艇的高度)Random rand = new Random();y = rand.nextInt(World.HEIGHT-World.SEA_LEVEL_HEIGHT-MineSubmarine.HEIGHT+1)+150;speed = rand.nextInt(3);}//画布上画子类的对象,行为一样,所以定义为抽象public abstract ImageIcon getObject();//画对象 g:画笔public void paintImage(Graphics g){this.getObject().paintIcon(null,g,this.x,this.y);}}
TorpedoSubmarine
package submarine;import javax.swing.*;public class TorpedoSubmarine extends SeaObject{//鱼雷艇的宽public static final int WIDTH = 64;//鱼雷艇的高public static final int HEIGHT = 20;//水雷潜艇的初始化TorpedoSubmarine(){super(TorpedoSubmarine.WIDTH,TorpedoSubmarine.HEIGHT);}//向右移动public void move(){}//画布上画TorpedoSubmarine对象public ImageIcon getObject(){return Images.torpesubm;}
}
World
package submarine;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
public class World extends JPanel {//海平面public static final int SEA_LEVEL_HEIGHT = 150;//窗口宽public static final int WIDTH = 641;//窗口长public static final int HEIGHT = 479;//定义一个战舰对象Battleship ship = new Battleship();SeaObject[] submarines = {new MineSubmarine(),new ObserveSubmarine(),new TorpedoSubmarine()};Bomb[] bombs = {new Bomb(200,200)};Mine[] mines = {new Mine(200,150)};public void paint(Graphics g){//先画背景图Images.sea.paintIcon(null,g,0,0);//画战舰ship.paintImage(g);//画潜水艇数组for(int i = 0;i<submarines.length;i++){submarines[i].paintImage(g);}//画深水炸弹数组for(int i = 0;i<bombs.length;i++){bombs[i].paintImage(g);}//画水雷数组for(int i = 0;i<mines.length;i++){mines[i].paintImage(g);}}//主方法public static void main(String[] args) {JFrame frame = new JFrame();World world = new World();world.setFocusable(true);frame.add(world);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setSize(WIDTH+16, HEIGHT+39);frame.setLocationRelativeTo(null);frame.setVisible(true);//1)设置窗口可见 2)尽快调用paint()方法}
}
代码呈现出来的是这样的
如果你跟我一样再画布上呈现了6个类说明你已经成功一半了,剩下的就是让这些类移动起来
5. 重写方法
这里使用定时器每10毫秒重写画一次对象(导入Timer和TimerTask两个类)
重写move方法
类 | 移动方向 |
---|---|
战舰移动 | 战舰由键盘左右控制移动 |
深水炸弹移动 | 由战舰发出,只能向下移动 |
潜水艇移动 | 潜水艇只能向右移动 |
水雷移动 | 水雷由水雷艇发射,向上移动 |
定时器
需要导入两个类一个是Timer,一个是TimerTask
import java.util.Timer;
import java.util.TimerTask;
public void action(){int period = 10;//delay和period都设置为10毫秒Timer timer = new Timer();//新建一个Timer对象timer.schedule(new TimerTask() {/*** 每10毫秒调用schedule* 并重写TimerTask里面的run方法* 这里用到的知识是匿名内部类*/@Overridepublic void run() {/*** 这里面需要写的是新建潜艇,深水炸弹,水雷对象* 移动* 撞击爆炸消失等方法*/repaint();//重写调用paint方法}}, period, period);
}
新建潜水艇对象
这里用随机数的方法来生成潜艇
public SeaObject newSubmarine(){Random rand = new Random();//生成一个Random对象int number = rand.nextInt(3);//随机数是0到2if(number<1){//如果number等于0,输出水雷艇return new MineSubmarine();}else if(number<2){//如果number等于1,输出侦查艇return new ObserveSubmarine();}else{//如果number等于2,输出鱼雷艇return new TorpedoSubmarine();}
}
private int submarineIndex = 0;
public void addSubmarine(){submarineIndex++;if(submarineIndex%40 == 25){//每40*10=400毫秒=0.4秒生成潜艇//给submarines数组扩容submarines = Arrays.copyOf(submarines,submarines.length+1);SeaObject new_Submarine = newSubmarine();//新建潜水艇对象//扩容之后,把新的潜水艇对象保存在submarines数组里面submarines[submarines.length-1] = new_Submarine;}
}
新建水雷
在Worls中添加方法
private int mineIndex = 0;
public void addMine(){/*** 水雷,因为是水雷潜水艇发射的,需要知道水雷潜水艇x和y的坐标* 所以写在MineSubmarine类里面* 我们先要分辨数组里面哪一个是MineSubmarine* 再给他添加水雷*/mineIndex++;if(mineIndex%80==79){for(int i = 0; i <submarines.length;i++){if(submarines[i] instanceof MineSubmarine){/*** 水雷是写在MineSubmarine类里面* 为了调用MineSubmarine* 我们需要强制转换submarines[i]成MineSubmarine类型*///给水雷数组扩容mines = Arrays.copyOf(mines,mines.length+1);//强转的目的是现在潜水艇的数据类型是父类SeaObjext类型//但是我们要调用子类的方法,所以要强转//调用newMine生成新的水雷mines[mines.length-1] = ((MineSubmarine) submarines[i]).newMine();}}}
}
新建深水炸弹
- 因为深水炸弹是在有人控制键盘,并在战舰中发射出去
- 要先得到战舰的坐标,所以在战舰类里面写一个shootBombs方法,里面生成一个新的深水炸弹对象。
- 最后在World类里面写一个addBomb方法调shootBombs方法,里面是按键盘触发相应的动作
战舰类里面的shootBombs方法
public Bomb shootBombs(){return new Bomb(this.x-10,this.y);
}
World类里面的addBomb方法
public void addBomb(){KeyAdapter k = new KeyAdapter() { //不要求掌握/** 重写keyReleased()按键抬起事件 */public void keyReleased(KeyEvent e) { //当按键抬起时会自动触发--不要求掌握if(e.getKeyCode()==KeyEvent.VK_SPACE){ //若抬起的是空格键--不要求掌握Bomb obj = ship.shootBombs(); //获取深水炸弹对象bombs = Arrays.copyOf(bombs,bombs.length+1); //扩容bombs[bombs.length-1] = obj; //将obj添加到bombs的最后一个元素上}if(e.getKeyCode()==KeyEvent.VK_LEFT){ //若抬起的是左键头--不要求掌握ship.moveLeft(); //战舰左移}if(e.getKeyCode()==KeyEvent.VK_RIGHT){ //若抬起的是右键头--不要求掌握ship.moveRight(); //战舰右移}}};this.addKeyListener(k); //不要求掌握
}
重写所有类的move方法
Battleship
public void moveLeft(){//键盘控制向左移动x-=7;
}
public void moveRight(){//键盘控制向右移动x+=7;
}
Bomb
//向下移动
public void move(){y+=speed;
}
Mine
//向上移动
public void move(){y-=speed;
}
MineSubmarine
//向右移动
public void move(){x+=speed;
}
ObserveSubmarine
//向右移动
public void move(){x+=speed;
}
TorpedoSubmarine
//向右移动
public void move(){x+=speed;
}
代码
记得数组初始化的时候清空里面的元素,之前是测试版
Battleship
package submarine;import javax.swing.*;public class Battleship extends SeaObject{//战舰的宽public static final int WIDTH = 66;//战舰的高public static final int HEIGHT = 26;//生命数量private int life;//初始化Battleship(){//把船放到海平面上的任意位置,x,y是左上角//初始位置是(200,150-Battleship.HEIGHT),速度是3super(Battleship.WIDTH,Battleship.HEIGHT,200,150-Battleship.HEIGHT,3);//初始命是5life = 5;}//左右移动public void move(){}//发射深水炸弹public Bomb shootBombs(){return new Bomb(this.x-10,this.y);}//画布上画battleship对象public ImageIcon getObject(){return Images.battleship;}public void moveLeft(){//键盘控制向左移动this.x-=7;}public void moveRight(){//键盘控制向右移动this.x+=7;}}
Bomb
package submarine;import javax.swing.*;public class Bomb extends SeaObject{//炸弹的宽public static final int WIDTH = 9;//炸弹的高public static final int HEIGHT = 12;//深水炸弹初始化Bomb(int x,int y){super(Bomb.WIDTH,Bomb.HEIGHT,x,y,3);}//向下移动public void move(){y+=speed;}//画布上画bomb对象public ImageIcon getObject(){return Images.bomb;}}
Images
package submarine;import javax.swing.*;public class Bomb extends SeaObject{//炸弹的宽public static final int WIDTH = 9;//炸弹的高public static final int HEIGHT = 12;//深水炸弹初始化Bomb(int x,int y){super(Bomb.WIDTH,Bomb.HEIGHT,x,y,3);}//向下移动public void move(){y+=speed;}//画布上画bomb对象public ImageIcon getObject(){return Images.bomb;}}
Mine
package submarine;import javax.swing.*;public class Mine extends SeaObject {//水雷的宽public static final int WIDTH = 11;//水雷的高public static final int HEIGHT = 11;//水雷初始化Mine(int x,int y){super(Bomb.WIDTH,Bomb.HEIGHT,x,y,2);}//向上移动public void move(){y-=speed;}//画布上画mine对象public ImageIcon getObject(){return Images.mine;}
}
MineSubmarine
package submarine;import javax.swing.*;public class MineSubmarine extends SeaObject{//水雷艇的宽public static final int WIDTH = 63;//水雷艇的高public static final int HEIGHT = 19;//向右移动public void move(){x+=speed;}//水雷潜艇初始化MineSubmarine(){super(MineSubmarine.WIDTH,MineSubmarine.HEIGHT);}//发射水雷public Mine newMine(){//生成鱼雷//可以控制水雷出现在水雷潜艇的哪一边//这里用的是出现在水雷潜艇中间偏上return new Mine(this.x+30,this.y-5);}//画布上画MineSubmarine对象public ImageIcon getObject(){return Images.minesubm;}
}
ObserveSubmarine
package submarine;import javax.swing.*;public class ObserveSubmarine extends SeaObject{//侦查艇的宽public static final int WIDTH = 63;//侦查艇的高public static final int HEIGHT = 19;//侦查潜艇初始化ObserveSubmarine(){super(ObserveSubmarine.WIDTH,ObserveSubmarine.HEIGHT);}//向右移动public void move(){x+=speed;}//画布上画ObserveSubmarine 对象public ImageIcon getObject(){return Images.obsersubm;}
}
SeaObject
package submarine;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.ImageIcon;
public abstract class SeaObject {int width; //宽int height; //高int x; //x坐标int y; //y坐标int speed; //移动速度public abstract void move();SeaObject(int width,int height,int x,int y,int speed ){//bomb还有minethis.width = width;this.height = height;this.x = x;this.y = y;this.speed = speed;}SeaObject(int width,int height){this.width = width;this.height = height;x = -width;//潜艇进场是在窗口最左边进场//海平面以下随机生成,随机高度在150到(最低减去一个潜艇的高度)Random rand = new Random();y = rand.nextInt(World.HEIGHT-World.SEA_LEVEL_HEIGHT-MineSubmarine.HEIGHT+1)+150;speed = rand.nextInt(3);}//画布上画子类的对象,行为一样,所以定义为抽象public abstract ImageIcon getObject();//画对象 g:画笔public void paintImage(Graphics g){this.getObject().paintIcon(null,g,this.x,this.y);}
}
TorpedoSubmarine
package submarine;import javax.swing.*;public class TorpedoSubmarine extends SeaObject{//鱼雷艇的宽public static final int WIDTH = 64;//鱼雷艇的高public static final int HEIGHT = 20;//水雷潜艇的初始化TorpedoSubmarine(){super(TorpedoSubmarine.WIDTH,TorpedoSubmarine.HEIGHT);}//向右移动public void move(){x+=speed;}//画布上画TorpedoSubmarine对象public ImageIcon getObject(){return Images.torpesubm;}
}
World
package submarine;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class World extends JPanel {//海平面public static final int SEA_LEVEL_HEIGHT = 150;//窗口宽public static final int WIDTH = 641;//窗口长public static final int HEIGHT = 479;//定义一个战舰对象Battleship ship = new Battleship();SeaObject[] submarines = {new MineSubmarine(),new ObserveSubmarine(),new TorpedoSubmarine()};Bomb[] bombs = {};Mine[] mines = {};public void paint(Graphics g){//先画背景图Images.sea.paintIcon(null,g,0,0);//画战舰ship.paintImage(g);//画潜水艇数组for(int i = 0;i<submarines.length;i++){submarines[i].paintImage(g);}//画深水炸弹数组for(int i = 0;i<bombs.length;i++){bombs[i].paintImage(g);}//画水雷数组for(int i = 0;i<mines.length;i++){mines[i].paintImage(g);}}public SeaObject newSubmarine(){Random rand = new Random();//生成一个Random对象int number = rand.nextInt(3);//随机数是0到2if(number<1){//如果number等于0,输出水雷艇return new MineSubmarine();}else if(number<2){//如果number等于1,输出侦查艇return new ObserveSubmarine();}else{//如果number等于2,输出鱼雷艇return new TorpedoSubmarine();}}private int submarineIndex = 0;public void addSubmarine(){submarineIndex++;if(submarineIndex%40 == 25){//每40*10=400毫秒=0.4秒生成潜艇//给submarines数组扩容submarines = Arrays.copyOf(submarines,submarines.length+1);SeaObject new_Submarine = newSubmarine();//新建潜水艇对象//扩容之后,把新的潜水艇对象保存在submarines数组里面submarines[submarines.length-1] = new_Submarine;}}private int mineIndex = 0;public void addMine(){/*** 水雷,因为是水雷潜水艇发射的,需要知道水雷潜水艇x和y的坐标* 所以写在MineSubmarine类里面* 我们先要分辨数组里面哪一个是MineSubmarine* 再给他添加水雷*/mineIndex++;if(mineIndex%80==79){for(int i = 0; i <submarines.length;i++){if(submarines[i] instanceof MineSubmarine){/*** 水雷是写在MineSubmarine类里面* 为了调用MineSubmarine* 我们需要强制转换submarines[i]成MineSubmarine类型*///给水雷数组扩容mines = Arrays.copyOf(mines,mines.length+1);//强转的目的是现在潜水艇的数据类型是父类SeaObjext类型//但是我们要调用子类的方法,所以要强转//调用newMine生成新的水雷mines[mines.length-1] = ((MineSubmarine) submarines[i]).newMine();}}}}public void addBomb(){KeyAdapter k = new KeyAdapter() { //不要求掌握/** 重写keyReleased()按键抬起事件 */public void keyReleased(KeyEvent e) { //当按键抬起时会自动触发--不要求掌握if(e.getKeyCode()==KeyEvent.VK_SPACE){ //若抬起的是空格键--不要求掌握Bomb obj = ship.shootBombs(); //获取深水炸弹对象bombs = Arrays.copyOf(bombs,bombs.length+1); //扩容bombs[bombs.length-1] = obj; //将obj添加到bombs的最后一个元素上}if(e.getKeyCode()==KeyEvent.VK_LEFT){ //若抬起的是左键头ship.moveLeft(); //战舰左移}if(e.getKeyCode()==KeyEvent.VK_RIGHT){ //若抬起的是右键头ship.moveRight(); //战舰右移}}};this.addKeyListener(k); //不要求掌握}public void objectMove(){/*** 遍历潜水艇,水雷,深水炸弹让它们移动* Battleship是由键盘控制的*/for(int i = 0;i<submarines.length;i++){submarines[i].move();}for(int i = 0;i<mines.length;i++){mines[i].move();}for(int i = 0;i<bombs.length;i++){bombs[i].move();}}public void action(){addBomb();int period = 10;//delay和period都设置为10毫秒Timer timer = new Timer();//新建一个Timer对象timer.schedule(new TimerTask() {/*** 每10毫秒调用schedule* 并重写TimerTask里面的run方法* 这里用到的知识是匿名内部类*/@Overridepublic void run() {/*** 这里面需要写的是新建潜艇,深水炸弹,鱼雷对象* 移动* 撞击爆炸消失等方法*/addSubmarine();//生成新的潜水艇对象addMine();//生成新的深水炸弹对象objectMove();repaint();//重写调用paint方法}}, period, period);}//主方法public static void main(String[] args) {JFrame frame = new JFrame();World world = new World();world.setFocusable(true);frame.add(world);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setSize(WIDTH+16, HEIGHT+39);frame.setLocationRelativeTo(null);frame.setVisible(true);//1)设置窗口可见 2)尽快调用paint()方法world.action();}
}
6. 把超过窗口和相互碰撞的物体删掉
删除超过窗口的对象
public void deleteOutOfBounds(){//删除超过边界的对象//潜水艇超过边界会被删除for(int i = 0;i<submarines.length;i++){//潜水艇只有向右的动作,所以当有潜水艇超过右边边界,就会被删除if(submarines[i].x>=World.WIDTH){//思路是让要删除的这个数组元素下标等于,最后一个数组元素,再缩容submarines[i] = submarines[submarines.length-1];submarines = Arrays.copyOf(submarines,submarines.length-1);}}//水雷超过边界会被删除for(int i = 0;i<mines.length;i++){//水雷只有向上的动作,所以当有水雷超过海平面,就会被删除if(mines[i].y<World.SEA_LEVEL_HEIGHT){//思路是让要删除的这个数组元素下标等于,最后一个数组元素,再缩容mines[i] = mines[mines.length-1];mines = Arrays.copyOf(mines,mines.length-1);}}//深水炸弹超过边界会被删除for(int i = 0;i<bombs.length;i++){//深水炸弹只有向下的动作,所以当有深水炸弹超过最下面边界,就会被删除if(bombs[i].y>World.HEIGHT){//思路是让要删除的这个数组元素下标等于,最后一个数组元素,再缩容bombs[i] = bombs[bombs.length-1];bombs = Arrays.copyOf(bombs,bombs.length-1);}}
}
删除相互碰撞的物体
- 这里要判断两个物体是否碰撞就可以定义一个为参照物,其他对象在哪个范围就代表着碰撞
- 战舰和水雷碰撞,深水炸弹和潜水艇碰撞
- 碰撞的结果:战舰和水雷碰撞,水雷消失,战舰命减一,如果命为零,游戏结束
- 深水炸弹和潜水艇碰撞两个都消失,战舰命加一
- 方法是写在SeaObject里面,返回值是boolean类型
因为坐标出现在每个物体的左上角,所以以other作为参照物,只需要计算黄色部分范围即可
public boolean isHit(SeaObject other){return other.x>=this.x-other.width && other.x<=this.x+this.width &&other.y>=this.y-other.height && other.y<=this.y+this.height;
}
在Battleship类里面写一个得到生命和失去生命的方法,因为在Battleship中life是私有的,所以用方法输出
public int getLife(){return life;
}
public void subtractLife(){life--;
}
在paint里面加两行,分别对应的是在画布上画出score和life来
g.drawString("SCORE: "+score,200,50); //画分
g.drawString("LIFE: "+ship.getLife(),400,50); //画命
- 我们设定只有水雷潜艇是得命,其他潜艇得分
- 为了区分它们,我们写两个接口让它们继承,这样如果判断潜艇和深水炸弹是碰撞的,那我们就判断是不是属于命或者得分接口
- 最后写了判断有没有碰撞的方法在World里面
public void judgeIsHit(){//判断潜水艇和深水炸弹碰撞for(int i = 0;i<submarines.length;i++){for(int j = 0;j<bombs.length;j++){if(submarines[i].isHit(bombs[j])){//把潜水艇和深水炸弹的状态设为DEADsubmarines[i].status = SeaObject.DEAD;bombs[j].status = SeaObject.DEAD;//得分 先判断这个潜艇对象是否继承EnemyScore接口if(submarines[i] instanceof EnemyScore){score += ((EnemyScore) submarines[i]).getScore();}//得命 先判断这个潜艇对象是否继承EnemyLife接口if(submarines[i] instanceof EnemyLife){ship.addLife();//加命}}}}//判断战舰和水雷碰撞for(int i = 0;i<mines.length;i++){System.out.println("ship"+(ship.y+ship.height));System.out.println("mines"+i+" "+mines[i].y);if(mines[i].isHit(ship)){//把水雷的状态设为DEADmines[i].status = SeaObject.DEAD;ship.subtractLife();}}
}
最后判断当命为0的时候 ,游戏结束
- 定义两个常量
- 写一个判断游戏状态的方法在World里面
public void checkGameOverAction(){if(ship.getLife()==0){gameStatus = GAMEOVER;}
}
最后改paint方法,当gameStatus = GAMEOVER;游戏就结束,当gameStatus = RUNNING;的时候,游戏没结束
7.最终代码
Battleship
package submarine;import javax.swing.*;public class Battleship extends SeaObject{//战舰的宽public static final int WIDTH = 66;//战舰的高public static final int HEIGHT = 26;//生命数量private int life;//初始化Battleship(){//把船放到海平面上的任意位置,x,y是左上角//初始位置是(200,150-Battleship.HEIGHT),速度是3super(Battleship.WIDTH,Battleship.HEIGHT,200,150-Battleship.HEIGHT,3);//初始命是5life = 5;}//左右移动public void move(){}//发射深水炸弹public Bomb shootBombs(){return new Bomb(this.x-10,this.y);}//画布上画battleship对象public ImageIcon getObject(){return Images.battleship;}public void moveLeft(){//键盘控制向左移动this.x-=7;}public void moveRight(){//键盘控制向右移动this.x+=7;}public int getLife(){return life;}public void addLife(){life++;}public void subtractLife(){life--;}
}
Bomb
package submarine;import javax.swing.*;public class Bomb extends SeaObject{//炸弹的宽public static final int WIDTH = 9;//炸弹的高public static final int HEIGHT = 12;//深水炸弹初始化Bomb(int x,int y){super(Bomb.WIDTH,Bomb.HEIGHT,x,y,3);}//向下移动public void move(){y+=speed;}//画布上画bomb对象public ImageIcon getObject(){return Images.bomb;}}
EnemyLife
package submarine;public interface EnemyLife {public int getLife();
}
EnemyScore
package submarine;public interface EnemyScore {public int getScore();
}
Images
package submarine;import javax.swing.ImageIcon;
/** 图片类 */
public class Images {// 公开的 静态的 图片数据类型 变量名public static ImageIcon battleship; //战舰图片public static ImageIcon obsersubm; //侦察潜艇图片public static ImageIcon torpesubm; //鱼雷潜艇图片public static ImageIcon minesubm; //水雷潜艇图片public static ImageIcon mine; //水雷图片public static ImageIcon bomb; //深水炸弹图片public static ImageIcon sea; //海洋图public static ImageIcon gameover; //游戏结束图static{ //给静态图片赋值battleship = new ImageIcon("img/battleship.png");obsersubm = new ImageIcon("img/obsersubm.png");torpesubm = new ImageIcon("img/torpesubm.png");minesubm = new ImageIcon("img/minesubm.png");mine = new ImageIcon("img/mine.png");bomb = new ImageIcon("img/bomb.png");sea = new ImageIcon("img/sea.png");gameover = new ImageIcon("img/gameover.png");}public static void main(String[] args) {//写完上面对象之后,测试,返回8表示读取成功System.out.println(battleship.getImageLoadStatus()); //返回8表示读取成功System.out.println(obsersubm.getImageLoadStatus());System.out.println(torpesubm.getImageLoadStatus());System.out.println(minesubm.getImageLoadStatus());System.out.println(mine.getImageLoadStatus());System.out.println(bomb.getImageLoadStatus());System.out.println(sea.getImageLoadStatus());System.out.println(gameover.getImageLoadStatus());}}
Mine
package submarine;import javax.swing.*;public class Mine extends SeaObject {//水雷的宽public static final int WIDTH = 11;//水雷的高public static final int HEIGHT = 11;//水雷初始化Mine(int x,int y){super(Bomb.WIDTH,Bomb.HEIGHT,x,y,1);}//向上移动public void move(){y-=speed;}//画布上画mine对象public ImageIcon getObject(){return Images.mine;}
}
MineSubmarine
package submarine;import javax.swing.*;public class MineSubmarine extends SeaObject implements EnemyLife{//水雷艇的宽public static final int WIDTH = 63;//水雷艇的高public static final int HEIGHT = 19;//向右移动public void move(){x+=speed;}//水雷潜艇初始化MineSubmarine(){super(MineSubmarine.WIDTH,MineSubmarine.HEIGHT);}//发射水雷public Mine newMine(){//生成鱼雷//可以控制水雷出现在水雷潜艇的哪一边//这里用的是出现在水雷潜艇中间偏上return new Mine(this.x+30,this.y-5);}//画布上画MineSubmarine对象public ImageIcon getObject(){return Images.minesubm;}public int getLife(){return 1; //打掉水雷潜艇,战舰得1条命}
}
ObserveSubmarine
package submarine;import javax.swing.*;public class ObserveSubmarine extends SeaObject implements EnemyScore{//侦查艇的宽public static final int WIDTH = 63;//侦查艇的高public static final int HEIGHT = 19;//侦查潜艇初始化ObserveSubmarine(){super(ObserveSubmarine.WIDTH,ObserveSubmarine.HEIGHT);}//向右移动public void move(){x+=speed;}//画布上画ObserveSubmarine 对象public ImageIcon getObject(){return Images.obsersubm;}public int getScore(){return 20;}
}
SeaObject
package submarine;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.ImageIcon;
public abstract class SeaObject{public static final int DEAD = 0;public static final int LIVE = 1;public int status = LIVE;protected int width; //宽protected int height; //高public int x; //x坐标public int y; //y坐标public int speed; //移动速度public abstract void move();SeaObject(int width,int height,int x,int y,int speed ){//bomb还有minethis.width = width;this.height = height;this.x = x;this.y = y;this.speed = speed;}SeaObject(int width,int height){this.width = width;this.height = height;x = -width;//潜艇进场是在窗口最左边进场//海平面以下随机生成,随机高度在150到(最低减去一个潜艇的高度)Random rand = new Random();y = rand.nextInt(World.HEIGHT-World.SEA_LEVEL_HEIGHT-MineSubmarine.HEIGHT+1)+150;speed = rand.nextInt(3);}//画布上画子类的对象,行为一样,所以定义为抽象public abstract ImageIcon getObject();//画对象 g:画笔public void paintImage(Graphics g){this.getObject().paintIcon(null,g,this.x,this.y);}public boolean isHit(SeaObject other){return other.x>=this.x-other.width && other.x<=this.x+this.width &&other.y>=this.y-other.height && other.y<=this.y+this.height;}}
TorpedoSubmarine
package submarine;import javax.swing.*;public class TorpedoSubmarine extends SeaObject implements EnemyScore{//鱼雷艇的宽public static final int WIDTH = 64;//鱼雷艇的高public static final int HEIGHT = 20;//水雷潜艇的初始化TorpedoSubmarine(){super(TorpedoSubmarine.WIDTH,TorpedoSubmarine.HEIGHT);}//向右移动public void move(){x+=speed;}//画布上画TorpedoSubmarine对象public ImageIcon getObject(){return Images.torpesubm;}public int getScore(){return 20;}
}
World
package submarine;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class World extends JPanel {//游戏运行public static final int RUNNING = 1;//海平面public static final int GAMEOVER = 0;//窗口宽public static final int WIDTH = 641;//窗口长public static final int HEIGHT = 479;//海平面public static final int SEA_LEVEL_HEIGHT = 150;//分数public int score = 0;//定义一个战舰对象Battleship ship = new Battleship();SeaObject[] submarines = {};Bomb[] bombs = {};Mine[] mines = {};//游戏状态,RUNNING就是游戏没有结束,GAMEOVER就是游戏结束public int gameStatus = RUNNING;public int numberLife = 0;public void paint(Graphics g){if(gameStatus==GAMEOVER){if(numberLife==0){//让画布上的life变成0g.drawString("LIFE: "+ship.getLife(),400,50); //画命numberLife=1;}Images.gameover.paintIcon(null,g,0,0);}else if(gameStatus==RUNNING){//先画背景图Images.sea.paintIcon(null,g,0,0);//画战舰ship.paintImage(g);//画潜水艇数组for(int i = 0;i<submarines.length;i++){submarines[i].paintImage(g);}//画深水炸弹数组for(int i = 0;i<bombs.length;i++){bombs[i].paintImage(g);}//画水雷数组for(int i = 0;i<mines.length;i++){mines[i].paintImage(g);}g.drawString("SCORE: "+score,200,50); //画分g.drawString("LIFE: "+ship.getLife(),400,50); //画命}}public SeaObject newSubmarine(){Random rand = new Random();//生成一个Random对象int number = rand.nextInt(3);//随机数是0到2if(number<1){//如果number等于0,输出水雷艇return new MineSubmarine();}else if(number<2){//如果number等于1,输出侦查艇return new ObserveSubmarine();}else{//如果number等于2,输出鱼雷艇return new TorpedoSubmarine();}}private int submarineIndex = 0;public void addSubmarine(){submarineIndex++;if(submarineIndex%40 == 25){//每40*10=400毫秒=0.4秒生成潜艇//给submarines数组扩容submarines = Arrays.copyOf(submarines,submarines.length+1);SeaObject new_Submarine = newSubmarine();//新建潜水艇对象//扩容之后,把新的潜水艇对象保存在submarines数组里面submarines[submarines.length-1] = new_Submarine;}}private int mineIndex = 0;public void addMine(){/*** 水雷,因为是水雷潜水艇发射的,需要知道水雷潜水艇x和y的坐标* 所以写在MineSubmarine类里面* 我们先要分辨数组里面哪一个是MineSubmarine* 再给他添加水雷*/mineIndex++;if(mineIndex%80==79){for(int i = 0; i <submarines.length;i++){if(submarines[i] instanceof MineSubmarine){/*** 水雷是写在MineSubmarine类里面* 为了调用MineSubmarine* 我们需要强制转换submarines[i]成MineSubmarine类型*///给水雷数组扩容mines = Arrays.copyOf(mines,mines.length+1);//强转的目的是现在潜水艇的数据类型是父类SeaObjext类型//但是我们要调用子类的方法,所以要强转//调用newMine生成新的水雷mines[mines.length-1] = ((MineSubmarine) submarines[i]).newMine();}}}}public void addBomb(){KeyAdapter k = new KeyAdapter() { //不要求掌握/** 重写keyReleased()按键抬起事件 */public void keyReleased(KeyEvent e) { //当按键抬起时会自动触发if(e.getKeyCode()==KeyEvent.VK_SPACE){ //若抬起的是空格键Bomb obj = ship.shootBombs(); //获取深水炸弹对象bombs = Arrays.copyOf(bombs,bombs.length+1); //扩容bombs[bombs.length-1] = obj; //将obj添加到bombs的最后一个元素上}if(e.getKeyCode()==KeyEvent.VK_LEFT){ //若抬起的是左键头--不要求掌握ship.moveLeft(); //战舰左移}if(e.getKeyCode()==KeyEvent.VK_RIGHT){ //若抬起的是右键头--不要求掌握ship.moveRight(); //战舰右移}}};this.addKeyListener(k); //不要求掌握}public void objectMove(){/*** 遍历潜水艇,水雷,深水炸弹让它们移动* Battleship是由键盘控制的*/for(int i = 0;i<submarines.length;i++){submarines[i].move();}for(int i = 0;i<mines.length;i++){mines[i].move();}for(int i = 0;i<bombs.length;i++){bombs[i].move();}}public void deleteOutOfBounds(){//删除超过边界的对象//潜水艇超过边界会被删除for(int i = 0;i<submarines.length;i++){//潜水艇只有向右的动作,所以当有潜水艇超过右边边界,就会被删除if(submarines[i].x>=World.WIDTH||submarines[i].status==SeaObject.DEAD){//思路是让要删除的这个数组元素下标等于,最后一个数组元素,再缩容submarines[i] = submarines[submarines.length-1];submarines = Arrays.copyOf(submarines,submarines.length-1);}}//水雷超过边界会被删除for(int i = 0;i<mines.length;i++){//水雷只有向上的动作,所以当有水雷超过海平面,就会被删除if(mines[i].y<World.SEA_LEVEL_HEIGHT||mines[i].status==SeaObject.DEAD){//思路是让要删除的这个数组元素下标等于,最后一个数组元素,再缩容mines[i] = mines[mines.length-1];mines = Arrays.copyOf(mines,mines.length-1);}}//深水炸弹超过边界会被删除for(int i = 0;i<bombs.length;i++){//深水炸弹只有向下的动作,所以当有深水炸弹超过最下面边界,就会被删除if(bombs[i].y>World.HEIGHT||bombs[i].status==SeaObject.DEAD){//思路是让要删除的这个数组元素下标等于,最后一个数组元素,再缩容bombs[i] = bombs[bombs.length-1];bombs = Arrays.copyOf(bombs,bombs.length-1);}}}public void judgeIsHit(){//判断潜水艇和深水炸弹碰撞for(int i = 0;i<submarines.length;i++){for(int j = 0;j<bombs.length;j++){if(submarines[i].isHit(bombs[j])){//把潜水艇和深水炸弹的状态设为DEADsubmarines[i].status = SeaObject.DEAD;bombs[j].status = SeaObject.DEAD;//得分 先判断这个潜艇对象是否继承EnemyScore接口if(submarines[i] instanceof EnemyScore){score += ((EnemyScore) submarines[i]).getScore();}//得命 先判断这个潜艇对象是否继承EnemyLife接口if(submarines[i] instanceof EnemyLife){ship.addLife();//加命}}}}//判断战舰和水雷碰撞for(int i = 0;i<mines.length;i++){if(mines[i].isHit(ship)){//把水雷的状态设为DEADmines[i].status = SeaObject.DEAD;ship.subtractLife();}}}public void checkGameOverAction(){if(ship.getLife()==0){gameStatus = GAMEOVER;}}public void action(){addBomb();int period = 10;//delay和period都设置为10毫秒Timer timer = new Timer();//新建一个Timer对象timer.schedule(new TimerTask() {/*** 每10毫秒调用schedule* 并重写TimerTask里面的run方法* 这里用到的知识是匿名内部类*/@Overridepublic void run() {/*** 这里面需要写的是新建潜艇,深水炸弹,鱼雷对象* 移动* 撞击爆炸消失等方法*/addSubmarine();//生成新的潜水艇对象addMine();//生成新的深水炸弹对象objectMove();//除了战舰所有对象移动deleteOutOfBounds();//删除超过边界的对象judgeIsHit();//判断两个对象是否碰撞checkGameOverAction();//检查游戏是不是结束repaint();//重写调用paint方法}}, period, period);}//主方法public static void main(String[] args) {JFrame frame = new JFrame();World world = new World();world.setFocusable(true);frame.add(world);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setSize(WIDTH+16, HEIGHT+39);frame.setLocationRelativeTo(null);frame.setVisible(true);//1)设置窗口可见 2)尽快调用paint()方法world.action();}
}
这篇关于Java 面向对象战舰小游戏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!