Java课程设计--大鱼吃小鱼

  • 前言
  • 1、创建FishFrame.java
  • 2、创建FishPanel.java
  • 3. 创建一个DataImg.java来统一加载图片
  • 3.1 将图片保存在一个包下面如图:
  • 4.创建鱼的类
  • 4.1 鱼的父类Fish.java
  • 4.2 其他鱼(都是相似的)
  • 4.3 自己的鱼
  • 5.结语


前言

游戏整体框架来着B站:这是链接:Java实战训练营 在我的课设中改进了让鱼有游动特效,以及增添了鼠标监听事件等等游戏优化

游戏效果:

Java游戏大鱼吃小鱼总结 大鱼吃小鱼游戏steam_ide


Java游戏大鱼吃小鱼总结 大鱼吃小鱼游戏steam_游戏开发_02

1、创建FishFrame.java

package FishGame;

import javax.swing.*;
import java.awt.event.*;
/*
 * 步骤:
 * 1.先创建窗体对象
 * 2.背景的绘制
 * 3.键盘的监听事件
 * 		1.实现接口
 * 		2.添加监听的事件
 * 4.将己方鱼放上去
 * 5.让小鱼移动
 * 6.敌方的🐟(先创建集合把鱼装起来,获取每个对象,画图)
 * 7.吃鱼
 * 8.被吃
 * 9.增加了鼠标事件
 * */

public class FishFrame extends JFrame{
    public FishFrame(String username){
        setTitle("大鱼吃小鱼:欢迎你 "+username);
        FishPanel fishPanel=new FishPanel(username);
        add(fishPanel);

        addMouseMotionListener(new MouseMotionListener() {

            @Override
            public void mouseDragged(MouseEvent e) {

            }

            @Override
            public void mouseMoved(MouseEvent e) {
                fishPanel.move(e.getPoint());
            }
        });
        addKeyListener(new MyFishKeyListener(){
            @Override
            public void keyPressed(KeyEvent e) {
                int vk=e.getKeyCode();
                fishPanel.move(vk);
            }
        });

        fishPanel.action();//启动线程
        setBounds(100,20,1440,900);
        setVisible(true);
        setResizable(false);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        addKeyListener(new MyFishKeyListener());
    }

    public static void main(String[] args){
        new FishFrame("用户");
    }
}
class MyFishKeyListener implements KeyListener{


    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

}

2、创建FishPanel.java

里面的hit()鱼碰撞事件可以改进

package FishGame;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.TimerTask;
import java.util.Timer;
import java.awt.event.KeyEvent;
import java.awt.Graphics;

public class FishPanel extends JPanel{
    标识状态0开始,1运行,2暂停,3是结束
    public int state = START;
    public static final int START=0;
    public static final int RUNNING =1;
    public static final int PAUSE =2;
    public static final int GAMEOVER =3;

    Image bkImg = DataImg.background;
    Image start =DataImg.start;

    int score=0;//经验得分
    ArrayList<Fish> fishes = new ArrayList<Fish>();//装其他🐟的集合

    int fish_1=0,fish_2=1,fish_3=1,fish_4=1,fish_5=1;
    boolean lock=true;
    Point p;
    myFish fish;

    String username;


    public FishPanel(String username){
        this.username=username;
        fish=new myFish();
    }
    @Override
    public void paint(Graphics g)  {
        super.paint(g);
        //绘制游戏背景界面
        switch(state) {
            case START: g.drawImage(start, 0, 0, 1440, 900, null);
                       g.setFont(new Font("微软雅黑",Font.BOLD,40));
                       g.setColor(Color.WHITE);
                       g.drawString("按下空格开始",600,600);
                       score=0;//再次初始化
                        break;
            case RUNNING:
                //背景绘制
                drawBackGround(g);
                //绘制己方的小鱼
                drawMyFish(g);
                //绘制其他的小鱼
                drawFishes(g);
                //设置字体颜色
                g.setColor(Color.white);
                Font f = new Font("黑体",Font.BOLD,20);//加粗
                g.setFont(f);  //传进去
                g.drawString("当前得分:"+score, 15, 20);//在x=15,y=20显示分数
                g.drawString("战斗力:"+fish.zhanli, 200, 20);
                break;//一样

            case PAUSE:
                drawBackGround(g);
                drawMyFish(g);
                drawFishes(g);
                g.setColor(Color.white);
                Font fff = new Font("黑体",Font.BOLD,50);
                g.setFont(fff);
                g.drawString("按下空格继续游戏",500 ,450);
                break;

            case GAMEOVER:
                drawBackGround(g);
                drawMyFish(g);
                drawFishes(g);
                g.drawString("当前得分:"+score, 15, 20);
                g.setColor(Color.white);
                Font ff = new Font("黑体",Font.BOLD,50);
                g.setFont(ff);
                g.drawString("游戏 结束",600 ,450);
                break;
        }
    }

    /*定时器、
	1.生成其他鱼
	2.移动*/
    public void action(){//多线程,timer内部实现
        Timer timer=new Timer();
        timer.schedule(new TimerTask() {//定时器任务
            @Override
            public void run() {
                if(state==1) {

                    createFish();//1.创建其他鱼2.不断的改变其他鱼的位置:
                    hitFish();//3.吃鱼
                    if(lock)move(p);
                    outOfBounds();//4.当鱼跑出圈外,我们要删除集合中的鱼;
                    repaint(); //重画
                }
            }
        },20,10);//20延迟执行,10每隔10ms执行run里面的内容一次

    }
    //产生鱼
    private void createFish() {
        if((fish_1++%200)==0) {//每隔10ms自加一次
            fishes.add(new Fish_1());
        }
        if((fish_2++%300)==0) {
            fishes.add(new Fish_2());
            fishes.add(new Fish_2_1());
        }
        if((fish_3++%400)==0) {
            fishes.add(new Fish_3());
        }
        if((fish_4++%600)==0) {
            fishes.add(new Fish_4());
        }
        if((fish_5++%1500)==0) {
            fishes.add(new Fish_5());
        }
    }
    private void hitFish() {
        for(int i=0;i<fishes.size();i++) {
            if(hit(fishes.get(i))) {
                if(fish.zhanli>=fishes.get(i).zhanli) {

                    switch(fishes.get(i).zhanli) {
                        case 1:
                            score++;
                            break;
                        case 2:
                            score+=2;
                            break;
                        case 3:
                            score+=3;
                            break;
                        case 4:
                            score+=4;
                            break;
                    }
                    fishes.remove(i);//根据分数加战力
                    if(score>=10 && score<40)
                        fish.zhanli=2;
                    if(score>=40 && score<80)
                        fish.zhanli=3;
                    if(score>=80)
                        fish.zhanli=4;
                }else {
                    state=3;//运行结束
                }

            }
        }
    }
    private void outOfBounds() {
        for(int i=0;i<fishes.size();i++) {
            if(fishes.get(i).isMoveLeft) {
                if(fishes.get(i).x+fishes.get(i).length<=0) {
                    fishes.remove(i);
                }
            } else
            if(fishes.get(i).x>=1440) {
                fishes.remove(i);
            }
        }
    }
    //中心点在鱼的xy范围内,检测碰撞
    public boolean hit(Fish fishs) {
        int x=(fish.x1+fish.x)/2,y=(fish.y+fish.y1)/2;
        int x1 = fish.x1,y1 = fish.y1;
        int x2 = fish.x,y2 = fish.y;
        if(((x>=fishs.x)&&(x<=fishs.x+fishs.length))||((x1>=fishs.x)&&(x1<=fishs.x+fishs.length))||((x2>=fishs.x)&&(x2<=fishs.x+fishs.length)) ){
            if(((y>=fishs.y)&&(y<=fishs.y+fishs.height))||((y1>=fishs.y)&&(y1<=fishs.y+fishs.height))||((y2>=fishs.y)&&(y2<=fishs.y+fishs.height))) {
                return true;//产生碰撞
            }
        }
        return false;
    }

    public void move(int keycode) {//键盘事件移动鱼
        switch(keycode) {
            case KeyEvent.VK_RIGHT:
                fish.moveRight();
                break;
            case KeyEvent.VK_LEFT:
                fish.moveLeft();
                break;
            case KeyEvent.VK_UP:
                fish.fishMoveUp();
                break;
            case KeyEvent.VK_DOWN:
                fish.fishMoveDown();
                break;
            case KeyEvent.VK_ESCAPE:
                if (state==RUNNING)state=GAMEOVER;
                break;
            case KeyEvent.VK_SPACE:
                if(state == 0) {
                    state=RUNNING;

                }else if(state==1){
                    state=PAUSE;
                }else if(state==2){
                    state=RUNNING;
                }
                else if(state==3) {
                    state=START;
                    fish=new myFish();
                    fishes = new ArrayList<Fish>();

                }
                break;

        }
        repaint();
    }

    public void move(Point point){
        p=point;
        lock=true;//产生鼠标事件
        if(p.x>(fish.x1+fish.x)/2 && p.y>=(fish.y1+fish.y)/2){fish.moveDownAndRight();}
        else if(p.x>(fish.x1+fish.x)/2 && p.y<=(fish.y1+fish.y)/2){fish.moveUpAndRight();}
        else if(p.x<(fish.x1+fish.x)/2 && p.y>=(fish.y1+fish.y)/2){fish.moveDownAndLeft();}
        else if(p.x<(fish.x1+fish.x)/2 && p.y<=(fish.y1+fish.y)/2){ fish.moveUpAndLeft();}
        else{lock=false;}
    }
    //画其他鱼
    private void drawFishes(Graphics g) {
        // TODO Auto-generated method stub
        for(int i=0;i<fishes.size();i++) {
            fishes.get(i).draw(g);
        }
    }


    //画自己的鱼
    private void drawMyFish(Graphics g) {
        // TODO Auto-generated method stub
        fish.draw(g);
    }

    private void drawBackGround(Graphics g) {
        // TODO Auto-generated method stub
        g.drawImage(bkImg, 0, 0, 1440, 900, 0, 0, 1920, 1080, null);
    }

}

3. 创建一个DataImg.java来统一加载图片

注:游戏鱼的图片要采用游戏素材半透明的图片,截图会有框。

package FishGame;

import javax.swing.*;
import java.awt.*;
import java.net.URL;

public class DataImg {
    public static URL start_path = DataImg.class.getResource("Img/begin_picture.jpg");
    public static URL fish08_path = DataImg.class.getResource("Img/fish08.png");
    public static URL fish12_path = DataImg.class.getResource("Img/fish12.png");
    public static URL fish03_path = DataImg.class.getResource("Img/fish03.png");
    public static URL fish17_path = DataImg.class.getResource("Img/fish17.png");
    public static URL background_path = DataImg.class.getResource("Img/background2.jpeg");
    public static URL fish06_path = DataImg.class.getResource("Img/fish06.png");
    public static URL lantern_path = DataImg.class.getResource("Img/fish.png");

    public static Image start = new ImageIcon(start_path).getImage();
    public static Image fish08 = new ImageIcon(fish08_path).getImage();
    public static Image fish12 = new ImageIcon(fish12_path).getImage();
    public static Image fish03 = new ImageIcon(fish03_path).getImage();
    public static Image fish17 = new ImageIcon(fish17_path).getImage();
    public static Image background = new ImageIcon(background_path).getImage();
    public static Image fish06 = new ImageIcon(fish06_path).getImage();
    public static Image lantern = new ImageIcon(lantern_path).getImage();
}

3.1 将图片保存在一个包下面如图:

Java游戏大鱼吃小鱼总结 大鱼吃小鱼游戏steam_Java游戏大鱼吃小鱼总结_03


Java游戏大鱼吃小鱼总结 大鱼吃小鱼游戏steam_ide_04

4.创建鱼的类

4.1 鱼的父类Fish.java

package FishGame;
import java.awt.Graphics;
import java.awt.Image;
//父类的鱼
public class Fish {
    int length,height;//鱼的宽高
    int x,y;//初始位置
    boolean isMoveLeft=true;//鱼的初始方向

    //原图片的坐标左上角和右下角(裁剪)
    int sx1,sy1;
    int sx2,sy2;

    int step;
    int zhanli;
    Image img;//鱼的图片

    //绘制
    public void draw(Graphics g) {};
}

4.2 其他鱼(都是相似的)

package FishGame;
import java.awt.Graphics;
import java.util.Timer;
import java.util.TimerTask;


public class Fish_1 extends Fish{
    int xx;
    int change=0;
    public Fish_1() {
        action();
        step=2;
        xx=(int)(Math.random()*2);//0或者1
        switch(xx) {//出场位置
            case 0:
                isMoveLeft=false;
                x=-68;
                break;
            case 1:
                isMoveLeft=true;
                x=1440;
                break;
        }
        y=(int)(Math.random()*900);//垂直位置
        length= 68;
        height=	55;
        zhanli=1;
        //界面坐标

        img = DataImg.fish08;
    }

    public void draw(Graphics g){
        if(isMoveLeft) {//左移
            sy1=height*change;;
            sx1=0;
            sy2=height+height*change;
            sx2=length;
            g.drawImage(img, x=x-4, y, x+length, y+height, sx1, sy1, sx2,sy2, null);//可以控制鱼的速度
        }
        else {//右移
            sx2=0;
            sy2=height*change;;
            sx1=length;
            sy1=height+height*change;
            g.drawImage(img, x=x+4, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
        }
    }
    public void action(){
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                change=(++change)%step;
            }
        },20,500);
    }


}

每条鱼里都有单独的时间线程,每0.5秒切换一次鱼的图片,达到游动动态效果

package FishGame;

import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;

public class Fish_2_1 extends Fish{
    int xx;
    int change=0;
    public Fish_2_1() {
        step=3;
        action();
        xx=(int)(Math.random()*2);
        switch(xx) {
            case 0:
                isMoveLeft=false;
                x=-96;
                break;
            case 1:
                isMoveLeft=true;
                x=1440;
                break;
        }
        y=(int)(Math.random()*900);
        length= 90;
        height=	29;
        zhanli=2;
        //界面坐标

        img = DataImg.fish06;
    }
    public void draw(Graphics g){
        if(isMoveLeft) {//左移
            sy1=height*change;;
            sx1=0;
            sy2=height+height*change;
            sx2=length;
            g.drawImage(img, x=x-3, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
        }
        else {//右移
            sx2=0;
            sy2=height*change;;
            sx1=length;
            sy1=height+height*change;
            g.drawImage(img, x=x+3, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
        }
    }
    public void action(){
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                change=(++change)%step;
            }
        },20,500);
    }
}
package FishGame;

import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;

public class Fish_2 extends Fish{
    int xx;
    int change=0;
    public Fish_2() {
        step=3;
        action();
        xx=(int)(Math.random()*2);
        switch(xx) {
            case 0:
                isMoveLeft=false;
                x=-96;
                break;
            case 1:
                isMoveLeft=true;
                x=1440;
                break;
        }
        y=(int)(Math.random()*900);
        length= 96;
        height=	29;
        zhanli=2;
        //界面坐标

        img = DataImg.fish12;
    }
    public void draw(Graphics g){
        if(isMoveLeft) {//左移
            sy1=height*change;;
            sx1=0;
            sy2=height+height*change;
            sx2=length;
            g.drawImage(img, x=x-3, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
        }
        else {//右移
            sx2=0;
            sy2=height*change;;
            sx1=length;
            sy1=height+height*change;
            g.drawImage(img, x=x+3, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
        }
    }
    public void action(){
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                change=(++change)%step;
            }
        },20,500);
    }
}
package FishGame;
import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;
public class Fish_3 extends Fish{
    int xx;
    int change=0;
    public Fish_3() {
        step=3;
        action();
        xx=(int)(Math.random()*2);
        switch(xx) {
            case 0:
                isMoveLeft=false;
                x=-96;
                break;
            case 1:
                isMoveLeft=true;
                x=1440;
                break;
        }
        y=(int)(Math.random()*900);
        length= 110;
        height=60;
        zhanli=3;
        //界面坐标

        img = DataImg.lantern;
    }
    public void draw(Graphics g){
        if(isMoveLeft) {//左移
            sy1=336+height*change;;
            sx1=330;
            sy2=336+height+height*change;
            sx2=336+length;
            g.drawImage(img, x=x-3, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
        }
        else {//右移
            sx2=330;
            sy2=336+height*change;;
            sx1=330+length;
            sy1=336+height+height*change;
            g.drawImage(img, x=x+3, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
        }
    }
    public void action(){
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                change=(++change)%step;
            }
        },20,500);
    }
}
package FishGame;

import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;

public class Fish_4 extends FishGame.Fish {
    int xx;
    int change=0;
    public Fish_4() {
        step=4;
        action();
        xx=(int)(Math.random()*2);
        switch(xx) {
            case 0:
                isMoveLeft=false;
                x=-310;
                break;
            case 1:
                isMoveLeft=true;
                x=1440;
                break;
        }
        y=(int)(Math.random()*900);
        length= 310;
        height=	104;
        zhanli=3;
        //界面坐标

        img = DataImg.fish03;
    }
    public void draw(Graphics g){
        if(isMoveLeft) {//左移
            sy1=height*change;;
            sx1=0;
            sy2=height+height*change;
            sx2=length;
            g.drawImage(img, x=x-2, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
        }
        else {//右移
            sx2=0;
            sy2=height*change;;
            sx1=length;
            sy1=height+height*change;
            g.drawImage(img, x=x+2, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
        }
    }
    public void action(){
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                change=(++change)%step;
            }
        },20,500);
    }


}
package FishGame;

import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;

public class Fish_5 extends Fish {
    int xx;
    int change=0;
    public Fish_5() {
        step=2;
        action();
        xx=(int)(Math.random()*2);
        switch(xx) {
            case 0:
                isMoveLeft=false;
                x=-380;
                break;
            case 1:
                isMoveLeft=true;
                x=1440;
                break;
        }
        y=(int)(Math.random()*900);
        length= 380;
        height=	210;
        zhanli=4;
        //界面坐标

        img = DataImg.fish17;
    }

    public void draw(Graphics g){
        if(isMoveLeft) {//左移
            sy1=height*change;;
            sx1=0;
            sy2=height+height*change;
            sx2=length;
            g.drawImage(img, x--, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
        }
        else {//右移
            sx2=0;
            sy2=height*change;;
            sx1=length;
            sy1=height+height*change;
            g.drawImage(img, x++, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
        }
    }
    public void action(){
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                change=(++change)%step;
            }
        },20,500);
    }

}

4.3 自己的鱼

package FishGame;

import java.util.TimerTask;
import java.util.Timer;
import java.awt.*;


public class myFish extends Fish{
    int x1,y1;//
    int change=0;
    public myFish() {
        action();
        length= 68;//鱼的大小
        height=	55;

        zhanli=1;
        //初始鱼界面坐标
        x=100;
        y=450;
        //初始坐标加上长宽后就确定了鱼图片的位置
        x1=x+68;
        y1=y+55;
        step=2;
    }
    //鱼的转向
    public void draw(Graphics g){
        super.draw(g);
        changeFishSize(zhanli);
        if(isMoveLeft) {
            sy1=height*change;
            sx1=0;
            sy2=height+height*change;
            sx2=length;

        }else {
            sy2=height*change;
            sx2=0;
            sy1=height+height*change;
            sx1=length;

        }

        Image img = selectImage(zhanli);
        //画图前4个坐标确定鱼显示位置,后4个对鱼进行剪裁

        g.drawImage(img, x, y, x1, y1, sx1, sy1, sx2,sy2, null);
    }

    private void changeFishSize(int level) {
        if(level<2){ }
        else if(level==2){
            length=96;
            height=29;
            step=3;
            x1=x+96;
            y1=y+29;
        }
        else if(level==3){
            length=310;
            height=106;
            step=4;
            x1=x+310;
            y1=y+104;
        }
        else {
            length=375;
            height=205;
            step=2;
            x1=x+380;
            y1=y+210;
        }
    }


    public void moveRight() {
        isMoveLeft=false;
        if(x<=1350) {//符合移动规范
            x+=10;
            x1+=10;
        }//水平移动y不变;
    }
    public void moveLeft() {
        isMoveLeft=true;
        if(x>=10) {
            x-=10;
            x1-=10;
        }//水平移动y不变;
    }
    //上下移动不关其他事
    public void fishMoveUp() {
        if(y>=0) {
            y-=10;
            y1-=10;
        }
    }
    public void fishMoveDown() {
        if(y<=800) {
            y+=10;
            y1+=10;
        }
    }
    public void moveUpAndRight() {
        isMoveLeft=false;
        y-=1;
        x+=1;
        x1=x+68;
        y1=y+55;
    }
    public void moveUpAndLeft() {
        isMoveLeft=true;
        y-=1;
        x-=1;
        x1=x+68;
        y1=y+55;
    }
    public void moveDownAndRight() {
        isMoveLeft=false;
        y+=1;
        x+=1;
        x1=x+68;
        y1=y+55;
    }
    public void moveDownAndLeft() {
        isMoveLeft=true;
        y+=1;
        x-=1;
        x1=x+68;
        y1=y+55;
    }

    public Image selectImage(int level){//进化
        if(level<2){
            return DataImg.fish08;
        }
        else if(level==2){
            return DataImg.fish12;
        }
        else if(level==3){
            return DataImg.fish03;
        }
        else {
            return DataImg.fish17;
        }
    }
    public void action(){
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                change=(++change)%step;
            }
        },20,500);
    }
}

5.结语

在FishFrame.java里运行main就可以开始游戏

原本我的课设是有登入界面的(涉及数据库这里已经删除了。。长这样)

Java游戏大鱼吃小鱼总结 大鱼吃小鱼游戏steam_Java游戏大鱼吃小鱼总结_05