【Java】Java小游戏之Shoot游戏源码及详解

来源:互联网 发布:无线网络控制软件 编辑:程序博客网 时间:2024/06/06 12:47

【Java】Java小游戏之Shoot游戏源码及详解


Shoot游戏是模仿微信中打飞机小游戏,这个游戏虽然简单,但通过这个游戏小项目,可以练习很多小的知识点,提高对面向对象的理解,还能提高逻辑思维能力。总之,好处多多,下面我将对游戏的结构及代码进行详细说明:

游戏运行状态界面:

1)游戏中类的结构图:

2)游戏步骤01:

1.class FlyingObject{    image,width,height,x,y  }2.interface Enemy{    int getScore();  }3.interface Award{    DOUBLE_FILE,LIFE    int getType();  }4.class Airplane extends 1 implements 2{    speed    Airplane(){}    重写getScore()  }5.class Bee extends 1 implements 3{    xSpeed,ySpeed,awardType    Bee(){}    重写getType()  }6.class Bullet extends 1{    speed    Bullet(int x,int y){}  }7.class Hero extends 1{    life,doubleFire,images,index    Hero(){}  }8.class ShootGame extends JPanel{    WIDTH,HEIGHT    background,start,pause,gameover    airplane,bee,bullet,hero0,hero1    hero(Hero)    flyings(FlyingObject[])    bullets(Bullet[])    ShootGame(){初始化对象}    static{}    重写paint(g){       画背景图       paintHero(g);       paintFlyingObjects(g);       paintBullets(g);    }    paintHero(g){} //画英雄机    paintFlyingObjects(g){} //画敌人    paintBullets(g){} //画子弹    main(){      ...      frame.setVisible(true);    }  }

3)游戏步骤02:

1.敌人入场的实现步骤:  1)main(){ game.action(); }  2)action(){      ...      run(){ //10毫秒定时执行        enteredAction(); //敌人入场repaint();      }    }  3)int index = 0;    enteredAction(){ //10毫秒      index++;      if(index%40==0){  //40*10毫秒        FlyingObject one = nextOne(); //创建一个敌人对象        flyings = Arrays.copyOf(flyings,flyings.length+1); //扩容        flyings[flyings.length-1] = one; //将敌人对象添加到敌人数组中      }    }  4)nextOne(){      生成0到19间的随机数      为0时return new Bee();      否则return new Airplane();    }2.飞行物走一步的实现步骤:  1)FlyingObject----抽象方法step();  2)Airplane,Bee,Bullet,Hero---重写step()  3)action(){      run(){        enterAction();stepAction();repaint(); //重画      }    }  4)stepAction(){      遍历所有敌人,调用step()      遍历所有子弹,调用step()      hero.step();    }3.子弹入场的实现步骤:  1)Hero---shoot()英雄机发射子弹  2)action(){      run(){        ...shootAction(); //发射子弹repaint();      }    }  3)int shootIndex = 0;    shootAction(){ //10毫秒走一次      shootIndex++;      if(shootIndex%30==0){ //300毫秒        调用Hero的shoot()得到发射出的子弹数组bs将bullets扩容将bs追加到bullets数组中--System.arraycopy()      }    }4.英雄机随着鼠标移动的实现步骤:  1)Hero---moveTo(int x,int y)  2)action(){      MouseAdapter l = new MouseAdapter(){         重写MouseMoved(){   获取鼠标的x和y   hero.moveTo(x,y); //移动 }      };      this.addMouseMotionListener(l);      this.addMouseListener(l);      run(){        ...      }    }5.子弹和敌人碰撞的实现步骤:  1)FlyingObject---shootBy(Bullet b)  2)Hero----addDoubleFire(),addLife()  3)action(){      run(){        ...bangAction(); //检查碰撞repaint();      }    }  4)bangAction(){      遍历所有子弹,将子弹传给bang()方法    }  5)bang(Bullet b){ //1发子弹与所有敌人撞      遍历所有敌人,获取每一个敌人f      判断f是否与b撞上了      若撞上了:        5.1)得分或得奖励      5.1.1)得到被撞敌人对象      5.1.2)判断是敌人还是奖励             若是敌人则增分     若是奖励则得奖励类型       判断不同的奖励类型:         增命或增火力值5.2)将被撞对象从flyings中删除    5.2.1)将被撞敌人与最后一个元素交换(追尾并绕圈)    5.2.2)缩容---删除最后一个元素(被撞的对象)    }

4)游戏步骤03:

1.画分和画命的实现步骤:  1)hero---getLife()获取命  2)paint(g){      ......      paintScore(g); //画分和命    }  3)paintScore(g){      设置颜色g.setColor(...)      设置字体g.setFont(...)      画分g.drawString(...);      画命g.drawString(...);    }2.删除越界的敌人和子弹的实现步骤:  1)FlyingObject----abstract outOfBounds();  2)Airplane,bee,bullet,Hero--重写outOfBounds()  3)action(){      run(){        ...outOfBoundsAction(); //删除越界的repaint();      }    }  4)outOfBoundsAction(){      1)声明活着的数组      2)遍历flyings/bullets数组        判断对象是否不越界:        若true:          将对象添加到活着的数组中      3)将活着的数组复制到flyings/bullets数组中    }3.英雄机与敌人碰撞、游戏结束检查的实现步骤:  1)Hero---boolean hit(FlyingObject other);  2)Hero---substractLife()                 setDoubleFire(int doubleFire)  3)action(){      重写run(){        ...checkGameOverAction(); //检测英雄机与敌人撞repaint();      }    }  4)checkGameOverAction(){      if(isGameOver()){      }    }  5)isGameOver(){ //检测游戏是否结束      遍历所有敌人,获取每一个敌人f      判断hero.hit(f){        减命火力值清零删除被撞的敌人(交换,缩容)      }      return hero.getLife()<=0;    }4.画状态的实现步骤:  1)START,RUNNING,PAUSE,GAME_OVER     state=0(存储当前状态)  2)paint(){      ...      paintState(g);    }  3)paintState(g){      START状态--贴start图      PAUSE状态--贴pause图      GAME_OVER状态--贴gameover图    }  4)run(){      if(state==RUNNING){        一堆action();      }      repaint();    }  5)mouseMoved(){      if(state== RUNNING){        获取x,y,调英雄机移动方法      }    }  6)重写mouseClicked(){      若为启动状态,则改为运行状态      若为游戏结束状态,则:        清理现场(hero,flyings,bullets,score)        改为启动状态    }  7)checkGameOverAction(){      if(isGameOver()){        state = GAME_OVER;      }    }  8)重写mouseExited(){      if(state == RUNNING){        state = PAUSE;      }    }  9)重写mouseEntered(){      if(state == PAUSE){        state = RUNNING;      }    }

5)类的作用及源码:

FlyingObject类:

package shootgame;import java.awt.image.BufferedImage;/** * 飞行物类 * @author long * */public abstract class FlyingObject {protected BufferedImage image; //图片protected int x; //x坐标protected int y; //y坐标protected int width; //图片宽度protected int height; //图片高度public abstract void step(); //走步方法public abstract boolean outOfBounds();public boolean shootBy(Bullet b){int x1 = this.x - b.width;int x2 = this.x + this.width;int y1 = this.y;int y2 = this.y + this.height;int x = b.x;int y = b.y;return (x>x1&&x<x2)&&(y>y1&&y<y2);}}

Award接口:

package shootgame;/** * 奖励接口 * @author long * */public interface Award {public int LIFE = 0; //命public int DOUBLE_FIRE = 1; //双倍火力public int getType(); //获取奖励类型}


Enemy接口:

package shootgame;/** * 敌机接口 * @author long * */public interface Enemy {public int getScore(); //得分}

Constant类:

package shootgame;import java.awt.image.BufferedImage;import java.io.IOException;import javax.imageio.ImageIO;/** * 常量类 * @author long * */public class Constant {public static final int WIDTH = 400;public static final int HEIGHT = 650;public static BufferedImage background;public static BufferedImage start;public static BufferedImage pause;public static BufferedImage gameover;public static BufferedImage airplane;public static BufferedImage bee;public static BufferedImage bullet;public static BufferedImage hero0;public static BufferedImage hero1;public static final int START = 0;public static final int PAUSE = 1;public static final int RUNNING = 2;public static final int GAME_OVER = 3;static {try {background=ImageIO.read(Constant.class.getResource("background.png"));start=ImageIO.read(Constant.class.getResource("start.png"));pause=ImageIO.read(Constant.class.getResource("pause.png"));gameover=ImageIO.read(Constant.class.getResource("gameover.png"));airplane=ImageIO.read(Constant.class.getResource("airplane.png"));bee=ImageIO.read(Constant.class.getResource("bee.png"));bullet=ImageIO.read(Constant.class.getResource("bullet.png"));hero0=ImageIO.read(Constant.class.getResource("hero0.png"));hero1=ImageIO.read(Constant.class.getResource("hero1.png"));} catch (IOException e) {System.out.println("图片加载异常");e.printStackTrace();}}}

Airplane类:

package shootgame;import java.util.Random;/** * 敌机类 * @author long * */public class Airplane extends FlyingObject implements Enemy{private int speed = 3; //飞行速度public Airplane(){this.image = Constant.airplane;this.width = image.getWidth();this.height = image.getHeight();this.y = -height;Random rand = new Random();this.x = rand.nextInt(Constant.WIDTH-this.width);rand = null;}/** * 打掉一个敌机获得的分数 */public int getScore(){return 5;}/** * 重写走步方法 * 向下走一步 */public void step(){y += speed;}/** * 重写边界检测方法 * 当敌机到最小面的时候越界 */public boolean outOfBounds(){return y>Constant.HEIGHT;}}

Bee类:

package shootgame;import java.util.Random;/** * 小蜜蜂类 * @author long * */public class Bee extends FlyingObject implements Award{private int xSpeed = 2; //水平方向移动速度private int ySpeed = 3; //垂直方向移动速度private int awardType; //奖励类型public Bee(){this.image = Constant.bee;this.width = image.getWidth();this.height = image.getHeight();this.y = -height;Random rand = new Random();this.x = rand.nextInt(Constant.WIDTH-this.width);this.awardType = rand.nextInt(2);rand = null;}/** * 打死一只小蜜蜂可以获取的奖励类型 * 生命或值双倍子弹 */public int getType(){return awardType;}/** * 重写走步方法 * 小蜜蜂可以左右走 * 到最左边或者最右边的时候转向 */public void step(){x += xSpeed;y += ySpeed;if(x>Constant.WIDTH-this.width){xSpeed = -1;}if(x<0){xSpeed = 1;}}/** * 小蜜蜂边界检测 */public boolean outOfBounds(){return y>Constant.HEIGHT;}}

Bullet类:

package shootgame;import java.util.Random;/** * 子弹类 * @author long * */public class Bullet extends FlyingObject{private int speed = 5; //子弹的速度public Bullet(int x,int y){this.image = Constant.bullet;this.width = image.getWidth();this.height = image.getHeight();this.x = x;this.y = y;}/** * 重写step方法 * 子弹向上走步 */public void step(){y -= speed;}/** * 子弹边界检测 * 当子弹到最上边的时候越界 */public boolean outOfBounds(){return y<-this.width;}}

Hero类:

package shootgame;import java.awt.image.BufferedImage;/** * 英雄机类 * @author long * */public class Hero extends FlyingObject{BufferedImage[] images; //图片数组private int index; //图片数组索引private int life; //命private int doubleFire; //双倍火力public Hero(){this.image = Constant.hero0;this.width = image.getWidth();this.height = image.getHeight();this.x = 150;this.y = 400;this.life = 3;this.doubleFire = 20;this.index = 0;this.images = new BufferedImage[]{Constant.hero0,Constant.hero1};}/** * 获取生命值 * @return */public int getLife() {return life;}/** * 增加一条命 */public void addLife(){life++;}/** * 减一条命 */public void substractLife(){life--;}/** * 设置双倍火力 * @param doubleFire */public void setDoubleFire(int doubleFire) {this.doubleFire = doubleFire;}public void addDoubleFire(){doubleFire += 40;}/** * 重写走步方法 * 英雄机走步即切换图片,实现动画效果 */public void step(){image = images[index++/10%images.length];}/** * 英雄机射出子弹 * @return */public Bullet[] shoot(){Bullet[] b;int temp = this.width/4;if(doubleFire>0){b = new Bullet[2];b[0] = new Bullet(this.x+1*temp-1,this.y-10);b[1] = new Bullet(this.x+3*temp-1,this.y-10);doubleFire -= 2;}else{b = new Bullet[1];b[0] = new Bullet(this.x+2*temp-1,this.y-10);}return b;}/** * 英雄机随鼠标移动方法 * @param x * @param y */public void move(int x,int y){this.x = x-this.width/2;this.y = y-this.height/2;}/** * 英雄机永不越界 */public boolean outOfBounds(){return false;}public boolean hit(FlyingObject f){int x1 = f.x-this.width/2;int x2 = f.x+f.width+this.width/2;int y1 = f.y-this.height/2;int y2 = f.y+f.height+this.height/2;int x = this.x+this.width/2;int y = this.y+this.height/2;return (x>x1&&x<x2)&&(y>y1&&y<y2);}}

ShootGame类:

package shootgame;import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;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 long * */public class ShootGame extends JPanel{private FlyingObject[] flyings = {}; //飞行物数组private Bullet[] bullets = {}; //子弹数组private Hero hero = new Hero(); //英雄机private int score = 0; //得分private int state = 0; //游戏状态/** * 重写paint方法 */@Overridepublic void paint(Graphics g) {g.drawImage(Constant.background,0,0,null);paintHero(g);paintFlyings(g);paintBullets(g);paintScore(g);paintState(g);}/** * 画游戏的开始、运行、暂停、结束四中状态 * @param g */public void paintState(Graphics g){switch (state) {case Constant.START:g.drawImage(Constant.start,0,0,null);break;case Constant.PAUSE:g.drawImage(Constant.pause,0,0,null);break;case Constant.GAME_OVER:g.drawImage(Constant.gameover,0,0,null);break;default:break;}}/** * 画分数和命 * @param g */public void paintScore(Graphics g){Color c = g.getColor();g.setColor(new Color(0x8A2BE2));g.setFont(new Font(Font.SANS_SERIF,Font.BOLD,20));g.drawString("SCORE:"+score,10,25);g.drawString("LIFE:"+hero.getLife(),10,50);g.setColor(c);}/** * 画英雄机 * @param g */private void paintHero(Graphics g) {g.drawImage(hero.image,hero.x,hero.y,null);}/** * 画飞行物 * @param g */private void paintFlyings(Graphics g) {for(int i=0;i<flyings.length;i++){FlyingObject f = flyings[i];g.drawImage(f.image,f.x,f.y,null);}}/** * 画子弹 * @param g */private void paintBullets(Graphics g) {for(int i=0;i<bullets.length;i++){Bullet b = bullets[i];g.drawImage(b.image,b.x,b.y,null);}}/** * 飞行物入场方法 * 每隔400ms入场一次 */private int enterIndex = 0;public void enterAction(){enterIndex ++;if(enterIndex%40==0){FlyingObject f = nextOne();flyings=Arrays.copyOf(flyings,flyings.length+1);flyings[flyings.length-1] = f;}}/** * 飞行物、子弹、英雄机走步方法 */public void stepAction(){hero.step();for(int i=0;i<flyings.length;i++){flyings[i].step();}for(int j=0;j<bullets.length;j++){bullets[j].step();}}/** * 子弹入场方法 * 子弹由英雄机射出 * 每隔300ms射击一次 */private int shootIndex = 0;public void shootAction(){shootIndex ++;if(shootIndex%30==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 outOfBoundsAction(){int index = 0;FlyingObject[] flyingLives = new FlyingObject[flyings.length];for(int i=0;i<flyings.length;i++){FlyingObject f = flyings[i];if(!f.outOfBounds()){flyingLives[index++] = f;}}flyings = Arrays.copyOf(flyingLives,index);index = 0;Bullet[] bs = new Bullet[bullets.length];for(int i=0;i<bullets.length;i++){Bullet b = bullets[i];if(!b.outOfBounds()){bs[index++] = b;}}bullets = Arrays.copyOf(bs,index);//System.out.println(flyings.length+"--"+bullets.length);}/** * 检测子弹是否击中敌人 */public void bangAction(){for(int i=0;i<bullets.length;i++){bang(bullets[i],i);}}/** * 一颗子弹与所有敌人检测 * @param b * @param num 子弹下标 */public void bang(Bullet b,int num){int index = -1;for(int i=0;i<flyings.length;i++){FlyingObject f = flyings[i];if(f.shootBy(b)){index = i;bullets[num] = bullets[bullets.length-1];bullets = Arrays.copyOf(bullets,bullets.length-1);break;}}if(index!=-1){FlyingObject one = flyings[index];if(one instanceof Enemy){Enemy e = (Enemy)one;score += e.getScore();}if(one instanceof Award){Award a = (Award)one;int type = a.getType();switch (type) {case Award.LIFE:hero.addLife();break;case Award.DOUBLE_FIRE:hero.addDoubleFire();break;default:break;}}flyings[index] = flyings[flyings.length-1];flyings=Arrays.copyOf(flyings, flyings.length-1);}}/** * 检测游戏是否结束 */public void checkGameOver(){if(isGameOVer()){state = Constant.GAME_OVER;}}/** * 检测英雄机是否与敌机碰撞 * 一但碰撞,减命、双倍火力清零 */public boolean isGameOVer(){for(int i=0;i<flyings.length;i++){FlyingObject f = flyings[i];if(hero.hit(f)){hero.substractLife();hero.setDoubleFire(0);flyings[i] = flyings[flyings.length-1];flyings=Arrays.copyOf(flyings, flyings.length-1);}if(hero.getLife()<0){break;}}return hero.getLife()<=0;}/** * 游戏启动方法 */private int interval = 10;Timer timer;public void action(){MouseAdapter l = new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {if(state==Constant.START){ //游戏开始state = Constant.RUNNING;}if(state==Constant.GAME_OVER){ //清理战场hero = new Hero();flyings = new FlyingObject[0];bullets = new Bullet[0];score = 0;state = Constant.START;}}@Overridepublic void mouseEntered(MouseEvent e) {if(state==Constant.PAUSE){ //state = Constant.RUNNING;}}@Overridepublic void mouseExited(MouseEvent e) {if(state==Constant.RUNNING){state=Constant.PAUSE;}}@Overridepublic void mouseMoved(MouseEvent e) {if(state ==Constant.RUNNING){int x = e.getX();int y = e.getY();hero.move(x,y);}}};this.addMouseListener(l);this.addMouseMotionListener(l);timer = new Timer();timer.schedule(new TimerTask(){public void run() {if(state ==Constant.RUNNING){enterAction(); //飞行物入场stepAction(); //飞行物走步shootAction(); //子弹射入唱outOfBoundsAction(); //越界检测bangAction(); //子弹射击飞行物checkGameOver(); //检查游戏是否结束}repaint();}}, interval,interval);}public static void main(String[] args) {JFrame frame = new JFrame("Fly");ShootGame game = new ShootGame();frame.add(game);frame.setSize(Constant.WIDTH,Constant.HEIGHT);frame.setLocationRelativeTo(null);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);game.action();}/** * 工厂方法: * 用于产生一个敌机或者小蜜蜂 * @return */public static FlyingObject nextOne(){Random rand = new Random();int type = rand.nextInt(20);if(type<2){return new Bee();}else{return new Airplane();}}}

注:每个类的作用及每个方法的作用都已在注释中详细说明。



1 0
原创粉丝点击