游戏实现的功能:玩家通过鼠标操作飞机,飞机自动发射子弹,系统随机生成敌机,并且检测子弹是否与敌机相碰,英雄机是否与敌机相碰;英雄机是否死亡;系统随时更新分数,游戏结束时,提醒点击屏幕开始游戏
用到的知识点:
java swing
多线程
集合
java飞机大战编程思路:
编写游戏面板和窗体----------编写App工具类,用来读取照片-----------在面板中添加背景图---------
面板使用画图方法,画出图片------------------------------
编写FlyObject类,里面的成员变量代表的图片、宽度、高度、纵坐标、横坐标---------------
英雄机的创建与移动:
编写英雄机类继承FlyObject类,设置英雄机的初始位置和大小,血量--------------------
在面板中使用画图方法,画出英雄机,从而在面板中显示英雄机-------------------------
自定义moveToMouse方法,让英雄机跟着鼠标移动--------------窗体中添加鼠标监听器,并让英雄机注册监听器-------------
英雄机调用moveToMouse方法,实现英雄机随着鼠标移动的功能
敌机的创建与移动:
编写敌机类继承FlyObject类,设置敌机的大小,初始血量----------------------------
统一设置敌机的纵坐标为-h,横坐标通过rd.nextInt(1024-w)方法决定,从而让敌机随机出现---------------------------------
为不同的敌机设置不同的速度,使它们的下落速度不同
在面板中利用集合创建敌机的大本营,即:List<Ep>eps = new ArrayList<Ep>();-----------
在面板中使用画图方法,遍历整个大本营,画出敌机,显示敌机-----------------------------------
子弹与敌机相碰,英雄机与敌机相碰:
编写子弹类继承FlyObject类,设置子弹的大小-------------------
在面板中利用集合创建火药库,即:List<Fire>fs = new ArrayList<Fire>();
在构造方法中设置子弹与英雄机的坐标相同---------------
自定义move方法,固定子弹移动的速度、方向------------------在面板中使用画图方法,画出子弹,在面板中显示子弹----
设置初始发射一颗子弹,逐渐增加子弹,直到三颗子弹,并且每颗子弹移动的速度不同-------------------------------------
进行子弹与敌机的碰撞检测,碰撞检测公式为 boolean hit = (x<=f.x+f.w) && (x>=f.x-w)&& (y<=f.y+f.h) && (y>=f.y-h);
判断子弹是否与敌机相碰,若相碰,调用remove()方法,移除子弹,并且如果敌机的血量<=0,移除敌机----------------
利用类似的方法判断敌机是否与英雄机相碰,若相碰,移除敌机,并且英雄机的血量-1,当英雄机的血量<=0时,游戏结束
开始游戏:
设置初始分数为0,每击倒一个敌机,分数+10
设置布尔类型的变量gameover为false,作为游戏的开关,当gameover为true时,游戏结束
利用单线程,固定格式为public void action(){new Thread(){}.start();},在里面while循环,运行游戏
当英雄机死亡时,提示“游戏结束,点击屏幕重新开始”,调用mouseCliked(Event e)方法,监听鼠标点击,若鼠标点击,重新开始游戏
并且重新开始游戏时,随机更换背景
代码实现:
import java.awt.*;
import javax.swing.*;
import javax.imageio.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
//处理图片的工具类
public class App{
//读取指定位置上的图片
public static BufferedImage getImg(String path){
try{
BufferedImage img = ImageIO.read(App.class.getResource(path));
return img;
}
catch(IOException e){
e.printStackTrace();
}
return null;
}
}
import java.awt.image.*;
import java.util.Random;
import java.util.List;
import java.awt.*;
public class Ep extends FlyObject{
int speed;
int hp = 3;
int type;
public Ep(){
Random rd = new Random();
int index = rd.nextInt(12)+1;
type = index;//道具机
img = App.getImg("/Img/ep"+index+".PNG");
w = img.getWidth();
h = img.getHeight();
x = rd.nextInt(1024-w);
y = -h;
speed = 13 - index;
}
public void move(){
if(type==5){
y += speed/2;
x += 2;
}
else if(type==6){
y += speed/2;
x -= 2;
}
else{
y += speed;
}
}
public boolean shootBy(Fire f){
boolean hit = (x<=f.x+f.w) && (x>=f.x-w)
&& (y<=f.y+f.h) && (y>=f.y-h);
return hit;
}
public boolean hitBy(Hero hero){
boolean hit = (x<=hero.x+hero.w) && (x>=hero.x-w)
&& (y<=hero.y+hero.h) && (y>=hero.y-h);
return hit;
}
}
public class Fire extends FlyObject{
int dir;//子弹移动的方向
//dir=0 左上角
//dir=1 垂直上飞
//dir=2 右上角
public Fire(int hx, int hy, int dir){
img = App.getImg("/img/fire.PNG");
w = img.getWidth();
h = img.getHeight();
//确定子弹的位置
x = hx;
y = hy;
this.dir = dir;
}
public void move(){
if(dir==0){
y -= 10;
x -= 1;
}
else if(dir==1){
y -= 10;
}
else if(dir==2){
y -= 10;
x += 1;
}
}
}
import java.awt.image.*;
//在开发中,将相同的特点抽离出来形成父类,从而提高代码的复用性
public class FlyObject{
BufferedImage img;
int x;//横坐标
int y;//纵坐标
int w;//宽度
int h;//高度
}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.*;
public class GameFrame extends JFrame{
public GameFrame(){
setTitle("飞机大战");
setSize(1024, 768);//宽1024, 高768
//默认界面居中显示
setLocationRelativeTo(null);
//不允许玩家改变页面大小
setResizable(false);
//设置默认的关闭选项
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String args[]){
GameFrame frame = new GameFrame();
GamePanel panel = new GamePanel(frame);
panel.action();
frame.add(panel);//将面板添加到窗体中
frame.setVisible(true);
}
}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
public class GamePanel extends JPanel{
BufferedImage bg;//背景图
Hero hero = new Hero();
//Ep ep = new Ep();
List<Ep> eps = new ArrayList<Ep>();
List<Fire> fs = new ArrayList<Fire>();
//定义分数
int score = 0;
boolean gameover = false;
int power = 1;//英雄机的火力
public void action(){
//创建并启动一个线程,控制游戏场景中物体活动
new Thread(){
public void run(){
//写一个死循环
while(true){
if(!gameover){
epEnter();
epMove();
shoot();
fireMove();
shootEp();
hit();
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
repaint();
}
}
}
}.start();
}
protected void hit(){
for(int i=0;i<eps.size();i++){
Ep e = eps.get(i);
if(e.hitBy(hero)){
eps.remove(e);
hero.hp--;
score += 10;
power = 1;
if(hero.hp<=0){
gameover = true;
}
}
}
}
protected void shootEp(){
//遍历所有的子弹
for(int i=0;i<fs.size();i++){
Fire f = fs.get(i);
bang(f);
}
}
//判断子弹是否击中敌机
private void bang(Fire f){
//遍历所有的敌机
for(int i=0;i<eps.size();i++){
Ep e = eps.get(i);
//判断子弹是否击中敌机
if(e.shootBy(f)){
e.hp--;
if(e.hp<=0){
if(e.type==8){
power++;
if(power > 3){
hero.hp++;
power = 3;
if(hero.hp > 3){
hero.hp = 3;
}
}
}
eps.remove(e);
score += 10;
}
fs.remove(f);
}
}
}
protected void fireMove(){
for(int i=0;i<fs.size();i++){
Fire fire = fs.get(i);
fire.move();
}
}
int index1 = 0;
protected void shoot(){
index1 ++;
if(index1>=20){
if(power == 1){
Fire fire2 = new Fire(hero.x-20, hero.y-20, 1);
fs.add(fire2);
}else if(power == 2){
Fire fire1 = new Fire(hero.x-50, hero.y, 0);
fs.add(fire1);
Fire fire2 = new Fire(hero.x-20, hero.y-20, 1);
fs.add(fire2);
}else{
Fire fire1 = new Fire(hero.x-50, hero.y, 0);
fs.add(fire1);
Fire fire2 = new Fire(hero.x-20, hero.y-20, 1);
fs.add(fire2);
Fire fire3 = new Fire(hero.x+10, hero.y, 2);
fs.add(fire3);
}
index1 = 0;
}
}
protected void epMove(){
for(int i=0;i<eps.size();i++){
Ep e = eps.get(i);
e.move();
}
}
int index = 0;
protected void epEnter(){
index ++;
if(index>=20){
Ep e = new Ep();
eps.add(e);
index = 0;
}
}
public GamePanel(GameFrame frame){
//设置背景
setBackground(Color.green);
//初始化图片
bg = App.getImg("/Img/start.BMP");
//添加鼠标适配器
MouseAdapter adapter = new MouseAdapter(){
public void mouseClicked(MouseEvent e){
if(gameover){
//重新开始游戏
hero = new Hero();
gameover = false;
score = 0;
eps.clear();
fs.clear();
//随机背景图
Random rd = new Random();
int index = rd.nextInt(6)+1;
bg = App.getImg("/img/bg"+index+".BMP");
power = 1;
action();
}
}
public void mouseMoved(MouseEvent e){
int mx = e.getX();
int my = e.getY();
if(!gameover){
hero.moveToMouse(mx, my);
//刷新界面
repaint();
}
}
};
//将适配器加入到监听器(固定格式)
addMouseListener(adapter);
addMouseMotionListener(adapter);
//使用键盘监听器(固定格式)
KeyAdapter kd = new KeyAdapter(){
public void keyPressed(KeyEvent e){
int keyCode = e.getKeyCode();
if(!gameover){
if(keyCode == KeyEvent.VK_UP){
hero.moveUP();
}else if(keyCode == KeyEvent.VK_DOWN){
hero.moveDOWN();
}else if(keyCode == KeyEvent.VK_LEFT){
hero.moveLEFT();
}else if(keyCode == KeyEvent.VK_RIGHT){
hero.moveRIGHT();
}
repaint();
}
}
};
//将适配器加到窗体监听器中
frame.addKeyListener(kd);
}
//专用画图方法
//Graphics g 画笔
public void paint(Graphics g){
super.paint(g);
//画图片 g.drawImage(图片,横坐标,纵坐标,null)
g.drawImage(bg, 0, 0, 1024, 768, null);
g.drawImage(hero.img, hero.x, hero.y, hero.w, hero.h, null);
for(int i=0;i<eps.size();i++){
Ep ep = eps.get(i);
g.drawImage(ep.img, ep.x, ep.y, ep.w, ep.h, null);
}
for(int i=0;i<fs.size();i++){
Fire fire = fs.get(i);
g.drawImage(fire.img, fire.x, fire.y, fire.w, fire.h, null);
}
g.setColor(Color.white);
g.setFont(new Font("楷体", Font.BOLD, 20));
g.drawString("分数:"+score, 10, 30);
//画英雄机的血量
for(int i=0;i<hero.hp;i++){
g.drawImage(hero.img, 350+i*35, 5, 30, 30, null);
}
//游戏结束
if(gameover == true){
g.setColor(Color.black);
g.setFont(new Font("楷体", Font.BOLD, 35));
g.drawString("GAMEOVER! 菜鸡!鸡你太美", 20, 300);
g.setColor(Color.red);
g.setFont(new Font("楷体", Font.BOLD, 35));
g.drawString("点击屏幕重新开始游戏,沙雕", 40, 350);
}
}
}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.*;
public class Hero extends FlyObject{
int hp;
public Hero(){
img = App.getImg("/Img/me3.PNG");
x = 500; y = 500;
w = img.getWidth();
h = img.getHeight();
hp = 3;//英雄机有三条生命
}
public void moveToMouse(int mx, int my){
x = mx-w/2;
y = my-h/2;
}
public void moveUP(){
y = y - 10;
}
public void moveDOWN(){
y = y + 10;
}
public void moveLEFT(){
x = x - 10;
}
public void moveRIGHT(){
x = x + 10;
}
}