整體思想:主界面、主角魚、被喫的魚、氣泡、聲音
程序主要有7個類組成:DrawStart、Fish、EatenFish、AirBubble、Music、GetImage、MyMouseListener
DrawStart:
主界面:簡單界面,用swing實現,只需要遊戲圖片和切換圖片;內含主方法,啓動遊戲;創建幾乎全部的屬性,最重要的是創建一
個內部類線程來實現被喫的魚
氣泡的產生
在這裏介紹一種獲得項目圖片資源的兩種方法:一:得到窗體的工具包 Toolkit tool = Toolkit.getDefaultToolkit();(包 java.awt.Toolkit;)
獲取圖 Image image = tool.getImage(DrawStart.class.getResource("圖片路徑"));(包 java.awt.Image;)
二:直接獲取 Image image = new ImageIcon("圖片路徑").getImage();
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();
}
}
GetImage: 獲取遊戲背景圖片,在DrawStart中調用
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);
}
}
MyMouseListener:通過將主角魚的座標設爲靜態的,然後在鼠標移動方發上實現“畫直線”的方法就可以實現對主角魚的拖動
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座標,取出來比較實現的效果不是很好
功能還在進一步實現過程中,希望能多收到點建議!