shoot射击游戏项目一
1.需求分析:
运行项目,看结果:
A:小敌机,大敌机,蜜蜂,--------敌人
英雄机发射子弹
B:
子弹击中小敌机----玩家得分 1分
子弹击中大敌机----玩家得分 5分
子弹击中小蜜蜂-----玩家得 1生命或者火力值30
C:
英雄机的火力值变为0 的时候,就变成单倍火力
火力值变为0 的时候,变为双倍火力;依次减少2
D:碰撞
敌人与英雄机发发生碰撞,碰撞之后,英雄机的生命值减少,变位0的时候,游戏结束
2.计数分析
设计类:
A:找对象:6个对象
英雄机,小敌机,大敌机,蜜蜂,子弹,天空
B:抽类
Hero/Airplane/BIgAirplane/Bee/Bullet/Sky
C:设计成员变量和方法
shoot射击游戏项目二
1.需求分析:
A:设计一个父类、超类:并且让6个对象继承超类,测试
B:给超类添加构造方法;让六个对象分别调用超类
C: 设置对象数组,进行测试
D:在六个子类,派生类中重写
E:画窗体
2.技术分析:
重写和重载:
重写:(Override)
- 发生在父子类中,方法名相同,参数列表相同,方法体不同;
- 遵循“运行期绑定”,看对象的类型来调用方法;
重载:(Overload)
- 发生在一个类中,方法名相同,参数列表不同,方法体不同:
- 遵循“编译器绑定”,看参数,引用类型绑定法;
shoot射击游戏项目三
1.需求分析:
A:给类中添加修饰符
B:给6个派生类中添加图片属性
1):6个类种添加Static
2)在父类中添加静态方法Loadlmage()添加图片
3):六个派生类中static代码块调用Loadlmage()方法
2:技术实现:
修饰符
y/n public protected default private同一个类 y y y y 同一个包中不同类 y y y 不同包类 y y 不同胞中的类 y
Shoot射击游戏四
1.需求分析
A:将窗体大小设置成常量
B:画对象:
想画对象先获取图片,针对每个对象能够获取到图片,
获取到图片的行为是共有的,设计到父类中;
每个对象得到图片的行为是不一样的,设计了抽象的方法----getImage();
在不同状态下,得到不同的图片;
状态:设计到父类中,设计常量:Life DEAD; REMOVE
默认状态:state=LIFE
获取图片的同时,需不需要判断当前的状态???? y
每个对象都需要判断。设计到超类,父类中;
而每个对象判断行为都是不一样的,设计普通方法即可;
-----FlyObject:isLife()/isDead()/isRemove()
C:在6个子类中重写getImage()方法
- Sky:直接返回即可
- 子弹Bullet:如果是存活的返回images即可
如果是over的删除即可 - 英雄机:如果是存活,返回imgaes[0]/images[1]
- 小敌机:如多存活,返回images[0]
如果over,images[1]—images[4]进行切换,切换完毕,到了images[4]后进行删除
D:得到不同状态下的图片,进行开始画出来;
画对象的行为是共有的,所以涉及到超类中;
每个对象画的方式都是一样的,所以设计为【普通方法】
E:测试,调用即可
设计规则:
将所有子类所共有的行为和属性,可以设计到超类中;抽共性
所有子类的行为都是一样的,设计为普通方法;所有子类的行为都是不一样的—设计成抽象方法
Shoot射击游戏六
子弹与敌人碰撞:
- 设计到父类中,hit()方法,实现检测子弹与敌人大声碰撞
- 在父类中设计一个goDead()实现飞行物over
- 在Hero类中设计实现addLife(),addDoubleFire()
- 通过AirPlane和BigAirplane中的接口来实现玩家得分
- 通过Bee中的接口来实现玩家获得奖励
代码实现
子弹:
package cn.tedu.shoot;import java.awt.image.BufferedImage;/** * 子弹 * @author Administrator * */public class Bullet extends FlyingObject{private static BufferedImage images;//静态代码块static {images = loadImage("bullet.png");}private int speed;//速度/**构造方法*/public Bullet(int x, int y){super(8, 14, x, y);speed = 2;}/**子弹的移动*/public void step(){this.y -= speed;}/**重写getImage()方法获取到图片*/@Overridepublic BufferedImage getImage() {if (isLife()) {return images;}else if(isDead()){state = REMOVE;//修改状态为删除状态}return null;}/**检测是否越界*/@Overridepublic boolean outOfBounds() {return this.y <= -this.height;}}
大敌机:
package cn.tedu.shoot;import java.awt.image.BufferedImage;import java.util.Random;/** * 大敌机: * * @author Administrator * */public class BigAirplane extends FlyingObject implements Enemy{private static BufferedImage[] images;// 静态代码块static {images = new BufferedImage[5];for (int i = 0; i < images.length; i++) {images[i] = loadImage("bigplane" + i + ".png");}}int speed;// 速度/** 构造方法 */public BigAirplane() {super(99, 89);this.speed = 2;}public void step(){this.y += speed;}// 得到图片int index = 1;@Overridepublic BufferedImage getImage() {// 10Mif (isLife()) {return images[0];} else if (isDead()) {// 图片的切换BufferedImage img = images[index++];if (index == images.length) {state = REMOVE;}return img;}/* * images[index++]; index = 1; 10M images[1] index = 2 返回images[1] 20M * images[2] index = 3 返回images[2] 30M images[3] index = 4 返回images[3] * 40M images[4] index = 5 返回images[4] */return null;}/**重写得分接口*/@Overridepublic int getScore() {return 3;}}
小敌机:
package cn.tedu.shoot;import java.awt.Graphics;import java.awt.image.BufferedImage;import java.util.Random;/** * 小敌机: * @author Administrator * */public class Airplane extends FlyingObject implements Enemy{private static BufferedImage[] images;//静态代码块static {images = new BufferedImage[5];for (int i = 0; i < images.length; i++) {images[i] = loadImage("airplane" + i + ".png");}}private int speed;//速度/**构造方法*/public Airplane(){super(49, 36);this.speed = 5;}/**移动*/public void step(){this.y += speed;}//得到图片int index = 1;@Overridepublic BufferedImage getImage() {//10Mif (isLife()) {return images[0];}else if(isDead()){//图片的切换BufferedImage img = images[index++];if (index == images.length) {state = REMOVE;}return img;}/*images[index++]; * index = 1; * 10M images[1] index = 2 返回images[1] * 20M images[2] index = 3 返回images[2] * 30M images[3] index = 4 返回images[3] * 40M images[4] index = 5 返回images[4] * */return null;}@Overridepublic int getScore() {return 1;}}
英雄机
package cn.tedu.shoot;import java.awt.image.BufferedImage;/** * 英雄机: * * @author Administrator * */public class Hero extends FlyingObject{private static BufferedImage[] images;//静态代码块static {images = new BufferedImage[2];for (int i = 0; i < images.length; i++) {images[i] = loadImage("hero" + i + ".png");}}//成员变量private int life;//生命值private int doubleFire;//火力/**构造方法*/public Hero() {super(97, 124, 140, 400);life = 6;doubleFire = 0;//单倍火力}/**英雄机的移动:随着鼠标的移动而动*/public void movedTo(int x, int y){this.x = x - this.width/2;this.y = y - this.height/2;}/**英雄机的移动*/public void step(){System.out.println("图片的切换");}int index = 0;@Overridepublic BufferedImage getImage() {//return images[0];return images[index++/10%images.length];}/**英雄机产生子弹*/public Bullet[] shoot(){int xStep = this.width/4;int yStep = 15;if (doubleFire > 0) {//双倍火力Bullet[] bs = new Bullet[2];bs[0] = new Bullet(this.x + xStep * 1, this.y - yStep);bs[1] = new Bullet(this.x + xStep * 3, this.y - yStep);doubleFire -= 2;return bs;}else{Bullet[] bs = new Bullet[1];bs[0] = new Bullet(this.x + xStep * 2, this.y - yStep);return bs;}}public void addDoubleFire(){doubleFire += 10;}public void addLife(){life++;}/**获得生命*/public int getLife(){return life;}/**减少生命*/public void substractLife(){life--;}/**清空火力*/public void clearDoubleFire(){doubleFire = 0;}}
蜜蜂:
package cn.tedu.shoot;import java.awt.image.BufferedImage;import java.util.Random;/** * 蜜蜂: * * @author 小二郎 * */public class Bee extends FlyingObject implements Award{private static BufferedImage[] images;// 静态代码块static {images = new BufferedImage[5];for (int i = 0; i < images.length; i++) {images[i] = loadImage("bee" + i + ".png");}}private int xSpeed;// x坐标的速度private int ySpeed;// y坐标的速度private int awardType;// 获取奖励的类型public Bee() {super(29, 39);xSpeed = 1;ySpeed = 2;Random rand = new Random();awardType = rand.nextInt(2);// 0 1}public void step() {x += xSpeed;y += ySpeed;if (x < 0 || x >= ShootMain.SCREEN_WIDTH - this.width) {xSpeed *= -1;}}// 得到图片int index = 1;@Overridepublic BufferedImage getImage() {// 10Mif (isLife()) {return images[0];} else if (isDead()) {// 图片的切换BufferedImage img = images[index++];if (index == images.length) {state = REMOVE;}return img;}return null;}@Overridepublic int getAwardType() {// TODO Auto-generated method stubreturn awardType;}}
天空:
package cn.tedu.shoot;import java.awt.Graphics;import java.awt.image.BufferedImage;/** * 天空: * * @author Administrator * */public class Sky extends FlyingObject {private static BufferedImage images;// 静态代码块static {images = loadImage("background.png");}private int speed;// 速度public int y1;// 第二张图片的坐标/** 构造方法 */public Sky() {super(ShootMain.SCREEN_WIDTH, ShootMain.SCREEN_HEIGHT, 0, 0);speed = 1;y1 = -ShootMain.SCREEN_HEIGHT;}/** 天空移动 */public void step() {y += speed;y1 += speed;if (y >= ShootMain.SCREEN_HEIGHT) {y = -ShootMain.SCREEN_HEIGHT;}if (y1 >= ShootMain.SCREEN_HEIGHT) {y1 = -ShootMain.SCREEN_HEIGHT;}}@Overridepublic BufferedImage getImage() {return images;}/** 重写父类中的方法 */@Overridepublic void paintObject(Graphics g) {g.drawImage(getImage(), x, y, null);g.drawImage(getImage(), x, y1, null);}}
飞行物的父类
package cn.tedu.shoot;import java.awt.Graphics;import java.awt.image.BufferedImage;import java.util.Random;import javax.imageio.ImageIO;/** * 父类:飞行物 * * @author 小二郎 * */public abstract class FlyingObject {// 成员变量protected int width;// 宽protected int height;// 高protected int x;// x坐标protected int y;// y坐标// 设计三种状态public static final int LIFE = 0;// 存活public static final int DEAD = 1;// overpublic static final int REMOVE = 2;// 删除public int state = LIFE;// 当前状态为存活/** 提供敌人(小敌机+大敌机+蜜蜂) */public FlyingObject(int width, int height) {this.width = width;this.height = height;Random rand = new Random();// 小敌机出现的位置this.x = rand.nextInt(ShootMain.SCREEN_WIDTH - this.width);this.y = -this.height;}/** 提供英雄机+子弹+天空的构造方法 */public FlyingObject(int width, int height, int x, int y) {this.width = width;this.height = height;this.x = x;this.y = y;}/** 移动的方法 */public void step() {}/** 读取图片 */public static BufferedImage loadImage(String fileName) {try {// 同包之内的图片读取BufferedImage img = ImageIO.read(FlyingObject.class.getResource(fileName));return img;} catch (Exception e) {e.printStackTrace();throw new RuntimeException();}}/** 获取图片 */public abstract BufferedImage getImage();/** 画图片 g:画笔 */public void paintObject(Graphics g) {g.drawImage(this.getImage(), this.x, this.y, null);}/** 判断当前状态是不是存活的 */public boolean isLife() {return state == LIFE;}/** 判断当前状态是不是over的 */public boolean isDead() {return state == DEAD;}/** 判断当前状态是不是删除的 */public boolean isRemove() {return state == REMOVE;}/** 检测越界的方法 */public boolean outOfBounds() {return this.y >= ShootMain.SCREEN_HEIGHT;}/* 实现子弹与敌人发生碰撞 other:子弹敌人 */public boolean hit(FlyingObject other) {int x1 = this.x - other.width;int y1 = this.y - other.height;int x2 = this.x + this.width;int y2 = this.y + this.height;int x = other.x;int y = other.y;return x >= x1 && x <= x2 && y >= y1 && y <= y2;}/** 飞行物over */public void goDead() {state = DEAD;// 将对象状态修改为DAED}public int getScore() {// TODO Auto-generated method stubreturn 0;}}
得分接口
package cn.tedu.shoot;/** * 得分接口 * @author 小二郎 * */public interface Enemy {/*得分*/public int getScore();}
奖励接口
package cn.tedu.shoot;/** * 得分接口 * @author 小二郎 * */public interface Enemy {/*得分*/public int getScore();}
主函数得类:
package cn.tedu.shoot;import java.awt.AWTError;import java.awt.Graphics;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.image.BufferedImage;import java.util.Arrays;import java.util.Random;import java.util.Timer;import java.util.TimerTask;import javax.swing.JFrame;import javax.swing.JPanel;/** * 主函数的类: * * @author Administrator * */public class ShootMain extends JPanel {public static final int SCREEN_WIDTH = 400;public static final int SCREEN_HEIGHT = 700;//起始状态START/RUNNING/PAUSE/GAME_OVER//默认起始状态/* * 鼠标点击事件: * 开始--运行 结束---开始 * 鼠标移动事件: * 启动状态:结束----启动 * 暂停状态:鼠标从屏幕里划到外 * 运行状态:从外到内的时候 * 结束状态:英雄机的生命为0 */public static final int START = 0;public static final int RUNNING = 1;public static final int PAUSE = 2;public static final int GAME_OVER = 3;public int state = START;//默认状态public static BufferedImage start;public static BufferedImage pause;public static BufferedImage gameover;//静态代码块static{start = FlyingObject.loadImage("start.png");pause = FlyingObject.loadImage("pause.png");gameover = FlyingObject.loadImage("gameover"+ ".png");}private Sky sky = new Sky();private Hero hero = new Hero();private FlyingObject[] flys = {};private Bullet[] bullets = {};/** 产生敌人对象 */public FlyingObject nextOne() {Random rand = new Random();int type = rand.nextInt(20);if (type < 5) {return new Airplane();} else if (type < 12) {return new Bee();} else {return new BigAirplane();}}/** 实现敌人入场 */int enterIndex = 0;public void enterAction() {enterIndex++;if (enterIndex % 40 == 0) {// 获取到敌人FlyingObject f = nextOne();// 敌人添加到数组的最后一位上flys = Arrays.copyOf(flys, flys.length + 1);flys[flys.length - 1] = f;}}/** 子弹入场 */int shootIndex = 0;public void shootAction() {shootIndex++;if (shootIndex % 40 == 0) {Bullet[] bs = hero.shoot();// 获取子弹数组bullets = Arrays.copyOf(bullets, bullets.length + bs.length);// 将产生的子弹数组放到源数组中的最后一个元素System.arraycopy(bs, 0, bullets, bullets.length - bs.length,bs.length);}}/** 飞行物移动 */public void stepAction() {sky.step();for (int i = 0; i < flys.length; i++) {flys[i].step();}for (int i = 0; i < bullets.length; i++) {bullets[i].step();}}/**删除越界的飞行物*/public void outOfBoundsAction(){int index = 0;//存放不越界数组的下标,个数//新建不越界的敌人数组FlyingObject[] flysLive = new FlyingObject[flys.length];for (int i = 0; i < flys.length; i++) {//获取到每一个敌人FlyingObject f = flys[i];//判断敌人是否不越界if (!f.outOfBounds()) {//如果不越界,flysLive[index] = f;index++;}//将不越界的敌人存放到不越界的数组中}flys = Arrays.copyOf(flysLive, index);//System.out.println("index == " + index);index = 0;Bullet[] bulletLive = new Bullet[bullets.length];for (int i = 0; i < bullets.length; i++) {Bullet b = bullets[i];if (!b.outOfBounds()) {bulletLive[index] = b;index++;}}bullets = Arrays.copyOf(bulletLive, index);}/**子弹与敌人的碰撞*/int score = 0;//玩家的得分记录public void bulletBangAction(){//遍历所有的子弹for (int i = 0; i < bullets.length; i++) {//获取每一个子弹Bullet b = bullets[i];//遍历所有的敌人for (int j = 0; j < flys.length; j++) {//获取每一个敌人FlyingObject f = flys[j];//判断碰撞if (f.isLife() && b.isLife() && f.hit(b)) {f.goDead();//敌人overb.goDead();//子弹overif (f instanceof Enemy) {//如果撞上的是敌人能得分Enemy e = (Enemy)f;score += e.getScore();}//如果撞上的是奖励if (f instanceof Award) {Award a = (Award)f;int type = a.getAwardType();switch (type) {case Award.DOUBLE_FIRE://火力hero.addDoubleFire();break;case Award.LIFE://生命hero.addLife();break;}}}}}}/**英雄机与敌人发生碰撞*/public void heroBangAction(){/* * 思路: * 1)借助FlyingObject中的hit()方法检测碰撞 * 2)借助FlyingObject中的goDead()方法over * 3)在Hero类中设计一个方法实现碰撞之后 * substractLife()减少生命, clearDoubleFire()火力清0 * 4) 在run()方法中实现英雄机与敌人发生碰撞 * heroBangAction(); * 遍历敌人获取到每一个敌人: * 判断撞上了: * 敌人over,英雄机减少生命,清空火力 *///遍历所有的敌人for (int i = 0; i < flys.length; i++) {//获取每一个敌人FlyingObject f = flys[i];if (hero.isLife() && f.isLife() && f.hit(hero)) {f.goDead();hero.substractLife();//减少生命hero.clearDoubleFire();//清空火力}}}/**检测游戏是否结束*/public void checkGameOverAction(){//判断英雄机的生命值,//如果小于0的话,游戏结束,修改状态if(hero.getLife() <= 0){state = GAME_OVER;}}/** 测试方法 */public void action() {// 数组越界、数组空指针异常//鼠标适配器MouseAdapter ma = new MouseAdapter() {/**重写鼠标的移动事件*/public void mouseMoved(MouseEvent e){int x = e.getX();int y = e.getY();hero.movedTo(x, y);}/**重写鼠标的点击事件*/@Overridepublic void mouseClicked(MouseEvent e) {//根据当前状态的不同,进行相应的处理switch (state) {case START:state = RUNNING;break;case GAME_OVER:score = 0;sky = new Sky();hero = new Hero();flys = new FlyingObject[0];bullets = new Bullet[0];state = START;//修改状态为开始状态break;}}/**重写鼠标的移入事件*/@Overridepublic void mouseEntered(MouseEvent e) {if (state == PAUSE) {state = RUNNING;}}/**重写鼠标的移出事件*/@Overridepublic void mouseExited(MouseEvent e) {if (state == RUNNING) {state = PAUSE;}}};this.addMouseListener(ma);//处理鼠标的操作事件this.addMouseMotionListener(ma);//处理鼠标的移动事件// 定时器对象Timer timer = new Timer();int inters = 10;timer.schedule(new TimerTask() {@Overridepublic void run() {if (state == RUNNING) {enterAction();// 敌人入场shootAction();// 子弹入场stepAction();// 飞行物移动outOfBoundsAction();//删除越界的飞行物bulletBangAction();//子弹与敌人的碰撞heroBangAction();//英雄机与敌人发生碰撞checkGameOverAction();//检测游戏是都结束}repaint();// 重绘,调用paint方法}}, inters, inters);// 计划任务/* * 7.30 20 第一次 10 第一次---第二次 */}/** 画对象 */@Overridepublic void paint(Graphics g) {super.paint(g);sky.paintObject(g);hero.paintObject(g);// 画敌人for (int i = 0; i < flys.length; i++) {flys[i].paintObject(g);}for (int i = 0; i < bullets.length; i++) {bullets[i].paintObject(g);}g.drawString("分数:" + score, 30, 60);g.drawString("生命:" + hero.getLife(), 30, 80);switch (state) {//根据不同状态画不同的状态图case START://开始状态的启动图g.drawImage(start, 0, 0, null);break;case PAUSE://暂停状态的图g.drawImage(pause, 0, 0, null);break;case GAME_OVER://游戏结束的时候状态图g.drawImage(gameover, 0, 0, null);break;}}/** 主函数:程序的入口 */public static void main(String[] args) {ShootMain sm = new ShootMain();JFrame jf = new JFrame();jf.add(sm);// 将画布装在窗体上jf.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);// 窗体的大小jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setLocationRelativeTo(null);// 居中显示jf.setVisible(true);sm.action();}}
改进思路
- 增加敌机被击中后的爆炸动画效果
- 抽象类实例化不同的敌机类,得分也设置为不同
- 设置奖励系统
- 设置生命系统和等级闯关系统,达到一定分数后增加难度
- 提供界面使玩家自选难度
如有问题,希望各位大佬指正!