前言 :
游戏参考于B站_【尚学堂】大鱼吃小鱼,主体框架不变,代码稍有改动。
大鱼吃小鱼:又称吞食鱼,是一款动作类小游戏。通过不断的吞吃比自己小的鱼类快速成长,最终成为海洋霸主。
游戏主要Java知识:变量、数据类型、判断语句、循环结构、类的继承、简单窗口创建、图形图片绘制、双缓存技术、鼠标事件、键盘事件。
非常适合在同学Java学习结束后,作为不错的结课作业或者练手项目。
源码已经在文章结束语后打包,有兴趣的同学可以免费下载,创作不易,点个免费的赞支持一下!
运行环境:jdk-17.05
操作方法:w,s,a,d (英文输入法)控制小鱼方向
游戏主要框架:
游戏素材:
游戏代码:
(1)Bg类
import java.awt.*;
public class Bg {
void paintSelf(Graphics g, int fishLevel) {
g.drawImage(GameUtils.bgimg, 0, 0, null);
switch (GameWin.state) {
case 0:
GameUtils.drawWord(g, "开始", Color.red, 80, 600, 400);
break;
case 1:
GameUtils.drawWord(g, "积分" + GameUtils.count, Color.ORANGE, 50, 200, 120);
GameUtils.drawWord(g, "难度" + GameUtils.level, Color.ORANGE, 50, 600, 120);
GameUtils.drawWord(g, "等级" + fishLevel, Color.ORANGE, 50, 1000, 120);
break;
case 2:
GameUtils.drawWord(g, "积分" + GameUtils.count, Color.ORANGE, 50, 200, 120);
GameUtils.drawWord(g, "难度" + GameUtils.level, Color.ORANGE, 50, 600, 120);
GameUtils.drawWord(g, "等级" + fishLevel, Color.ORANGE, 50, 1000, 120);
GameUtils.drawWord(g, "失败", Color.red, 80, 580, 450);
break;
case 3:
GameUtils.drawWord(g, "积分" + GameUtils.count, Color.ORANGE, 50, 200, 120);
GameUtils.drawWord(g, "难度" + GameUtils.level, Color.ORANGE, 50, 600, 120);
GameUtils.drawWord(g, "等级" + fishLevel, Color.ORANGE, 50, 1000, 120);
GameUtils.drawWord(g, "胜利了!", Color.ORANGE, 80, 580, 450);
case 4:
break;
default:
}
}
}
(2)Enamy类
import java.awt.*;
//敌方鱼父类
public class Enamy {
//定义图片
Image img;
//物体坐标
int x;
int y;
int width;
int height;
//移动速度
int speed;
//方向
int dir = 1;
//类型
int type;
//分值
int count;
//绘制自身方法
public void paintSelf(Graphics g) {
g.drawImage(img, x, y, width, height, null);
}
//获取自身矩形,用于碰撞检测
public Rectangle getRec() {
return new Rectangle(x, y, width - 45, height - 30);
}
}
//敌方鱼左类
class Enamy_1_L extends Enamy {
Enamy_1_L() {
this.x = -45;
this.y = (int) (Math.random() * 980);
this.width = 40;
this.height = 55;
this.speed = 1;
this.count = 1;
this.type = 1;
this.img = GameUtils.enamyl_1img;
}
@Override
public Rectangle getRec() {
return new Rectangle(x, y, width, height);
}
}
//敌方鱼右类
class Enamy_1_R extends Enamy_1_L {
Enamy_1_R() {
this.x = 1400;
dir = -1;
this.img = GameUtils.enamyr_1img;
}
}
class Enamy_2_L extends Enamy {
Enamy_2_L() {
this.x = -100;
this.y = (int) (Math.random() * 900 + 100);
this.width = 180;
this.height = 80;
this.speed = 5;
this.count = 3;
this.type = 2;
this.img = GameUtils.enamyl_2img;
}
}
class Enamy_2_R extends Enamy_2_L {
Enamy_2_R() {
this.x = 1400;
dir = -1;
this.img = GameUtils.enamyr_2img;
}
}
class Enamy_3_L extends Enamy {
Enamy_3_L() {
this.x = -300;
this.y = (int) (Math.random() * 980);
this.width = 250;
this.height = 150;
this.speed = 3;
this.count = 10;
this.type = 3;
this.img = GameUtils.enamyl_3img;
}
}
class Enamy_3_R extends Enamy_3_L {
Enamy_3_R() {
this.x = 1400;
dir = -1;
this.img = GameUtils.enamyr_3img;
}
}
class Enamy_Boss extends Enamy {
Enamy_Boss() {
this.x = -1200;
this.y = (int) (Math.random() * 700 + 100);
this.width = 250;
this.height = 200;
this.speed = 80;
this.type = 10;
this.img = GameUtils.bossimg;
}
}
(3)GameUtils类
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class GameUtils {
//方向
static boolean UP = false;
static boolean DOWN = false;
static boolean LEFT = false;
static boolean RIGHT = false;
//分数
static int count = 0;
//关卡等级
static int level = 0;
//背景图
public static Image bgimg = Toolkit.getDefaultToolkit().createImage("src/images/sea.jpg");
//敌方鱼类集合
public static List<Enamy> EnamyList = new ArrayList<>();
//敌方鱼类
public static Image enamyl_1img = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/fish1_r.gif");
public static Image enamyr_1img = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/fish1_l.gif");
public static Image enamyl_2img = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/fish2_r.png");
public static Image enamyr_2img = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/fish2_l.png");
public static Image enamyl_3img = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/fish3_r.gif");
public static Image enamyr_3img = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/fish3_l.gif");
public static Image bossimg = Toolkit.getDefaultToolkit().createImage("src/images/enemyFish/boss.gif");
//我方鱼类
public static Image MyFishimg_L = Toolkit.getDefaultToolkit().createImage("src/images/myFish/myfish_left.gif");
public static Image MyFishimg_R = Toolkit.getDefaultToolkit().createImage("src/images/myFish/myfish_right.gif");
//绘制文字的工具类
public static void drawWord(Graphics g, String str, Color color, int size, int x, int y) {
g.setColor(color);
g.setFont(new Font("宋体", Font.BOLD, size));
g.drawString(str, x, y);
}
}
(4)GameWin类
package com.mzy;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class GameWin extends JFrame {
/**
* 游戏状态 0未开始,1游戏中,2通关失败,3通关成功,4暂停,5重新开始
*/
//定义游戏默认状态
static int state = 0;
//双缓存图片
Image offScreenImage;
//窗口宽高
int width = 1320;
int height = 780;
//计数器
double random;
int time = 0;
//背景对象
Bg bg = new Bg();
//敌方鱼类
Enamy enamy = new Enamy_1_L();
//我方鱼类
MyFish myFish = new MyFish();
//boss鱼类
Enamy boss;
//是否生成boss
boolean isboss = false;
/**
* 游戏操作方法
*/
public void launch() {
Music audioPlayWave = new Music("src/皇家萌卫.wav");
audioPlayWave.start();
@SuppressWarnings("unused")
int musicOpenLab = 1;
//界面布局
this.setVisible(true);
this.setSize(width, height);
this.setLocationRelativeTo(null);
this.setTitle("大鱼吃小鱼");
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//开始或者失败后重新游戏
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (e.getButton() == 1 && state == 0) {
state = 1;
repaint();
}
if (e.getButton() == 1 && (state == 2 || state == 3)) {
reGame();
state = 1;
}
}
});
//键盘移动我方鱼类
this.addKeyListener(new KeyAdapter() {
@Override //按压
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
if (e.getKeyCode() == 87) {
GameUtils.UP = true;
}
if (e.getKeyCode() == 83) {
GameUtils.DOWN = true;
}
if (e.getKeyCode() == 65) {
GameUtils.LEFT = true;
}
if (e.getKeyCode() == 68) {
GameUtils.RIGHT = true;
}
if (e.getKeyCode() == 32) {
switch (state) {
case 1:
state = 4;
GameUtils.drawWord(getGraphics(), "游戏暂停!", Color.red, 50, 580, 450);
break;
case 4:
state = 1;
break;
}
}
}
@Override //抬起
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == 87) {
GameUtils.UP = false;
}
if (e.getKeyCode() == 83) {
GameUtils.DOWN = false;
}
if (e.getKeyCode() == 65) {
GameUtils.LEFT = false;
}
if (e.getKeyCode() == 68) {
GameUtils.RIGHT = false;
}
}
});
//线程操纵游戏帧率
while (true) {
repaint();
time++;
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 游戏阶段绘制鱼类
*/
@Override
public void paint(Graphics g) {
//双缓存加载图片
offScreenImage = createImage(width, height);
Graphics gImage = offScreenImage.getGraphics();
bg.paintSelf(gImage, myFish.level);
switch (state) {
case 0:
break;
case 1:
myFish.paintSelf(gImage);
logic();
for (Enamy enamy : GameUtils.EnamyList) {
enamy.paintSelf(gImage);
}
if (isboss) {
boss.x = boss.x + boss.dir * boss.speed;
boss.paintSelf(gImage);
if (boss.x < 0) {
gImage.setColor(Color.red);
gImage.fillRect(boss.x, boss.y + 100, 2400, boss.height / 20);
}
}
break;
case 2:
for (Enamy enamy : GameUtils.EnamyList) {
enamy.paintSelf(gImage);
}
if (isboss) {
boss.paintSelf(gImage);
}
break;
case 3:
myFish.paintSelf(gImage);
break;
case 4:
return;
default:
}
g.drawImage(offScreenImage, 0, 0, null);
}
/**
* 游戏关卡难度逻辑
*/
void logic() {
//关卡难度
if (GameUtils.count < 5) {
GameUtils.level = 0;
} else if (GameUtils.count < 15) {
GameUtils.level = 1;
} else if (GameUtils.count < 40) {
GameUtils.level = 2;
} else if (GameUtils.count < 75) {
GameUtils.level = 3;
} else if (GameUtils.count > 150) {
state = 3;
}
//我方鱼升级
if (29 < GameUtils.count && GameUtils.count < 79) {
myFish.level = 2;
} else if (GameUtils.count > 79) {
myFish.level = 3;
}
//阶段生成敌方鱼
random = Math.random();
switch (GameUtils.level) {
case 3:
if (time % 120 == 0) {
boss = new Enamy_Boss();
isboss = true;
}
case 2:
if (time % 120 == 0) {
if (random < 0.5) {
enamy = new Enamy_3_L();
} else {
enamy = new Enamy_3_R();
}
}
GameUtils.EnamyList.add(enamy);
case 1:
if (time % 60 == 0) {
if (random < 0.5) {
enamy = new Enamy_2_L();
} else {
enamy = new Enamy_2_R();
}
}
GameUtils.EnamyList.add(enamy);
case 0:
if (time % 10 == 0) {
if (random < 0.5) {
enamy = new Enamy_1_L();
} else {
enamy = new Enamy_1_R();
}
}
GameUtils.EnamyList.add(enamy);
break;
default:
}
//生成敌方鱼
for (Enamy enamy : GameUtils.EnamyList) {
enamy.x = enamy.x + enamy.dir * enamy.speed;
//boss鱼碰撞检测
if (isboss) {
if (boss.getRec().intersects(enamy.getRec())) {
enamy.x = -200;
enamy.y = -200;
}
if (boss.getRec().intersects(myFish.getRec())) {
state = 2;
}
}
//我方鱼与敌方鱼碰撞检测
if (myFish.getRec().intersects(enamy.getRec())) {
if (myFish.level >= enamy.type) {
enamy.x = -200;
enamy.y = -200;
GameUtils.count += enamy.count;
} else {
state = 2;
}
}
}
}
public static void main(String[] args) {
GameWin gameWin = new GameWin();
gameWin.launch();
}
//重新开始
void reGame() {
GameUtils.EnamyList.clear();
time = 0;
myFish.level = 1;
GameUtils.count = 0;
myFish.x = 650;
myFish.y = 400;
myFish.width = 45;
myFish.height = 45;
boss = null;
isboss = false;
}
}
(5)Music类
package com.mzy;
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.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Music extends Thread {
private String fileName;
private final int EXTERNAL_BUFFER_SIZE = 524288;
public Music(String wavFile) {
this.fileName = wavFile;
}
@SuppressWarnings("unused")
public void run() {
System.out.println("音乐播放");
File soundFile = new File(fileName); // 播放音乐的文件名
if (!soundFile.exists()) {
System.err.println("Wave file not found:" + fileName);
return;
}
while (true) { // 设置循环播放
AudioInputStream audioInputStream = null; // 创建音频输入流对象
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile); // 创建音频对象
} catch (UnsupportedAudioFileException e1) {
e1.printStackTrace();
return;
} catch (IOException e1) {
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat(); // 音频格式
SourceDataLine auline = null; // 源数据线
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
} catch (LineUnavailableException e) {
e.printStackTrace();
return;
} catch (Exception e) {
e.printStackTrace();
return;
}
if (auline.isControlSupported(FloatControl.Type.PAN)) {
FloatControl pan = (FloatControl) auline.getControl(FloatControl.Type.PAN);
}
auline.start();
int nBytesRead = 0;
byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
try {
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0)
auline.write(abData, 0, nBytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
// auline.close();
}
}
}
}
(6)MyFish类
import java.awt.*;
public class MyFish {
//图片
Image img = GameUtils.MyFishimg_L;
//坐标
int x = 650;
int y = 400;
int width = 45;
int height = 45;
//移动速度
int speed = 20;
//等级
int level = 1;
//移动
void logic() {
if (GameUtils.UP) {
y = y - speed;
}
if (GameUtils.DOWN) {
y = y + speed;
}
if (GameUtils.LEFT) {
x = x - speed;
img = GameUtils.MyFishimg_L;
}
if (GameUtils.RIGHT) {
x = x + speed;
img = GameUtils.MyFishimg_R;
}
}
//绘制自身方法
public void paintSelf(Graphics g) {
logic();
g.drawImage(img, x, y, width + GameUtils.count, height + GameUtils.count, null);
}
//获取自身矩形方法,用于碰撞检测
public Rectangle getRec() {
return new Rectangle(x, y, width + GameUtils.count, height + GameUtils.count);
}
}
结束语:
游戏还有很多缺陷地方,比如我方鱼可以离开界面,敌方鱼在离开界面后没有及时清除,游戏玩法过于简单。都需要小伙伴们自己去改进,挖掘。
游戏源码下载解压后,注意打开项目的文件夹位置,出现报错,游戏界面白屏等问题,都可以私信帮忙解决。
源码:
github:GitHub - ZhaoyangClassmate/Game: 编程小游戏文章来源:https://www.toymoban.com/news/detail-492064.html
链接:https://pan.baidu.com/s/1QyuhE1KaM_RupqLpUkr1JA
提取码:2czk文章来源地址https://www.toymoban.com/news/detail-492064.html
到了这里,关于Java实现大鱼吃小鱼游戏(开源)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!