一、项目目录结构 二、关于游戏窗体和游戏面板这是一个Java小游戏,带背景音乐的飞机大战,简单易上手,一共九个代码段,具体代码和游戏制作如下:
Gameframe.Java
package ui; import javax.swing.Jframe; public class Gameframe extends Jframe { public Gameframe() { //设置标题 方法来源于Jframe类 setTitle("全民飞机大战"); //设置大小 setSize(宽度,高度); setSize(512,768); //设置位置居中显示 //快捷键:Alt+? 开启代码提示 //null相对于屏幕左上角居中 setLocationRelativeTo(null); //设置不允许玩家改变界面大小 setResizable(false); //设置默认的关闭选项 //关闭窗体的时候退出程序 setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); } public static void main(String arg[]) { //创建窗体对象:调用窗体的构造方法,制作窗体 Gameframe frame=new Gameframe(); //创建面板对象:调用面板的构造方法,制作面板 GamePanel panel = new GamePanel(frame);//方便在面板中添加键盘监听器 //调用开始游戏的方法,启动游戏 panel.action(); //将面板加入到窗体中 frame.add(panel); //显示窗体 true显示 false隐藏 frame.setVisible(true); //Music music=new Music(); //music.player(); String filepath="src/img/game_music.wav"; musicStuff musicObject=new musicStuff(); musicObject.playMusic(filepath); } }
package ui; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; //import java.awt.List; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Random; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import javax.sound.sampled.UnsupportedAudioFileException; import javax.swing.JPanel; public class GamePanel extends JPanel{ //1.定义背景图 BufferedImage bg;//背景图 //创建英雄机对象 Hero hero=new Hero(); //创建敌机对象 //Ep ep=new Ep(); //创建敌机的大本营(所有的敌机都放在这里) //使用集合不使用数组,是因为数组必须指定长度,而此游戏中,敌机数量不确定。 Listeps = new ArrayList (); //英雄机的d药库 List fs = new ArrayList (); //定义分数 int score; //设置游戏开关 boolean gameover;//游戏开始时,gameover为false,游戏结束时,gameover为true。 //设置英雄机的活力 int power=1; public void action() { //创建并启动一个线程,线程作用控制游戏场景中物体的移动 //固定格式 //new Thread(){public void run(){线程需要做的事情}}.start(); new Thread(){ public void run(){ //写一个死循环,让游戏一直运行 while(true) { if(!gameover) { //调用敌机入场的方法 epEnter(); //调用让敌机移动的方法 epMove(); //发射子d shoot(); //让子d移动 fireMove(); //判断子d是否打到敌机 shootEp(); //判断敌机是否撞到英雄机 hit(); } //每执行一次,休息一会 //线程休眠 sleep(毫秒数) try { //每隔10毫秒,执行一次epEnter方法 Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //重绘,刷新界面 repaint(); } } }.start(); } protected void hit() { //遍历敌机 for(int i=0;i 3) { hero.hp++; power=3; } } //1.敌机死亡,从敌机大本营中删掉 eps.remove(e); //增加分数 score+=10; //当英雄机的血量减少到0时,游戏结束 if(hero.hp<=0) { //游戏结束 gameover=true; } } } //2.子弹消失,从弹药库中删除子弹 fs.remove(f); } } } protected void fireMove() { //遍历所有子弹 for(int i=0;i =10) { if(power==1) { //创建第三排子d Fire fire3=new Fire(hero.x+45,hero.y-20,1); //将子d加入到d药库中 fs.add(fire3); }else if(power==2) { //创建第一排子d Fire fire1=new Fire(hero.x+15,hero.y,0); //将子d加入到d药库中 fs.add(fire1); //创建第二排子d Fire fire2=new Fire(hero.x+75,hero.y,2); //将子d加入到d药库中 fs.add(fire2); }else { //创建第一排子d Fire fire1=new Fire(hero.x+15,hero.y,0); //将子d加入到d药库中 fs.add(fire1); //创建第二排子d Fire fire2=new Fire(hero.x+75,hero.y,2); //将子d加入到d药库中 fs.add(fire2); //创建第三排子d Fire fire3=new Fire(hero.x+45,hero.y-20,1); //将子d加入到d药库中 fs.add(fire3); } //将计数器归零 findex=0; } } protected void epMove() { //遍历所有的敌机 for(int i=0; i =8) { //创建敌机 Ep e=new Ep(); //将敌机加入到敌机大本营中 eps.add(e); //将index重新设置为0 index=0; } } public GamePanel(Gameframe frame){ //设置背景 setBackground(Color.blue); //初始化图片 //如果工具类中没有加static,则要加App app=new App(); bg=App.getImg("/img/bg2.jpg"); //使用鼠标监听器(固定格式) //1.创建鼠标适配器 MouseAdapter adapter= new MouseAdapter() { //确定需要监听的鼠标事件 @Override public void mouseClicked(MouseEvent e) { //点击鼠标时会执行的代码 //如果游戏结束了,点击屏幕重新开始游戏 if(gameover) { //重新开始游戏,重新创建一个英雄机 hero=new Hero(); //重置游戏开关 gameover=false; //分数清0 score=0; //清空敌机集合 eps.clear(); //清空子d集合 fs.clear(); //随机背景图 Random rd=new Random(); int index=rd.nextInt(5)+1; bg=App.getImg("/img/bg"+index+".jpg"); //刷新界面 repaint(); } } @Override public void mouseMoved(MouseEvent e) { //当鼠标在游戏界面中移动时,会触发的方法 //当写入如下代码时,鼠标每移动一次就会触发一次“移动了鼠标~~” //System.out.println("移动了鼠标~~"); //让英雄机跟着鼠标一起移动,让英雄机的横纵坐标等于鼠标的横纵坐标 //获取鼠标的横纵坐标 int mx=e.getX();//鼠标的横坐标 int my=e.getY();//鼠标的纵坐标 if(!gameover) { //让英雄机移动到鼠标的位置上(英雄机的行为,可以在英雄机中定义移动到鼠标的方法) hero.moveToMouse(mx, my); } //刷新界面,将英雄机绘制到新的位置上 //重新调用paint方法 repaint(); } }; //3.将适配器加入到监听器中(固定格式) addMouseListener(adapter); addMouseMotionListener(adapter); //使用键盘监听器(固定格式) //1.创建键盘适配器 KeyAdapter kd=new KeyAdapter() { //2.确定需要监听的键盘事件 public void keyPressed(KeyEvent e) { //当按下键盘按键时,会触发的方法 //监听键盘的按键 //每一个按键都会对应一个数字 //获取键盘上按键的数字 int keyCode=e.getKeyCode(); System.out.println(keyCode); if(keyCode==KeyEvent.VK_W) { //英雄机向上移动 hero.moveUp(); }else if(keyCode==KeyEvent.VK_A) { //英雄机向左移动 hero.moveLeft(); }else if(keyCode==KeyEvent.VK_D) { //英雄机向右移动 hero.moveRight(); }else if(keyCode==KeyEvent.VK_S) { //英雄机向下移动 hero.moveDown(); } //重绘,将飞机画到新的位置上 repaint(); } }; //3.将适配器加入到窗体的监听器中 frame.addKeyListener(kd); } @Override public void paint(Graphics g) { super.paint(g); //画图片 //g.drawImage(图片,图片的横坐标,图片的纵坐标,null); //横纵坐标,是设置图片左上角的坐标 g.drawImage(bg,0,0,null); //画图片时,如果不加宽度,高度,画的就是原图的大小 //如果想要改变图片的大小,可以使用如下的格式 //g.drawImage(图片,图片的横坐标,图片的纵坐标,图片的宽度,图片的高度,null); //在paint中画图是有顺序的,先画的会被后画的覆盖,向栈一样 //画英雄机 g.drawImage(hero.img,hero.x,hero.y,hero.w,hero.h,null); //画敌机 //遍历敌机大本营集合,画出所有的敌机 for(int i=0;i 三、编写游戏中的飞行物 Ep.java
package ui; import java.awt.image.BufferedImage; import java.util.Random; public class Ep extends FlyObject { int sp;//敌机的速度 public int hp;//敌机的血量 int type;//敌机的类型 //BufferedImage img; //int x;//敌机的横坐标 //int y;//敌机的纵坐标 //int w;//敌机的宽度 //int h;//敌机的高度 public Ep() { //确定随机数的类 Random rd=new Random(); //生成一个随机数,用来选取图片,随机数为1,则为第一张图片以此类推 int index=rd.nextInt(15)+1; //设置敌机的类型 type=index; //三目运算符 //格式:条件表达式?值1:值2 //表达式为true,取值1,否则值2 String path="/img/ep"+(index<10?"0":"")+index+".png"; //常见笔试题 //加号可以用来做加法运算,也可以用连接内容 //加号遇到双引号之前,都做加法运算 //加号遇到双引号开始及之后,都只能做连接,连接之后的结果为字符串 //确定敌机显示的图片 img=App.getImg(path); y=-h; //确定敌机的大小 w=img.getWidth(); //确定敌机的位置 //nextInt(num) 表示会在[0,num)之间随机生成一个整数 x=rd.nextInt(512-w); h=img.getHeight(); //设置敌机的速度,序号越大,速度越慢 sp=17-index; } public void move() { if(type==1||type==7||type==12) { x-=1; y+=sp; }else if(type==2||type==6||type==11) { x+=2; y+=sp; }else if(type==3||type==8||type==13){ x+=1; y+=sp; }else if(type==4||type==9||type==14){ x-=2; y+=sp; }else if(type==15) { //敌机导弹速度快 y+=20; }else if(type==5||type==10) { y+=sp; } } 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; } //将英雄机看成子d,复制上面的代码 public boolean hitBy(Hero f) { boolean hit=x<=f.x+f.w && x>=f.x-w && y<=f.y+f.h && y>=f.y-h; return hit; } }
FlyObject.java
package ui; import java.awt.image.BufferedImage; public class FlyObject { //飞行物的图片 BufferedImage img; int x;//飞行物的横坐标 int y;//飞行物的纵坐标 int w;//飞行物的宽度 int h;//飞行物的高度 }package ui; public class Fire extends FlyObject { //子d当前移动的方向 int dir;//dir 为0:左上角 为1:垂直向上 为2:右上角 public Fire(int hx,int hy,int dir) { //确定子d的图片 img=App.getImg("/img/fire.png"); //确定子d的大小 w=img.getWidth()/4; h=img.getHeight()/4; //确定子d的位置(初始位置在英雄机的上方) x=hx; y=hy; //属性的名字和参数的名字相同时,要加this this.dir=dir; } public void move(){ if(dir==0) { //左上角飞 x-=1; y-=10; }else if(dir==1){ //垂直飞 y-=10; }else { //右上角飞 x+=1; y-=10; } } }Hero.java
package ui; import java.awt.image.BufferedImage; public class Hero extends FlyObject { int hp;//确定英雄机的血量 //英雄机的图片 //BufferedImage img; //英雄机的横坐标 //int x; //英雄机的纵坐标 //int y; //英雄机的宽度 //int w; //英雄机的高度 //int h; public Hero() { //确定游戏开始时,英雄机显示的图片 img=App.getImg("/img/hero.png"); //使用横纵坐标,确定英雄机的初始位置 x=200; 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; //x,y各减1/2,让鼠标作用在英雄机的中心位置 //System.out.println(x+","+y); } public void moveUp() { //英雄机向上移动 y-=100; } public void moveDown() { //英雄机向下移动 y+=100; } public void moveLeft() { //英雄机向左移动 x-=100; } public void moveRight() { //英雄机向右移动 x+=100; } }四、插入背景音乐Music.java
package ui; import java.io.File; import java.io.IOException; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import javax.sound.sampled.UnsupportedAudioFileException; public class Music { private int t = 0; // 音乐播放时间 AudioInputStream bgm; private boolean playing = false; public boolean isPlaying() { return playing; } public void setPlaying(boolean playing) { this.playing = playing; } public int getT() { return t; } public void setT(int t) { this.t = t; } public Music() { try { bgm = AudioSystem.getAudioInputStream(new File("src/img/game_music.wav")); } catch (UnsupportedAudioFileException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // 获得音频输入流 } public void player() { AudioInputStream ais; AudioFormat baseFormat; DataLine.Info info; ais = bgm; baseFormat = ais.getFormat(); // 指定声音流中特定数据安排 info = new DataLine.Info(SourceDataLine.class, baseFormat); SourceDataLine line = null; //该数据线处理字节的缓冲并将其传递到混频器 try { line = (SourceDataLine) AudioSystem.getLine(info); line.open(baseFormat); // 打开具有指定格式的行,这样可使行获得所有所需的系统资源并变得可 *** 作。 line.start();// 允许数据行执行数据 I/O int BUFFER_SIZE = 4000 * 4; int intBytes = 0; byte[] audioData = new byte[BUFFER_SIZE]; // 音频数据数组 while (intBytes != -1 && (playing == false)) { intBytes = ais.read(audioData, 0, BUFFER_SIZE); // 从音频流读取指定的最大数量的数据字节,并将其放入给定的字节数组中。 if (intBytes >= 0) { line.write(audioData, 0, intBytes);// 通过此源数据行将音频数据写入混频器。 t += 1; } //System.out.println(t); } } catch (LineUnavailableException | IOException e1) { e1.printStackTrace(); } } }五、 处理图片的工具类
App.java
package ui; import java.awt.image.BufferedImage; import java.io.IOException; import javax.imageio.ImageIO; public class App { public static BufferedImage getImg(String path) { //加载图片 //java中的IO流,输送数据的管道 //输入输出流 //App.class找到App类的路径 //getResource()获取资源 try { BufferedImage img=ImageIO.read(App.class.getResource(path)); //如果找到图片就将图片返回 return img; } catch (IOException e) { //catch如果找不到图片,就会捕获找不到图片的原因 e.printStackTrace(); } return null; } }六、运行截图
需要游戏素材的小伙伴点赞加关注私聊哈~~~ 瑞斯拜~~~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)