java打飞机游戏完整代码

写在前面

技术源于分享,所以今天抽空把自己之前用java做过的小游戏整理贴出来给大家参考学习。java确实不适合写桌面应用,这里只是通过这个游戏让大家理解oop面向对象编程的过程,纯属娱乐。代码写的很简单,也很容易理解,并且注释写的很清楚了,还有问题,自己私下去补课学习。

完整代码

敌飞机

  1. import java.util.Random;

  2. 敌飞机: 是飞行物,也是敌人

  3. public class Airplane extends FlyingObject implements Enemy {

  4. private int speed = 3; //移动步骤

  5. /** 初始化数据 */

  6. public Airplane(){

  7. this.image = ShootGame.airplane;

  8. width = image.getWidth();

  9. height = image.getHeight();

  10. y = -height;

  11. Random rand = new Random();

  12. x = rand.nextInt(ShootGame.WIDTH - width);

  13. }

  14. /** 获取分数 */

  15. @Override

  16. public int getScore() {

  17. return 5;

  18. }

  19. /** //越界处理 */

  20. @Override

  21. public boolean outOfBounds() {

  22. return y>ShootGame.HEIGHT;

  23. }

  24. /** 移动 */

  25. @Override

  26. public void step() {

  27. y += speed;

  28. }

  29. }

分数奖励

  1. /**

  2. * 奖励

  3. */

  4. public interface Award {

  5. int DOUBLE_FIRE = 0; //双倍火力

  6. int LIFE = 1; //1条命

  7. /** 获得奖励类型(上面的0或1) */

  8. int getType();

  9. }

蜜蜂

  1. import java.util.Random;

  2. /** 蜜蜂 */

  3. public class Bee extends FlyingObject implements Award{

  4. private int xSpeed = 1; //x坐标移动速度

  5. private int ySpeed = 2; //y坐标移动速度

  6. private int awardType; //奖励类型

  7. /** 初始化数据 */

  8. public Bee(){

  9. this.image = ShootGame.bee;

  10. width = image.getWidth();

  11. height = image.getHeight();

  12. y = -height;

  13. Random rand = new Random();

  14. x = rand.nextInt(ShootGame.WIDTH - width);

  15. awardType = rand.nextInt(2); //初始化时给奖励

  16. }

  17. /** 获得奖励类型 */

  18. public int getType(){

  19. return awardType;

  20. }

  21. /** 越界处理 */

  22. @Override

  23. public boolean outOfBounds() {

  24. return y>ShootGame.HEIGHT;

  25. }

  26. /** 移动,可斜着飞 */

  27. @Override

  28. public void step() {

  29. x += xSpeed;

  30. y += ySpeed;

  31. if(x > ShootGame.WIDTH-width){

  32. xSpeed = -1;

  33. }

  34. if(x < 0){

  35. xSpeed = 1;

  36. }

  37. }

  38. }

子弹类:是飞行物体

  1. /**

  2. * 子弹类:是飞行物

  3. */

  4. public class Bullet extends FlyingObject {

  5. private int speed = 3; //移动的速度

  6. /** 初始化数据 */

  7. public Bullet(int x,int y){

  8. this.x = x;

  9. this.y = y;

  10. this.image = ShootGame.bullet;

  11. }

  12. /** 移动 */

  13. @Override

  14. public void step(){

  15. y-=speed;

  16. }

  17. /** 越界处理 */

  18. @Override

  19. public boolean outOfBounds() {

  20. return y<-height;

  21. }

  22. }

敌人的分数

  1. /**

  2. * 敌人,可以有分数

  3. */

  4. public interface Enemy {

  5. /** 敌人的分数 */

  6. int getScore();

  7. }

飞行物(敌机,蜜蜂,子弹,英雄机)

  1. import java.awt.image.BufferedImage;

  2. /**

  3. * 飞行物(敌机,蜜蜂,子弹,英雄机)

  4. */

  5. public abstract class FlyingObject {

  6. protected int x; //x坐标

  7. protected int y; //y坐标

  8. protected int width; //宽

  9. protected int height; //高

  10. protected BufferedImage image; //图片

  11. public int getX() {

  12. return x;

  13. }

  14. public void setX(int x) {

  15. this.x = x;

  16. }

  17. public int getY() {

  18. return y;

  19. }

  20. public void setY(int y) {

  21. this.y = y;

  22. }

  23. public int getWidth() {

  24. return width;

  25. }

  26. public void setWidth(int width) {

  27. this.width = width;

  28. }

  29. public int getHeight() {

  30. return height;

  31. }

  32. public void setHeight(int height) {

  33. this.height = height;

  34. }

  35. public BufferedImage getImage() {

  36. return image;

  37. }

  38. public void setImage(BufferedImage image) {

  39. this.image = image;

  40. }

  41. /**

  42. * 检查是否出界

  43. * @return true 出界与否

  44. */

  45. public abstract boolean outOfBounds();

  46. /**

  47. * 飞行物移动一步

  48. */

  49. public abstract void step();

  50. /**

  51. * 检查当前飞行物体是否被子弹(x,y)击(shoot)中

  52. * @param Bullet 子弹对象

  53. * @return true表示被击中了

  54. */

  55. public boolean shootBy(Bullet bullet){

  56. int x = bullet.x; //子弹横坐标

  57. int y = bullet.y; //子弹纵坐标

  58. return this.x<x && x<this.x+width && this.y<y && y<this.y+height;

  59. }

  60. }

英雄机

  1. import java.awt.image.BufferedImage;

  2. /**

  3. * 英雄机:是飞行物

  4. */

  5. public class Hero extends FlyingObject{

  6. private BufferedImage[] images = {}; //英雄机图片

  7. private int index = 0; //英雄机图片切换索引

  8. private int doubleFire; //双倍火力

  9. private int life; //命

  10. /** 初始化数据 */

  11. public Hero(){

  12. life = 3; //初始3条命

  13. doubleFire = 0; //初始火力为0

  14. images = new BufferedImage[]{ShootGame.hero0, ShootGame.hero1}; //英雄机图片数组

  15. image = ShootGame.hero0; //初始为hero0图片

  16. width = image.getWidth();

  17. height = image.getHeight();

  18. x = 150;

  19. y = 400;

  20. }

  21. /** 获取双倍火力 */

  22. public int isDoubleFire() {

  23. return doubleFire;

  24. }

  25. /** 设置双倍火力 */

  26. public void setDoubleFire(int doubleFire) {

  27. this.doubleFire = doubleFire;

  28. }

  29. /** 增加火力 */

  30. public void addDoubleFire(){

  31. doubleFire = 40;

  32. }

  33. /** 增命 */

  34. public void addLife(){ //增命

  35. life++;

  36. }

  37. /** 减命 */

  38. public void subtractLife(){ //减命

  39. life--;

  40. }

  41. /** 获取命 */

  42. public int getLife(){

  43. return life;

  44. }

  45. /** 当前物体移动了一下,相对距离,x,y鼠标位置 */

  46. public void moveTo(int x,int y){

  47. this.x = x - width/2;

  48. this.y = y - height/2;

  49. }

  50. /** 越界处理 */

  51. @Override

  52. public boolean outOfBounds() {

  53. return false;

  54. }

  55. /** 发射子弹 */

  56. public Bullet[] shoot(){

  57. int xStep = width/4; //4半

  58. int yStep = 20; //步

  59. if(doubleFire>0){ //双倍火力

  60. Bullet[] bullets = new Bullet[2];

  61. bullets[0] = new Bullet(x+xStep,y-yStep); //y-yStep(子弹距飞机的位置)

  62. bullets[1] = new Bullet(x+3*xStep,y-yStep);

  63. return bullets;

  64. }else{ //单倍火力

  65. Bullet[] bullets = new Bullet[1];

  66. bullets[0] = new Bullet(x+2*xStep,y-yStep);

  67. return bullets;

  68. }

  69. }

  70. /** 移动 */

  71. @Override

  72. public void step() {

  73. if(images.length>0){

  74. image = images[index++/10%images.length]; //切换图片hero0,hero1

  75. }

  76. }

  77. /** 碰撞算法 */

  78. public boolean hit(FlyingObject other){

  79. int x1 = other.x - this.width/2; //x坐标最小距离

  80. int x2 = other.x + this.width/2 + other.width; //x坐标最大距离

  81. int y1 = other.y - this.height/2; //y坐标最小距离

  82. int y2 = other.y + this.height/2 + other.height; //y坐标最大距离

  83. int herox = this.x + this.width/2; //英雄机x坐标中心点距离

  84. int heroy = this.y + this.height/2; //英雄机y坐标中心点距离

  85. return herox>x1 && herox<x2 && heroy>y1 && heroy<y2; //区间范围内为撞上了

  86. }

  87. }

游戏启动主类

  1. import java.awt.Font;

  2. import java.awt.Color;

  3. import java.awt.Graphics;

  4. import java.awt.event.MouseAdapter;

  5. import java.awt.event.MouseEvent;

  6. import java.util.Arrays;

  7. import java.util.Random;

  8. import java.util.Timer;

  9. import java.util.TimerTask;

  10. import java.awt.image.BufferedImage;

  11. import javax.imageio.ImageIO;

  12. import javax.swing.ImageIcon;

  13. import javax.swing.JFrame;

  14. import javax.swing.JPanel;

  15. /**

  16. *

  17. */

  18. public class ShootGame extends JPanel {

  19. public static final int WIDTH = 400; // 面板宽

  20. public static final int HEIGHT = 654; // 面板高

  21. /** 游戏的当前状态: START RUNNING PAUSE GAME_OVER */

  22. private int state;

  23. private static final int START = 0;

  24. private static final int RUNNING = 1;

  25. private static final int PAUSE = 2;

  26. private static final int GAME_OVER = 3;

  27. private int score = 0; // 得分

  28. private Timer timer; // 定时器

  29. private int intervel = 1000 / 100; // 时间间隔(毫秒)

  30. public static BufferedImage background;

  31. public static BufferedImage start;

  32. public static BufferedImage airplane;

  33. public static BufferedImage bee;

  34. public static BufferedImage bullet;

  35. public static BufferedImage hero0;

  36. public static BufferedImage hero1;

  37. public static BufferedImage pause;

  38. public static BufferedImage gameover;

  39. private FlyingObject[] flyings = {}; // 敌机数组

  40. private Bullet[] bullets = {}; // 子弹数组

  41. private Hero hero = new Hero(); // 英雄机

  42. static { // 静态代码块,初始化图片资源

  43. try {

  44. background = ImageIO.read(ShootGame.class

  45. .getResource("background.png"));

  46. start = ImageIO.read(ShootGame.class.getResource("start.png"));

  47. airplane = ImageIO

  48. .read(ShootGame.class.getResource("airplane.png"));

  49. bee = ImageIO.read(ShootGame.class.getResource("bee.png"));

  50. bullet = ImageIO.read(ShootGame.class.getResource("bullet.png"));

  51. hero0 = ImageIO.read(ShootGame.class.getResource("hero0.png"));

  52. hero1 = ImageIO.read(ShootGame.class.getResource("hero1.png"));

  53. pause = ImageIO.read(ShootGame.class.getResource("pause.png"));

  54. gameover = ImageIO

  55. .read(ShootGame.class.getResource("gameover.png"));

  56. } catch (Exception e) {

  57. e.printStackTrace();

  58. }

  59. }

  60. /** 画 */

  61. @Override

  62. public void paint(Graphics g) {

  63. g.drawImage(background, 0, 0, null); // 画背景图

  64. paintHero(g); // 画英雄机

  65. paintBullets(g); // 画子弹

  66. paintFlyingObjects(g); // 画飞行物

  67. paintScore(g); // 画分数

  68. paintState(g); // 画游戏状态

  69. }

  70. /** 画英雄机 */

  71. public void paintHero(Graphics g) {

  72. g.drawImage(hero.getImage(), hero.getX(), hero.getY(), null);

  73. }

  74. /** 画子弹 */

  75. public void paintBullets(Graphics g) {

  76. for (int i = 0; i < bullets.length; i++) {

  77. Bullet b = bullets[i];

  78. g.drawImage(b.getImage(), b.getX() - b.getWidth() / 2, b.getY(),

  79. null);

  80. }

  81. }

  82. /** 画飞行物 */

  83. public void paintFlyingObjects(Graphics g) {

  84. for (int i = 0; i < flyings.length; i++) {

  85. FlyingObject f = flyings[i];

  86. g.drawImage(f.getImage(), f.getX(), f.getY(), null);

  87. }

  88. }

  89. /** 画分数 */

  90. public void paintScore(Graphics g) {

  91. int x = 10; // x坐标

  92. int y = 25; // y坐标

  93. Font font = new Font(Font.SANS_SERIF, Font.BOLD, 22); // 字体

  94. g.setColor(new Color(0xFF0000));

  95. g.setFont(font); // 设置字体

  96. g.drawString("SCORE:" + score, x, y); // 画分数

  97. y=y+20; // y坐标增20

  98. g.drawString("LIFE:" + hero.getLife(), x, y); // 画命

  99. }

  100. /** 画游戏状态 */

  101. public void paintState(Graphics g) {

  102. switch (state) {

  103. case START: // 启动状态

  104. g.drawImage(start, 0, 0, null);

  105. break;

  106. case PAUSE: // 暂停状态

  107. g.drawImage(pause, 0, 0, null);

  108. break;

  109. case GAME_OVER: // 游戏终止状态

  110. g.drawImage(gameover, 0, 0, null);

  111. break;

  112. }

  113. }

  114. public static void main(String[] args) {

  115. JFrame frame = new JFrame("Fly");

  116. ShootGame game = new ShootGame(); // 面板对象

  117. frame.add(game); // 将面板添加到JFrame中

  118. frame.setSize(WIDTH, HEIGHT); // 设置大小

  119. frame.setAlwaysOnTop(true); // 设置其总在最上

  120. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 默认关闭操作

  121. frame.setIconImage(new ImageIcon("images/icon.jpg").getImage()); // 设置窗体的图标

  122. frame.setLocationRelativeTo(null); // 设置窗体初始位置

  123. frame.setVisible(true); // 尽快调用paint

  124. game.action(); // 启动执行

  125. }

  126. /** 启动执行代码 */

  127. public void action() {

  128. // 鼠标监听事件

  129. MouseAdapter l = new MouseAdapter() {

  130. @Override

  131. public void mouseMoved(MouseEvent e) { // 鼠标移动

  132. if (state == RUNNING) { // 运行状态下移动英雄机--随鼠标位置

  133. int x = e.getX();

  134. int y = e.getY();

  135. hero.moveTo(x, y);

  136. }

  137. }

  138. @Override

  139. public void mouseEntered(MouseEvent e) { // 鼠标进入

  140. if (state == PAUSE) { // 暂停状态下运行

  141. state = RUNNING;

  142. }

  143. }

  144. @Override

  145. public void mouseExited(MouseEvent e) { // 鼠标退出

  146. if (state == RUNNING) { // 游戏未结束,则设置其为暂停

  147. state = PAUSE;

  148. }

  149. }

  150. @Override

  151. public void mouseClicked(MouseEvent e) { // 鼠标点击

  152. switch (state) {

  153. case START:

  154. state = RUNNING; // 启动状态下运行

  155. break;

  156. case GAME_OVER: // 游戏结束,清理现场

  157. flyings = new FlyingObject[0]; // 清空飞行物

  158. bullets = new Bullet[0]; // 清空子弹

  159. hero = new Hero(); // 重新创建英雄机

  160. score = 0; // 清空成绩

  161. state = START; // 状态设置为启动

  162. break;

  163. }

  164. }

  165. };

  166. this.addMouseListener(l); // 处理鼠标点击操作

  167. this.addMouseMotionListener(l); // 处理鼠标滑动操作

  168. timer = new Timer(); // 主流程控制

  169. timer.schedule(new TimerTask() {

  170. @Override

  171. public void run() {

  172. if (state == RUNNING) { // 运行状态

  173. enterAction(); // 飞行物入场

  174. stepAction(); // 走一步

  175. shootAction(); // 英雄机射击

  176. bangAction(); // 子弹打飞行物

  177. outOfBoundsAction(); // 删除越界飞行物及子弹

  178. checkGameOverAction(); // 检查游戏结束

  179. }

  180. repaint(); // 重绘,调用paint()方法

  181. }

  182. }, intervel, intervel);

  183. }

  184. int flyEnteredIndex = 0; // 飞行物入场计数

  185. /** 飞行物入场 */

  186. public void enterAction() {

  187. flyEnteredIndex++;

  188. if (flyEnteredIndex % 40 == 0) { // 400毫秒生成一个飞行物--10*40

  189. FlyingObject obj = nextOne(); // 随机生成一个飞行物

  190. flyings = Arrays.copyOf(flyings, flyings.length + 1);

  191. flyings[flyings.length - 1] = obj;

  192. }

  193. }

  194. /** 走一步 */

  195. public void stepAction() {

  196. for (int i = 0; i < flyings.length; i++) { // 飞行物走一步

  197. FlyingObject f = flyings[i];

  198. f.step();

  199. }

  200. for (int i = 0; i < bullets.length; i++) { // 子弹走一步

  201. Bullet b = bullets[i];

  202. b.step();

  203. }

  204. hero.step(); // 英雄机走一步

  205. }

  206. /** 飞行物走一步 */

  207. public void flyingStepAction() {

  208. for (int i = 0; i < flyings.length; i++) {

  209. FlyingObject f = flyings[i];

  210. f.step();

  211. }

  212. }

  213. int shootIndex = 0; // 射击计数

  214. /** 射击 */

  215. public void shootAction() {

  216. shootIndex++;

  217. if (shootIndex % 30 == 0) { // 300毫秒发一颗

  218. Bullet[] bs = hero.shoot(); // 英雄打出子弹

  219. bullets = Arrays.copyOf(bullets, bullets.length + bs.length); // 扩容

  220. System.arraycopy(bs, 0, bullets, bullets.length - bs.length,

  221. bs.length); // 追加数组

  222. }

  223. }

  224. /** 子弹与飞行物碰撞检测 */

  225. public void bangAction() {

  226. for (int i = 0; i < bullets.length; i++) { // 遍历所有子弹

  227. Bullet b = bullets[i];

  228. bang(b); // 子弹和飞行物之间的碰撞检查

  229. }

  230. }

  231. /** 删除越界飞行物及子弹 */

  232. public void outOfBoundsAction() {

  233. int index = 0; // 索引

  234. FlyingObject[] flyingLives = new FlyingObject[flyings.length]; // 活着的飞行物

  235. for (int i = 0; i < flyings.length; i++) {

  236. FlyingObject f = flyings[i];

  237. if (!f.outOfBounds()) {

  238. flyingLives[index++] = f; // 不越界的留着

  239. }

  240. }

  241. flyings = Arrays.copyOf(flyingLives, index); // 将不越界的飞行物都留着

  242. index = 0; // 索引重置为0

  243. Bullet[] bulletLives = new Bullet[bullets.length];

  244. for (int i = 0; i < bullets.length; i++) {

  245. Bullet b = bullets[i];

  246. if (!b.outOfBounds()) {

  247. bulletLives[index++] = b;

  248. }

  249. }

  250. bullets = Arrays.copyOf(bulletLives, index); // 将不越界的子弹留着

  251. }

  252. /** 检查游戏结束 */

  253. public void checkGameOverAction() {

  254. if (isGameOver()==true) {

  255. state = GAME_OVER; // 改变状态

  256. }

  257. }

  258. /** 检查游戏是否结束 */

  259. public boolean isGameOver() {

  260. for (int i = 0; i < flyings.length; i++) {

  261. int index = -1;

  262. FlyingObject obj = flyings[i];

  263. if (hero.hit(obj)) { // 检查英雄机与飞行物是否碰撞

  264. hero.subtractLife(); // 减命

  265. hero.setDoubleFire(0); // 双倍火力解除

  266. index = i; // 记录碰上的飞行物索引

  267. }

  268. if (index != -1) {

  269. FlyingObject t = flyings[index];

  270. flyings[index] = flyings[flyings.length - 1];

  271. flyings[flyings.length - 1] = t; // 碰上的与最后一个飞行物交换

  272. flyings = Arrays.copyOf(flyings, flyings.length - 1); // 删除碰上的飞行物

  273. }

  274. }

  275. return hero.getLife() <= 0;

  276. }

  277. /** 子弹和飞行物之间的碰撞检查 */

  278. public void bang(Bullet bullet) {

  279. int index = -1; // 击中的飞行物索引

  280. for (int i = 0; i < flyings.length; i++) {

  281. FlyingObject obj = flyings[i];

  282. if (obj.shootBy(bullet)) { // 判断是否击中

  283. index = i; // 记录被击中的飞行物的索引

  284. break;

  285. }

  286. }

  287. if (index != -1) { // 有击中的飞行物

  288. FlyingObject one = flyings[index]; // 记录被击中的飞行物

  289. FlyingObject temp = flyings[index]; // 被击中的飞行物与最后一个飞行物交换

  290. flyings[index] = flyings[flyings.length - 1];

  291. flyings[flyings.length - 1] = temp;

  292. flyings = Arrays.copyOf(flyings, flyings.length - 1); // 删除最后一个飞行物(即被击中的)

  293. // 检查one的类型(敌人加分,奖励获取)

  294. if (one instanceof Enemy) { // 检查类型,是敌人,则加分

  295. Enemy e = (Enemy) one; // 强制类型转换

  296. score += e.getScore(); // 加分

  297. } else { // 若为奖励,设置奖励

  298. Award a = (Award) one;

  299. int type = a.getType(); // 获取奖励类型

  300. switch (type) {

  301. case Award.DOUBLE_FIRE:

  302. hero.addDoubleFire(); // 设置双倍火力

  303. break;

  304. case Award.LIFE:

  305. hero.addLife(); // 设置加命

  306. break;

  307. }

  308. }

  309. }

  310. }

  311. /**

  312. * 随机生成飞行物

  313. *

  314. * @return 飞行物对象

  315. */

  316. public static FlyingObject nextOne() {

  317. Random random = new Random();

  318. int type = random.nextInt(20); // [0,20)

  319. if (type < 4) {

  320. return new Bee();

  321. } else {

  322. return new Airplane();

  323. }

  324. }

  325. }

文章知识点与官方知识档案匹配,可进一步学习相关知识