DrawStart:
主界面:简单界面,用swing实现,只需要游戏图片和切换图片;内含主方法,启动游戏;创建几乎全部的属性,最重要的是创建一
个内部类线程来实现被吃的鱼
气泡的产生
在这里介绍一种获得项目图片资源的两种方法:
import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.Random; import javax.swing.JFrame; public class DrawStart extends JFrame{ int Gametype = 0; public Toolkit tool = Toolkit.getDefaultToolkit();//得到窗体的工具包 Image logo = tool.getImage(DrawStart.class.getResource("logo.png"));//窗体标志 //创建缓冲图片 Image bg_img = null; //创建线程类对象 MyThread thread = new MyThread(); //创建一个集合存放多个气泡 ArrayList<AirBubble> air_list = new ArrayList<AirBubble>(); //创建鱼类对象 private Fish fish = new Fish(this); //创建一个集合存放多个被吃的鱼 ArrayList<EatenFish> eatenfish_list = new ArrayList<EatenFish>(); //创建背景类对象 GetImage startBg = new GetImage(this); //创建一个音乐对象 Music music = new Music(); //显示游戏界面 public void showFrame(){ this.setTitle("大鱼吃小鱼"); this.setSize(850,710); this.setResizable(false); setIconImage(logo);//窗体上的标志 //设置窗体可见 this.setVisible(true); //添加鼠标监听 MyMouseListener mouse_listener = new MyMouseListener(); this.addMouseListener(mouse_listener); this.addMouseMotionListener(mouse_listener); //添加键盘监听 addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent key) { if (key.getKeyCode() == 10 && Gametype == 0) { Gametype = 1; music.playBgMusic(); repaint(); } } }); this.setDefaultCloseOperation(EXIT_ON_CLOSE);//关闭窗体 thread.start(); } public void createFish(){ //Fish fish = new Fish(370,300); Fish fish = new Fish(this); } //创建随机数对象 Random r = new Random(); //创建被吃的鱼 public void createEatenfish() { if (r.nextInt(2) == 0) { EatenFish cr_eatenfish = new EatenFish(this, -50, r.nextInt(705),r.nextInt(2)); eatenfish_list.add(cr_eatenfish); } if (r.nextInt(2) == 1) { EatenFish cr_eatenfish = new EatenFish(this, getWidth() + 110, r.nextInt(705),r.nextInt(2)); eatenfish_list.add(cr_eatenfish); } } //创建气泡 public void createAirBubble() { music.playBubblesMusic(); AirBubble ab_air = new AirBubble(this, r.nextInt(getWidth() - 40), 705); air_list.add(ab_air); } //重写paint方法 public void paint(Graphics p) { //判断游戏是否是开始的 if (Gametype == 0) { startBg.startBackground(p); } //判断游戏是否是在加载中 if (Gametype == 1) { startBg.loadBackground(p); for (int i = 0; i < eatenfish_list.size(); i++) { EatenFish eatenfish = eatenfish_list.get(i); // 画被吃的鱼 eatenfish.drawEatenfish(p); } for (int i = 0; i < air_list.size(); i++) { AirBubble Dr_qipao = air_list.get(i); //画气泡 Dr_qipao.drawAirBubble(p); } fish.drawFish(p);//画主角 } } // 创建定时器 int time = 0; int eaten = 0; // 内部类,不停的重绘窗体图像 private class MyThread extends Thread { public void run() { Fish.list.add( 1); Fish.list.add( 2); while (true) { try { Thread.sleep(50); time++; eaten++; createFish(); if (Gametype == 1 && time % 25 == 0) { createAirBubble(); time = 0; } if (Gametype == 1 && eaten % 10 == 0) { createEatenfish(); eaten = 0; } //重绘 repaint(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args){ DrawStart ds = new DrawStart(); ds.showFrame(); } }
AirBubble:得到气泡的图片并实现随机在界面底层生成,并创建数组来实现它的产生和消失,通过线程控制
import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; public class AirBubble { //得到窗体的工具包 Toolkit tool = Toolkit.getDefaultToolkit(); Image air = tool.getImage( AirBubble.class.getResource("qipao.png"));// 气泡图片 Image air_1 = tool.getImage( AirBubble.class.getResource("qipao.png"));//气泡图片 //设置气泡的初始坐标 int air_x = 0; int air_y = 705; DrawStart StartBg = null; //通过构造方法传递窗体对象和气泡的初始位置 public AirBubble(DrawStart StartBg,int air_x,int air_y){ this.StartBg = StartBg; this.air_x = air_x; this.air_y = air_y; } //画气泡 public void drawAirBubble(Graphics g){ g.drawImage(air, air_x, air_y, StartBg); moveBackGround(); } //气泡的移动 public void moveBackGround(){ air_y -=5; if(air_y <=0){ StartBg.air_list.remove(this); air_y = 705; } } }
EatenFish:得到被吃的鱼的图片,并实现随机产生和随机游动的方法,也有队列存起来,再被吃掉时可用remove方法删除,通过线
程实现(主要是随机数的运用)
import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; import java.awt.Toolkit; import java.util.Random; public class EatenFish { //得到窗体的工具包 public Toolkit tool = Toolkit.getDefaultToolkit(); //得到被吃的小鱼的图片 Random r = new Random(); //获取向左图片 Image smallFish_1 = tool.getImage(DrawStart.class.getResource("eatenfish_right/"+r.nextInt(3)+".gif")); //Image bigFish_1 = tool.getImage(DrawStart.class.getResource("eatenfish_right/"+2+".gif")); //向右游动的初始坐标 Image smallFish_2 = tool.getImage(DrawStart.class.getResource("eatenfish_left/"+r.nextInt(3)+".gif")); //Image bigFish_2 = tool.getImage(DrawStart.class.getResource("eatenfish_right/"+2+".gif")); //向右游动的初始坐标 int eaten_x = 0; int eaten_y = 0; //存储判断传过来的数 0表示向右游 反之向左 int m = 0; DrawStart StartBg =null; //通过构造方法传递窗体类和被吃鱼的初始坐标 public EatenFish(DrawStart StartBg,int eaten_x,int eaten_y,int m){ this.StartBg = StartBg; if(this.m == m ){ this.eaten_x = eaten_x; }else{ //向左游的初始坐标 this.eaten_x = 1000; } this.eaten_y = eaten_y; } public EatenFish(DrawStart StartBg){ this.StartBg = StartBg; } //定义定时器 int time = 0; //定义存储随机数变量,如果随机数等于0画向右的鱼 等于1画向左的鱼 int oo = 0; //画被吃的鱼 public void drawEatenfish(Graphics g){ if(time%(StartBg.getWidth()+100)==0){ oo = r.nextInt(5); } if(oo==0){ g.drawImage(smallFish_1, eaten_x, eaten_y,70,60, StartBg); fishmove_right(); } if(oo==1){ g.drawImage(smallFish_2, eaten_x, eaten_y, 70,60,StartBg); fishmove_left(); } if(oo==2){ g.drawImage(smallFish_1, eaten_x, eaten_y,70,60, StartBg); fishmove_lu(); } if(oo==3){ g.drawImage(smallFish_2, eaten_x, eaten_y, 70,60,StartBg); fishmove_ru(); } time++; } //画被吃的鱼的游动 右边 public void fishmove_right(){ eaten_x +=3; if(eaten_x >= StartBg.getWidth()){ StartBg.eatenfish_list.remove(this); eaten_x = 0; } } //画被吃的鱼的游动 左边 public void fishmove_left(){ eaten_x -=3; if(eaten_x <= -50){ StartBg.eatenfish_list.remove(this); eaten_x = 1000; } } //画左斜线 public void fishmove_lu(){ eaten_x +=2; eaten_y +=2; if(eaten_x >1000&&eaten_y>750){ StartBg.eatenfish_list.remove(this); eaten_x = 0; eaten_y = 1000; } } //画右斜线 public void fishmove_ru(){ eaten_x -=2; eaten_y +=2; if(eaten_x <= -50&&eaten_y>1000){ StartBg.eatenfish_list.remove(this); eaten_x = 1000; eaten_y = 0; } } //返回被吃鱼的矩形区域 public Rectangle getRectangle(){ return new Rectangle(eaten_x, eaten_y, 60,50); } }
Fish: 得到主角鱼的图片,并判断鱼游动的方向,能实现变大,能实现吃掉小鱼,玩家用鼠标控制的鱼
主角鱼和被吃的鱼都会返回一个和自身位置差不多大小的矩形,只要判断矩形相交就可以“吃鱼”!
import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; import java.awt.Toolkit; import java.util.ArrayList; import java.util.List; public class Fish { int count = 0;//统计吃鱼的个数 static List<Integer> list = new ArrayList<Integer>() ; Rectangle rect ; //得到窗体的工具包 Toolkit tool = Toolkit.getDefaultToolkit(); //得到主角图片 Image fish_right = tool.getImage(Fish.class.getResource("right.png")); Image fish_left = tool.getImage(Fish.class.getResource("left.png")); private DrawStart StartBg = null ; public Fish(DrawStart StartBg){ this.StartBg=StartBg; } static int eat_x = 400; static int eat_y = 350; //创建被吃鱼类对象 EatenFish eatenfish = new EatenFish(StartBg); //画主角鱼 public void drawFish(Graphics g) { if(count<25){ if(list.get(list.size()-2)<list.get(list.size()-1)){ g.drawImage(fish_right,eat_x-40,eat_y-35,80,70,StartBg); }else{ g.drawImage(fish_left,eat_x-40,eat_y-35,80,70,StartBg); } }else{ if(list.get(list.size()-2)<list.get(list.size()-1)){ g.drawImage(fish_right,eat_x-55,eat_y-48,110,96,StartBg); }else{ g.drawImage(fish_left,eat_x-55,eat_y-48,110,96,StartBg); } } if(list.size()>4){ list.remove(0); list.remove(1); } eatenFish_bye(); } //返回主角鱼的矩形区域 public Rectangle getRectangle(){ if(count<25){ rect = new Rectangle(eat_x-35, eat_y-30, 70,60); }else{ rect = new Rectangle(eat_x-50, eat_y-43, 100,87); } return rect; } //被吃鱼消失 public void eatenFish_bye(){ for(int i=0;i<StartBg.eatenfish_list.size();i++){ EatenFish eatenfish = StartBg.eatenfish_list.get(i); //判断两个矩形区域是否相交 if(getRectangle().intersects(eatenfish.getRectangle()) || eatenfish.getRectangle().intersects(getRectangle())){ StartBg.eatenfish_list.remove(eatenfish); StartBg.music.playEatMusic(); count++; } } } }
Music:游戏运行时的背景声音、气泡产生的声音、吃鱼时的声音
java一种简单的音乐播放方法:(包 java.applet.AudioClip)
AudioClip shot=Applet.newAudioClip(Music.class.getClassLoader().getResource("音乐路径"));
缺点:只能播放wav格式的音乐
import java.applet.Applet; import java.applet.AudioClip; public class Music{ private AudioClip shot,shot1,shot2,shot3; public void playBgMusic(){ shot=Applet.newAudioClip(Music.class.getClassLoader().getResource("music/startMusic.wav")); shot.loop(); } public void playBubblesMusic(){ shot2=Applet.newAudioClip(Music.class.getClassLoader().getResource("music/bubbles.wav")); shot2.play(); } public void playEatMusic(){ shot1=Applet.newAudioClip(Music.class.getClassLoader().getResource("music/bite3.wav")); shot1.play(); } public void playMusic(){ shot3=Applet.newAudioClip(Music.class.getClassLoader().getResource("music/wave2.wav")); shot3.play(); } }
import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; public class GetImage { //得到窗体的工具包 public Toolkit tool = Toolkit.getDefaultToolkit(); //得到开始界面图片 Image start_1 = tool.getImage(GetImage.class.getResource("start_1.png")); Image start_2 = tool.getImage(GetImage.class.getResource("start_2.png")); Image main_bg_1 = tool.getImage(GetImage.class.getResource("mainbg.png")); DrawStart StartBg = null; //通过构造方法传递窗体对象 public GetImage(DrawStart StartBg){ this.StartBg = StartBg; } //画游戏开始时的图片 public void startBackground(Graphics g){ g.drawImage(start_1, 0, 0,StartBg.getWidth(),StartBg.getHeight(), StartBg); } //画加载时的背景 public void loadBackground(Graphics g){ g.drawImage(main_bg_1, 0, 0,StartBg.getWidth(),StartBg.getHeight(), StartBg); } }
public class MyMouseListener implements java.awt.event.MouseListener,java.awt.event.MouseMotionListener{ @SuppressWarnings("unused") private int x1,y1,x2,y2; // 鼠标按键在组件上单击(按下并释放)时调用。 public void mouseClicked(java.awt.event.MouseEvent e){ } // 鼠标进入到组件上时调用。 public void mouseEntered(java.awt.event.MouseEvent e) { } // 鼠标离开组件时调用。 public void mouseExited(java.awt.event.MouseEvent e) { } //按压 public void mousePressed(java.awt.event.MouseEvent e) { x1 = e.getX(); y1 = e.getY(); } // 鼠标按钮在组件上释放时调用。 public void mouseReleased(java.awt.event.MouseEvent e) { } //鼠标按下并拖动时调用 public void mouseDragged(java.awt.event.MouseEvent e){ x2 = e.getX(); y2 = e.getY(); Fish.eat_x=x2; Fish.eat_y=y2; Fish.list.add(x2); x1 = x2; y1 = y2; } //鼠标光标在组件上按下并移动时调用 public void mouseMoved(java.awt.event.MouseEvent e){ } }
这个游戏的实现最主要的是掌握多线程的思想
实现游戏难点:气泡、被吃的鱼的随机生成和鱼的随机游动,这个关系到整个画面是否有活跃
游戏的升级及鱼的变动,改动鱼之后相应的参数都要改变
鱼游动方向的判断,由于是用的静态变量,所以用的是队列存取X坐标,取出来比较实现的效果不是很好
功能还在进一步实现过程中,希望能多收到点建议!